@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.
Files changed (119) hide show
  1. package/README.md +37 -2
  2. package/dist/chunk-2GUYATUM.js +643 -0
  3. package/dist/chunk-2GUYATUM.js.map +1 -0
  4. package/dist/{chunk-5S7GSXJG.js → chunk-5QY7HK6G.js} +3145 -1306
  5. package/dist/chunk-5QY7HK6G.js.map +1 -0
  6. package/dist/{chunk-BCJ47SX7.js → chunk-OR5FNVUE.js} +460 -1
  7. package/dist/chunk-OR5FNVUE.js.map +1 -0
  8. package/dist/{chunk-FIAXPNNY.js → chunk-PKK6GLSA.js} +143 -551
  9. package/dist/chunk-PKK6GLSA.js.map +1 -0
  10. package/dist/devtools.js +508 -372
  11. package/dist/devtools.js.map +1 -1
  12. package/dist/dom.js +3 -11
  13. package/dist/ground.js +715 -0
  14. package/dist/ground.js.map +1 -0
  15. package/dist/index.js +80 -2
  16. package/dist/kernel.js +31 -1
  17. package/dist/r3f.js +605 -62
  18. package/dist/r3f.js.map +1 -1
  19. package/dist/react.js +36 -418
  20. package/dist/react.js.map +1 -1
  21. package/dist/types/packages/core/src/catalog/camera-derived.d.ts +65 -3
  22. package/dist/types/packages/core/src/catalog/gesture.d.ts +40 -4
  23. package/dist/types/packages/core/src/catalog/graph.d.ts +7 -6
  24. package/dist/types/packages/core/src/catalog/index.d.ts +1 -0
  25. package/dist/types/packages/core/src/catalog/insert.d.ts +31 -0
  26. package/dist/types/packages/core/src/catalog/pointer.d.ts +11 -0
  27. package/dist/types/packages/core/src/catalog/scene.d.ts +37 -4
  28. package/dist/types/packages/core/src/catalog/selection-presence.d.ts +7 -0
  29. package/dist/types/packages/core/src/catalog/settings-resources.d.ts +21 -0
  30. package/dist/types/packages/core/src/doc/autosave.d.ts +49 -2
  31. package/dist/types/packages/core/src/doc/bootstrap.d.ts +29 -0
  32. package/dist/types/packages/core/src/doc/channels.d.ts +9 -0
  33. package/dist/types/packages/core/src/doc/doc-commit-sink.d.ts +2 -1
  34. package/dist/types/packages/core/src/doc/doc-kit.d.ts +16 -1
  35. package/dist/types/packages/core/src/doc/envelope.d.ts +2 -1
  36. package/dist/types/packages/core/src/doc/migrate.d.ts +8 -6
  37. package/dist/types/packages/core/src/doc/schema-migrate.d.ts +50 -0
  38. package/dist/types/packages/core/src/doc/version-gate.d.ts +3 -0
  39. package/dist/types/packages/core/src/engine/commit-sink.d.ts +24 -2
  40. package/dist/types/packages/core/src/engine/engine.d.ts +11 -0
  41. package/dist/types/packages/core/src/engine/frame-control.d.ts +71 -0
  42. package/dist/types/packages/core/src/engine/frame-info.d.ts +16 -1
  43. package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +79 -6
  44. package/dist/types/packages/core/src/guards/guarded-tx.d.ts +4 -2
  45. package/dist/types/packages/core/src/helpers/churn-guard.d.ts +40 -0
  46. package/dist/types/packages/core/src/index.d.ts +15 -7
  47. package/dist/types/packages/core/src/input/queue.d.ts +11 -0
  48. package/dist/types/packages/core/src/interaction/gesture-status.d.ts +13 -0
  49. package/dist/types/packages/core/src/nav/nested-canvas.d.ts +47 -11
  50. package/dist/types/packages/core/src/ops/arrange.d.ts +15 -0
  51. package/dist/types/packages/core/src/ops/insert.d.ts +62 -0
  52. package/dist/types/packages/core/src/ops/point-pick.d.ts +11 -7
  53. package/dist/types/packages/core/src/ops/sibling-order.d.ts +70 -0
  54. package/dist/types/packages/core/src/schema/meta.d.ts +1 -0
  55. package/dist/types/packages/core/src/settings/defaults.d.ts +45 -0
  56. package/dist/types/packages/core/src/settings/ground-config.d.ts +55 -0
  57. package/dist/types/packages/core/src/systems/chrome.d.ts +6 -2
  58. package/dist/types/packages/core/src/systems/insert-ghost.d.ts +25 -0
  59. package/dist/types/packages/core/src/systems/l1-pick.d.ts +25 -11
  60. package/dist/types/packages/core/src/systems/l2-recognize.d.ts +10 -4
  61. package/dist/types/packages/core/src/systems/l3-behave.d.ts +6 -4
  62. package/dist/types/packages/core/src/systems/l3-claim.d.ts +7 -3
  63. package/dist/types/packages/core/src/systems/l3-drop.d.ts +3 -1
  64. package/dist/types/packages/core/src/systems/l3-resize.d.ts +3 -1
  65. package/dist/types/packages/core/src/systems/l3-snap.d.ts +25 -7
  66. package/dist/types/packages/core/src/systems/nav-flight.d.ts +95 -0
  67. package/dist/types/packages/core/src/widget/define-widget.d.ts +39 -0
  68. package/dist/types/packages/core/src/widget/mount-store.d.ts +11 -3
  69. package/dist/types/packages/core/src/widget/set-props.d.ts +16 -0
  70. package/dist/types/packages/core/src/widget/spawn.d.ts +21 -1
  71. package/dist/types/packages/devtools/src/attach.d.ts +77 -0
  72. package/dist/types/packages/devtools/src/dock.d.ts +38 -0
  73. package/dist/types/packages/devtools/src/gl-panel.d.ts +69 -0
  74. package/dist/types/packages/devtools/src/index.d.ts +8 -6
  75. package/dist/types/packages/dom/src/index.d.ts +1 -3
  76. package/dist/types/packages/dom/src/loop.d.ts +11 -0
  77. package/dist/types/packages/dom/src/measure-wiring.d.ts +2 -2
  78. package/dist/types/packages/dom/src/pointer-adapter.d.ts +21 -1
  79. package/dist/types/packages/dom/src/reflectors/dom-widgets.d.ts +5 -0
  80. package/dist/types/packages/ground/src/index.d.ts +52 -0
  81. package/dist/types/packages/ground/src/layer.d.ts +40 -0
  82. package/dist/types/packages/ground/src/pass.d.ts +41 -0
  83. package/dist/types/packages/ground/src/passes/grid.d.ts +21 -0
  84. package/dist/types/packages/ground/src/passes/guides-collect.d.ts +14 -0
  85. package/dist/types/packages/ground/src/passes/guides.d.ts +3 -0
  86. package/dist/types/packages/ground/src/passes/soup-collect.d.ts +35 -0
  87. package/dist/types/packages/ground/src/passes/soup-mesh.d.ts +8 -0
  88. package/dist/types/packages/ground/src/passes/wires-collect.d.ts +31 -0
  89. package/dist/types/packages/ground/src/passes/wires.d.ts +10 -0
  90. package/dist/types/packages/ground/src/renderer.d.ts +15 -0
  91. package/dist/types/packages/ice/src/ground.d.ts +1 -0
  92. package/dist/types/packages/kernel/src/bezier.d.ts +15 -0
  93. package/dist/types/packages/kernel/src/coords.d.ts +15 -0
  94. package/dist/types/packages/kernel/src/easing.d.ts +11 -0
  95. package/dist/types/packages/kernel/src/index.d.ts +3 -0
  96. package/dist/types/packages/kernel/src/layout.d.ts +118 -0
  97. package/dist/types/packages/kernel/src/nav-flight.d.ts +93 -0
  98. package/dist/types/packages/r3f/src/bridge.d.ts +73 -12
  99. package/dist/types/packages/r3f/src/composite-material.d.ts +9 -0
  100. package/dist/types/packages/r3f/src/compositor-pass.d.ts +22 -0
  101. package/dist/types/packages/r3f/src/gl-root.d.ts +76 -1
  102. package/dist/types/packages/r3f/src/gl-router.d.ts +10 -0
  103. package/dist/types/packages/r3f/src/index.d.ts +3 -2
  104. package/dist/types/packages/r3f/src/island-state.d.ts +44 -0
  105. package/dist/types/packages/r3f/src/preview-capture.d.ts +19 -0
  106. package/dist/types/packages/r3f/src/self-sustain.d.ts +39 -0
  107. package/dist/types/packages/r3f/src/use-island-frame.d.ts +16 -1
  108. package/dist/types/packages/react/src/engine-context.d.ts +21 -0
  109. package/dist/types/packages/react/src/index.d.ts +4 -2
  110. package/dist/types/packages/react/src/infinite-canvas.d.ts +40 -6
  111. package/dist/types/packages/react/src/preview-snapshots.d.ts +17 -0
  112. package/dist/types/packages/react/src/widget-preview.d.ts +14 -0
  113. package/package.json +32 -61
  114. package/dist/chunk-5S7GSXJG.js.map +0 -1
  115. package/dist/chunk-BCJ47SX7.js.map +0 -1
  116. package/dist/chunk-FIAXPNNY.js.map +0 -1
  117. package/dist/types/packages/devtools/src/panel.d.ts +0 -48
  118. package/dist/types/packages/dom/src/reflectors/grid.d.ts +0 -63
  119. 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
