@jamesyong42/infinite-canvas 1.0.0 → 1.2.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.
Files changed (54) hide show
  1. package/README.md +170 -9
  2. package/dist/SelectionRenderer-CR2PBQwx.d.cts +105 -0
  3. package/dist/SelectionRenderer-CR2PBQwx.d.cts.map +1 -0
  4. package/dist/SelectionRenderer-DlsBstAq.d.mts +105 -0
  5. package/dist/SelectionRenderer-DlsBstAq.d.mts.map +1 -0
  6. package/dist/WebGLWidgetLayer-BBMuwzHq.cjs +3560 -0
  7. package/dist/WebGLWidgetLayer-BBMuwzHq.cjs.map +1 -0
  8. package/dist/WebGLWidgetLayer-C3p1tnpm.mjs +3375 -0
  9. package/dist/WebGLWidgetLayer-C3p1tnpm.mjs.map +1 -0
  10. package/dist/advanced.cjs +110 -165
  11. package/dist/advanced.cjs.map +1 -1
  12. package/dist/advanced.d.cts +58 -40
  13. package/dist/advanced.d.cts.map +1 -0
  14. package/dist/advanced.d.mts +99 -0
  15. package/dist/advanced.d.mts.map +1 -0
  16. package/dist/advanced.mjs +105 -0
  17. package/dist/advanced.mjs.map +1 -0
  18. package/dist/devtools.cjs +654 -0
  19. package/dist/devtools.cjs.map +1 -0
  20. package/dist/devtools.d.cts +23 -0
  21. package/dist/devtools.d.cts.map +1 -0
  22. package/dist/devtools.d.mts +23 -0
  23. package/dist/devtools.d.mts.map +1 -0
  24. package/dist/devtools.mjs +652 -0
  25. package/dist/devtools.mjs.map +1 -0
  26. package/dist/engine-BfbvWXSk.d.mts +982 -0
  27. package/dist/engine-BfbvWXSk.d.mts.map +1 -0
  28. package/dist/engine-CCjuFMC-.d.cts +982 -0
  29. package/dist/engine-CCjuFMC-.d.cts.map +1 -0
  30. package/dist/hooks-BwY7rRHg.mjs +425 -0
  31. package/dist/hooks-BwY7rRHg.mjs.map +1 -0
  32. package/dist/hooks-DHShH86C.cjs +707 -0
  33. package/dist/hooks-DHShH86C.cjs.map +1 -0
  34. package/dist/index.cjs +909 -803
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +199 -67
  37. package/dist/index.d.cts.map +1 -0
  38. package/dist/index.d.mts +258 -0
  39. package/dist/index.d.mts.map +1 -0
  40. package/dist/index.mjs +855 -0
  41. package/dist/index.mjs.map +1 -0
  42. package/package.json +47 -15
  43. package/dist/SelectionRenderer-CeWSNZT8.d.cts +0 -891
  44. package/dist/SelectionRenderer-CeWSNZT8.d.ts +0 -891
  45. package/dist/advanced.d.ts +0 -81
  46. package/dist/advanced.js +0 -124
  47. package/dist/advanced.js.map +0 -1
  48. package/dist/chunk-VSHXWTJH.cjs +0 -3228
  49. package/dist/chunk-VSHXWTJH.cjs.map +0 -1
  50. package/dist/chunk-Z6JQQOWL.js +0 -3142
  51. package/dist/chunk-Z6JQQOWL.js.map +0 -1
  52. package/dist/index.d.ts +0 -126
  53. package/dist/index.js +0 -602
  54. package/dist/index.js.map +0 -1
