@react-three-dom/core 0.1.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/index.cjs +2666 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1054 -0
- package/dist/index.d.ts +1054 -0
- package/dist/index.js +2619 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1054 @@
|
|
|
1
|
+
import { Object3D, Camera, WebGLRenderer, Vector3 } from 'three';
|
|
2
|
+
|
|
3
|
+
declare const version = "0.1.0";
|
|
4
|
+
|
|
5
|
+
interface ObjectMetadata {
|
|
6
|
+
/** Three.js internal UUID */
|
|
7
|
+
uuid: string;
|
|
8
|
+
/** Object name (object.name) */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Three.js class type: "Mesh", "Group", "PointLight", etc. */
|
|
11
|
+
type: string;
|
|
12
|
+
/** Whether the object itself is visible (does not check parent chain) */
|
|
13
|
+
visible: boolean;
|
|
14
|
+
/** User-defined test identifier from userData.testId */
|
|
15
|
+
testId?: string;
|
|
16
|
+
/** Geometry class name: "BoxGeometry", "BufferGeometry", etc. */
|
|
17
|
+
geometryType?: string;
|
|
18
|
+
/** Material class name: "MeshStandardMaterial", etc. */
|
|
19
|
+
materialType?: string;
|
|
20
|
+
/** Total vertex count (from geometry attributes) */
|
|
21
|
+
vertexCount?: number;
|
|
22
|
+
/** Triangle count (derived from index or vertex count) */
|
|
23
|
+
triangleCount?: number;
|
|
24
|
+
/** Instance count for InstancedMesh */
|
|
25
|
+
instanceCount?: number;
|
|
26
|
+
/** Local position as [x, y, z] */
|
|
27
|
+
position: [number, number, number];
|
|
28
|
+
/** Local euler rotation as [x, y, z] in radians */
|
|
29
|
+
rotation: [number, number, number];
|
|
30
|
+
/** Local scale as [x, y, z] */
|
|
31
|
+
scale: [number, number, number];
|
|
32
|
+
/** UUID of parent object, or null for scene root */
|
|
33
|
+
parentUuid: string | null;
|
|
34
|
+
/** UUIDs of direct children */
|
|
35
|
+
childrenUuids: string[];
|
|
36
|
+
/** Flag indicating bounds need recomputation */
|
|
37
|
+
boundsDirty: boolean;
|
|
38
|
+
}
|
|
39
|
+
interface GeometryInspection {
|
|
40
|
+
/** Geometry class type */
|
|
41
|
+
type: string;
|
|
42
|
+
/** Map of attribute name → { itemSize, count } */
|
|
43
|
+
attributes: Record<string, {
|
|
44
|
+
itemSize: number;
|
|
45
|
+
count: number;
|
|
46
|
+
}>;
|
|
47
|
+
/** Index buffer info, if indexed geometry */
|
|
48
|
+
index?: {
|
|
49
|
+
count: number;
|
|
50
|
+
};
|
|
51
|
+
/** Bounding sphere computed from geometry */
|
|
52
|
+
boundingSphere?: {
|
|
53
|
+
center: [number, number, number];
|
|
54
|
+
radius: number;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
interface MaterialInspection {
|
|
58
|
+
/** Material class type */
|
|
59
|
+
type: string;
|
|
60
|
+
/** Hex color string, if applicable */
|
|
61
|
+
color?: string;
|
|
62
|
+
/** Texture name/uuid of the main map, if any */
|
|
63
|
+
map?: string;
|
|
64
|
+
/** Shader material uniforms (keys only for non-shader materials) */
|
|
65
|
+
uniforms?: Record<string, unknown>;
|
|
66
|
+
/** Whether material is transparent */
|
|
67
|
+
transparent?: boolean;
|
|
68
|
+
/** Material opacity */
|
|
69
|
+
opacity?: number;
|
|
70
|
+
/** Whether the material is double-sided */
|
|
71
|
+
side?: number;
|
|
72
|
+
}
|
|
73
|
+
interface ObjectInspection {
|
|
74
|
+
/** Tier 1 cached metadata */
|
|
75
|
+
metadata: ObjectMetadata;
|
|
76
|
+
/** World matrix as 16-element flat array */
|
|
77
|
+
worldMatrix: number[];
|
|
78
|
+
/** World-space axis-aligned bounding box */
|
|
79
|
+
bounds: {
|
|
80
|
+
min: [number, number, number];
|
|
81
|
+
max: [number, number, number];
|
|
82
|
+
};
|
|
83
|
+
/** Geometry details (meshes only) */
|
|
84
|
+
geometry?: GeometryInspection;
|
|
85
|
+
/** Material details (meshes/points/lines only) */
|
|
86
|
+
material?: MaterialInspection;
|
|
87
|
+
/** Full userData object from the Three.js object */
|
|
88
|
+
userData: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
interface SnapshotNode {
|
|
91
|
+
uuid: string;
|
|
92
|
+
name: string;
|
|
93
|
+
type: string;
|
|
94
|
+
testId?: string;
|
|
95
|
+
visible: boolean;
|
|
96
|
+
position: [number, number, number];
|
|
97
|
+
rotation: [number, number, number];
|
|
98
|
+
scale: [number, number, number];
|
|
99
|
+
children: SnapshotNode[];
|
|
100
|
+
}
|
|
101
|
+
interface SceneSnapshot {
|
|
102
|
+
/** Timestamp when snapshot was taken (Date.now()) */
|
|
103
|
+
timestamp: number;
|
|
104
|
+
/** Total number of objects in the scene */
|
|
105
|
+
objectCount: number;
|
|
106
|
+
/** Recursive tree of snapshot nodes */
|
|
107
|
+
tree: SnapshotNode;
|
|
108
|
+
}
|
|
109
|
+
type StoreEventType = 'add' | 'remove' | 'update';
|
|
110
|
+
interface StoreEvent {
|
|
111
|
+
type: StoreEventType;
|
|
112
|
+
object: Object3D;
|
|
113
|
+
metadata: ObjectMetadata;
|
|
114
|
+
}
|
|
115
|
+
type StoreListener = (event: StoreEvent) => void;
|
|
116
|
+
interface R3FDOM {
|
|
117
|
+
/** Tier 1: O(1) lookup by testId */
|
|
118
|
+
getByTestId(id: string): ObjectMetadata | null;
|
|
119
|
+
/** Tier 1: O(1) lookup by uuid */
|
|
120
|
+
getByUuid(uuid: string): ObjectMetadata | null;
|
|
121
|
+
/** Tier 1: O(1) lookup by name (returns array, names aren't unique) */
|
|
122
|
+
getByName(name: string): ObjectMetadata[];
|
|
123
|
+
/** Total number of tracked objects */
|
|
124
|
+
getCount(): number;
|
|
125
|
+
/** Full structured JSON snapshot from Tier 1 store */
|
|
126
|
+
snapshot(): SceneSnapshot;
|
|
127
|
+
/** Tier 2: on-demand heavy inspection (reads live Three.js object) */
|
|
128
|
+
inspect(idOrUuid: string): ObjectInspection | null;
|
|
129
|
+
/** Deterministic click on a 3D object */
|
|
130
|
+
click(idOrUuid: string): void;
|
|
131
|
+
/** Deterministic double-click on a 3D object */
|
|
132
|
+
doubleClick(idOrUuid: string): void;
|
|
133
|
+
/** Deterministic right-click / context menu on a 3D object */
|
|
134
|
+
contextMenu(idOrUuid: string): void;
|
|
135
|
+
/** Deterministic hover on a 3D object */
|
|
136
|
+
hover(idOrUuid: string): void;
|
|
137
|
+
/** Deterministic drag on a 3D object */
|
|
138
|
+
drag(idOrUuid: string, delta: {
|
|
139
|
+
x: number;
|
|
140
|
+
y: number;
|
|
141
|
+
z: number;
|
|
142
|
+
}): void;
|
|
143
|
+
/** Dispatch a wheel/scroll event on a 3D object */
|
|
144
|
+
wheel(idOrUuid: string, options?: {
|
|
145
|
+
deltaY?: number;
|
|
146
|
+
deltaX?: number;
|
|
147
|
+
}): void;
|
|
148
|
+
/** Click empty space to trigger onPointerMissed */
|
|
149
|
+
pointerMiss(): void;
|
|
150
|
+
/** Select an object (shows highlight wireframe in scene) */
|
|
151
|
+
select(idOrUuid: string): void;
|
|
152
|
+
/** Clear selection */
|
|
153
|
+
clearSelection(): void;
|
|
154
|
+
/** Raw Three.js object access (for advanced debugging) */
|
|
155
|
+
getObject3D(idOrUuid: string): Object3D | null;
|
|
156
|
+
/** Library version */
|
|
157
|
+
version: string;
|
|
158
|
+
}
|
|
159
|
+
declare global {
|
|
160
|
+
interface Window {
|
|
161
|
+
__R3F_DOM__?: R3FDOM;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
declare class ObjectStore {
|
|
166
|
+
private _metaByObject;
|
|
167
|
+
private _objectByUuid;
|
|
168
|
+
private _objectsByTestId;
|
|
169
|
+
private _objectsByName;
|
|
170
|
+
private _flatList;
|
|
171
|
+
private _flatListDirty;
|
|
172
|
+
private _dirtyQueue;
|
|
173
|
+
private _listeners;
|
|
174
|
+
private _trackedRoots;
|
|
175
|
+
/**
|
|
176
|
+
* Register a single object into the store.
|
|
177
|
+
* Populates Tier 1 metadata and all indexes.
|
|
178
|
+
*/
|
|
179
|
+
register(obj: Object3D): ObjectMetadata;
|
|
180
|
+
/**
|
|
181
|
+
* Register an entire subtree (object + all descendants).
|
|
182
|
+
*/
|
|
183
|
+
registerTree(root: Object3D): void;
|
|
184
|
+
/**
|
|
185
|
+
* Unregister a single object from the store.
|
|
186
|
+
*/
|
|
187
|
+
unregister(obj: Object3D): void;
|
|
188
|
+
/**
|
|
189
|
+
* Unregister an entire subtree (object + all descendants).
|
|
190
|
+
*/
|
|
191
|
+
unregisterTree(root: Object3D): void;
|
|
192
|
+
/**
|
|
193
|
+
* Refresh Tier 1 metadata from the live Three.js object.
|
|
194
|
+
* Returns true if any values changed.
|
|
195
|
+
*/
|
|
196
|
+
update(obj: Object3D): boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Compute full inspection data from a live Three.js object.
|
|
199
|
+
* This reads geometry buffers, material properties, world bounds, etc.
|
|
200
|
+
* Cost: 0.1–2ms depending on geometry complexity.
|
|
201
|
+
*/
|
|
202
|
+
inspect(idOrUuid: string): ObjectInspection | null;
|
|
203
|
+
/** Get metadata by testId. O(1). */
|
|
204
|
+
getByTestId(testId: string): ObjectMetadata | null;
|
|
205
|
+
/** Get metadata by uuid. O(1). */
|
|
206
|
+
getByUuid(uuid: string): ObjectMetadata | null;
|
|
207
|
+
/** Get metadata by name (returns array since names aren't unique). O(1). */
|
|
208
|
+
getByName(name: string): ObjectMetadata[];
|
|
209
|
+
/** Get the raw Three.js Object3D by testId or uuid. */
|
|
210
|
+
getObject3D(idOrUuid: string): Object3D | null;
|
|
211
|
+
/** Get metadata for a known Object3D reference. */
|
|
212
|
+
getMetadata(obj: Object3D): ObjectMetadata | null;
|
|
213
|
+
/** Check if an object is registered. */
|
|
214
|
+
has(obj: Object3D): boolean;
|
|
215
|
+
/** Total number of tracked objects. */
|
|
216
|
+
getCount(): number;
|
|
217
|
+
/** Check if a root scene is tracked. */
|
|
218
|
+
isTrackedRoot(obj: Object3D): boolean;
|
|
219
|
+
/**
|
|
220
|
+
* Walk up from `obj` to see if any ancestor is a tracked root.
|
|
221
|
+
* Used by Object3D.add/remove patch to determine if an object
|
|
222
|
+
* belongs to a monitored scene.
|
|
223
|
+
*/
|
|
224
|
+
isInTrackedScene(obj: Object3D): boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Get a flat array of all tracked objects for amortized batch processing.
|
|
227
|
+
* Rebuilds lazily when the list is dirty (objects added/removed).
|
|
228
|
+
*/
|
|
229
|
+
getFlatList(): Object3D[];
|
|
230
|
+
/** Mark an object as dirty (needs priority sync next frame). */
|
|
231
|
+
markDirty(obj: Object3D): void;
|
|
232
|
+
/**
|
|
233
|
+
* Drain the dirty queue, returning all objects that need priority sync.
|
|
234
|
+
* Clears the queue after draining.
|
|
235
|
+
*/
|
|
236
|
+
drainDirtyQueue(): Object3D[];
|
|
237
|
+
/** Number of objects currently in the dirty queue. */
|
|
238
|
+
getDirtyCount(): number;
|
|
239
|
+
/** Subscribe to store events (add, remove, update). */
|
|
240
|
+
subscribe(listener: StoreListener): () => void;
|
|
241
|
+
private _emit;
|
|
242
|
+
/** Remove all tracked objects and reset state. */
|
|
243
|
+
dispose(): void;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Manages the parallel DOM tree that mirrors the Three.js scene graph.
|
|
248
|
+
*
|
|
249
|
+
* Key design for 100k-scale:
|
|
250
|
+
* - ObjectStore holds Tier 1 metadata for ALL objects (cheap, ~120 bytes each)
|
|
251
|
+
* - DomMirror only materializes DOM nodes for actively viewed/queried objects
|
|
252
|
+
* - Max materialized DOM nodes capped (default 2,000) with LRU eviction
|
|
253
|
+
* - DOM writes only happen for materialized nodes where values actually differ
|
|
254
|
+
*/
|
|
255
|
+
declare class DomMirror {
|
|
256
|
+
private _store;
|
|
257
|
+
private _rootElement;
|
|
258
|
+
private _nodes;
|
|
259
|
+
private _lruHead;
|
|
260
|
+
private _lruTail;
|
|
261
|
+
private _lruSize;
|
|
262
|
+
private _maxNodes;
|
|
263
|
+
private _parentMap;
|
|
264
|
+
constructor(store: ObjectStore, maxNodes?: number);
|
|
265
|
+
/**
|
|
266
|
+
* Set the root DOM element where the mirror tree will be appended.
|
|
267
|
+
* Typically a hidden div: <div id="three-dom-root" style="display:none">
|
|
268
|
+
*/
|
|
269
|
+
setRoot(rootElement: HTMLElement): void;
|
|
270
|
+
/**
|
|
271
|
+
* Build the initial DOM tree from the scene.
|
|
272
|
+
* Materializes the top 2 levels of the scene hierarchy.
|
|
273
|
+
*/
|
|
274
|
+
buildInitialTree(scene: Object3D): void;
|
|
275
|
+
/**
|
|
276
|
+
* Create a DOM node for a single object.
|
|
277
|
+
* If already materialized, touches the LRU and returns the existing element.
|
|
278
|
+
*/
|
|
279
|
+
materialize(uuid: string): HTMLElement | null;
|
|
280
|
+
/**
|
|
281
|
+
* Materialize a subtree starting from the given uuid, up to the specified depth.
|
|
282
|
+
* depth=0 materializes just the node, depth=1 includes direct children, etc.
|
|
283
|
+
*/
|
|
284
|
+
materializeSubtree(uuid: string, depth: number): void;
|
|
285
|
+
/**
|
|
286
|
+
* Remove a DOM node but keep JS metadata in the ObjectStore.
|
|
287
|
+
* Called by LRU eviction or when an object is removed from the scene.
|
|
288
|
+
*/
|
|
289
|
+
dematerialize(uuid: string): void;
|
|
290
|
+
/**
|
|
291
|
+
* Called when a new object is added to the tracked scene.
|
|
292
|
+
* Only materializes if the parent is already materialized (lazy expansion).
|
|
293
|
+
*/
|
|
294
|
+
onObjectAdded(obj: Object3D): void;
|
|
295
|
+
/**
|
|
296
|
+
* Called when an object is removed from the tracked scene.
|
|
297
|
+
* Dematerializes the object and all its descendants.
|
|
298
|
+
*/
|
|
299
|
+
onObjectRemoved(obj: Object3D): void;
|
|
300
|
+
/**
|
|
301
|
+
* Sync Tier 1 attributes for an object if it's materialized.
|
|
302
|
+
* No-op if the object has no materialized DOM node.
|
|
303
|
+
* Returns the number of DOM writes performed.
|
|
304
|
+
*/
|
|
305
|
+
syncAttributes(obj: Object3D): number;
|
|
306
|
+
/**
|
|
307
|
+
* Sync attributes by uuid (when you don't have the Object3D ref).
|
|
308
|
+
*/
|
|
309
|
+
syncAttributesByUuid(uuid: string): number;
|
|
310
|
+
/**
|
|
311
|
+
* Get the root DOM element.
|
|
312
|
+
*/
|
|
313
|
+
getRootElement(): HTMLElement | null;
|
|
314
|
+
/**
|
|
315
|
+
* Get the materialized DOM element for an object, if it exists.
|
|
316
|
+
*/
|
|
317
|
+
getElement(uuid: string): HTMLElement | null;
|
|
318
|
+
/**
|
|
319
|
+
* Check if an object has a materialized DOM node.
|
|
320
|
+
*/
|
|
321
|
+
isMaterialized(uuid: string): boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Query the mirror DOM using a CSS selector.
|
|
324
|
+
* Falls back to searching the ObjectStore if no materialized nodes match,
|
|
325
|
+
* then materializes the matching objects.
|
|
326
|
+
*/
|
|
327
|
+
querySelector(selector: string): HTMLElement | null;
|
|
328
|
+
/**
|
|
329
|
+
* Query all matching elements in the mirror DOM.
|
|
330
|
+
*/
|
|
331
|
+
querySelectorAll(selector: string): HTMLElement[];
|
|
332
|
+
/**
|
|
333
|
+
* Set the maximum number of materialized DOM nodes.
|
|
334
|
+
* If current count exceeds the new max, excess nodes are evicted immediately.
|
|
335
|
+
*/
|
|
336
|
+
setMaxNodes(max: number): void;
|
|
337
|
+
/** Current number of materialized DOM nodes. */
|
|
338
|
+
getMaterializedCount(): number;
|
|
339
|
+
/** Maximum allowed materialized DOM nodes. */
|
|
340
|
+
getMaxNodes(): number;
|
|
341
|
+
/**
|
|
342
|
+
* Remove all materialized DOM nodes and reset state.
|
|
343
|
+
*/
|
|
344
|
+
dispose(): void;
|
|
345
|
+
/**
|
|
346
|
+
* Insert a newly created element into the correct position in the DOM tree.
|
|
347
|
+
*/
|
|
348
|
+
private _insertIntoDom;
|
|
349
|
+
/**
|
|
350
|
+
* Parse common CSS selector patterns and resolve to a uuid from the store.
|
|
351
|
+
* Supports:
|
|
352
|
+
* [data-test-id="value"]
|
|
353
|
+
* [data-name="value"]
|
|
354
|
+
* [data-uuid="value"]
|
|
355
|
+
* three-mesh, three-light, etc. (by tag/type)
|
|
356
|
+
*/
|
|
357
|
+
private _findUuidBySelector;
|
|
358
|
+
/**
|
|
359
|
+
* Find all UUIDs matching a selector pattern.
|
|
360
|
+
*/
|
|
361
|
+
private _findAllUuidsBySelector;
|
|
362
|
+
/** Add a node to the front (most recently used). */
|
|
363
|
+
private _lruPush;
|
|
364
|
+
/** Remove a node from the list. */
|
|
365
|
+
private _lruRemove;
|
|
366
|
+
/** Move a node to the front (most recently used). */
|
|
367
|
+
private _lruTouch;
|
|
368
|
+
/** Evict the least recently used node. */
|
|
369
|
+
private _evictLRU;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Maps Three.js object types to custom element tag names.
|
|
374
|
+
* Multiple Three.js types can map to the same tag.
|
|
375
|
+
*/
|
|
376
|
+
declare const TAG_MAP: Record<string, string>;
|
|
377
|
+
/** All unique tag names that need to be registered. */
|
|
378
|
+
declare const ALL_TAGS: readonly ["three-scene", "three-group", "three-mesh", "three-light", "three-camera", "three-object"];
|
|
379
|
+
type ThreeTagName = (typeof ALL_TAGS)[number];
|
|
380
|
+
/**
|
|
381
|
+
* Get the custom element tag name for a Three.js object type.
|
|
382
|
+
*/
|
|
383
|
+
declare function getTagForType(type: string): ThreeTagName;
|
|
384
|
+
/**
|
|
385
|
+
* Base custom element class for the DOM mirror.
|
|
386
|
+
* Provides interactive properties and methods accessible via DevTools console.
|
|
387
|
+
*
|
|
388
|
+
* Usage in DevTools after selecting a <three-mesh> in the Elements panel:
|
|
389
|
+
* $0.metadata → Tier 1 cached metadata (instant)
|
|
390
|
+
* $0.inspect() → Tier 2 heavy inspection (reads live Three.js object)
|
|
391
|
+
* $0.object3D → raw THREE.Object3D reference
|
|
392
|
+
* $0.position → [x, y, z] shortcut
|
|
393
|
+
* $0.bounds → { min, max } shortcut
|
|
394
|
+
* $0.click() → trigger deterministic click
|
|
395
|
+
* $0.hover() → trigger deterministic hover
|
|
396
|
+
*/
|
|
397
|
+
declare class ThreeElement extends HTMLElement {
|
|
398
|
+
/**
|
|
399
|
+
* Returns the Tier 1 cached metadata for this object.
|
|
400
|
+
* Instant, no computation. Returns null if the element is not linked.
|
|
401
|
+
*/
|
|
402
|
+
get metadata(): ObjectMetadata | null;
|
|
403
|
+
/**
|
|
404
|
+
* Performs a full inspection of the linked Three.js object.
|
|
405
|
+
* Reads geometry buffers, material properties, world bounds, etc.
|
|
406
|
+
* Cost: 0.1–2ms depending on geometry complexity.
|
|
407
|
+
*/
|
|
408
|
+
inspect(): ObjectInspection | null;
|
|
409
|
+
/**
|
|
410
|
+
* Returns the raw Three.js Object3D linked to this DOM element.
|
|
411
|
+
* Allows direct access to any Three.js property or method.
|
|
412
|
+
*/
|
|
413
|
+
get object3D(): Object3D | null;
|
|
414
|
+
/**
|
|
415
|
+
* Local position as [x, y, z].
|
|
416
|
+
*/
|
|
417
|
+
get position(): [number, number, number] | null;
|
|
418
|
+
/**
|
|
419
|
+
* Local euler rotation as [x, y, z] in radians.
|
|
420
|
+
*/
|
|
421
|
+
get rotation(): [number, number, number] | null;
|
|
422
|
+
/**
|
|
423
|
+
* Local scale as [x, y, z].
|
|
424
|
+
*/
|
|
425
|
+
get scale(): [number, number, number] | null;
|
|
426
|
+
/**
|
|
427
|
+
* Whether the object is visible (does not check parent chain).
|
|
428
|
+
*/
|
|
429
|
+
get visible(): boolean;
|
|
430
|
+
/**
|
|
431
|
+
* The testId from userData.testId, if set.
|
|
432
|
+
*/
|
|
433
|
+
get testId(): string | undefined;
|
|
434
|
+
/**
|
|
435
|
+
* World-space bounding box. Computed on-demand (Tier 2).
|
|
436
|
+
*/
|
|
437
|
+
get bounds(): {
|
|
438
|
+
min: [number, number, number];
|
|
439
|
+
max: [number, number, number];
|
|
440
|
+
} | null;
|
|
441
|
+
/**
|
|
442
|
+
* Trigger a deterministic click on the linked 3D object.
|
|
443
|
+
* Projects the object center to screen coordinates and dispatches pointer events.
|
|
444
|
+
*/
|
|
445
|
+
click(): void;
|
|
446
|
+
/**
|
|
447
|
+
* Trigger a deterministic hover on the linked 3D object.
|
|
448
|
+
*/
|
|
449
|
+
hover(): void;
|
|
450
|
+
/**
|
|
451
|
+
* Returns a readable string representation for console output.
|
|
452
|
+
*/
|
|
453
|
+
toString(): string;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Register all custom elements (<three-scene>, <three-mesh>, etc.).
|
|
457
|
+
* Safe to call multiple times — only registers once.
|
|
458
|
+
*
|
|
459
|
+
* @param store - The ObjectStore instance for element property lookups
|
|
460
|
+
*/
|
|
461
|
+
declare function ensureCustomElements(store: ObjectStore): void;
|
|
462
|
+
|
|
463
|
+
/** All attribute names we manage (for diffing). */
|
|
464
|
+
declare const MANAGED_ATTRIBUTES: string[];
|
|
465
|
+
/**
|
|
466
|
+
* Compute all attribute key-value pairs for a metadata object.
|
|
467
|
+
* Returns a map of attribute name → value.
|
|
468
|
+
* Attributes with undefined values are excluded.
|
|
469
|
+
*/
|
|
470
|
+
declare function computeAttributes(meta: ObjectMetadata): Map<string, string>;
|
|
471
|
+
/**
|
|
472
|
+
* Apply attributes to a DOM element, only writing those that changed.
|
|
473
|
+
* Returns the number of attributes that were actually written (for perf tracking).
|
|
474
|
+
*
|
|
475
|
+
* @param element - The custom element to update
|
|
476
|
+
* @param meta - Current Tier 1 metadata
|
|
477
|
+
* @param prevAttrs - Previous attribute values (mutated in-place to reflect new state)
|
|
478
|
+
* @returns Number of DOM setAttribute calls made
|
|
479
|
+
*/
|
|
480
|
+
declare function applyAttributes(element: HTMLElement, meta: ObjectMetadata, prevAttrs: Map<string, string>): number;
|
|
481
|
+
|
|
482
|
+
type SelectionListener = (selected: Object3D[]) => void;
|
|
483
|
+
declare class SelectionManager {
|
|
484
|
+
/** Currently selected objects (ordered by selection time). */
|
|
485
|
+
private _selected;
|
|
486
|
+
/** Listeners notified on selection change. */
|
|
487
|
+
private _listeners;
|
|
488
|
+
/** Select a single object (clears previous selection). */
|
|
489
|
+
select(obj: Object3D): void;
|
|
490
|
+
/** Add an object to the current selection (multi-select). */
|
|
491
|
+
addToSelection(obj: Object3D): void;
|
|
492
|
+
/** Remove an object from the selection. */
|
|
493
|
+
removeFromSelection(obj: Object3D): void;
|
|
494
|
+
/** Toggle an object in/out of the selection. */
|
|
495
|
+
toggleSelection(obj: Object3D): void;
|
|
496
|
+
/** Clear all selections. */
|
|
497
|
+
clearSelection(): void;
|
|
498
|
+
/** Get the currently selected objects. */
|
|
499
|
+
getSelected(): readonly Object3D[];
|
|
500
|
+
/** Get the primary (first) selected object, or null. */
|
|
501
|
+
getPrimary(): Object3D | null;
|
|
502
|
+
/** Check if an object is selected. */
|
|
503
|
+
isSelected(obj: Object3D): boolean;
|
|
504
|
+
/** Number of selected objects. */
|
|
505
|
+
get count(): number;
|
|
506
|
+
/** Subscribe to selection changes. Returns unsubscribe function. */
|
|
507
|
+
subscribe(listener: SelectionListener): () => void;
|
|
508
|
+
private _notify;
|
|
509
|
+
dispose(): void;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
interface HighlighterOptions {
|
|
513
|
+
/** Whether to show a tooltip above highlighted objects. Default: true */
|
|
514
|
+
showTooltip?: boolean;
|
|
515
|
+
}
|
|
516
|
+
declare class Highlighter {
|
|
517
|
+
/** Selected object overlays (persistent until deselected) */
|
|
518
|
+
private _selectedEntries;
|
|
519
|
+
/** Hover overlay (temporary, single object at a time) */
|
|
520
|
+
private _hoverEntries;
|
|
521
|
+
private _camera;
|
|
522
|
+
private _renderer;
|
|
523
|
+
private _unsubscribe;
|
|
524
|
+
private _showTooltip;
|
|
525
|
+
/** DevTools hover polling interval */
|
|
526
|
+
private _hoverPollId;
|
|
527
|
+
private _lastHoveredElement;
|
|
528
|
+
/** Store reference for resolving objects */
|
|
529
|
+
private _store;
|
|
530
|
+
constructor(options?: HighlighterOptions);
|
|
531
|
+
attach(_scene: Object3D, selectionManager: SelectionManager, camera: Camera, renderer: WebGLRenderer, store: {
|
|
532
|
+
getObject3D(uuid: string): Object3D | null;
|
|
533
|
+
}): void;
|
|
534
|
+
detach(): void;
|
|
535
|
+
update(): void;
|
|
536
|
+
highlight(obj: Object3D): void;
|
|
537
|
+
unhighlight(obj: Object3D): void;
|
|
538
|
+
clearAll(): void;
|
|
539
|
+
isHighlighted(obj: Object3D): boolean;
|
|
540
|
+
/** Show a temporary hover highlight for an object and its children */
|
|
541
|
+
showHoverHighlight(obj: Object3D): void;
|
|
542
|
+
/** Clear the hover highlight */
|
|
543
|
+
clearHoverHighlight(): void;
|
|
544
|
+
private _syncSelectedHighlights;
|
|
545
|
+
private _addSelectedHighlight;
|
|
546
|
+
private _addHoverHighlightRecursive;
|
|
547
|
+
private _startHoverPolling;
|
|
548
|
+
private _stopHoverPolling;
|
|
549
|
+
private _pollDevToolsHover;
|
|
550
|
+
private _removeOverlay;
|
|
551
|
+
private _clearAllOverlays;
|
|
552
|
+
dispose(): void;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
interface ThreeDomProps {
|
|
556
|
+
/** CSS selector or HTMLElement for the mirror DOM root. Default: "#three-dom-root" */
|
|
557
|
+
root?: string | HTMLElement;
|
|
558
|
+
/** Objects to process per amortized batch per frame. Default: 500 */
|
|
559
|
+
batchSize?: number;
|
|
560
|
+
/** Max time budget (ms) for sync work per frame. Default: 0.5 */
|
|
561
|
+
timeBudgetMs?: number;
|
|
562
|
+
/** Max materialized DOM nodes (LRU eviction). Default: 2000 */
|
|
563
|
+
maxDomNodes?: number;
|
|
564
|
+
/** Initial DOM tree materialization depth. Default: 3 */
|
|
565
|
+
initialDepth?: number;
|
|
566
|
+
/** Disable all sync. Default: true */
|
|
567
|
+
enabled?: boolean;
|
|
568
|
+
}
|
|
569
|
+
declare function getStore(): ObjectStore | null;
|
|
570
|
+
declare function getMirror(): DomMirror | null;
|
|
571
|
+
declare function getSelectionManager(): SelectionManager | null;
|
|
572
|
+
declare function getHighlighter(): Highlighter | null;
|
|
573
|
+
declare function ThreeDom({ root, batchSize, timeBudgetMs, maxDomNodes, initialDepth, enabled, }?: ThreeDomProps): null;
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Patch Object3D.prototype.add and Object3D.prototype.remove to intercept
|
|
577
|
+
* structural changes for tracked scenes.
|
|
578
|
+
*
|
|
579
|
+
* @param store - The ObjectStore managing scene metadata
|
|
580
|
+
* @param mirror - The DomMirror managing the parallel DOM tree
|
|
581
|
+
* @returns A cleanup function that unregisters this store/mirror pair
|
|
582
|
+
*/
|
|
583
|
+
declare function patchObject3D(store: ObjectStore, mirror: DomMirror): () => void;
|
|
584
|
+
/**
|
|
585
|
+
* Restore the original Object3D.prototype.add and remove methods.
|
|
586
|
+
* Called automatically when the last store/mirror pair is removed.
|
|
587
|
+
* Can also be called manually for testing.
|
|
588
|
+
*/
|
|
589
|
+
declare function restoreObject3D(): void;
|
|
590
|
+
/**
|
|
591
|
+
* Check if Object3D prototype is currently patched.
|
|
592
|
+
*/
|
|
593
|
+
declare function isPatched(): boolean;
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Create a full scene snapshot from the ObjectStore.
|
|
597
|
+
*
|
|
598
|
+
* Returns a structured JSON tree built entirely from Tier 1 cached metadata.
|
|
599
|
+
* No Three.js objects or DOM nodes are accessed.
|
|
600
|
+
*
|
|
601
|
+
* @example
|
|
602
|
+
* ```ts
|
|
603
|
+
* const snap = createSnapshot(store);
|
|
604
|
+
* console.log(snap.objectCount); // 1234
|
|
605
|
+
* console.log(snap.tree.children[0].name); // "Furniture"
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
declare function createSnapshot(store: ObjectStore): SceneSnapshot;
|
|
609
|
+
/**
|
|
610
|
+
* Create a flat snapshot — an array of all object metadata without tree structure.
|
|
611
|
+
* Useful for searching/filtering without recursion.
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* ```ts
|
|
615
|
+
* const flat = createFlatSnapshot(store);
|
|
616
|
+
* const meshes = flat.objects.filter(m => m.type === 'Mesh');
|
|
617
|
+
* ```
|
|
618
|
+
*/
|
|
619
|
+
declare function createFlatSnapshot(store: ObjectStore): {
|
|
620
|
+
timestamp: number;
|
|
621
|
+
objectCount: number;
|
|
622
|
+
objects: ObjectMetadata[];
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
/** Screen-space coordinates in CSS pixels relative to the canvas. */
|
|
626
|
+
interface ScreenPoint {
|
|
627
|
+
/** X coordinate in CSS pixels, left = 0. */
|
|
628
|
+
x: number;
|
|
629
|
+
/** Y coordinate in CSS pixels, top = 0. */
|
|
630
|
+
y: number;
|
|
631
|
+
}
|
|
632
|
+
/** Canvas dimensions in CSS pixels. */
|
|
633
|
+
interface CanvasSize {
|
|
634
|
+
width: number;
|
|
635
|
+
height: number;
|
|
636
|
+
}
|
|
637
|
+
/** Result of a projection attempt. */
|
|
638
|
+
interface ProjectionResult {
|
|
639
|
+
/** The screen-space point (CSS pixels relative to the canvas element). */
|
|
640
|
+
point: ScreenPoint;
|
|
641
|
+
/** Which strategy produced the result. */
|
|
642
|
+
strategy: 'center' | 'corner' | 'face-center' | 'fallback-origin';
|
|
643
|
+
/** NDC coordinates (-1..+1 range) for the projected point. */
|
|
644
|
+
ndc: {
|
|
645
|
+
x: number;
|
|
646
|
+
y: number;
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Project a 3D object to screen coordinates using a multi-strategy approach:
|
|
651
|
+
*
|
|
652
|
+
* 1. **Center**: Try the bounding box center (most natural click target).
|
|
653
|
+
* 2. **Face centers**: Try the 6 face centers (better for large/flat objects).
|
|
654
|
+
* 3. **Corners**: Try the 8 bbox corners (catches partially visible objects).
|
|
655
|
+
* 4. **Fallback origin**: Try the object's world position (lights, empty groups).
|
|
656
|
+
*
|
|
657
|
+
* For each strategy, we prefer points that are both on-screen AND closest to
|
|
658
|
+
* the viewport center (most reliable for event dispatch).
|
|
659
|
+
*
|
|
660
|
+
* Returns `null` if no part of the object is visible on screen.
|
|
661
|
+
*/
|
|
662
|
+
declare function projectToScreen(obj: Object3D, camera: Camera, size: CanvasSize): ProjectionResult | null;
|
|
663
|
+
/**
|
|
664
|
+
* Check whether any part of an Object3D is within the camera frustum.
|
|
665
|
+
* Uses the bounding box intersection test (fast, conservative).
|
|
666
|
+
*/
|
|
667
|
+
declare function isInFrustum(obj: Object3D, camera: Camera): boolean;
|
|
668
|
+
/**
|
|
669
|
+
* Convert a screen-space delta (CSS pixels) to a world-space displacement
|
|
670
|
+
* vector on the plane perpendicular to the camera at the given depth.
|
|
671
|
+
*
|
|
672
|
+
* Used by drag3D to convert pixel movements to 3D movements that feel
|
|
673
|
+
* natural regardless of camera position/zoom.
|
|
674
|
+
*/
|
|
675
|
+
declare function screenDeltaToWorld(dx: number, dy: number, obj: Object3D, camera: Camera, size: CanvasSize): Vector3;
|
|
676
|
+
/**
|
|
677
|
+
* Project multiple sample points of an object to screen space.
|
|
678
|
+
* Returns all on-screen points, useful for assertions like
|
|
679
|
+
* "object covers at least 50px² of screen area".
|
|
680
|
+
*/
|
|
681
|
+
declare function projectAllSamplePoints(obj: Object3D, camera: Camera, size: CanvasSize): ScreenPoint[];
|
|
682
|
+
|
|
683
|
+
/** Result of a raycast verification. */
|
|
684
|
+
interface RaycastResult {
|
|
685
|
+
/** Whether the intended object was hit. */
|
|
686
|
+
hit: boolean;
|
|
687
|
+
/** If not hit, the object that was hit instead (occluder). */
|
|
688
|
+
occluder?: Object3D;
|
|
689
|
+
/** Name or testId of the occluder, for error messages. */
|
|
690
|
+
occluderLabel?: string;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Verify that a raycast from the given screen point hits the intended object.
|
|
694
|
+
*
|
|
695
|
+
* Returns a RaycastResult indicating success or failure with details about
|
|
696
|
+
* what was hit instead (for useful error messages).
|
|
697
|
+
*
|
|
698
|
+
* @param point Screen-space coordinates (CSS pixels relative to canvas)
|
|
699
|
+
* @param target The intended Object3D to hit
|
|
700
|
+
* @param camera The active camera
|
|
701
|
+
* @param size Canvas size in CSS pixels
|
|
702
|
+
*/
|
|
703
|
+
declare function verifyRaycastHit(point: ScreenPoint, target: Object3D, camera: Camera, size: CanvasSize): RaycastResult;
|
|
704
|
+
/**
|
|
705
|
+
* Verify a hit, trying multiple sample points if the first fails.
|
|
706
|
+
* This is more robust than single-point verification for objects
|
|
707
|
+
* that are partially occluded.
|
|
708
|
+
*
|
|
709
|
+
* @param points Array of screen-space points to try
|
|
710
|
+
* @param target The intended Object3D to hit
|
|
711
|
+
* @param camera The active camera
|
|
712
|
+
* @param size Canvas size in CSS pixels
|
|
713
|
+
*/
|
|
714
|
+
declare function verifyRaycastHitMultiPoint(points: ScreenPoint[], target: Object3D, camera: Camera, size: CanvasSize): RaycastResult;
|
|
715
|
+
|
|
716
|
+
/** Options for click3D. */
|
|
717
|
+
interface Click3DOptions {
|
|
718
|
+
/**
|
|
719
|
+
* Whether to verify the click hit via raycast.
|
|
720
|
+
* Set to false for non-mesh objects (lights, cameras, groups).
|
|
721
|
+
* Default: true
|
|
722
|
+
*/
|
|
723
|
+
verify?: boolean;
|
|
724
|
+
}
|
|
725
|
+
/** Result of a click3D operation. */
|
|
726
|
+
interface Click3DResult {
|
|
727
|
+
/** Whether the click was dispatched. Always true if no error thrown. */
|
|
728
|
+
dispatched: true;
|
|
729
|
+
/** Raycast verification result (only if verify: true). */
|
|
730
|
+
raycast?: RaycastResult;
|
|
731
|
+
/** The screen point where the click was dispatched. */
|
|
732
|
+
screenPoint: {
|
|
733
|
+
x: number;
|
|
734
|
+
y: number;
|
|
735
|
+
};
|
|
736
|
+
/** Which projection strategy was used. */
|
|
737
|
+
strategy: string;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Programmatically click a 3D object by its testId or uuid.
|
|
741
|
+
*
|
|
742
|
+
* Projects the object to screen space, dispatches a synthetic click event
|
|
743
|
+
* on the canvas at the projected coordinates, and optionally verifies
|
|
744
|
+
* the click hit the intended object via raycasting.
|
|
745
|
+
*
|
|
746
|
+
* @param idOrUuid The object's testId or uuid
|
|
747
|
+
* @param options Click options
|
|
748
|
+
* @returns Click result with dispatch and verification info
|
|
749
|
+
* @throws If the object is not found or not visible on screen
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* ```typescript
|
|
753
|
+
* // From the global API
|
|
754
|
+
* window.__R3F_DOM__.click('chair-primary');
|
|
755
|
+
*
|
|
756
|
+
* // With verification disabled (for lights, cameras)
|
|
757
|
+
* click3D('sun-light', { verify: false });
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
declare function click3D(idOrUuid: string, options?: Click3DOptions): Click3DResult;
|
|
761
|
+
/**
|
|
762
|
+
* Programmatically double-click a 3D object by its testId or uuid.
|
|
763
|
+
*
|
|
764
|
+
* Dispatches the full double-click sequence:
|
|
765
|
+
* pointerdown → pointerup → click → pointerdown → pointerup → click → dblclick
|
|
766
|
+
*
|
|
767
|
+
* Triggers R3F's `onDoubleClick` handler on the hit object.
|
|
768
|
+
*
|
|
769
|
+
* @param idOrUuid The object's testId or uuid
|
|
770
|
+
* @param options Same options as click3D
|
|
771
|
+
* @returns Click result with dispatch and verification info
|
|
772
|
+
* @throws If the object is not found or not visible on screen
|
|
773
|
+
*/
|
|
774
|
+
declare function doubleClick3D(idOrUuid: string, options?: Click3DOptions): Click3DResult;
|
|
775
|
+
/**
|
|
776
|
+
* Programmatically right-click a 3D object by its testId or uuid.
|
|
777
|
+
*
|
|
778
|
+
* Dispatches: pointerdown (button=2) → pointerup (button=2) → contextmenu
|
|
779
|
+
*
|
|
780
|
+
* Triggers R3F's `onContextMenu` handler on the hit object.
|
|
781
|
+
*
|
|
782
|
+
* @param idOrUuid The object's testId or uuid
|
|
783
|
+
* @param options Same options as click3D
|
|
784
|
+
* @returns Click result with dispatch and verification info
|
|
785
|
+
* @throws If the object is not found or not visible on screen
|
|
786
|
+
*/
|
|
787
|
+
declare function contextMenu3D(idOrUuid: string, options?: Click3DOptions): Click3DResult;
|
|
788
|
+
|
|
789
|
+
/** Options for hover3D. */
|
|
790
|
+
interface Hover3DOptions {
|
|
791
|
+
/**
|
|
792
|
+
* Whether to verify the hover hit via raycast.
|
|
793
|
+
* Default: true
|
|
794
|
+
*/
|
|
795
|
+
verify?: boolean;
|
|
796
|
+
}
|
|
797
|
+
/** Result of a hover3D operation. */
|
|
798
|
+
interface Hover3DResult {
|
|
799
|
+
/** Whether the hover was dispatched. Always true if no error thrown. */
|
|
800
|
+
dispatched: true;
|
|
801
|
+
/** Raycast verification result (only if verify: true). */
|
|
802
|
+
raycast?: RaycastResult;
|
|
803
|
+
/** The screen point where the hover was dispatched. */
|
|
804
|
+
screenPoint: {
|
|
805
|
+
x: number;
|
|
806
|
+
y: number;
|
|
807
|
+
};
|
|
808
|
+
/** Which projection strategy was used. */
|
|
809
|
+
strategy: string;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Programmatically hover over a 3D object by its testId or uuid.
|
|
813
|
+
*
|
|
814
|
+
* Projects the object to screen space, dispatches a synthetic hover event
|
|
815
|
+
* sequence on the canvas, and optionally verifies the hit.
|
|
816
|
+
*
|
|
817
|
+
* @param idOrUuid The object's testId or uuid
|
|
818
|
+
* @param options Hover options
|
|
819
|
+
* @returns Hover result with dispatch and verification info
|
|
820
|
+
* @throws If the object is not found or not visible on screen
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
* ```typescript
|
|
824
|
+
* window.__R3F_DOM__.hover('chair-primary');
|
|
825
|
+
* ```
|
|
826
|
+
*/
|
|
827
|
+
declare function hover3D(idOrUuid: string, options?: Hover3DOptions): Hover3DResult;
|
|
828
|
+
/**
|
|
829
|
+
* Clear hover state by moving the pointer off-canvas.
|
|
830
|
+
* Call between hover/click interactions to reset R3F's internal pointer state.
|
|
831
|
+
*/
|
|
832
|
+
declare function unhover3D(): void;
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Dispatch a full click sequence on the canvas at the given screen point.
|
|
836
|
+
*
|
|
837
|
+
* Sequence: pointerdown → pointerup → click
|
|
838
|
+
*
|
|
839
|
+
* This matches what R3F's event system expects. The canvas is the event
|
|
840
|
+
* target because R3F attaches its listeners to the canvas element.
|
|
841
|
+
*/
|
|
842
|
+
declare function dispatchClick(canvas: HTMLCanvasElement, point: ScreenPoint): void;
|
|
843
|
+
/**
|
|
844
|
+
* Dispatch a hover sequence on the canvas at the given screen point.
|
|
845
|
+
*
|
|
846
|
+
* Sequence: pointermove → pointerover → pointerenter
|
|
847
|
+
*
|
|
848
|
+
* R3F translates pointermove into onPointerMove/onPointerOver/onPointerEnter
|
|
849
|
+
* via its internal raycaster. We dispatch the raw DOM events and let R3F
|
|
850
|
+
* do the rest.
|
|
851
|
+
*/
|
|
852
|
+
declare function dispatchHover(canvas: HTMLCanvasElement, point: ScreenPoint): void;
|
|
853
|
+
/** Options for a drag interaction. */
|
|
854
|
+
interface DragOptions {
|
|
855
|
+
/** Number of intermediate pointermove steps. Default: 10 */
|
|
856
|
+
steps?: number;
|
|
857
|
+
/** Delay between steps in ms (for requestAnimationFrame pacing). Default: 0 */
|
|
858
|
+
stepDelayMs?: number;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Dispatch a full drag sequence from `start` to `end` on the canvas.
|
|
862
|
+
*
|
|
863
|
+
* Sequence: pointerdown → N × pointermove (interpolated) → pointerup
|
|
864
|
+
*
|
|
865
|
+
* Returns a Promise that resolves when the drag is complete.
|
|
866
|
+
* The async nature allows optional frame-pacing via stepDelayMs.
|
|
867
|
+
*/
|
|
868
|
+
declare function dispatchDrag(canvas: HTMLCanvasElement, start: ScreenPoint, end: ScreenPoint, options?: DragOptions): Promise<void>;
|
|
869
|
+
/**
|
|
870
|
+
* Dispatch a full double-click sequence on the canvas at the given screen point.
|
|
871
|
+
*
|
|
872
|
+
* Sequence: pointerdown → pointerup → click → pointerdown → pointerup → click → dblclick
|
|
873
|
+
*
|
|
874
|
+
* R3F translates the `dblclick` DOM event into `onDoubleClick` on the hit object.
|
|
875
|
+
*/
|
|
876
|
+
declare function dispatchDoubleClick(canvas: HTMLCanvasElement, point: ScreenPoint): void;
|
|
877
|
+
/**
|
|
878
|
+
* Dispatch a right-click / context menu sequence on the canvas.
|
|
879
|
+
*
|
|
880
|
+
* Sequence: pointerdown (button=2) → pointerup (button=2) → contextmenu
|
|
881
|
+
*
|
|
882
|
+
* R3F translates the `contextmenu` DOM event into `onContextMenu`.
|
|
883
|
+
*/
|
|
884
|
+
declare function dispatchContextMenu(canvas: HTMLCanvasElement, point: ScreenPoint): void;
|
|
885
|
+
/** Options for a wheel dispatch. */
|
|
886
|
+
interface WheelOptions {
|
|
887
|
+
/** Vertical scroll delta (positive = scroll down). Default: 100 */
|
|
888
|
+
deltaY?: number;
|
|
889
|
+
/** Horizontal scroll delta. Default: 0 */
|
|
890
|
+
deltaX?: number;
|
|
891
|
+
/** DOM_DELTA_PIXEL (0), DOM_DELTA_LINE (1), or DOM_DELTA_PAGE (2). Default: 0 */
|
|
892
|
+
deltaMode?: number;
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Dispatch a wheel event on the canvas at the given screen point.
|
|
896
|
+
*
|
|
897
|
+
* R3F translates the `wheel` DOM event into `onWheel` on the hit object.
|
|
898
|
+
*/
|
|
899
|
+
declare function dispatchWheel(canvas: HTMLCanvasElement, point: ScreenPoint, options?: WheelOptions): void;
|
|
900
|
+
/**
|
|
901
|
+
* Dispatch a click on the canvas at a point where no meshes are present.
|
|
902
|
+
*
|
|
903
|
+
* R3F fires `onPointerMissed` on all objects that have that handler when
|
|
904
|
+
* a click lands on empty space. This dispatches a click at a configurable
|
|
905
|
+
* point (default: top-left corner, which is very unlikely to hit a mesh).
|
|
906
|
+
*
|
|
907
|
+
* @param canvas The canvas element
|
|
908
|
+
* @param point Optional specific screen point. Default: { x: 1, y: 1 }
|
|
909
|
+
*/
|
|
910
|
+
declare function dispatchPointerMiss(canvas: HTMLCanvasElement, point?: ScreenPoint): void;
|
|
911
|
+
/**
|
|
912
|
+
* Dispatch an unhover sequence — moves the pointer off-canvas.
|
|
913
|
+
* Useful for cleaning up hover state between interactions.
|
|
914
|
+
*/
|
|
915
|
+
declare function dispatchUnhover(canvas: HTMLCanvasElement): void;
|
|
916
|
+
|
|
917
|
+
/** World-space drag delta. */
|
|
918
|
+
interface WorldDelta {
|
|
919
|
+
x: number;
|
|
920
|
+
y: number;
|
|
921
|
+
z: number;
|
|
922
|
+
}
|
|
923
|
+
/** Screen-space drag delta (CSS pixels). */
|
|
924
|
+
interface ScreenDelta {
|
|
925
|
+
dx: number;
|
|
926
|
+
dy: number;
|
|
927
|
+
}
|
|
928
|
+
/** Options for drag3D. */
|
|
929
|
+
interface Drag3DOptions extends DragOptions {
|
|
930
|
+
/**
|
|
931
|
+
* If 'world', the delta is interpreted as world units.
|
|
932
|
+
* If 'screen', the delta is interpreted as CSS pixels.
|
|
933
|
+
* Default: 'world'
|
|
934
|
+
*/
|
|
935
|
+
mode?: 'world' | 'screen';
|
|
936
|
+
}
|
|
937
|
+
/** Result of a drag3D operation. */
|
|
938
|
+
interface Drag3DResult {
|
|
939
|
+
/** Whether the drag was dispatched. */
|
|
940
|
+
dispatched: true;
|
|
941
|
+
/** Start screen point. */
|
|
942
|
+
startPoint: {
|
|
943
|
+
x: number;
|
|
944
|
+
y: number;
|
|
945
|
+
};
|
|
946
|
+
/** End screen point. */
|
|
947
|
+
endPoint: {
|
|
948
|
+
x: number;
|
|
949
|
+
y: number;
|
|
950
|
+
};
|
|
951
|
+
/** Which projection strategy was used for the start point. */
|
|
952
|
+
strategy: string;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Programmatically drag a 3D object by its testId or uuid.
|
|
956
|
+
*
|
|
957
|
+
* Projects the object to screen space for the start point, then computes
|
|
958
|
+
* the end point based on the delta (world-space or screen-space), and
|
|
959
|
+
* dispatches a full drag sequence on the canvas.
|
|
960
|
+
*
|
|
961
|
+
* @param idOrUuid The object's testId or uuid
|
|
962
|
+
* @param delta Drag delta (world-space { x, y, z } or screen-space { dx, dy })
|
|
963
|
+
* @param options Drag options (steps, delay, mode)
|
|
964
|
+
* @returns Drag result with start/end points
|
|
965
|
+
* @throws If the object is not found or not visible on screen
|
|
966
|
+
*
|
|
967
|
+
* @example
|
|
968
|
+
* ```typescript
|
|
969
|
+
* // World-space drag: move 2 units on X axis
|
|
970
|
+
* window.__R3F_DOM__.drag('chair-primary', { x: 2, y: 0, z: 0 });
|
|
971
|
+
*
|
|
972
|
+
* // Screen-space drag: move 100px right, 50px down
|
|
973
|
+
* drag3D('chair-primary', { dx: 100, dy: 50 }, { mode: 'screen' });
|
|
974
|
+
* ```
|
|
975
|
+
*/
|
|
976
|
+
declare function drag3D(idOrUuid: string, delta: WorldDelta | ScreenDelta, options?: Drag3DOptions): Promise<Drag3DResult>;
|
|
977
|
+
/**
|
|
978
|
+
* Compute what world-space displacement a screen-space drag would produce.
|
|
979
|
+
* Useful for previewing drag effects before committing.
|
|
980
|
+
*/
|
|
981
|
+
declare function previewDragWorldDelta(idOrUuid: string, screenDx: number, screenDy: number): Vector3;
|
|
982
|
+
|
|
983
|
+
/** Options for wheel3D. */
|
|
984
|
+
interface Wheel3DOptions extends WheelOptions {
|
|
985
|
+
}
|
|
986
|
+
/** Result of a wheel3D operation. */
|
|
987
|
+
interface Wheel3DResult {
|
|
988
|
+
/** Whether the wheel event was dispatched. */
|
|
989
|
+
dispatched: true;
|
|
990
|
+
/** The screen point where the wheel was dispatched. */
|
|
991
|
+
screenPoint: {
|
|
992
|
+
x: number;
|
|
993
|
+
y: number;
|
|
994
|
+
};
|
|
995
|
+
/** Which projection strategy was used. */
|
|
996
|
+
strategy: string;
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Programmatically scroll the wheel over a 3D object by its testId or uuid.
|
|
1000
|
+
*
|
|
1001
|
+
* Projects the object to screen space and dispatches a synthetic WheelEvent
|
|
1002
|
+
* on the canvas. Triggers R3F's `onWheel` handler on the hit object.
|
|
1003
|
+
*
|
|
1004
|
+
* @param idOrUuid The object's testId or uuid
|
|
1005
|
+
* @param options Wheel options (deltaY, deltaX, deltaMode)
|
|
1006
|
+
* @returns Wheel result with screen point info
|
|
1007
|
+
* @throws If the object is not found or not visible on screen
|
|
1008
|
+
*
|
|
1009
|
+
* @example
|
|
1010
|
+
* ```typescript
|
|
1011
|
+
* // Scroll down 200 units over the chair
|
|
1012
|
+
* wheel3D('chair-primary', { deltaY: 200 });
|
|
1013
|
+
*
|
|
1014
|
+
* // Scroll up
|
|
1015
|
+
* wheel3D('chair-primary', { deltaY: -100 });
|
|
1016
|
+
* ```
|
|
1017
|
+
*/
|
|
1018
|
+
declare function wheel3D(idOrUuid: string, options?: Wheel3DOptions): Wheel3DResult;
|
|
1019
|
+
|
|
1020
|
+
/** Options for pointerMiss3D. */
|
|
1021
|
+
interface PointerMiss3DOptions {
|
|
1022
|
+
/**
|
|
1023
|
+
* Specific screen point to click. If not provided, clicks at (1, 1)
|
|
1024
|
+
* which is the top-left corner — very unlikely to hit any mesh.
|
|
1025
|
+
*/
|
|
1026
|
+
point?: ScreenPoint;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Dispatch a click on empty canvas space, triggering `onPointerMissed`.
|
|
1030
|
+
*
|
|
1031
|
+
* R3F fires `onPointerMissed` on all objects that have that handler
|
|
1032
|
+
* when a click doesn't hit any mesh. This is commonly used for
|
|
1033
|
+
* deselection workflows.
|
|
1034
|
+
*
|
|
1035
|
+
* @param options Optional point to click at
|
|
1036
|
+
*
|
|
1037
|
+
* @example
|
|
1038
|
+
* ```typescript
|
|
1039
|
+
* // Click empty space to deselect
|
|
1040
|
+
* pointerMiss3D();
|
|
1041
|
+
*
|
|
1042
|
+
* // Click at a specific empty spot
|
|
1043
|
+
* pointerMiss3D({ point: { x: 10, y: 10 } });
|
|
1044
|
+
* ```
|
|
1045
|
+
*/
|
|
1046
|
+
declare function pointerMiss3D(options?: PointerMiss3DOptions): void;
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* Resolve a testId or uuid to a live Object3D reference.
|
|
1050
|
+
* Throws a descriptive error if the object is not found.
|
|
1051
|
+
*/
|
|
1052
|
+
declare function resolveObject(idOrUuid: string): Object3D;
|
|
1053
|
+
|
|
1054
|
+
export { type CanvasSize, type Click3DOptions, type Click3DResult, DomMirror, type Drag3DOptions, type Drag3DResult, type DragOptions, type GeometryInspection, Highlighter, type HighlighterOptions, type Hover3DOptions, type Hover3DResult, MANAGED_ATTRIBUTES, type MaterialInspection, type ObjectInspection, type ObjectMetadata, ObjectStore, type PointerMiss3DOptions, type ProjectionResult, type R3FDOM, type RaycastResult, type SceneSnapshot, type ScreenDelta, type ScreenPoint, type SelectionListener, SelectionManager, type SnapshotNode, type StoreEvent, type StoreEventType, type StoreListener, TAG_MAP, ThreeDom, type ThreeDomProps, ThreeElement, type ThreeTagName, type Wheel3DOptions, type Wheel3DResult, type WheelOptions, type WorldDelta, applyAttributes, click3D, computeAttributes, contextMenu3D, createFlatSnapshot, createSnapshot, dispatchClick, dispatchContextMenu, dispatchDoubleClick, dispatchDrag, dispatchHover, dispatchPointerMiss, dispatchUnhover, dispatchWheel, doubleClick3D, drag3D, ensureCustomElements, getHighlighter, getMirror, getSelectionManager, getStore, getTagForType, hover3D, isInFrustum, isPatched, patchObject3D, pointerMiss3D, previewDragWorldDelta, projectAllSamplePoints, projectToScreen, resolveObject, restoreObject3D, screenDeltaToWorld, unhover3D, verifyRaycastHit, verifyRaycastHitMultiPoint, version, wheel3D };
|