@vibecook/ice 0.1.0 → 0.3.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/README.md +37 -2
- package/dist/chunk-2GUYATUM.js +643 -0
- package/dist/chunk-2GUYATUM.js.map +1 -0
- package/dist/{chunk-5S7GSXJG.js → chunk-5QY7HK6G.js} +3145 -1306
- package/dist/chunk-5QY7HK6G.js.map +1 -0
- package/dist/{chunk-BCJ47SX7.js → chunk-OR5FNVUE.js} +460 -1
- package/dist/chunk-OR5FNVUE.js.map +1 -0
- package/dist/{chunk-FIAXPNNY.js → chunk-PKK6GLSA.js} +143 -551
- package/dist/chunk-PKK6GLSA.js.map +1 -0
- package/dist/devtools.js +508 -372
- package/dist/devtools.js.map +1 -1
- package/dist/dom.js +3 -11
- package/dist/ground.js +715 -0
- package/dist/ground.js.map +1 -0
- package/dist/index.js +80 -2
- package/dist/kernel.js +31 -1
- package/dist/r3f.js +605 -62
- package/dist/r3f.js.map +1 -1
- package/dist/react.js +36 -418
- package/dist/react.js.map +1 -1
- package/dist/types/packages/core/src/catalog/camera-derived.d.ts +65 -3
- package/dist/types/packages/core/src/catalog/gesture.d.ts +40 -4
- package/dist/types/packages/core/src/catalog/graph.d.ts +7 -6
- package/dist/types/packages/core/src/catalog/index.d.ts +1 -0
- package/dist/types/packages/core/src/catalog/insert.d.ts +31 -0
- package/dist/types/packages/core/src/catalog/pointer.d.ts +11 -0
- package/dist/types/packages/core/src/catalog/scene.d.ts +37 -4
- package/dist/types/packages/core/src/catalog/selection-presence.d.ts +7 -0
- package/dist/types/packages/core/src/catalog/settings-resources.d.ts +21 -0
- package/dist/types/packages/core/src/doc/autosave.d.ts +49 -2
- package/dist/types/packages/core/src/doc/bootstrap.d.ts +29 -0
- package/dist/types/packages/core/src/doc/channels.d.ts +9 -0
- package/dist/types/packages/core/src/doc/doc-commit-sink.d.ts +2 -1
- package/dist/types/packages/core/src/doc/doc-kit.d.ts +16 -1
- package/dist/types/packages/core/src/doc/envelope.d.ts +2 -1
- package/dist/types/packages/core/src/doc/migrate.d.ts +8 -6
- package/dist/types/packages/core/src/doc/schema-migrate.d.ts +50 -0
- package/dist/types/packages/core/src/doc/version-gate.d.ts +3 -0
- package/dist/types/packages/core/src/engine/commit-sink.d.ts +24 -2
- package/dist/types/packages/core/src/engine/engine.d.ts +11 -0
- package/dist/types/packages/core/src/engine/frame-control.d.ts +71 -0
- package/dist/types/packages/core/src/engine/frame-info.d.ts +16 -1
- package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +79 -6
- package/dist/types/packages/core/src/guards/guarded-tx.d.ts +4 -2
- package/dist/types/packages/core/src/helpers/churn-guard.d.ts +40 -0
- package/dist/types/packages/core/src/index.d.ts +15 -7
- package/dist/types/packages/core/src/input/queue.d.ts +11 -0
- package/dist/types/packages/core/src/interaction/gesture-status.d.ts +13 -0
- package/dist/types/packages/core/src/nav/nested-canvas.d.ts +47 -11
- package/dist/types/packages/core/src/ops/arrange.d.ts +15 -0
- package/dist/types/packages/core/src/ops/insert.d.ts +62 -0
- package/dist/types/packages/core/src/ops/point-pick.d.ts +11 -7
- package/dist/types/packages/core/src/ops/sibling-order.d.ts +70 -0
- package/dist/types/packages/core/src/schema/meta.d.ts +1 -0
- package/dist/types/packages/core/src/settings/defaults.d.ts +45 -0
- package/dist/types/packages/core/src/settings/ground-config.d.ts +55 -0
- package/dist/types/packages/core/src/systems/chrome.d.ts +6 -2
- package/dist/types/packages/core/src/systems/insert-ghost.d.ts +25 -0
- package/dist/types/packages/core/src/systems/l1-pick.d.ts +25 -11
- package/dist/types/packages/core/src/systems/l2-recognize.d.ts +10 -4
- package/dist/types/packages/core/src/systems/l3-behave.d.ts +6 -4
- package/dist/types/packages/core/src/systems/l3-claim.d.ts +7 -3
- package/dist/types/packages/core/src/systems/l3-drop.d.ts +3 -1
- package/dist/types/packages/core/src/systems/l3-resize.d.ts +3 -1
- package/dist/types/packages/core/src/systems/l3-snap.d.ts +25 -7
- package/dist/types/packages/core/src/systems/nav-flight.d.ts +95 -0
- package/dist/types/packages/core/src/widget/define-widget.d.ts +39 -0
- package/dist/types/packages/core/src/widget/mount-store.d.ts +11 -3
- package/dist/types/packages/core/src/widget/set-props.d.ts +16 -0
- package/dist/types/packages/core/src/widget/spawn.d.ts +21 -1
- package/dist/types/packages/devtools/src/attach.d.ts +77 -0
- package/dist/types/packages/devtools/src/dock.d.ts +38 -0
- package/dist/types/packages/devtools/src/gl-panel.d.ts +69 -0
- package/dist/types/packages/devtools/src/index.d.ts +8 -6
- package/dist/types/packages/dom/src/index.d.ts +1 -3
- package/dist/types/packages/dom/src/loop.d.ts +11 -0
- package/dist/types/packages/dom/src/measure-wiring.d.ts +2 -2
- package/dist/types/packages/dom/src/pointer-adapter.d.ts +21 -1
- package/dist/types/packages/dom/src/reflectors/dom-widgets.d.ts +5 -0
- package/dist/types/packages/ground/src/index.d.ts +52 -0
- package/dist/types/packages/ground/src/layer.d.ts +40 -0
- package/dist/types/packages/ground/src/pass.d.ts +41 -0
- package/dist/types/packages/ground/src/passes/grid.d.ts +21 -0
- package/dist/types/packages/ground/src/passes/guides-collect.d.ts +14 -0
- package/dist/types/packages/ground/src/passes/guides.d.ts +3 -0
- package/dist/types/packages/ground/src/passes/soup-collect.d.ts +35 -0
- package/dist/types/packages/ground/src/passes/soup-mesh.d.ts +8 -0
- package/dist/types/packages/ground/src/passes/wires-collect.d.ts +31 -0
- package/dist/types/packages/ground/src/passes/wires.d.ts +10 -0
- package/dist/types/packages/ground/src/renderer.d.ts +15 -0
- package/dist/types/packages/ice/src/ground.d.ts +1 -0
- package/dist/types/packages/kernel/src/bezier.d.ts +15 -0
- package/dist/types/packages/kernel/src/coords.d.ts +15 -0
- package/dist/types/packages/kernel/src/easing.d.ts +11 -0
- package/dist/types/packages/kernel/src/index.d.ts +3 -0
- package/dist/types/packages/kernel/src/layout.d.ts +118 -0
- package/dist/types/packages/kernel/src/nav-flight.d.ts +93 -0
- package/dist/types/packages/r3f/src/bridge.d.ts +73 -12
- package/dist/types/packages/r3f/src/composite-material.d.ts +9 -0
- package/dist/types/packages/r3f/src/compositor-pass.d.ts +22 -0
- package/dist/types/packages/r3f/src/gl-root.d.ts +76 -1
- package/dist/types/packages/r3f/src/gl-router.d.ts +10 -0
- package/dist/types/packages/r3f/src/index.d.ts +3 -2
- package/dist/types/packages/r3f/src/island-state.d.ts +44 -0
- package/dist/types/packages/r3f/src/preview-capture.d.ts +19 -0
- package/dist/types/packages/r3f/src/self-sustain.d.ts +39 -0
- package/dist/types/packages/r3f/src/use-island-frame.d.ts +16 -1
- package/dist/types/packages/react/src/engine-context.d.ts +21 -0
- package/dist/types/packages/react/src/index.d.ts +4 -2
- package/dist/types/packages/react/src/infinite-canvas.d.ts +40 -6
- package/dist/types/packages/react/src/preview-snapshots.d.ts +17 -0
- package/dist/types/packages/react/src/widget-preview.d.ts +14 -0
- package/package.json +32 -61
- package/dist/chunk-5S7GSXJG.js.map +0 -1
- package/dist/chunk-BCJ47SX7.js.map +0 -1
- package/dist/chunk-FIAXPNNY.js.map +0 -1
- package/dist/types/packages/devtools/src/panel.d.ts +0 -48
- package/dist/types/packages/dom/src/reflectors/grid.d.ts +0 -63
- package/dist/types/packages/dom/src/reflectors/wires.d.ts +0 -88
|
@@ -6,28 +6,21 @@ import {
|
|
|
6
6
|
HandleSpec,
|
|
7
7
|
MeasuredSize,
|
|
8
8
|
NO_MODS,
|
|
9
|
-
|
|
10
|
-
PortAnchor,
|
|
9
|
+
Opacity,
|
|
11
10
|
Position,
|
|
12
11
|
PrefabId,
|
|
13
12
|
PresenceInfo,
|
|
14
|
-
RoutedConnect,
|
|
15
|
-
Selected,
|
|
16
13
|
SelectionBox,
|
|
17
14
|
Size,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
WirePorts,
|
|
21
|
-
WireTo,
|
|
15
|
+
compareStackOrder,
|
|
16
|
+
createSiblingOrderIndex,
|
|
22
17
|
defineQuery,
|
|
23
18
|
widgets
|
|
24
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-5QY7HK6G.js";
|
|
25
20
|
import {
|
|
26
21
|
planeCssTransform,
|
|
27
|
-
portAnchor,
|
|
28
|
-
wireCubic,
|
|
29
22
|
worldToScreen
|
|
30
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OR5FNVUE.js";
|
|
31
24
|
|
|
32
25
|
// ../dom/src/host.ts
|
|
33
26
|
var CONTAINER_STYLE = {
|
|
@@ -47,6 +40,10 @@ function createCanvasHost(container) {
|
|
|
47
40
|
const position = container.style.position !== "" ? container.style.position : view?.getComputedStyle(container).position ?? "";
|
|
48
41
|
const promoteToRelative = position === "" || position === "static";
|
|
49
42
|
if (promoteToRelative) container.style.position = "relative";
|
|
43
|
+
const priorContainerStyle = Object.keys(CONTAINER_STYLE).map((prop) => {
|
|
44
|
+
const cssName = prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
45
|
+
return [cssName, container.style.getPropertyValue(cssName)];
|
|
46
|
+
});
|
|
50
47
|
Object.assign(container.style, CONTAINER_STYLE);
|
|
51
48
|
const contentPlane = container.ownerDocument.createElement("div");
|
|
52
49
|
Object.assign(contentPlane.style, PLANE_STYLE);
|
|
@@ -57,11 +54,9 @@ function createCanvasHost(container) {
|
|
|
57
54
|
dispose() {
|
|
58
55
|
contentPlane.remove();
|
|
59
56
|
if (promoteToRelative) container.style.removeProperty("position");
|
|
60
|
-
for (const
|
|
61
|
-
container.style.
|
|
62
|
-
|
|
63
|
-
prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)
|
|
64
|
-
);
|
|
57
|
+
for (const [cssName, prior] of priorContainerStyle) {
|
|
58
|
+
if (prior !== "") container.style.setProperty(cssName, prior);
|
|
59
|
+
else container.style.removeProperty(cssName);
|
|
65
60
|
}
|
|
66
61
|
}
|
|
67
62
|
};
|
|
@@ -73,7 +68,12 @@ var LIFTED_PLANE_STYLE = {
|
|
|
73
68
|
left: "0",
|
|
74
69
|
top: "0",
|
|
75
70
|
transformOrigin: "0 0",
|
|
76
|
-
willChange: "transform"
|
|
71
|
+
willChange: "transform",
|
|
72
|
+
// The ONE explicit z in the plane sandwich (2026-07-19): in-container app
|
|
73
|
+
// chrome may slot BETWEEN the planes with z-index 1 — resting widgets
|
|
74
|
+
// slide under it while the dragged (promoted) widget floats over it. DOM
|
|
75
|
+
// order alone leaves no gap for that; everything else stays order-stacked.
|
|
76
|
+
zIndex: "2"
|
|
77
77
|
};
|
|
78
78
|
function createPlanes(host) {
|
|
79
79
|
const lifted = host.container.ownerDocument.createElement("div");
|
|
@@ -191,6 +191,7 @@ function createGrayboxReflector(host) {
|
|
|
191
191
|
var geometryQuery = defineQuery([Position, Size]);
|
|
192
192
|
var measuredQuery = defineQuery([MeasuredSize]);
|
|
193
193
|
var grabQuery = defineQuery([Grab]);
|
|
194
|
+
var opacityQuery = defineQuery([Opacity]);
|
|
194
195
|
function writeGeom2(el, x, y, w, h) {
|
|
195
196
|
el.style.left = `${x}px`;
|
|
196
197
|
el.style.top = `${y}px`;
|
|
@@ -200,11 +201,14 @@ function writeGeom2(el, x, y, w, h) {
|
|
|
200
201
|
function createDomWidgetsReflector(host, world, store) {
|
|
201
202
|
const doc = host.contentPlane.ownerDocument;
|
|
202
203
|
const hosts = /* @__PURE__ */ new Map();
|
|
204
|
+
const order = createSiblingOrderIndex(world);
|
|
203
205
|
let lastSnapshot;
|
|
204
206
|
let geometryWrites = 0;
|
|
205
207
|
let inert = false;
|
|
206
208
|
let geometryDirty = false;
|
|
207
209
|
let promoteDirty = false;
|
|
210
|
+
let opacityDirty = false;
|
|
211
|
+
let orderDirty = false;
|
|
208
212
|
const unsubs = [
|
|
209
213
|
world.reactive.observeQuery(geometryQuery, () => {
|
|
210
214
|
geometryDirty = true;
|
|
@@ -216,14 +220,35 @@ function createDomWidgetsReflector(host, world, store) {
|
|
|
216
220
|
}, { cols: [MeasuredSize] }),
|
|
217
221
|
world.reactive.observeQuery(grabQuery, () => {
|
|
218
222
|
promoteDirty = true;
|
|
219
|
-
}, { cols: [] })
|
|
223
|
+
}, { cols: [] }),
|
|
224
|
+
// Opacity is an optional rider like MeasuredSize: membership (attach/detach)
|
|
225
|
+
// and value changes both arm the flag; detach resets the host to the
|
|
226
|
+
// default via the `?? 1` read.
|
|
227
|
+
world.reactive.observeQuery(opacityQuery, () => {
|
|
228
|
+
opacityDirty = true;
|
|
229
|
+
}, { cols: [Opacity] }),
|
|
230
|
+
// Within-plane stacking IS the frame's ChildOf sibling sequence (petition
|
|
231
|
+
// 8, superseding the StackZ sort that fixed the 2026-07-18 comment-box
|
|
232
|
+
// paint bug). The wake names the relation (Related grammar — pure
|
|
233
|
+
// reorders fire it); the ordinal cache's stamp check in updateOrder
|
|
234
|
+
// keeps other-frame churn cheap.
|
|
235
|
+
order.observe(() => {
|
|
236
|
+
orderDirty = true;
|
|
237
|
+
})
|
|
220
238
|
];
|
|
239
|
+
function promotable(e) {
|
|
240
|
+
const type = world.get(e, PrefabId)?.id;
|
|
241
|
+
return typeof type !== "string" || widgets.get(type)?.surface !== "gl";
|
|
242
|
+
}
|
|
221
243
|
function readGeom(e) {
|
|
222
244
|
const p = world.get(e, Position);
|
|
223
245
|
const measured = world.get(e, MeasuredSize);
|
|
224
246
|
const s = measured !== void 0 && measured.w > 0 ? measured : world.get(e, Size);
|
|
225
247
|
return { x: p?.x ?? 0, y: p?.y ?? 0, w: s?.w ?? 0, h: s?.h ?? 0 };
|
|
226
248
|
}
|
|
249
|
+
function readOpacity(e) {
|
|
250
|
+
return world.get(e, Opacity)?.a ?? 1;
|
|
251
|
+
}
|
|
227
252
|
function createHost(e) {
|
|
228
253
|
const el = doc.createElement("div");
|
|
229
254
|
el.style.position = "absolute";
|
|
@@ -236,9 +261,11 @@ function createDomWidgetsReflector(host, world, store) {
|
|
|
236
261
|
const g = readGeom(e);
|
|
237
262
|
writeGeom2(el, g.x, g.y, g.w, g.h);
|
|
238
263
|
geometryWrites++;
|
|
239
|
-
const
|
|
264
|
+
const opacity = readOpacity(e);
|
|
265
|
+
if (opacity !== 1) el.style.opacity = String(opacity);
|
|
266
|
+
const lifted = world.has(e, Grab) && promotable(e);
|
|
240
267
|
(lifted ? host.liftedPlane : host.contentPlane).appendChild(el);
|
|
241
|
-
return { host: el, content, x: g.x, y: g.y, w: g.w, h: g.h, hidden: false, lifted };
|
|
268
|
+
return { host: el, content, x: g.x, y: g.y, w: g.w, h: g.h, hidden: false, lifted, opacity };
|
|
242
269
|
}
|
|
243
270
|
function reconcile(snapshot) {
|
|
244
271
|
let membershipChanged = false;
|
|
@@ -277,14 +304,57 @@ function createDomWidgetsReflector(host, world, store) {
|
|
|
277
304
|
}
|
|
278
305
|
}
|
|
279
306
|
}
|
|
307
|
+
function updateOrder() {
|
|
308
|
+
const ordinals = order.ordinals();
|
|
309
|
+
for (const plane of [host.contentPlane, host.liftedPlane]) {
|
|
310
|
+
const active = doc.activeElement;
|
|
311
|
+
if (active !== null && active !== doc.body && plane.contains(active)) continue;
|
|
312
|
+
const mine = [];
|
|
313
|
+
for (const [e, rec] of hosts) {
|
|
314
|
+
if (rec.host.parentNode !== plane) continue;
|
|
315
|
+
mine.push({ el: rec.host, e });
|
|
316
|
+
}
|
|
317
|
+
if (mine.length < 2) continue;
|
|
318
|
+
const target = [...mine].sort((a, b) => compareStackOrder(world, ordinals, a.e, b.e));
|
|
319
|
+
let cursor = 0;
|
|
320
|
+
let inOrder = true;
|
|
321
|
+
for (let i = 0; i < plane.children.length; i++) {
|
|
322
|
+
const child = plane.children.item(i);
|
|
323
|
+
if (cursor >= target.length || child === null) break;
|
|
324
|
+
if (child === target[cursor].el) cursor += 1;
|
|
325
|
+
else if (mine.some((m) => m.el === child)) {
|
|
326
|
+
inOrder = false;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (inOrder && cursor === target.length) continue;
|
|
331
|
+
for (const m of target) plane.appendChild(m.el);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function updateOpacity() {
|
|
335
|
+
for (const [e, rec] of hosts) {
|
|
336
|
+
const o = readOpacity(e);
|
|
337
|
+
if (o !== rec.opacity) {
|
|
338
|
+
rec.host.style.opacity = o === 1 ? "" : String(o);
|
|
339
|
+
rec.opacity = o;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
280
343
|
function updatePromote() {
|
|
281
344
|
let anyLifted = false;
|
|
282
345
|
for (const [e, rec] of hosts) {
|
|
283
|
-
const
|
|
346
|
+
const grabbed = world.has(e, Grab);
|
|
347
|
+
const shouldLift = grabbed && promotable(e);
|
|
284
348
|
if (shouldLift) anyLifted = true;
|
|
285
349
|
if (shouldLift !== rec.lifted) {
|
|
286
350
|
rec.lifted = shouldLift;
|
|
287
351
|
(shouldLift ? host.liftedPlane : host.contentPlane).appendChild(rec.host);
|
|
352
|
+
orderDirty = true;
|
|
353
|
+
}
|
|
354
|
+
if (grabbed && !shouldLift) {
|
|
355
|
+
if (rec.host.style.zIndex !== "1000") rec.host.style.zIndex = "1000";
|
|
356
|
+
} else if (rec.host.style.zIndex !== "") {
|
|
357
|
+
rec.host.style.zIndex = "";
|
|
288
358
|
}
|
|
289
359
|
}
|
|
290
360
|
if (anyLifted !== inert) {
|
|
@@ -308,10 +378,18 @@ function createDomWidgetsReflector(host, world, store) {
|
|
|
308
378
|
geometryDirty = false;
|
|
309
379
|
updateGeometry();
|
|
310
380
|
}
|
|
381
|
+
if (opacityDirty) {
|
|
382
|
+
opacityDirty = false;
|
|
383
|
+
updateOpacity();
|
|
384
|
+
}
|
|
311
385
|
if (promoteDirty || membershipChanged) {
|
|
312
386
|
promoteDirty = false;
|
|
313
387
|
updatePromote();
|
|
314
388
|
}
|
|
389
|
+
if (orderDirty || membershipChanged) {
|
|
390
|
+
orderDirty = false;
|
|
391
|
+
updateOrder();
|
|
392
|
+
}
|
|
315
393
|
},
|
|
316
394
|
hostFor: (entity) => hosts.get(entity)?.content,
|
|
317
395
|
hostCount: () => hosts.size,
|
|
@@ -327,19 +405,33 @@ function createDomWidgetsReflector(host, world, store) {
|
|
|
327
405
|
function startRafLoop(engine) {
|
|
328
406
|
let handle = 0;
|
|
329
407
|
let stopped = false;
|
|
408
|
+
let parked = false;
|
|
330
409
|
const tick = (now) => {
|
|
331
410
|
if (stopped) return;
|
|
411
|
+
if (!engine.frame.claimStep()) {
|
|
412
|
+
parked = true;
|
|
413
|
+
handle = 0;
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
332
416
|
engine.step(now);
|
|
333
417
|
handle = requestAnimationFrame(tick);
|
|
334
418
|
};
|
|
419
|
+
const wake = () => {
|
|
420
|
+
if (stopped || !parked || engine.frame.isFrozen()) return;
|
|
421
|
+
parked = false;
|
|
422
|
+
handle = requestAnimationFrame(tick);
|
|
423
|
+
};
|
|
424
|
+
const unsubscribe = engine.frame.onChange(wake);
|
|
335
425
|
handle = requestAnimationFrame(tick);
|
|
336
426
|
return () => {
|
|
337
427
|
stopped = true;
|
|
428
|
+
unsubscribe();
|
|
338
429
|
cancelAnimationFrame(handle);
|
|
339
430
|
};
|
|
340
431
|
}
|
|
341
432
|
|
|
342
433
|
// ../dom/src/pointer-adapter.ts
|
|
434
|
+
var asVerdict = (v) => typeof v === "object" ? v : { handled: v === true };
|
|
343
435
|
var WHEEL_LINE_PX = 16;
|
|
344
436
|
var INTERACTIVE_SELECTOR = 'input, textarea, select, button, a[href], [contenteditable=""], [contenteditable="true"], audio[controls], video[controls], [data-canvas-interactive]';
|
|
345
437
|
function crossesInteractive(target, container) {
|
|
@@ -388,7 +480,8 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
388
480
|
const device = deviceOf(e);
|
|
389
481
|
const { x, y } = relative(e.clientX, e.clientY);
|
|
390
482
|
const native = crossesInteractive(e.target, container);
|
|
391
|
-
const
|
|
483
|
+
const gl = asVerdict(glRoute?.("down", x, y, e));
|
|
484
|
+
const glClaimed = gl.handled;
|
|
392
485
|
live.set(id, { device, x, y, downX: x, downY: y, native, captured: glClaimed });
|
|
393
486
|
if (glClaimed) capture(e.pointerId);
|
|
394
487
|
const surfaceHandled = native || glClaimed;
|
|
@@ -401,14 +494,21 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
401
494
|
buttons: e.buttons,
|
|
402
495
|
mods: pointerMods(e),
|
|
403
496
|
tMs: e.timeStamp,
|
|
404
|
-
...surfaceHandled ? { surfaceHandled: true } : {}
|
|
497
|
+
...surfaceHandled ? { surfaceHandled: true } : {},
|
|
498
|
+
// The down IS a hover-bearing fact: a touch's first event must seed the
|
|
499
|
+
// pointer's OverInteractive truth (no prior moves exist to).
|
|
500
|
+
overInteractive: surfaceHandled || gl.overInteractive === true
|
|
405
501
|
});
|
|
406
502
|
};
|
|
407
503
|
const onPointerMove = (e) => {
|
|
408
504
|
const id = pointerIdOf(e);
|
|
409
505
|
const device = deviceOf(e);
|
|
410
506
|
const { x, y } = relative(e.clientX, e.clientY);
|
|
411
|
-
|
|
507
|
+
let seen = live.get(id);
|
|
508
|
+
if (seen === void 0 && e.buttons !== 0 && !crossesInteractive(e.target, container)) {
|
|
509
|
+
seen = { device, x, y, downX: x, downY: y, native: false, captured: false };
|
|
510
|
+
live.set(id, seen);
|
|
511
|
+
}
|
|
412
512
|
if (seen !== void 0) {
|
|
413
513
|
seen.x = x;
|
|
414
514
|
seen.y = y;
|
|
@@ -417,7 +517,7 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
417
517
|
seen.captured = true;
|
|
418
518
|
}
|
|
419
519
|
}
|
|
420
|
-
const
|
|
520
|
+
const gl = asVerdict(glRoute?.("move", x, y, e));
|
|
421
521
|
queue.enqueue({
|
|
422
522
|
kind: "move",
|
|
423
523
|
pointerId: id,
|
|
@@ -427,7 +527,10 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
427
527
|
buttons: e.buttons,
|
|
428
528
|
mods: pointerMods(e),
|
|
429
529
|
tMs: e.timeStamp,
|
|
430
|
-
...
|
|
530
|
+
...gl.handled ? { surfaceHandled: true } : {},
|
|
531
|
+
// Hover fact, every move: DOM chain check ∪ GL verdict. A gl-captured
|
|
532
|
+
// move (island drag) counts — the widget owns the pointer right now.
|
|
533
|
+
overInteractive: crossesInteractive(e.target, container) || gl.handled || gl.overInteractive === true
|
|
431
534
|
});
|
|
432
535
|
};
|
|
433
536
|
const endPointer = (kind) => (e) => {
|
|
@@ -441,7 +544,7 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
441
544
|
} catch {
|
|
442
545
|
}
|
|
443
546
|
}
|
|
444
|
-
const
|
|
547
|
+
const gl = asVerdict(glRoute?.(kind, x, y, e));
|
|
445
548
|
queue.enqueue({
|
|
446
549
|
kind,
|
|
447
550
|
pointerId: id,
|
|
@@ -450,7 +553,9 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
450
553
|
screenY: y,
|
|
451
554
|
buttons: e.buttons,
|
|
452
555
|
mods: pointerMods(e),
|
|
453
|
-
...
|
|
556
|
+
...gl.handled ? { surfaceHandled: true } : {}
|
|
557
|
+
// No overInteractive stamp: a capture-retargeted up reads the container,
|
|
558
|
+
// not the content under the pointer — the next real move re-truths it.
|
|
454
559
|
});
|
|
455
560
|
};
|
|
456
561
|
const onPointerUp = endPointer("up");
|
|
@@ -485,7 +590,7 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
485
590
|
}
|
|
486
591
|
emitKeyIfChanged(e);
|
|
487
592
|
};
|
|
488
|
-
const
|
|
593
|
+
const cancelAllInput = () => {
|
|
489
594
|
for (const [id, s] of live) {
|
|
490
595
|
queue.enqueue({ kind: "cancel", pointerId: id, device: s.device, screenX: s.x, screenY: s.y, buttons: 0, mods: { ...NO_MODS, space: spaceHeld } });
|
|
491
596
|
}
|
|
@@ -504,6 +609,9 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
504
609
|
});
|
|
505
610
|
}
|
|
506
611
|
};
|
|
612
|
+
const onBlur = () => {
|
|
613
|
+
cancelAllInput();
|
|
614
|
+
};
|
|
507
615
|
container.addEventListener("pointerdown", onPointerDown);
|
|
508
616
|
container.addEventListener("pointermove", onPointerMove);
|
|
509
617
|
container.addEventListener("pointerup", onPointerUp);
|
|
@@ -513,6 +621,7 @@ function attachPointerAdapter(host, queue, opts = {}) {
|
|
|
513
621
|
view?.addEventListener("keyup", onKeyUp);
|
|
514
622
|
view?.addEventListener("blur", onBlur);
|
|
515
623
|
return () => {
|
|
624
|
+
cancelAllInput();
|
|
516
625
|
container.removeEventListener("pointerdown", onPointerDown);
|
|
517
626
|
container.removeEventListener("pointermove", onPointerMove);
|
|
518
627
|
container.removeEventListener("pointerup", onPointerUp);
|
|
@@ -647,519 +756,6 @@ function createRemoteCursorsReflector(host, world) {
|
|
|
647
756
|
};
|
|
648
757
|
}
|
|
649
758
|
|
|
650
|
-
// ../dom/src/reflectors/grid.ts
|
|
651
|
-
var DEFAULT_GRID_CONFIG = {
|
|
652
|
-
spacings: [20, 100, 500],
|
|
653
|
-
dotColor: [0.75, 0.77, 0.8],
|
|
654
|
-
dotAlpha: 1,
|
|
655
|
-
fadeIn: [8, 16],
|
|
656
|
-
fadeOut: [120, 200],
|
|
657
|
-
dotRadius: [0.75, 0.75],
|
|
658
|
-
levelWeight: [1, 0]
|
|
659
|
-
};
|
|
660
|
-
var VERTEX_SHADER = (
|
|
661
|
-
/* glsl */
|
|
662
|
-
`
|
|
663
|
-
attribute vec2 position;
|
|
664
|
-
void main() {
|
|
665
|
-
gl_Position = vec4(position, 0.0, 1.0);
|
|
666
|
-
}
|
|
667
|
-
`
|
|
668
|
-
);
|
|
669
|
-
var FRAGMENT_SHADER = (
|
|
670
|
-
/* glsl */
|
|
671
|
-
`
|
|
672
|
-
precision highp float;
|
|
673
|
-
|
|
674
|
-
uniform vec2 u_resolution; // device pixels
|
|
675
|
-
uniform vec2 u_camera; // world-space top-left
|
|
676
|
-
uniform float u_zoom; // CSS zoom
|
|
677
|
-
uniform float u_dpr; // device pixel ratio
|
|
678
|
-
uniform vec3 u_spacings; // world-unit grid spacings
|
|
679
|
-
uniform vec3 u_dotColor; // dot RGB
|
|
680
|
-
uniform float u_dotAlpha; // dot base alpha
|
|
681
|
-
uniform vec2 u_fadeIn; // CSS-px [start, end]
|
|
682
|
-
uniform vec2 u_fadeOut; // CSS-px [start, end]
|
|
683
|
-
uniform vec2 u_dotRadius; // CSS-px [min, max]
|
|
684
|
-
uniform vec2 u_levelWeight; // [base, step]
|
|
685
|
-
|
|
686
|
-
void main() {
|
|
687
|
-
vec2 devicePos = gl_FragCoord.xy;
|
|
688
|
-
devicePos.y = u_resolution.y - devicePos.y;
|
|
689
|
-
|
|
690
|
-
float effectiveZoom = u_zoom * u_dpr;
|
|
691
|
-
vec2 worldPos = devicePos / effectiveZoom + u_camera;
|
|
692
|
-
|
|
693
|
-
float totalAlpha = 0.0;
|
|
694
|
-
|
|
695
|
-
for (int i = 0; i < 3; i++) {
|
|
696
|
-
float spacing;
|
|
697
|
-
if (i == 0) spacing = u_spacings.x;
|
|
698
|
-
else if (i == 1) spacing = u_spacings.y;
|
|
699
|
-
else spacing = u_spacings.z;
|
|
700
|
-
|
|
701
|
-
// Screen spacing in CSS pixels (DPR-independent for consistent fading)
|
|
702
|
-
float cssSpacing = spacing * u_zoom;
|
|
703
|
-
|
|
704
|
-
// Fade curve
|
|
705
|
-
float opacity = 0.0;
|
|
706
|
-
if (cssSpacing >= u_fadeIn.x && cssSpacing < u_fadeIn.y) {
|
|
707
|
-
opacity = (cssSpacing - u_fadeIn.x) / (u_fadeIn.y - u_fadeIn.x);
|
|
708
|
-
} else if (cssSpacing >= u_fadeIn.y && cssSpacing < u_fadeOut.x) {
|
|
709
|
-
opacity = 1.0;
|
|
710
|
-
} else if (cssSpacing >= u_fadeOut.x && cssSpacing < u_fadeOut.y) {
|
|
711
|
-
opacity = 1.0 - (cssSpacing - u_fadeOut.x) / (u_fadeOut.y - u_fadeOut.x);
|
|
712
|
-
}
|
|
713
|
-
if (opacity <= 0.001) continue;
|
|
714
|
-
|
|
715
|
-
// Distance to nearest grid intersection in device pixels
|
|
716
|
-
vec2 f = fract(worldPos / spacing + 0.5) - 0.5;
|
|
717
|
-
float dist = length(f) * spacing * effectiveZoom;
|
|
718
|
-
|
|
719
|
-
// Dot radius in device pixels \u2014 optionally grows for sparser levels
|
|
720
|
-
// (set u_dotRadius.x == u_dotRadius.y for Freeform/FigJam-style
|
|
721
|
-
// constant-size dots)
|
|
722
|
-
float t = clamp((cssSpacing - u_fadeIn.x) / 40.0, 0.0, 1.0);
|
|
723
|
-
float radius = mix(u_dotRadius.x, u_dotRadius.y, t) * u_dpr;
|
|
724
|
-
|
|
725
|
-
// Anti-aliased dot (0.5 device pixel smoothstep)
|
|
726
|
-
float dot = 1.0 - smoothstep(radius - 0.5, radius + 0.5, dist);
|
|
727
|
-
|
|
728
|
-
// Per-level weight: base + i * step. Step=0 keeps all levels at equal
|
|
729
|
-
// intensity; positive step emphasizes coarser levels (CAD feel).
|
|
730
|
-
float weight = u_levelWeight.x + float(i) * u_levelWeight.y;
|
|
731
|
-
|
|
732
|
-
// Composite with max, not sum. Additive compositing causes anti-
|
|
733
|
-
// aliased dot rims to stack at joint intersections (every N-th dot
|
|
734
|
-
// visibly fatter \u2014 a CAD tell). max() guarantees a joint intersection
|
|
735
|
-
// looks identical to a single-level dot, matching Freeform / FigJam.
|
|
736
|
-
totalAlpha = max(totalAlpha, dot * opacity * weight);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
gl_FragColor = vec4(u_dotColor, clamp(totalAlpha * u_dotAlpha, 0.0, 1.0));
|
|
740
|
-
}
|
|
741
|
-
`
|
|
742
|
-
);
|
|
743
|
-
var FULLSCREEN_TRIANGLE = new Float32Array([-1, -1, 3, -1, -1, 3]);
|
|
744
|
-
var UNIFORM_NAMES = [
|
|
745
|
-
"u_resolution",
|
|
746
|
-
"u_camera",
|
|
747
|
-
"u_zoom",
|
|
748
|
-
"u_dpr",
|
|
749
|
-
"u_spacings",
|
|
750
|
-
"u_dotColor",
|
|
751
|
-
"u_dotAlpha",
|
|
752
|
-
"u_fadeIn",
|
|
753
|
-
"u_fadeOut",
|
|
754
|
-
"u_dotRadius",
|
|
755
|
-
"u_levelWeight"
|
|
756
|
-
];
|
|
757
|
-
function compileShader(gl, type, source) {
|
|
758
|
-
const shader = gl.createShader(type);
|
|
759
|
-
if (shader === null) return null;
|
|
760
|
-
gl.shaderSource(shader, source);
|
|
761
|
-
gl.compileShader(shader);
|
|
762
|
-
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) !== true) {
|
|
763
|
-
gl.deleteShader(shader);
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
766
|
-
return shader;
|
|
767
|
-
}
|
|
768
|
-
function linkProgram(gl) {
|
|
769
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
770
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
|
|
771
|
-
if (vs === null || fs === null) return null;
|
|
772
|
-
const program = gl.createProgram();
|
|
773
|
-
if (program === null) return null;
|
|
774
|
-
gl.attachShader(program, vs);
|
|
775
|
-
gl.attachShader(program, fs);
|
|
776
|
-
gl.linkProgram(program);
|
|
777
|
-
const linked = gl.getProgramParameter(program, gl.LINK_STATUS) === true;
|
|
778
|
-
gl.deleteShader(vs);
|
|
779
|
-
gl.deleteShader(fs);
|
|
780
|
-
if (!linked) {
|
|
781
|
-
gl.deleteProgram(program);
|
|
782
|
-
return null;
|
|
783
|
-
}
|
|
784
|
-
return program;
|
|
785
|
-
}
|
|
786
|
-
function setupGeometry(gl, program) {
|
|
787
|
-
const buffer = gl.createBuffer();
|
|
788
|
-
if (buffer === null) return false;
|
|
789
|
-
const loc = gl.getAttribLocation(program, "position");
|
|
790
|
-
if (loc < 0) return false;
|
|
791
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
792
|
-
gl.bufferData(gl.ARRAY_BUFFER, FULLSCREEN_TRIANGLE, gl.STATIC_DRAW);
|
|
793
|
-
gl.enableVertexAttribArray(loc);
|
|
794
|
-
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
|
|
795
|
-
return true;
|
|
796
|
-
}
|
|
797
|
-
function collectUniforms(gl, program) {
|
|
798
|
-
const out = {};
|
|
799
|
-
for (const name of UNIFORM_NAMES) out[name] = gl.getUniformLocation(program, name);
|
|
800
|
-
return out;
|
|
801
|
-
}
|
|
802
|
-
function createGridReflector(host, opts = {}) {
|
|
803
|
-
const config = { ...DEFAULT_GRID_CONFIG, ...opts };
|
|
804
|
-
const doc = host.container.ownerDocument;
|
|
805
|
-
const canvas = doc.createElement("canvas");
|
|
806
|
-
canvas.style.position = "absolute";
|
|
807
|
-
canvas.style.left = "0";
|
|
808
|
-
canvas.style.top = "0";
|
|
809
|
-
canvas.style.width = "100%";
|
|
810
|
-
canvas.style.height = "100%";
|
|
811
|
-
canvas.style.display = "block";
|
|
812
|
-
canvas.style.pointerEvents = "none";
|
|
813
|
-
host.container.insertBefore(canvas, host.container.firstChild);
|
|
814
|
-
let gl = null;
|
|
815
|
-
let program = null;
|
|
816
|
-
let uniforms = null;
|
|
817
|
-
let dpr = 1;
|
|
818
|
-
let lastCamera = { x: 0, y: 0, zoom: 1 };
|
|
819
|
-
try {
|
|
820
|
-
const attrs = { alpha: true, antialias: false, premultipliedAlpha: false };
|
|
821
|
-
gl = canvas.getContext("webgl2", attrs) ?? canvas.getContext("webgl", attrs);
|
|
822
|
-
if (gl !== null) {
|
|
823
|
-
const prog = linkProgram(gl);
|
|
824
|
-
if (prog !== null && setupGeometry(gl, prog)) {
|
|
825
|
-
program = prog;
|
|
826
|
-
uniforms = collectUniforms(gl, prog);
|
|
827
|
-
} else {
|
|
828
|
-
gl = null;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
} catch {
|
|
832
|
-
gl = null;
|
|
833
|
-
program = null;
|
|
834
|
-
uniforms = null;
|
|
835
|
-
}
|
|
836
|
-
function draw(camera) {
|
|
837
|
-
if (gl === null || program === null || uniforms === null) return;
|
|
838
|
-
lastCamera = camera;
|
|
839
|
-
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
840
|
-
gl.useProgram(program);
|
|
841
|
-
gl.uniform2f(uniforms.u_resolution, canvas.width, canvas.height);
|
|
842
|
-
gl.uniform2f(uniforms.u_camera, camera.x, camera.y);
|
|
843
|
-
gl.uniform1f(uniforms.u_zoom, camera.zoom);
|
|
844
|
-
gl.uniform1f(uniforms.u_dpr, dpr);
|
|
845
|
-
gl.uniform3f(uniforms.u_spacings, ...config.spacings);
|
|
846
|
-
gl.uniform3f(uniforms.u_dotColor, ...config.dotColor);
|
|
847
|
-
gl.uniform1f(uniforms.u_dotAlpha, config.dotAlpha);
|
|
848
|
-
gl.uniform2f(uniforms.u_fadeIn, ...config.fadeIn);
|
|
849
|
-
gl.uniform2f(uniforms.u_fadeOut, ...config.fadeOut);
|
|
850
|
-
gl.uniform2f(uniforms.u_dotRadius, ...config.dotRadius);
|
|
851
|
-
gl.uniform2f(uniforms.u_levelWeight, ...config.levelWeight);
|
|
852
|
-
gl.clearColor(0, 0, 0, 0);
|
|
853
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
854
|
-
gl.enable(gl.BLEND);
|
|
855
|
-
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
856
|
-
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
857
|
-
}
|
|
858
|
-
function applySize(cssWidth, cssHeight) {
|
|
859
|
-
dpr = doc.defaultView?.devicePixelRatio ?? 1;
|
|
860
|
-
const bufW = Math.max(1, Math.round(cssWidth * dpr));
|
|
861
|
-
const bufH = Math.max(1, Math.round(cssHeight * dpr));
|
|
862
|
-
if (canvas.width !== bufW) canvas.width = bufW;
|
|
863
|
-
if (canvas.height !== bufH) canvas.height = bufH;
|
|
864
|
-
try {
|
|
865
|
-
draw(lastCamera);
|
|
866
|
-
} catch {
|
|
867
|
-
gl = null;
|
|
868
|
-
program = null;
|
|
869
|
-
uniforms = null;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
const initialRect = host.container.getBoundingClientRect();
|
|
873
|
-
applySize(initialRect.width, initialRect.height);
|
|
874
|
-
let ro;
|
|
875
|
-
try {
|
|
876
|
-
ro = new ResizeObserver((entries) => {
|
|
877
|
-
const entry = entries[0];
|
|
878
|
-
if (entry === void 0) return;
|
|
879
|
-
applySize(entry.contentRect.width, entry.contentRect.height);
|
|
880
|
-
});
|
|
881
|
-
ro.observe(host.container);
|
|
882
|
-
} catch {
|
|
883
|
-
}
|
|
884
|
-
return {
|
|
885
|
-
name: "grid",
|
|
886
|
-
observe: { resources: [Camera] },
|
|
887
|
-
flush(world) {
|
|
888
|
-
if (gl === null) return;
|
|
889
|
-
const camera = world.getResource(Camera);
|
|
890
|
-
if (camera === void 0) return;
|
|
891
|
-
try {
|
|
892
|
-
draw(camera);
|
|
893
|
-
} catch {
|
|
894
|
-
gl = null;
|
|
895
|
-
program = null;
|
|
896
|
-
uniforms = null;
|
|
897
|
-
}
|
|
898
|
-
},
|
|
899
|
-
available: () => gl !== null,
|
|
900
|
-
// Live re-tune (theme switches, settings panels): draw() uploads every
|
|
901
|
-
// config uniform per call, so a merge + one redraw at the last camera is
|
|
902
|
-
// the whole story. Outside the frame contract by design — config is host
|
|
903
|
-
// input, not world state (same class as the RO resize path).
|
|
904
|
-
configure(next) {
|
|
905
|
-
Object.assign(config, next);
|
|
906
|
-
if (gl !== null) {
|
|
907
|
-
try {
|
|
908
|
-
draw(lastCamera);
|
|
909
|
-
} catch {
|
|
910
|
-
gl = null;
|
|
911
|
-
program = null;
|
|
912
|
-
uniforms = null;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
},
|
|
916
|
-
// Unregistering a reflector only stops its flushes — the canvas this
|
|
917
|
-
// factory inserted (and its ResizeObserver) must be torn down explicitly,
|
|
918
|
-
// or a React StrictMode remount stacks a second frozen grid under the
|
|
919
|
-
// live one (field report 2026-07-11).
|
|
920
|
-
dispose() {
|
|
921
|
-
ro?.disconnect();
|
|
922
|
-
gl = null;
|
|
923
|
-
program = null;
|
|
924
|
-
uniforms = null;
|
|
925
|
-
canvas.remove();
|
|
926
|
-
}
|
|
927
|
-
};
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
// ../dom/src/reflectors/wires.ts
|
|
931
|
-
var INACTIVE_PREVIEW = { sx: 0, sy: 0, tx: 0, ty: 0, active: false, compatible: false };
|
|
932
|
-
var DEFAULT_WIRES_CONFIG = {
|
|
933
|
-
wireColor: "rgba(120, 132, 145, 0.9)",
|
|
934
|
-
selectedColor: "#4a90d9",
|
|
935
|
-
wireWidth: 1.5,
|
|
936
|
-
selectedWidth: 2,
|
|
937
|
-
portRadius: 4,
|
|
938
|
-
portColor: "rgba(120, 132, 145, 0.9)",
|
|
939
|
-
portActiveColor: "#4a90d9"
|
|
940
|
-
};
|
|
941
|
-
var wireQ = defineQuery([Wire]);
|
|
942
|
-
var geometryQ = defineQuery([Position, Size]);
|
|
943
|
-
var selectedQ = defineQuery([Selected]);
|
|
944
|
-
var portQ = defineQuery([Port, PortAnchor]);
|
|
945
|
-
var routedConnectQ = defineQuery([RoutedConnect]);
|
|
946
|
-
function readRect(world, e) {
|
|
947
|
-
const p = world.get(e, Position);
|
|
948
|
-
if (p === void 0) return void 0;
|
|
949
|
-
const measured = world.get(e, MeasuredSize);
|
|
950
|
-
const s = measured !== void 0 && measured.w > 0 ? measured : world.get(e, Size);
|
|
951
|
-
if (s === void 0) return void 0;
|
|
952
|
-
return { x: p.x, y: p.y, width: s.w, height: s.h };
|
|
953
|
-
}
|
|
954
|
-
function makePortSlotResolver() {
|
|
955
|
-
const cache = /* @__PURE__ */ new Map();
|
|
956
|
-
const build = (wt) => {
|
|
957
|
-
const bySide = /* @__PURE__ */ new Map();
|
|
958
|
-
for (const d of wt.ports) {
|
|
959
|
-
let list = bySide.get(d.side);
|
|
960
|
-
if (list === void 0) {
|
|
961
|
-
list = [];
|
|
962
|
-
bySide.set(d.side, list);
|
|
963
|
-
}
|
|
964
|
-
list.push(d);
|
|
965
|
-
}
|
|
966
|
-
const out = /* @__PURE__ */ new Map();
|
|
967
|
-
for (const [side, list] of bySide) {
|
|
968
|
-
for (let i = 0; i < list.length; i++) {
|
|
969
|
-
const d = list[i];
|
|
970
|
-
if (d === void 0) continue;
|
|
971
|
-
out.set(d.id, { side, index: d.index ?? i, count: list.length });
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
return out;
|
|
975
|
-
};
|
|
976
|
-
return (wt, portId) => {
|
|
977
|
-
let slots = cache.get(wt.type);
|
|
978
|
-
if (slots === void 0) {
|
|
979
|
-
slots = build(wt);
|
|
980
|
-
cache.set(wt.type, slots);
|
|
981
|
-
}
|
|
982
|
-
return slots.get(portId);
|
|
983
|
-
};
|
|
984
|
-
}
|
|
985
|
-
function cubicToScreen(c, cam) {
|
|
986
|
-
const p0 = worldToScreen(c.x0, c.y0, cam);
|
|
987
|
-
const p1 = worldToScreen(c.x1, c.y1, cam);
|
|
988
|
-
const p2 = worldToScreen(c.x2, c.y2, cam);
|
|
989
|
-
const p3 = worldToScreen(c.x3, c.y3, cam);
|
|
990
|
-
return { x0: p0.x, y0: p0.y, x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y, x3: p3.x, y3: p3.y };
|
|
991
|
-
}
|
|
992
|
-
function createWiresReflector(host, world, opts = {}) {
|
|
993
|
-
const config = { ...DEFAULT_WIRES_CONFIG, ...opts.config };
|
|
994
|
-
const readPreview = opts.readPreview ?? (() => INACTIVE_PREVIEW);
|
|
995
|
-
const doc = host.container.ownerDocument;
|
|
996
|
-
const canvas = doc.createElement("canvas");
|
|
997
|
-
canvas.style.position = "absolute";
|
|
998
|
-
canvas.style.left = "0";
|
|
999
|
-
canvas.style.top = "0";
|
|
1000
|
-
canvas.style.width = "100%";
|
|
1001
|
-
canvas.style.height = "100%";
|
|
1002
|
-
canvas.style.display = "block";
|
|
1003
|
-
canvas.style.pointerEvents = "none";
|
|
1004
|
-
host.container.insertBefore(canvas, host.contentPlane);
|
|
1005
|
-
let ctx = null;
|
|
1006
|
-
try {
|
|
1007
|
-
ctx = canvas.getContext("2d");
|
|
1008
|
-
} catch {
|
|
1009
|
-
ctx = null;
|
|
1010
|
-
}
|
|
1011
|
-
let dpr = 1;
|
|
1012
|
-
const slotOf = makePortSlotResolver();
|
|
1013
|
-
let dirty = true;
|
|
1014
|
-
let lastPreviewKey = "";
|
|
1015
|
-
let redraws = 0;
|
|
1016
|
-
const wake = () => {
|
|
1017
|
-
dirty = true;
|
|
1018
|
-
};
|
|
1019
|
-
const unsubs = [
|
|
1020
|
-
world.reactive.observeResource(Camera, wake),
|
|
1021
|
-
world.reactive.observeQuery(wireQ, wake, { cols: [] }),
|
|
1022
|
-
world.reactive.observeQuery(geometryQ, wake, { cols: [Position, Size] }),
|
|
1023
|
-
world.reactive.observeQuery(selectedQ, wake, { cols: [] }),
|
|
1024
|
-
world.reactive.observeQuery(portQ, wake, { cols: [PortAnchor] }),
|
|
1025
|
-
world.reactive.observeQuery(routedConnectQ, wake, { cols: [] })
|
|
1026
|
-
];
|
|
1027
|
-
function applySize(cssWidth, cssHeight) {
|
|
1028
|
-
dpr = doc.defaultView?.devicePixelRatio ?? 1;
|
|
1029
|
-
const bufW = Math.max(1, Math.round(cssWidth * dpr));
|
|
1030
|
-
const bufH = Math.max(1, Math.round(cssHeight * dpr));
|
|
1031
|
-
if (canvas.width !== bufW) canvas.width = bufW;
|
|
1032
|
-
if (canvas.height !== bufH) canvas.height = bufH;
|
|
1033
|
-
dirty = true;
|
|
1034
|
-
}
|
|
1035
|
-
const initialRect = host.container.getBoundingClientRect();
|
|
1036
|
-
applySize(initialRect.width, initialRect.height);
|
|
1037
|
-
let ro = null;
|
|
1038
|
-
try {
|
|
1039
|
-
ro = new ResizeObserver((entries) => {
|
|
1040
|
-
const entry = entries[0];
|
|
1041
|
-
if (entry === void 0) return;
|
|
1042
|
-
applySize(entry.contentRect.width, entry.contentRect.height);
|
|
1043
|
-
});
|
|
1044
|
-
ro.observe(host.container);
|
|
1045
|
-
} catch {
|
|
1046
|
-
ro = null;
|
|
1047
|
-
}
|
|
1048
|
-
function strokeCubic(c2d, s) {
|
|
1049
|
-
c2d.beginPath();
|
|
1050
|
-
c2d.moveTo(s.x0, s.y0);
|
|
1051
|
-
c2d.bezierCurveTo(s.x1, s.y1, s.x2, s.y2, s.x3, s.y3);
|
|
1052
|
-
c2d.stroke();
|
|
1053
|
-
}
|
|
1054
|
-
function endpointAnchor(widget, portId) {
|
|
1055
|
-
if (widget === void 0) return void 0;
|
|
1056
|
-
const rect = readRect(world, widget);
|
|
1057
|
-
if (rect === void 0) return void 0;
|
|
1058
|
-
const type = world.get(widget, PrefabId)?.id;
|
|
1059
|
-
if (typeof type !== "string") return void 0;
|
|
1060
|
-
const wt = widgets.get(type);
|
|
1061
|
-
if (wt === void 0) return void 0;
|
|
1062
|
-
const slot = slotOf(wt, portId);
|
|
1063
|
-
if (slot === void 0) return void 0;
|
|
1064
|
-
return { anchor: rect, slot };
|
|
1065
|
-
}
|
|
1066
|
-
function drawWires(c2d, cam) {
|
|
1067
|
-
world.query(wireQ).each((batch) => {
|
|
1068
|
-
for (const r of batch) {
|
|
1069
|
-
const wire = batch.entity(r);
|
|
1070
|
-
const ports = world.get(wire, WirePorts);
|
|
1071
|
-
if (ports === void 0) continue;
|
|
1072
|
-
const from = endpointAnchor(world.getRelation(wire, WireFrom), ports.from ?? "");
|
|
1073
|
-
const to = endpointAnchor(world.getRelation(wire, WireTo), ports.to ?? "");
|
|
1074
|
-
if (from === void 0 || to === void 0) continue;
|
|
1075
|
-
const a0 = portAnchor(from.anchor, from.slot);
|
|
1076
|
-
const a1 = portAnchor(to.anchor, to.slot);
|
|
1077
|
-
const cubic = wireCubic(a0, from.slot.side, a1, to.slot.side);
|
|
1078
|
-
const selected = world.hasTag(wire, Selected);
|
|
1079
|
-
c2d.strokeStyle = selected ? config.selectedColor : config.wireColor;
|
|
1080
|
-
c2d.lineWidth = selected ? config.selectedWidth : config.wireWidth;
|
|
1081
|
-
c2d.setLineDash([]);
|
|
1082
|
-
strokeCubic(c2d, cubicToScreen(cubic, cam));
|
|
1083
|
-
}
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
function drawPreview(c2d, cam, preview) {
|
|
1087
|
-
if (!preview.active) return;
|
|
1088
|
-
const stub = Math.max(24, Math.abs(preview.tx - preview.sx) * 0.5);
|
|
1089
|
-
const cubic = {
|
|
1090
|
-
x0: preview.sx,
|
|
1091
|
-
y0: preview.sy,
|
|
1092
|
-
x1: preview.sx + stub,
|
|
1093
|
-
y1: preview.sy,
|
|
1094
|
-
x2: preview.tx - stub,
|
|
1095
|
-
y2: preview.ty,
|
|
1096
|
-
x3: preview.tx,
|
|
1097
|
-
y3: preview.ty
|
|
1098
|
-
};
|
|
1099
|
-
c2d.strokeStyle = preview.compatible ? config.selectedColor : config.wireColor;
|
|
1100
|
-
c2d.lineWidth = config.wireWidth;
|
|
1101
|
-
c2d.setLineDash(preview.compatible ? [] : [6, 4]);
|
|
1102
|
-
strokeCubic(c2d, cubicToScreen(cubic, cam));
|
|
1103
|
-
c2d.setLineDash([]);
|
|
1104
|
-
}
|
|
1105
|
-
function drawPorts(c2d, cam) {
|
|
1106
|
-
const connecting = world.firstOf(routedConnectQ) !== void 0;
|
|
1107
|
-
c2d.fillStyle = connecting ? config.portActiveColor : config.portColor;
|
|
1108
|
-
world.query(portQ).each((batch) => {
|
|
1109
|
-
const ax = batch.col(PortAnchor).x;
|
|
1110
|
-
const ay = batch.col(PortAnchor).y;
|
|
1111
|
-
for (const r of batch) {
|
|
1112
|
-
const s = worldToScreen(ax[r], ay[r], cam);
|
|
1113
|
-
c2d.beginPath();
|
|
1114
|
-
c2d.arc(s.x, s.y, config.portRadius, 0, Math.PI * 2);
|
|
1115
|
-
c2d.fill();
|
|
1116
|
-
}
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
function redraw(c2d, cam, preview) {
|
|
1120
|
-
c2d.setTransform(1, 0, 0, 1, 0, 0);
|
|
1121
|
-
c2d.clearRect(0, 0, canvas.width, canvas.height);
|
|
1122
|
-
c2d.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
1123
|
-
redraws++;
|
|
1124
|
-
drawWires(c2d, cam);
|
|
1125
|
-
drawPreview(c2d, cam, preview);
|
|
1126
|
-
drawPorts(c2d, cam);
|
|
1127
|
-
}
|
|
1128
|
-
return {
|
|
1129
|
-
name: "wires",
|
|
1130
|
-
// The preview buffer has no ECS stamp; self-gate on a private dirty flag
|
|
1131
|
-
// (chrome/dom-widgets pattern) rather than the registry's observe dirt.
|
|
1132
|
-
always: true,
|
|
1133
|
-
flush(w) {
|
|
1134
|
-
if (ctx === null) return;
|
|
1135
|
-
const cam = w.getResource(Camera);
|
|
1136
|
-
if (cam === void 0) return;
|
|
1137
|
-
const preview = readPreview();
|
|
1138
|
-
const previewKey = preview.active ? `${preview.sx},${preview.sy},${preview.tx},${preview.ty},${preview.compatible ? 1 : 0}` : "";
|
|
1139
|
-
if (previewKey !== lastPreviewKey) {
|
|
1140
|
-
lastPreviewKey = previewKey;
|
|
1141
|
-
dirty = true;
|
|
1142
|
-
}
|
|
1143
|
-
if (!dirty) return;
|
|
1144
|
-
dirty = false;
|
|
1145
|
-
try {
|
|
1146
|
-
redraw(ctx, cam, preview);
|
|
1147
|
-
} catch {
|
|
1148
|
-
ctx = null;
|
|
1149
|
-
}
|
|
1150
|
-
},
|
|
1151
|
-
available: () => ctx !== null,
|
|
1152
|
-
redraws: () => redraws,
|
|
1153
|
-
dispose() {
|
|
1154
|
-
for (const u of unsubs) u();
|
|
1155
|
-
unsubs.length = 0;
|
|
1156
|
-
ro?.disconnect();
|
|
1157
|
-
ro = null;
|
|
1158
|
-
canvas.remove();
|
|
1159
|
-
}
|
|
1160
|
-
};
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
759
|
// ../dom/src/reflectors/chrome.ts
|
|
1164
760
|
var HANDLE_DRAW_PX = 8;
|
|
1165
761
|
var boxQ = defineQuery([SelectionBox]);
|
|
@@ -1219,7 +815,7 @@ function createChromeReflector(host, _world, marqueeBuffer) {
|
|
|
1219
815
|
const tl = worldToScreen(bx[r], by[r], cam);
|
|
1220
816
|
const sw = bw[r] * cam.zoom;
|
|
1221
817
|
const sh = bh[r] * cam.zoom;
|
|
1222
|
-
const key = `${tl.x}:${tl.y}:${sw}:${sh}`;
|
|
818
|
+
const key = `${tl.x}:${tl.y}:${sw}:${sh}:${cam.zoom}`;
|
|
1223
819
|
let node = boxNodes.get(e);
|
|
1224
820
|
if (node === void 0) {
|
|
1225
821
|
node = makeNode(doc, { border: "1px solid #4a90d9" });
|
|
@@ -1229,6 +825,7 @@ function createChromeReflector(host, _world, marqueeBuffer) {
|
|
|
1229
825
|
}
|
|
1230
826
|
if (boxCache.get(e) !== key) {
|
|
1231
827
|
writeRect(node, tl.x, tl.y, sw, sh);
|
|
828
|
+
node.style.borderRadius = `calc(var(--ic-selection-radius, 0px) * ${cam.zoom})`;
|
|
1232
829
|
boxCache.set(e, key);
|
|
1233
830
|
}
|
|
1234
831
|
}
|
|
@@ -1361,8 +958,7 @@ function attachMeasureAdapter(hostFor, queue) {
|
|
|
1361
958
|
|
|
1362
959
|
// ../dom/src/measure-wiring.ts
|
|
1363
960
|
function defaultMeasure(el) {
|
|
1364
|
-
|
|
1365
|
-
return { w: rect.width, h: rect.height };
|
|
961
|
+
return { w: el.offsetWidth, h: el.offsetHeight };
|
|
1366
962
|
}
|
|
1367
963
|
function wireMeasurement(store, hosts, queue, opts = {}) {
|
|
1368
964
|
const adapter = attachMeasureAdapter((e) => hosts.hostFor(e), queue);
|
|
@@ -1434,13 +1030,9 @@ export {
|
|
|
1434
1030
|
attachPointerAdapter,
|
|
1435
1031
|
createCursorReflector,
|
|
1436
1032
|
createRemoteCursorsReflector,
|
|
1437
|
-
DEFAULT_GRID_CONFIG,
|
|
1438
|
-
createGridReflector,
|
|
1439
|
-
DEFAULT_WIRES_CONFIG,
|
|
1440
|
-
createWiresReflector,
|
|
1441
1033
|
createChromeReflector,
|
|
1442
1034
|
attachMeasureAdapter,
|
|
1443
1035
|
wireMeasurement,
|
|
1444
1036
|
DOM_VERSION
|
|
1445
1037
|
};
|
|
1446
|
-
//# sourceMappingURL=chunk-
|
|
1038
|
+
//# sourceMappingURL=chunk-PKK6GLSA.js.map
|