package/dist/index.js DELETED
@@ -1,602 +0,0 @@
1
- import { GridRenderer, SelectionRenderer, WorldBounds, Widget, WidgetSlot, SelectionOverlaySlot, EngineProvider, ContainerRefProvider, useWidgetResolver, WebGLWidgetLayer, DEAD_ZONE_TOUCH_PX, CursorResource, NavigationStackResource, isR3FWidget, WidgetResolverProvider, useComponent, WidgetData, WidgetBreakpoint, Children, useTag, Selected, useLayoutEngine } from './chunk-Z6JQQOWL.js';
2
- export { Active, BreakpointConfigResource, CameraResource, Children, CommandBuffer, Container, CursorHint, CursorResource, DEFAULT_GRID_CONFIG, DEFAULT_SELECTION_CONFIG, Draggable, HandleSet, Hitbox, InteractionRole, Locked, MoveCommand, NavigationStackResource, Parent, Resizable, ResizeCommand, Selectable, Selected, SetComponentCommand, Transform2D, ViewportResource, Visible, Widget, WidgetBreakpoint, WidgetData, WidgetResolverProvider, WorldBounds, ZIndex, ZoomConfigResource, clamp, createArchetypeRegistry, createLayoutEngine, createWidgetRegistry, intersectsAABB, isR3FWidget, pointInAABB, screenToWorld, useCamera, useComponent, useContainerRef, useLayoutEngine, useQuery, useResource, useTag, useTaggedEntities, useWidgetResolver, worldBoundsToAABB, worldToScreen } from './chunk-Z6JQQOWL.js';
3
- import React, { useRef, useEffect, useImperativeHandle, useState, useCallback, useLayoutEffect, useMemo } from 'react';
4
- import { Vector2 } from 'three';
5
- import { jsxs, jsx } from 'react/jsx-runtime';
6
-
7
- function WidgetProvider({ engine, children }) {
8
- const resolver = useCallback(
9
- (_entityId, widgetType) => {
10
- const def = engine.getWidget(widgetType);
11
- if (!def) return null;
12
- if (isR3FWidget(def)) {
13
- return { surface: "webgl", component: def.component };
14
- }
15
- return { surface: "dom", component: def.component };
16
- },
17
- [engine]
18
- );
19
- return /* @__PURE__ */ jsx(WidgetResolverProvider, { value: resolver, children });
20
- }
21
- var InfiniteCanvas = React.forwardRef(
22
- function InfiniteCanvas2({
23
- engine,
24
- grid,
25
- selection,
26
- onSelectionChange,
27
- onCameraChange,
28
- onNavigationChange,
29
- className,
30
- style,
31
- children
32
- }, ref) {
33
- const containerRef = useRef(null);
34
- const onSelectionChangeRef = useRef(onSelectionChange);
35
- const onCameraChangeRef = useRef(onCameraChange);
36
- const onNavigationChangeRef = useRef(onNavigationChange);
37
- useEffect(() => {
38
- onSelectionChangeRef.current = onSelectionChange;
39
- }, [onSelectionChange]);
40
- useEffect(() => {
41
- onCameraChangeRef.current = onCameraChange;
42
- }, [onCameraChange]);
43
- useEffect(() => {
44
- onNavigationChangeRef.current = onNavigationChange;
45
- }, [onNavigationChange]);
46
- useImperativeHandle(
47
- ref,
48
- () => ({
49
- panTo: (x, y) => {
50
- engine.panTo(x, y);
51
- engine.markDirty();
52
- },
53
- zoomTo: (zoom) => {
54
- engine.zoomTo(zoom);
55
- engine.markDirty();
56
- },
57
- zoomToFit: (padding) => {
58
- engine.zoomToFit(void 0, padding);
59
- engine.markDirty();
60
- },
61
- undo: () => {
62
- engine.undo();
63
- engine.markDirty();
64
- },
65
- redo: () => {
66
- engine.redo();
67
- engine.markDirty();
68
- },
69
- getEngine: () => engine
70
- }),
71
- [engine]
72
- );
73
- const webglCanvasRef = useRef(null);
74
- const gridRendererRef = useRef(null);
75
- const selectionRendererRef = useRef(null);
76
- const cameraLayerRef = useRef(null);
77
- const slotRefs = useRef(/* @__PURE__ */ new Map());
78
- const [visibleEntities, setVisibleEntities] = useState([]);
79
- const registerSlotRef = useCallback((entityId, el) => {
80
- if (el) {
81
- slotRefs.current.set(entityId, el);
82
- } else {
83
- slotRefs.current.delete(entityId);
84
- }
85
- }, []);
86
- useLayoutEffect(() => {
87
- const container = containerRef.current;
88
- const canvas = webglCanvasRef.current;
89
- if (!container || !canvas) return;
90
- const gridEnabled = grid !== false;
91
- let gridInst = null;
92
- if (gridEnabled) {
93
- gridInst = new GridRenderer(canvas);
94
- gridRendererRef.current = gridInst;
95
- }
96
- const selInst = new SelectionRenderer();
97
- selectionRendererRef.current = selInst;
98
- const updateSize = () => {
99
- const rect = container.getBoundingClientRect();
100
- const dpr = window.devicePixelRatio;
101
- engine.setViewport(rect.width, rect.height, dpr);
102
- canvas.style.width = `${rect.width}px`;
103
- canvas.style.height = `${rect.height}px`;
104
- if (gridInst) {
105
- gridInst.setSize(rect.width, rect.height, dpr);
106
- }
107
- selInst.setSize(new Vector2(rect.width * dpr, rect.height * dpr), dpr);
108
- };
109
- updateSize();
110
- const observer = new ResizeObserver(updateSize);
111
- observer.observe(container);
112
- return () => {
113
- observer.disconnect();
114
- if (gridInst) {
115
- gridInst.dispose();
116
- gridRendererRef.current = null;
117
- }
118
- selInst.dispose();
119
- selectionRendererRef.current = null;
120
- };
121
- }, [engine, grid]);
122
- useEffect(() => {
123
- const gridR = gridRendererRef.current;
124
- if (gridR && grid !== false) {
125
- const isDark = document.documentElement.classList.contains("dark");
126
- gridR.setConfig({
127
- dotColor: isDark ? [1, 1, 1] : [0, 0, 0],
128
- dotAlpha: isDark ? 0.12 : 0.18,
129
- ...grid
130
- });
131
- }
132
- const selR = selectionRendererRef.current;
133
- if (selR && selection) {
134
- selR.setConfig(selection);
135
- }
136
- engine.markDirty();
137
- }, [engine, grid, selection]);
138
- useEffect(() => {
139
- const container = containerRef.current;
140
- if (!container) return;
141
- const onWheel = (e) => {
142
- e.preventDefault();
143
- if (e.ctrlKey || e.metaKey) {
144
- const rect = container.getBoundingClientRect();
145
- engine.zoomAtPoint(e.clientX - rect.left, e.clientY - rect.top, -e.deltaY * 0.01);
146
- } else {
147
- engine.panBy(-e.deltaX, -e.deltaY);
148
- }
149
- };
150
- container.addEventListener("wheel", onWheel, { passive: false });
151
- return () => container.removeEventListener("wheel", onWheel);
152
- }, [engine]);
153
- useEffect(() => {
154
- const container = containerRef.current;
155
- if (!container) return;
156
- let gesture = { type: "idle" };
157
- let lastTapTime = 0;
158
- let lastTapX = 0;
159
- let lastTapY = 0;
160
- const DOUBLE_TAP_MS = 300;
161
- const DOUBLE_TAP_DIST = 30;
162
- function isOnWidget(target) {
163
- let el = target;
164
- while (el && el !== container) {
165
- if (el.hasAttribute("data-widget-slot")) return true;
166
- el = el.parentElement;
167
- }
168
- return false;
169
- }
170
- function isInteractive(target) {
171
- const el = target;
172
- if (!el) return false;
173
- const tag = el.tagName;
174
- return tag === "INPUT" || tag === "TEXTAREA" || tag === "BUTTON" || tag === "SELECT" || el.isContentEditable || el.closest("button") !== null;
175
- }
176
- function getRect() {
177
- return container?.getBoundingClientRect() ?? new DOMRect();
178
- }
179
- function touchDist(t1, t2) {
180
- const dx = t1.clientX - t2.clientX;
181
- const dy = t1.clientY - t2.clientY;
182
- return Math.sqrt(dx * dx + dy * dy);
183
- }
184
- function touchCenter(t1, t2, rect) {
185
- return {
186
- x: (t1.clientX + t2.clientX) / 2 - rect.left,
187
- y: (t1.clientY + t2.clientY) / 2 - rect.top
188
- };
189
- }
190
- function cancelEngineGesture() {
191
- if (gesture.type === "pending-entity" || gesture.type === "entity-dragging") {
192
- engine.handlePointerUp();
193
- }
194
- }
195
- const noMods = { shift: false, ctrl: false, alt: false, meta: false };
196
- function onTouchStart(e) {
197
- const rect = getRect();
198
- const touches = e.touches;
199
- if (touches.length >= 2) {
200
- e.preventDefault();
201
- cancelEngineGesture();
202
- const dist = touchDist(touches[0], touches[1]);
203
- const center = touchCenter(touches[0], touches[1], rect);
204
- gesture = { type: "pinching", lastDist: dist, lastCx: center.x, lastCy: center.y };
205
- return;
206
- }
207
- const touch = touches[0];
208
- const x = touch.clientX - rect.left;
209
- const y = touch.clientY - rect.top;
210
- if (isInteractive(e.target)) return;
211
- e.preventDefault();
212
- const now = Date.now();
213
- if (now - lastTapTime < DOUBLE_TAP_MS && Math.abs(x - lastTapX) < DOUBLE_TAP_DIST && Math.abs(y - lastTapY) < DOUBLE_TAP_DIST) {
214
- lastTapTime = 0;
215
- const directive = engine.handlePointerDown(x, y, 0, noMods);
216
- try {
217
- if (directive.action === "passthrough-track-drag") {
218
- const selected = engine.getSelectedEntities();
219
- if (selected.length === 1) {
220
- engine.enterContainer(selected[0]);
221
- }
222
- } else {
223
- const camera = engine.getCamera();
224
- const target = camera.zoom < 0.9 ? 1 : camera.zoom < 1.8 ? 2 : 1;
225
- engine.zoomAtPoint(x, y, (target - camera.zoom) / camera.zoom);
226
- }
227
- } finally {
228
- engine.handlePointerUp();
229
- engine.markDirty();
230
- }
231
- gesture = { type: "idle" };
232
- return;
233
- }
234
- if (isOnWidget(e.target)) {
235
- engine.handlePointerDown(x, y, 0, noMods);
236
- gesture = { type: "pending-entity", x, y, time: now };
237
- } else {
238
- gesture = { type: "pending-pan", x, y, time: now };
239
- }
240
- }
241
- function onTouchMove(e) {
242
- e.preventDefault();
243
- const rect = getRect();
244
- const touches = e.touches;
245
- if (gesture.type === "pinching" && touches.length >= 2) {
246
- const dist = touchDist(touches[0], touches[1]);
247
- const center = touchCenter(touches[0], touches[1], rect);
248
- const scale = dist / gesture.lastDist;
249
- engine.zoomAtPoint(center.x, center.y, scale - 1);
250
- engine.panBy(center.x - gesture.lastCx, center.y - gesture.lastCy);
251
- gesture.lastDist = dist;
252
- gesture.lastCx = center.x;
253
- gesture.lastCy = center.y;
254
- return;
255
- }
256
- if (touches.length >= 2) {
257
- cancelEngineGesture();
258
- const dist = touchDist(touches[0], touches[1]);
259
- const center = touchCenter(touches[0], touches[1], rect);
260
- gesture = { type: "pinching", lastDist: dist, lastCx: center.x, lastCy: center.y };
261
- return;
262
- }
263
- if (touches.length < 1) return;
264
- const touch = touches[0];
265
- const x = touch.clientX - rect.left;
266
- const y = touch.clientY - rect.top;
267
- if (gesture.type === "pending-pan") {
268
- if (Math.abs(x - gesture.x) > DEAD_ZONE_TOUCH_PX || Math.abs(y - gesture.y) > DEAD_ZONE_TOUCH_PX) {
269
- gesture = { type: "panning", lastX: x, lastY: y };
270
- }
271
- return;
272
- }
273
- if (gesture.type === "panning") {
274
- engine.panBy(x - gesture.lastX, y - gesture.lastY);
275
- gesture.lastX = x;
276
- gesture.lastY = y;
277
- return;
278
- }
279
- if (gesture.type === "pending-entity" || gesture.type === "entity-dragging") {
280
- engine.handlePointerMove(x, y, noMods);
281
- if (gesture.type === "pending-entity") {
282
- if (Math.abs(x - gesture.x) > DEAD_ZONE_TOUCH_PX || Math.abs(y - gesture.y) > DEAD_ZONE_TOUCH_PX) {
283
- gesture = { type: "entity-dragging" };
284
- }
285
- }
286
- }
287
- }
288
- function onTouchEnd(e) {
289
- e.preventDefault();
290
- const remaining = e.touches.length;
291
- const rect = getRect();
292
- if (gesture.type === "pinching") {
293
- if (remaining === 1) {
294
- const t = e.touches[0];
295
- gesture = {
296
- type: "panning",
297
- lastX: t.clientX - rect.left,
298
- lastY: t.clientY - rect.top
299
- };
300
- } else if (remaining === 0) {
301
- gesture = { type: "idle" };
302
- }
303
- return;
304
- }
305
- if (remaining > 0) return;
306
- if (gesture.type === "pending-pan") {
307
- engine.handlePointerDown(gesture.x, gesture.y, 0, noMods);
308
- engine.handlePointerUp();
309
- engine.markDirty();
310
- lastTapTime = Date.now();
311
- lastTapX = gesture.x;
312
- lastTapY = gesture.y;
313
- }
314
- if (gesture.type === "pending-entity") {
315
- engine.handlePointerUp();
316
- engine.markDirty();
317
- lastTapTime = Date.now();
318
- lastTapX = gesture.x;
319
- lastTapY = gesture.y;
320
- }
321
- if (gesture.type === "entity-dragging") {
322
- engine.handlePointerUp();
323
- engine.markDirty();
324
- }
325
- gesture = { type: "idle" };
326
- }
327
- function onTouchCancel(_e) {
328
- gesture = { type: "idle" };
329
- engine.handlePointerCancel();
330
- }
331
- container.addEventListener("touchstart", onTouchStart, { passive: false });
332
- container.addEventListener("touchmove", onTouchMove, { passive: false });
333
- container.addEventListener("touchend", onTouchEnd, { passive: false });
334
- container.addEventListener("touchcancel", onTouchCancel, { passive: true });
335
- return () => {
336
- container.removeEventListener("touchstart", onTouchStart);
337
- container.removeEventListener("touchmove", onTouchMove);
338
- container.removeEventListener("touchend", onTouchEnd);
339
- container.removeEventListener("touchcancel", onTouchCancel);
340
- };
341
- }, [engine]);
342
- const onCanvasPointerDown = useCallback(
343
- (e) => {
344
- const target = e.target;
345
- if (target?.closest("button, input, textarea, select, [contenteditable]")) return;
346
- const rect = containerRef.current?.getBoundingClientRect();
347
- if (!rect) return;
348
- const directive = engine.handlePointerDown(
349
- e.clientX - rect.left,
350
- e.clientY - rect.top,
351
- e.button,
352
- {
353
- shift: e.shiftKey,
354
- ctrl: e.ctrlKey,
355
- alt: e.altKey,
356
- meta: e.metaKey
357
- }
358
- );
359
- if (directive.action === "capture-resize" || directive.action === "passthrough-track-drag") {
360
- containerRef.current?.setPointerCapture(e.pointerId);
361
- }
362
- if (directive.action === "capture-resize") e.preventDefault();
363
- },
364
- [engine]
365
- );
366
- const onCanvasPointerMove = useCallback(
367
- (e) => {
368
- const target = e.target;
369
- if (target.closest?.("[data-widget-slot]") && target !== containerRef.current) {
370
- return;
371
- }
372
- const rect = containerRef.current?.getBoundingClientRect();
373
- if (!rect) return;
374
- engine.handlePointerMove(e.clientX - rect.left, e.clientY - rect.top, {
375
- shift: e.shiftKey,
376
- ctrl: e.ctrlKey,
377
- alt: e.altKey,
378
- meta: e.metaKey
379
- });
380
- },
381
- [engine]
382
- );
383
- const onCanvasPointerUp = useCallback(
384
- (e) => {
385
- if (containerRef.current?.hasPointerCapture(e.pointerId)) {
386
- containerRef.current.releasePointerCapture(e.pointerId);
387
- }
388
- engine.handlePointerUp();
389
- },
390
- [engine]
391
- );
392
- useEffect(() => {
393
- let rafId;
394
- let running = true;
395
- function loop() {
396
- if (!running) return;
397
- const didTick = engine.flushIfDirty();
398
- if (didTick) {
399
- const camera2 = engine.getCamera();
400
- const changes = engine.getFrameChanges();
401
- if (cameraLayerRef.current) {
402
- cameraLayerRef.current.style.transform = `scale(${camera2.zoom}) translate(${-camera2.x}px, ${-camera2.y}px)`;
403
- }
404
- const cursor = engine.world.getResource(CursorResource).cursor;
405
- if (containerRef.current && containerRef.current.style.cursor !== cursor) {
406
- containerRef.current.style.cursor = cursor;
407
- }
408
- if (gridRendererRef.current) {
409
- gridRendererRef.current.render(camera2.x, camera2.y, camera2.zoom);
410
- }
411
- if (selectionRendererRef.current && gridRendererRef.current) {
412
- const selected = engine.getSelectedEntities();
413
- const selBounds = [];
414
- for (const id of selected) {
415
- const wb = engine.get(id, WorldBounds);
416
- if (wb)
417
- selBounds.push({
418
- x: wb.worldX,
419
- y: wb.worldY,
420
- width: wb.worldWidth,
421
- height: wb.worldHeight
422
- });
423
- }
424
- const hovId = engine.getHoveredEntity();
425
- let hovBounds = null;
426
- if (hovId !== null) {
427
- const wb = engine.get(hovId, WorldBounds);
428
- if (wb)
429
- hovBounds = {
430
- x: wb.worldX,
431
- y: wb.worldY,
432
- width: wb.worldWidth,
433
- height: wb.worldHeight
434
- };
435
- }
436
- selectionRendererRef.current.render(
437
- gridRendererRef.current.getWebGLRenderer(),
438
- camera2.x,
439
- camera2.y,
440
- camera2.zoom,
441
- selBounds,
442
- hovBounds,
443
- engine.getSnapGuides(),
444
- engine.getEqualSpacing()
445
- );
446
- }
447
- for (const entityId of changes.positionsChanged) {
448
- const el = slotRefs.current.get(entityId);
449
- if (!el) continue;
450
- const wb = engine.get(entityId, WorldBounds);
451
- if (!wb) continue;
452
- el.style.transform = `translate(${wb.worldX}px, ${wb.worldY}px)`;
453
- el.style.width = `${wb.worldWidth}px`;
454
- el.style.height = `${wb.worldHeight}px`;
455
- }
456
- if (changes.entered.length > 0 || changes.exited.length > 0) {
457
- const visible2 = engine.getVisibleEntities();
458
- setVisibleEntities(visible2.map((v) => v.entityId));
459
- }
460
- if (changes.selectionChanged && onSelectionChangeRef.current) {
461
- onSelectionChangeRef.current(engine.getSelectedEntities());
462
- }
463
- if (changes.cameraChanged && onCameraChangeRef.current) {
464
- onCameraChangeRef.current({ x: camera2.x, y: camera2.y, zoom: camera2.zoom });
465
- }
466
- if (changes.navigationChanged && onNavigationChangeRef.current) {
467
- const navStack = engine.world.getResource(NavigationStackResource);
468
- const depth = navStack.frames.length - 1;
469
- const containerId = navStack.frames[navStack.frames.length - 1].containerId;
470
- onNavigationChangeRef.current(depth, containerId);
471
- }
472
- }
473
- rafId = requestAnimationFrame(loop);
474
- }
475
- engine.tick();
476
- const visible = engine.getVisibleEntities();
477
- setVisibleEntities(visible.map((v) => v.entityId));
478
- const camera = engine.getCamera();
479
- if (cameraLayerRef.current) {
480
- cameraLayerRef.current.style.transform = `scale(${camera.zoom}) translate(${-camera.x}px, ${-camera.y}px)`;
481
- }
482
- if (gridRendererRef.current) {
483
- gridRendererRef.current.render(camera.x, camera.y, camera.zoom);
484
- }
485
- for (const v of visible) {
486
- const el = slotRefs.current.get(v.entityId);
487
- if (!el) continue;
488
- el.style.transform = `translate(${v.worldX}px, ${v.worldY}px)`;
489
- el.style.width = `${v.worldWidth}px`;
490
- el.style.height = `${v.worldHeight}px`;
491
- }
492
- rafId = requestAnimationFrame(loop);
493
- return () => {
494
- running = false;
495
- cancelAnimationFrame(rafId);
496
- };
497
- }, [engine]);
498
- useLayoutEffect(() => {
499
- for (const entityId of visibleEntities) {
500
- const el = slotRefs.current.get(entityId);
501
- if (!el) continue;
502
- const wb = engine.get(entityId, WorldBounds);
503
- if (!wb) continue;
504
- el.style.transform = `translate(${wb.worldX}px, ${wb.worldY}px)`;
505
- el.style.width = `${wb.worldWidth}px`;
506
- el.style.height = `${wb.worldHeight}px`;
507
- }
508
- }, [visibleEntities, engine]);
509
- const { domEntities, webglEntities } = useMemo(() => {
510
- const dom = [];
511
- const webgl = [];
512
- for (const id of visibleEntities) {
513
- const w = engine.get(id, Widget);
514
- if (w?.surface === "webgl") {
515
- webgl.push(id);
516
- } else {
517
- dom.push(id);
518
- }
519
- }
520
- return { domEntities: dom, webglEntities: webgl };
521
- }, [visibleEntities, engine]);
522
- const canvasContent = /* @__PURE__ */ jsxs(
523
- "div",
524
- {
525
- ref: containerRef,
526
- className: `relative overflow-hidden ${className ?? ""}`,
527
- style: {
528
- ...style,
529
- touchAction: "none",
530
- backgroundColor: "var(--canvas-bg, #fafafa)"
531
- },
532
- onPointerDown: onCanvasPointerDown,
533
- onPointerMove: onCanvasPointerMove,
534
- onPointerUp: onCanvasPointerUp,
535
- children: [
536
- /* @__PURE__ */ jsx("canvas", { ref: webglCanvasRef, className: "absolute inset-0 pointer-events-none" }),
537
- webglEntities.length > 0 && /* @__PURE__ */ jsx(WebGLWidgetBridge, { engine, entities: webglEntities }),
538
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 pointer-events-none" }),
539
- /* @__PURE__ */ jsxs(
540
- "div",
541
- {
542
- ref: cameraLayerRef,
543
- className: "absolute left-0 top-0 origin-top-left will-change-transform",
544
- children: [
545
- domEntities.map((entityId) => /* @__PURE__ */ jsx(WidgetSlot, { entityId, slotRef: registerSlotRef }, entityId)),
546
- webglEntities.map((entityId) => /* @__PURE__ */ jsx(SelectionOverlaySlot, { entityId, slotRef: registerSlotRef }, entityId))
547
- ]
548
- }
549
- ),
550
- children
551
- ]
552
- }
553
- );
554
- return /* @__PURE__ */ jsx(EngineProvider, { value: engine, children: /* @__PURE__ */ jsx(ContainerRefProvider, { value: containerRef, children: /* @__PURE__ */ jsx(WidgetProvider, { engine, children: canvasContent }) }) });
555
- }
556
- );
557
- function WebGLWidgetBridge({ engine, entities }) {
558
- const resolver = useWidgetResolver();
559
- const resolve = useCallback(
560
- (entityId) => {
561
- if (!resolver) return null;
562
- const w = engine.get(entityId, Widget);
563
- return resolver(entityId, w?.type ?? "");
564
- },
565
- [resolver, engine]
566
- );
567
- if (!resolver) return null;
568
- return /* @__PURE__ */ jsx(WebGLWidgetLayer, { engine, entities, resolve });
569
- }
570
- function useWidgetData(entityId) {
571
- const comp = useComponent(entityId, WidgetData);
572
- return comp?.data ?? {};
573
- }
574
- function useBreakpoint(entityId) {
575
- const comp = useComponent(entityId, WidgetBreakpoint);
576
- return comp?.current ?? "normal";
577
- }
578
- function useChildren(entityId) {
579
- const comp = useComponent(entityId, Children);
580
- return comp?.ids ?? [];
581
- }
582
- function useIsSelected(entityId) {
583
- return useTag(entityId, Selected);
584
- }
585
- function useUpdateWidget(entityId) {
586
- const engine = useLayoutEngine();
587
- return useCallback(
588
- (patch) => {
589
- const existing = engine.get(entityId, WidgetData);
590
- if (existing) {
591
- engine.set(entityId, WidgetData, {
592
- data: { ...existing.data, ...patch }
593
- });
594
- }
595
- },
596
- [engine, entityId]
597
- );
598
- }
599
-
600
- export { InfiniteCanvas, WidgetProvider, useBreakpoint, useChildren, useIsSelected, useUpdateWidget, useWidgetData };
601
- //# sourceMappingURL=index.js.map
602
- //# sourceMappingURL=index.js.map