- Port,
10
- PortAnchor,
9
+ Opacity,
11
10
  Position,
12
11
  PrefabId,
13
12
  PresenceInfo,
14
- RoutedConnect,
15
- Selected,
16
13
  SelectionBox,
17
14
  Size,
18
- Wire,
19
- WireFrom,
20
- WirePorts,
21
- WireTo,
15
+ compareStackOrder,
16
+ createSiblingOrderIndex,
22
17
  defineQuery,
23
18
  widgets
24
- } from "./chunk-5S7GSXJG.js";
19
+ } from "./chunk-5QY7HK6G.js";
25
20
  import {
26
21
  planeCssTransform,
27
- portAnchor,
28
- wireCubic,
29
22
  worldToScreen
30
- } from "./chunk-BCJ47SX7.js";
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 prop of Object.keys(CONTAINER_STYLE)) {
61
- container.style.removeProperty(
62
- // camelCase → kebab-case for removeProperty (touchAction → touch-action).
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 lifted = world.has(e, Grab);
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 shouldLift = world.has(e, Grab);
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 glClaimed = glRoute?.("down", x, y, e) === true;
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
- const seen = live.get(id);
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 glHandled = glRoute?.("move", x, y, e) === true;
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
- ...glHandled ? { surfaceHandled: true } : {}
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 glHandled = glRoute?.(kind, x, y, e) === true;
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
- ...glHandled ? { surfaceHandled: true } : {}
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 onBlur = () => {
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
- const rect = el.getBoundingClientRect();
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-FIAXPNNY.js.map
1038
+ //# sourceMappingURL=chunk-PKK6GLSA.js.map