@vibecook/ice 0.3.0 → 0.4.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 (31) hide show
  1. package/dist/{chunk-PKK6GLSA.js → chunk-3PHPWRB2.js} +133 -11
  2. package/dist/chunk-3PHPWRB2.js.map +1 -0
  3. package/dist/{chunk-5QY7HK6G.js → chunk-7LZAXQAO.js} +333 -51
  4. package/dist/chunk-7LZAXQAO.js.map +1 -0
  5. package/dist/{chunk-2GUYATUM.js → chunk-ENMRSITH.js} +31 -11
  6. package/dist/chunk-ENMRSITH.js.map +1 -0
  7. package/dist/devtools.js +1 -1
  8. package/dist/dom.js +16 -2
  9. package/dist/ground.js +1 -1
  10. package/dist/index.js +7 -1
  11. package/dist/r3f.js +3 -3
  12. package/dist/react.js +3 -3
  13. package/dist/types/packages/core/src/catalog/pointer.d.ts +11 -0
  14. package/dist/types/packages/core/src/catalog/selection-presence.d.ts +10 -0
  15. package/dist/types/packages/core/src/doc/rename-sweep.d.ts +3 -0
  16. package/dist/types/packages/core/src/doc/rename.d.ts +7 -0
  17. package/dist/types/packages/core/src/doc/version-gate.d.ts +14 -1
  18. package/dist/types/packages/core/src/index.d.ts +1 -1
  19. package/dist/types/packages/core/src/input/queue.d.ts +9 -0
  20. package/dist/types/packages/core/src/schema/meta.d.ts +12 -0
  21. package/dist/types/packages/core/src/widget/define-widget.d.ts +61 -0
  22. package/dist/types/packages/dom/src/index.d.ts +2 -0
  23. package/dist/types/packages/dom/src/input-ownership.d.ts +52 -0
  24. package/dist/types/packages/dom/src/pointer-adapter.d.ts +16 -3
  25. package/dist/types/packages/dom/src/widget-focus.d.ts +58 -0
  26. package/dist/types/packages/react/src/infinite-canvas.d.ts +20 -2
  27. package/dist/types/packages/react/src/keymap.d.ts +23 -4
  28. package/package.json +61 -27
  29. package/dist/chunk-2GUYATUM.js.map +0 -1
  30. package/dist/chunk-5QY7HK6G.js.map +0 -1
  31. package/dist/chunk-PKK6GLSA.js.map +0 -1
@@ -43,6 +43,7 @@ import {
43
43
  defineTag as strataDefineTag
44
44
  } from "@vibecook/strata-ecs";
45
45
  var componentMeta = /* @__PURE__ */ new Map();
46
+ var componentsByIceName = /* @__PURE__ */ new Map();
46
47
  var tagNames = /* @__PURE__ */ new Map();
47
48
  var relationMeta = /* @__PURE__ */ new Map();
48
49
  var resourceMeta = /* @__PURE__ */ new Map();
@@ -62,8 +63,18 @@ function defineComponent(name, schema) {
62
63
  eidFields: fields.filter(([, f]) => isEidField(f)).map(([k]) => k),
63
64
  requiredFields: fields.filter(([, f]) => !hasDefault(f)).map(([k]) => k)
64
65
  });
66
+ componentsByIceName.set(name, c);
65
67
  return c;
66
68
  }
69
+ function ensureComponent(name, schema) {
70
+ const existing = componentsByIceName.get(name);
71
+ if (existing === void 0) return defineComponent(name, schema);
72
+ const recorded = componentMeta.get(existing);
73
+ if (recorded === void 0 || JSON.stringify(recorded.schema) !== JSON.stringify(schema)) {
74
+ throw new Error(`ice: ensureComponent("${name}") \u2014 a component with this name exists with a DIFFERENT shape.`);
75
+ }
76
+ return existing;
77
+ }
67
78
  function defineTag(name) {
68
79
  const t = strataDefineTag(name);
69
80
  tagNames.set(t, name);
@@ -837,6 +848,7 @@ var WentDown = defineTag("WentDown");
837
848
  var WentUp = defineTag("WentUp");
838
849
  var WentCancelled = defineTag("WentCancelled");
839
850
  var HandledByWidget = defineTag("HandledByWidget");
851
+ var WheelHandled = defineTag("WheelHandled");
840
852
  var OverInteractive = defineTag("OverInteractive");
841
853
  var LocalPointer = defineTag("LocalPointer");
842
854
  var PointerWorld = defineComponent("PointerWorld", {
@@ -1025,6 +1037,7 @@ var Resizable = defineTag("Resizable");
1025
1037
  var SnapSource = defineTag("SnapSource");
1026
1038
  var SnapTarget = defineTag("SnapTarget");
1027
1039
  var SweepsContained = defineTag("SweepsContained");
1040
+ var KeyboardExclusive = defineTag("KeyboardExclusive");
1028
1041
  var PresencePeer = defineTag("PresencePeer");
1029
1042
  var PresenceInfo = defineComponent("PresenceInfo", { name: "string", color: "string" });
1030
1043
  var PresenceCursor = defineComponent("PresenceCursor", {
@@ -1106,6 +1119,7 @@ function makeVersionGuard(world, resources) {
1106
1119
  import { field as field10, enumOf as enumOf6 } from "@vibecook/strata-ecs";
1107
1120
  var WidgetEquipped = defineTag("WidgetEquipped");
1108
1121
  var registry2 = /* @__PURE__ */ new Map();
1122
+ var renameRegistry = /* @__PURE__ */ new Map();
1109
1123
  var widgets = {
1110
1124
  get(type) {
1111
1125
  return registry2.get(type);
@@ -1114,6 +1128,14 @@ var widgets = {
1114
1128
  return [...registry2.values()];
1115
1129
  }
1116
1130
  };
1131
+ var renames = {
1132
+ get(oldType) {
1133
+ return renameRegistry.get(oldType);
1134
+ },
1135
+ all() {
1136
+ return [...renameRegistry.values()];
1137
+ }
1138
+ };
1117
1139
  function normalizeProps(props) {
1118
1140
  if (props === void 0) return {};
1119
1141
  if ("kind" in props && props.kind === "object") {
@@ -1204,11 +1226,35 @@ function defineWidget(def) {
1204
1226
  fields[name] = spec;
1205
1227
  }
1206
1228
  const groups = [];
1229
+ const rawByGroup = /* @__PURE__ */ new Map();
1207
1230
  for (const [g, fields] of byGroup) {
1208
1231
  const raw = {};
1209
1232
  for (const [name, spec] of Object.entries(fields)) raw[name] = strataFieldOf(name, spec);
1233
+ rawByGroup.set(g, raw);
1210
1234
  groups.push({ name: g, component: defineComponent(`${def.type}:${g}`, raw), fields });
1211
1235
  }
1236
+ const renameDecls = def.renamedFrom ?? [];
1237
+ const legacyByOld = /* @__PURE__ */ new Map();
1238
+ for (const decl of renameDecls) {
1239
+ if (decl.type === def.type) {
1240
+ throw new Error(`ice: widget "${def.type}" lists itself in renamedFrom.`);
1241
+ }
1242
+ if (registry2.has(decl.type)) {
1243
+ throw new Error(`ice: widget "${def.type}" renamedFrom "${decl.type}" \u2014 that type is still a registered widget.`);
1244
+ }
1245
+ const holder = renameRegistry.get(decl.type);
1246
+ if (holder !== void 0 && holder.widget.type !== def.type) {
1247
+ throw new Error(`ice: widget "${def.type}" renamedFrom "${decl.type}" \u2014 already claimed by "${holder.widget.type}".`);
1248
+ }
1249
+ if (legacyByOld.has(decl.type)) {
1250
+ throw new Error(`ice: widget "${def.type}" lists renamedFrom "${decl.type}" twice.`);
1251
+ }
1252
+ const legacy = [];
1253
+ for (const g of groups) {
1254
+ legacy.push(ensureComponent(`${decl.type}:${g.name}`, rawByGroup.get(g.name)));
1255
+ }
1256
+ legacyByOld.set(decl.type, legacy);
1257
+ }
1212
1258
  const defaultSize = def.defaultSize ?? { w: 240, h: 160 };
1213
1259
  const essential = [
1214
1260
  init(Position, { x: 0, y: 0 }),
@@ -1262,6 +1308,7 @@ function defineWidget(def) {
1262
1308
  if (interaction.solid === true) capabilityTags.push(Solid);
1263
1309
  if (interaction.dragOn === "longPress") capabilityTags.push(LongPressDrag);
1264
1310
  if (interaction.sweepContained === true) capabilityTags.push(SweepsContained);
1311
+ if (interaction.keyboard === "exclusive") capabilityTags.push(KeyboardExclusive);
1265
1312
  const snap = interaction.snap ?? "target";
1266
1313
  if (snap === "source" || snap === "both") capabilityTags.push(SnapSource);
1267
1314
  if (snap === "target" || snap === "both") capabilityTags.push(SnapTarget);
@@ -1281,11 +1328,21 @@ function defineWidget(def) {
1281
1328
  animated: def.animated === true,
1282
1329
  ports: def.ports ?? [],
1283
1330
  capabilityTags,
1331
+ keyboard: interaction.keyboard ?? "shared",
1332
+ keyboardEscape: interaction.keyboardEscape ?? "release",
1284
1333
  migrate: def.migrate ?? {},
1285
1334
  previewComponent: previewDecl.component,
1286
1335
  ...previewDecl.props !== void 0 ? { previewProps: previewDecl.props } : {}
1287
1336
  };
1288
1337
  registry2.set(def.type, widget);
1338
+ for (const decl of renameDecls) {
1339
+ renameRegistry.set(decl.type, {
1340
+ widget,
1341
+ oldType: decl.type,
1342
+ atVersion: decl.atVersion ?? 1,
1343
+ legacyGroups: legacyByOld.get(decl.type)
1344
+ });
1345
+ }
1289
1346
  return widget;
1290
1347
  }
1291
1348
 
@@ -2476,7 +2533,7 @@ var DEFAULT_SPAWN_PROFILES = {
2476
2533
  var anyKindQ = defineQuery7([Any(Tap, LongPress, Drag, Pinch, WheelPan, WheelZoom)]);
2477
2534
  var downQ = defineQuery7([Pointer, WentDown, Not(HandledByWidget), LocalPointer]);
2478
2535
  var heldTouchQ = defineQuery7([Pointer, PointerButtons, LocalPointer]);
2479
- var wheelSourceQ = defineQuery7([Pointer, PointerWheel, LocalPointer]);
2536
+ var wheelSourceQ = defineQuery7([Pointer, PointerWheel, LocalPointer, Not(WheelHandled)]);
2480
2537
  var tapQ = defineQuery7([Tap, Not(GestureSuspended)]);
2481
2538
  var longPressQ = defineQuery7([LongPress, Not(GestureSuspended)]);
2482
2539
  var dragQ = defineQuery7([Drag, Not(GestureSuspended)]);
@@ -2910,7 +2967,8 @@ function createL2Systems({ world, profiles = DEFAULT_SPAWN_PROFILES }) {
2910
2967
  const screen = ctx.read(pointer, PointerScreen);
2911
2968
  const down = ctx.read(e, Down);
2912
2969
  const isZoom = ctx.has(e, WheelZoom);
2913
- const active = isZoom ? wheel.pinch !== 0 : wheel.dx !== 0 || wheel.dy !== 0;
2970
+ const ceded = ctx.hasTag(pointer, WheelHandled);
2971
+ const active = !ceded && (isZoom ? wheel.pinch !== 0 : wheel.dx !== 0 || wheel.dy !== 0);
2914
2972
  if (active) {
2915
2973
  if (isZoom) {
2916
2974
  ctx.edit(e).set(WheelZoom, { pinch: wheel.pinch, anchorX: screen.x, anchorY: screen.y });
@@ -3863,6 +3921,7 @@ function createCleanupSystems(world) {
3863
3921
  if (ctx.hasTag(e, WentUp)) ctx.removeTag(e, WentUp);
3864
3922
  if (ctx.hasTag(e, WentCancelled)) ctx.removeTag(e, WentCancelled);
3865
3923
  if (ctx.hasTag(e, HandledByWidget)) ctx.removeTag(e, HandledByWidget);
3924
+ if (ctx.hasTag(e, WheelHandled)) ctx.removeTag(e, WheelHandled);
3866
3925
  const w = ctx.read(e, PointerWheel);
3867
3926
  if (w.dx !== 0 || w.dy !== 0 || w.pinch !== 0) {
3868
3927
  ctx.edit(e).set(PointerWheel, { dx: 0, dy: 0, pinch: 0 });
@@ -3956,7 +4015,8 @@ function createL0Systems(world, queue) {
3956
4015
  wheelDx: 0,
3957
4016
  wheelDy: 0,
3958
4017
  wheelPinch: 0,
3959
- hasWheel: false
4018
+ hasWheel: false,
4019
+ wheelHandled: false
3960
4020
  };
3961
4021
  samples.set(ev.pointerId, s);
3962
4022
  }
@@ -3978,6 +4038,7 @@ function createL0Systems(world, queue) {
3978
4038
  s.wheelDy += ev.wheel.dy;
3979
4039
  s.wheelPinch += ev.wheel.pinch;
3980
4040
  s.hasWheel = true;
4041
+ if (ev.wheelHandled === true) s.wheelHandled = true;
3981
4042
  }
3982
4043
  if (ev.surfaceHandled === true) s.handled = true;
3983
4044
  if (ev.overInteractive !== void 0) s.overInteractive = ev.overInteractive;
@@ -4002,6 +4063,7 @@ function createL0Systems(world, queue) {
4002
4063
  if (s.wentUp) ctx.addTag(spawned, WentUp);
4003
4064
  if (s.wentCancelled) ctx.addTag(spawned, WentCancelled);
4004
4065
  if (s.handled) ctx.addTag(spawned, HandledByWidget);
4066
+ if (s.wheelHandled) ctx.addTag(spawned, WheelHandled);
4005
4067
  if (s.overInteractive === true) ctx.addTag(spawned, OverInteractive);
4006
4068
  byId.set(id, spawned);
4007
4069
  continue;
@@ -4027,6 +4089,7 @@ function createL0Systems(world, queue) {
4027
4089
  if (s.wentUp) ctx.addTag(existing, WentUp);
4028
4090
  if (s.wentCancelled) ctx.addTag(existing, WentCancelled);
4029
4091
  if (s.handled) ctx.addTag(existing, HandledByWidget);
4092
+ if (s.wheelHandled) ctx.addTag(existing, WheelHandled);
4030
4093
  if (s.overInteractive !== void 0 && s.overInteractive !== ctx.hasTag(existing, OverInteractive)) {
4031
4094
  if (s.overInteractive) ctx.addTag(existing, OverInteractive);
4032
4095
  else ctx.removeTag(existing, OverInteractive);
@@ -5467,6 +5530,7 @@ function decodeEnvelope(bytes) {
5467
5530
  // ../core/src/doc/version-gate.ts
5468
5531
  var SCHEMA_PREFIX = "engine.schema.";
5469
5532
  var PACK_PREFIX = "engine.pack.";
5533
+ var RENAMED_PREFIX = "engine.renamed.";
5470
5534
  function stampEngineMeta(store) {
5471
5535
  store.metaTransaction((meta) => {
5472
5536
  const stamp = (key) => {
@@ -5479,14 +5543,50 @@ function stampEngineMeta(store) {
5479
5543
  }
5480
5544
  });
5481
5545
  }
5546
+ function foldRenames(rawPacks, tombstoned) {
5547
+ const docPacks = {};
5548
+ const renamedInDoc = {};
5549
+ for (const [id, v] of Object.entries(rawPacks)) {
5550
+ if (tombstoned.has(id)) continue;
5551
+ const rename = renames.get(id);
5552
+ if (rename !== void 0) {
5553
+ renamedInDoc[id] = Math.max(renamedInDoc[id] ?? 0, v);
5554
+ const target = rename.widget.type;
5555
+ docPacks[target] = Math.max(docPacks[target] ?? 0, v);
5556
+ continue;
5557
+ }
5558
+ docPacks[id] = Math.max(docPacks[id] ?? 0, v);
5559
+ }
5560
+ return { docPacks, renamedInDoc };
5561
+ }
5562
+ function compare(docPacks, localPacks) {
5563
+ const newerInDoc = [];
5564
+ const olderInDoc = [];
5565
+ for (const [id, v] of Object.entries(docPacks)) {
5566
+ const local = localPacks[id];
5567
+ if (local === void 0 || v > local) newerInDoc.push(id);
5568
+ else if (v < local) olderInDoc.push(id);
5569
+ }
5570
+ return { newerInDoc, olderInDoc };
5571
+ }
5572
+ function localPackVersions() {
5573
+ const localPacks = {};
5574
+ for (const p2 of prefabs.all()) {
5575
+ if (p2.store === "durable") localPacks[p2.id] = p2.version ?? 1;
5576
+ }
5577
+ return localPacks;
5578
+ }
5482
5579
  function readDocVersionReport(doc) {
5483
5580
  const meta = doc.getMap("meta");
5484
5581
  let docSchema = 0;
5485
- const docPacks = {};
5582
+ const rawPacks = {};
5583
+ const tombstoned = /* @__PURE__ */ new Set();
5486
5584
  for (const key of meta.keys()) {
5487
5585
  if (key.startsWith(SCHEMA_PREFIX)) {
5488
5586
  const n = Number(key.slice(SCHEMA_PREFIX.length));
5489
5587
  if (Number.isInteger(n) && n > docSchema) docSchema = n;
5588
+ } else if (key.startsWith(RENAMED_PREFIX)) {
5589
+ tombstoned.add(key.slice(RENAMED_PREFIX.length));
5490
5590
  } else if (key.startsWith(PACK_PREFIX)) {
5491
5591
  const rest = key.slice(PACK_PREFIX.length);
5492
5592
  const dot = rest.lastIndexOf(".");
@@ -5494,49 +5594,35 @@ function readDocVersionReport(doc) {
5494
5594
  const id = rest.slice(0, dot);
5495
5595
  const v = Number(rest.slice(dot + 1));
5496
5596
  if (!Number.isInteger(v)) continue;
5497
- if ((docPacks[id] ?? 0) < v) docPacks[id] = v;
5597
+ if ((rawPacks[id] ?? 0) < v) rawPacks[id] = v;
5498
5598
  }
5499
5599
  }
5500
- const localPacks = {};
5501
- for (const p2 of prefabs.all()) {
5502
- if (p2.store === "durable") localPacks[p2.id] = p2.version ?? 1;
5503
- }
5504
- const newerInDoc = [];
5505
- const olderInDoc = [];
5506
- for (const [id, v] of Object.entries(docPacks)) {
5507
- const local = localPacks[id];
5508
- if (local === void 0 || v > local) newerInDoc.push(id);
5509
- else if (v < local) olderInDoc.push(id);
5510
- }
5511
- return { docSchema, localSchema: ENGINE_SCHEMA_VERSION, docPacks, localPacks, newerInDoc, olderInDoc };
5600
+ const localPacks = localPackVersions();
5601
+ const { docPacks, renamedInDoc } = foldRenames(rawPacks, tombstoned);
5602
+ const { newerInDoc, olderInDoc } = compare(docPacks, localPacks);
5603
+ return { docSchema, localSchema: ENGINE_SCHEMA_VERSION, docPacks, localPacks, newerInDoc, olderInDoc, renamedInDoc };
5512
5604
  }
5513
5605
  function readEnvelopeVersionReport(header) {
5514
- const localPacks = {};
5515
- for (const p2 of prefabs.all()) {
5516
- if (p2.store === "durable") localPacks[p2.id] = p2.version ?? 1;
5517
- }
5518
- const docPacks = { ...header.prefabVersions };
5519
- const newerInDoc = [];
5520
- const olderInDoc = [];
5521
- for (const [id, version] of Object.entries(docPacks)) {
5522
- const local = localPacks[id];
5523
- if (local === void 0 || version > local) newerInDoc.push(id);
5524
- else if (version < local) olderInDoc.push(id);
5525
- }
5606
+ const localPacks = localPackVersions();
5607
+ const { docPacks, renamedInDoc } = foldRenames(header.prefabVersions, /* @__PURE__ */ new Set());
5608
+ const { newerInDoc, olderInDoc } = compare(docPacks, localPacks);
5526
5609
  return {
5527
5610
  docSchema: header.engineSchema,
5528
5611
  localSchema: ENGINE_SCHEMA_VERSION,
5529
5612
  docPacks,
5530
5613
  localPacks,
5531
5614
  newerInDoc,
5532
- olderInDoc
5615
+ olderInDoc,
5616
+ renamedInDoc
5533
5617
  };
5534
5618
  }
5535
5619
  function gateVerdict(report) {
5536
5620
  if (report.docSchema === 0) return "reject";
5537
5621
  if (report.docSchema > report.localSchema) return "readOnly";
5538
5622
  if (report.newerInDoc.length > 0) return "readOnly";
5539
- if (report.docSchema < report.localSchema || report.olderInDoc.length > 0) return "migrate";
5623
+ if (report.docSchema < report.localSchema || report.olderInDoc.length > 0 || Object.keys(report.renamedInDoc).length > 0) {
5624
+ return "migrate";
5625
+ }
5540
5626
  return "ok";
5541
5627
  }
5542
5628
 
@@ -5620,11 +5706,200 @@ function runMigrations(ctx, report) {
5620
5706
  import { LoroDoc } from "loro-crdt";
5621
5707
  import { attachDurable, createDurableStore } from "@vibecook/strata-ecs/durable";
5622
5708
 
5623
- // ../core/src/doc/schema-migrate.ts
5709
+ // ../core/src/doc/rename.ts
5624
5710
  import { defineQuery as defineQuery27 } from "@vibecook/strata-ecs";
5711
+ var PACK_PREFIX3 = "engine.pack.";
5712
+ var RENAMED_PREFIX2 = "engine.renamed.";
5713
+ var allDurableQ2 = defineQuery27([PrefabId]);
5714
+ function runRenames(ctx, report) {
5715
+ const { store, world } = ctx;
5716
+ const renamed = [];
5717
+ for (const [oldId, docOldV] of Object.entries(report.renamedInDoc)) {
5718
+ const entry = renames.get(oldId);
5719
+ if (entry === void 0) continue;
5720
+ const { widget, legacyGroups } = entry;
5721
+ const plans = [];
5722
+ world.query(allDurableQ2).each((batch) => {
5723
+ for (const row of batch) {
5724
+ const e = batch.entity(row);
5725
+ if (world.read(e, PrefabId).id !== oldId) continue;
5726
+ const legacyValues = [];
5727
+ const newPresent = [];
5728
+ for (let i = 0; i < widget.groups.length; i++) {
5729
+ const legacy = world.get(e, legacyGroups[i]);
5730
+ legacyValues.push(legacy);
5731
+ newPresent.push(world.get(e, widget.groups[i].component) !== void 0);
5732
+ }
5733
+ plans.push({ e, legacyValues, newPresent });
5734
+ }
5735
+ });
5736
+ if (plans.length > 0) {
5737
+ store.transaction(
5738
+ (tx) => {
5739
+ for (const { e, legacyValues, newPresent } of plans) {
5740
+ tx.edit(e).set(PrefabId, { id: widget.type });
5741
+ for (let i = 0; i < widget.groups.length; i++) {
5742
+ const value = legacyValues[i];
5743
+ if (value === void 0) continue;
5744
+ if (!newPresent[i]) {
5745
+ tx.addComponent(e, widget.groups[i].component, value);
5746
+ }
5747
+ tx.removeComponent(e, legacyGroups[i]);
5748
+ }
5749
+ }
5750
+ },
5751
+ { undoable: false }
5752
+ );
5753
+ }
5754
+ store.metaTransaction((meta) => {
5755
+ const tomb = `${RENAMED_PREFIX2}${oldId}`;
5756
+ if (meta.get(tomb) === void 0) meta.set(tomb, widget.type);
5757
+ const pack = `${PACK_PREFIX3}${widget.type}.${docOldV}`;
5758
+ if (meta.get(pack) === void 0) meta.set(pack, true);
5759
+ });
5760
+ renamed.push(oldId);
5761
+ }
5762
+ return { renamed };
5763
+ }
5764
+
5765
+ // ../core/src/doc/rename-sweep.ts
5766
+ import { Any as Any5, defineQuery as defineQuery28 } from "@vibecook/strata-ecs";
5767
+ var RENAMED_PREFIX3 = "engine.renamed.";
5768
+ var prefabQ = defineQuery28([PrefabId]);
5769
+ var legacyQByEntry = /* @__PURE__ */ new WeakMap();
5770
+ function legacyQueryOf(entry) {
5771
+ if (entry.legacyGroups.length === 0) return void 0;
5772
+ let q = legacyQByEntry.get(entry);
5773
+ if (q === void 0) {
5774
+ q = entry.legacyGroups.length === 1 ? defineQuery28([entry.legacyGroups[0]]) : defineQuery28([Any5(...entry.legacyGroups)]);
5775
+ legacyQByEntry.set(entry, q);
5776
+ }
5777
+ return q;
5778
+ }
5779
+ function chainCovered(entry) {
5780
+ for (let v = entry.atVersion; v < entry.widget.version; v++) {
5781
+ if (typeof entry.widget.migrate[v] !== "function") return false;
5782
+ }
5783
+ return true;
5784
+ }
5785
+ function armRenameSweep(world, store) {
5786
+ const entries = renames.all();
5787
+ if (entries.length === 0) return () => {
5788
+ };
5789
+ let pending = false;
5790
+ let disposed = false;
5791
+ const warnedGap = /* @__PURE__ */ new Set();
5792
+ const sweep = () => {
5793
+ for (const entry of entries) {
5794
+ const { widget, legacyGroups, oldType } = entry;
5795
+ const covered = chainCovered(entry);
5796
+ const seen = /* @__PURE__ */ new Set();
5797
+ const plans = [];
5798
+ const consider = (e) => {
5799
+ if (seen.has(e)) return;
5800
+ seen.add(e);
5801
+ const id = world.get(e, PrefabId)?.id;
5802
+ const rewriteId = id === oldType;
5803
+ let anyLegacy = false;
5804
+ const flat = {};
5805
+ const removeLegacy = [];
5806
+ for (let i = 0; i < widget.groups.length; i++) {
5807
+ const legacy = world.get(e, legacyGroups[i]);
5808
+ if (legacy === void 0) continue;
5809
+ anyLegacy = true;
5810
+ Object.assign(flat, legacy);
5811
+ removeLegacy.push(legacyGroups[i]);
5812
+ }
5813
+ if (!rewriteId && !anyLegacy) return;
5814
+ if (!rewriteId && anyLegacy && id !== widget.type) return;
5815
+ if (anyLegacy && !covered) {
5816
+ if (!warnedGap.has(oldType)) {
5817
+ warnedGap.add(oldType);
5818
+ console.warn(
5819
+ `ice: rename sweep \u2014 "${oldType}" values are at pack v${entry.atVersion} but "${widget.type}"'s migrate chain has a gap; leaving legacy cells in place (design-008 \xA76.3).`
5820
+ );
5821
+ }
5822
+ return;
5823
+ }
5824
+ let folded = flat;
5825
+ for (let v = entry.atVersion; v < widget.version; v++) {
5826
+ const step = widget.migrate[v];
5827
+ if (typeof step === "function") folded = step(folded);
5828
+ }
5829
+ const writeGroups = [];
5830
+ if (anyLegacy) {
5831
+ for (let i = 0; i < widget.groups.length; i++) {
5832
+ const present = world.get(e, widget.groups[i].component) !== void 0;
5833
+ if (!present) writeGroups.push(i);
5834
+ }
5835
+ }
5836
+ plans.push({ e, rewriteId, folded, writeGroups, removeLegacy });
5837
+ };
5838
+ if (legacyGroups.length === 0) {
5839
+ world.query(prefabQ).each((batch) => {
5840
+ for (const row of batch) {
5841
+ const e = batch.entity(row);
5842
+ if (world.read(e, PrefabId).id === oldType) consider(e);
5843
+ }
5844
+ });
5845
+ }
5846
+ const legacyQ = legacyQueryOf(entry);
5847
+ if (legacyQ !== void 0) {
5848
+ world.query(legacyQ).each((batch) => {
5849
+ for (const row of batch) consider(batch.entity(row));
5850
+ });
5851
+ }
5852
+ if (plans.length === 0) continue;
5853
+ store.transaction(
5854
+ (tx) => {
5855
+ for (const plan of plans) {
5856
+ if (plan.rewriteId) tx.edit(plan.e).set(PrefabId, { id: widget.type });
5857
+ for (const i of plan.writeGroups) {
5858
+ tx.addComponent(plan.e, widget.groups[i].component, plan.folded);
5859
+ }
5860
+ for (const legacy of plan.removeLegacy) tx.removeComponent(plan.e, legacy);
5861
+ }
5862
+ },
5863
+ { undoable: false }
5864
+ );
5865
+ store.metaTransaction((meta) => {
5866
+ const tomb = `${RENAMED_PREFIX3}${oldType}`;
5867
+ if (meta.get(tomb) === void 0) meta.set(tomb, widget.type);
5868
+ });
5869
+ }
5870
+ };
5871
+ const schedule = () => {
5872
+ if (pending || disposed) return;
5873
+ pending = true;
5874
+ queueMicrotask(() => {
5875
+ pending = false;
5876
+ if (!disposed) sweep();
5877
+ });
5878
+ };
5879
+ const watchers = [];
5880
+ let anyZeroProp = false;
5881
+ for (const entry of entries) {
5882
+ const q = legacyQueryOf(entry);
5883
+ if (q !== void 0) {
5884
+ watchers.push(world.reactive.observeQuery(q, schedule, { cols: [...entry.legacyGroups] }));
5885
+ } else {
5886
+ anyZeroProp = true;
5887
+ }
5888
+ }
5889
+ if (anyZeroProp) {
5890
+ watchers.push(world.reactive.observeQuery(prefabQ, schedule, { cols: [PrefabId] }));
5891
+ }
5892
+ return () => {
5893
+ disposed = true;
5894
+ for (const u of watchers) u();
5895
+ };
5896
+ }
5897
+
5898
+ // ../core/src/doc/schema-migrate.ts
5899
+ import { defineQuery as defineQuery29 } from "@vibecook/strata-ecs";
5625
5900
  var SCHEMA_PREFIX2 = "engine.schema.";
5626
5901
  var BOARD_ROOT_META = "engine.boardRoot";
5627
- var allDurableQ2 = defineQuery27([PrefabId]);
5902
+ var allDurableQ3 = defineQuery29([PrefabId]);
5628
5903
  function ensureBoardRoot(world, store) {
5629
5904
  let recorded;
5630
5905
  store.metaTransaction((meta) => {
@@ -5662,7 +5937,7 @@ function migrateToOrderedRelations(ctx) {
5662
5937
  const { store, world } = ctx;
5663
5938
  const root = ensureBoardRoot(world, store);
5664
5939
  const groups = /* @__PURE__ */ new Map();
5665
- world.query(allDurableQ2).each((batch) => {
5940
+ world.query(allDurableQ3).each((batch) => {
5666
5941
  for (const row of batch) {
5667
5942
  const e = batch.entity(row);
5668
5943
  if (e === root) continue;
@@ -5736,6 +6011,7 @@ function makeSession(world, doc, store, attachment, readOnly, report) {
5736
6011
  mayDiverge: makeDefaultMayDiverge(world),
5737
6012
  cellInDoc: (e, c) => store.getComponent(e, c) !== void 0
5738
6013
  });
6014
+ const disarmRenameSweep = readOnly ? void 0 : armRenameSweep(world, store);
5739
6015
  let closed = false;
5740
6016
  const remoteSubs = /* @__PURE__ */ new Set();
5741
6017
  return {
@@ -5767,6 +6043,7 @@ function makeSession(world, doc, store, attachment, readOnly, report) {
5767
6043
  close() {
5768
6044
  if (closed) return;
5769
6045
  closed = true;
6046
+ disarmRenameSweep?.();
5770
6047
  cancelActiveGestures(world);
5771
6048
  store.setHistoryHooks(null);
5772
6049
  remoteSubs.clear();
@@ -5835,6 +6112,8 @@ function openDocSession(world, bytes, opts = {}) {
5835
6112
  if (verdict === "migrate" && (opts.migrate ?? true)) {
5836
6113
  try {
5837
6114
  runSchemaMigrations({ store, world }, report);
6115
+ const renamed = runRenames({ store, world }, report);
6116
+ if (renamed.renamed.length > 0) world.sync();
5838
6117
  runMigrations({ store, world }, readDocVersionReport(doc));
5839
6118
  effectiveReport = readDocVersionReport(doc);
5840
6119
  readOnly = gateVerdict(effectiveReport) !== "ok";
@@ -5989,8 +6268,8 @@ var p = {
5989
6268
  };
5990
6269
 
5991
6270
  // ../core/src/widget/equip.ts
5992
- import { Not as Not4, defineQuery as defineQuery28, defineSystem as defineSystem17 } from "@vibecook/strata-ecs";
5993
- var unequippedQ = defineQuery28([PrefabId, Not4(WidgetEquipped)]);
6271
+ import { Not as Not4, defineQuery as defineQuery30, defineSystem as defineSystem17 } from "@vibecook/strata-ecs";
6272
+ var unequippedQ = defineQuery30([PrefabId, Not4(WidgetEquipped)]);
5994
6273
  function createWidgetEquipSystem() {
5995
6274
  return defineSystem17(
5996
6275
  unequippedQ,
@@ -6084,8 +6363,8 @@ function createMeasureIngest(world, queue) {
6084
6363
  }
6085
6364
 
6086
6365
  // ../core/src/widget/mount-store.ts
6087
- import { Not as Not5, defineQuery as defineQuery30, defineTickSystem as defineTickSystem13 } from "@vibecook/strata-ecs";
6088
- var widgetQ = defineQuery30([Position, Size, WidgetEquipped, Active]);
6366
+ import { Not as Not5, defineQuery as defineQuery32, defineTickSystem as defineTickSystem13 } from "@vibecook/strata-ecs";
6367
+ var widgetQ = defineQuery32([Position, Size, WidgetEquipped, Active]);
6089
6368
  function createWidgetRuntime(world, opts = {}) {
6090
6369
  const budget = opts.keepMounted ?? RUNTIME_BUDGETS.keepMountedWidgets;
6091
6370
  let lastWin = null;
@@ -6168,8 +6447,8 @@ function createWidgetRuntime(world, opts = {}) {
6168
6447
  let snapshot = [];
6169
6448
  let dirty = false;
6170
6449
  const listeners = /* @__PURE__ */ new Set();
6171
- const visibleWidgetsQ = defineQuery30([Position, Size, WidgetEquipped, Active, Visible]);
6172
- const culledWidgetsQ = defineQuery30([Position, Size, WidgetEquipped, Not5(Visible)]);
6450
+ const visibleWidgetsQ = defineQuery32([Position, Size, WidgetEquipped, Active, Visible]);
6451
+ const culledWidgetsQ = defineQuery32([Position, Size, WidgetEquipped, Not5(Visible)]);
6173
6452
  const mountGuard = makeChurnGuard(world, { tags: [Visible, Culled], coarse: false });
6174
6453
  const mountSystem = defineTickSystem13(
6175
6454
  (ctx) => {
@@ -6645,10 +6924,10 @@ function attachPresence(world, opts) {
6645
6924
  }
6646
6925
 
6647
6926
  // ../core/src/presence/publish.ts
6648
- import { defineQuery as defineQuery31 } from "@vibecook/strata-ecs";
6927
+ import { defineQuery as defineQuery33 } from "@vibecook/strata-ecs";
6649
6928
  var SELECTION_KEY_CAP = 32;
6650
6929
  var COUNT_MAX = 65535;
6651
- var localMouseQ = defineQuery31([Pointer, LocalPointer, PointerWorld]);
6930
+ var localMouseQ = defineQuery33([Pointer, LocalPointer, PointerWorld]);
6652
6931
  function createPresencePublish(world, session, opts = {}) {
6653
6932
  const { eph } = session;
6654
6933
  const keyOf = opts.keyOf;
@@ -6742,9 +7021,9 @@ function summaryEquals(a, b) {
6742
7021
  }
6743
7022
 
6744
7023
  // ../core/src/presence/remote-cursors.ts
6745
- import { Not as Not6, defineQuery as defineQuery32, defineTickSystem as defineTickSystem14 } from "@vibecook/strata-ecs";
7024
+ import { Not as Not6, defineQuery as defineQuery34, defineTickSystem as defineTickSystem14 } from "@vibecook/strata-ecs";
6746
7025
  import { Local } from "@vibecook/strata-ecs";
6747
- var remotePeerCursorsQ = defineQuery32([PresenceCursor, PresencePeer, Not6(Local)]);
7026
+ var remotePeerCursorsQ = defineQuery34([PresenceCursor, PresencePeer, Not6(Local)]);
6748
7027
  function createRemoteCursorsSystem(_world) {
6749
7028
  const pool = /* @__PURE__ */ new Map();
6750
7029
  return defineTickSystem14(
@@ -7128,7 +7407,7 @@ function webSocketByteChannel(ws) {
7128
7407
  }
7129
7408
 
7130
7409
  // ../core/src/facade/create-canvas-engine.ts
7131
- import { createWorld, defineQuery as defineQuery33 } from "@vibecook/strata-ecs";
7410
+ import { createWorld, defineQuery as defineQuery35 } from "@vibecook/strata-ecs";
7132
7411
 
7133
7412
  // ../core/src/ops/insert.ts
7134
7413
  var IDENTITY_CAM5 = { x: 0, y: 0, zoom: 1 };
@@ -7184,7 +7463,7 @@ function createForwardingSink() {
7184
7463
  }
7185
7464
  };
7186
7465
  }
7187
- var selectableWidgetsQ = defineQuery33([Position, Size, Selectable, Active, WidgetEquipped]);
7466
+ var selectableWidgetsQ = defineQuery35([Position, Size, Selectable, Active, WidgetEquipped]);
7188
7467
  function createCanvasEngine(opts = {}) {
7189
7468
  registerBuiltinTools();
7190
7469
  for (const w of opts.widgets ?? []) {
@@ -7562,11 +7841,11 @@ function createCanvasEngine(opts = {}) {
7562
7841
  // ../core/src/index.ts
7563
7842
  import {
7564
7843
  All,
7565
- Any as Any5,
7844
+ Any as Any6,
7566
7845
  Not as Not7,
7567
7846
  Related as Related2,
7568
7847
  createWorld as createWorld2,
7569
- defineQuery as defineQuery34,
7848
+ defineQuery as defineQuery36,
7570
7849
  defineSystem as defineSystem19,
7571
7850
  defineTickSystem as defineTickSystem15,
7572
7851
  enumOf as enumOf8,
@@ -7663,6 +7942,7 @@ export {
7663
7942
  WentUp,
7664
7943
  WentCancelled,
7665
7944
  HandledByWidget,
7945
+ WheelHandled,
7666
7946
  OverInteractive,
7667
7947
  LocalPointer,
7668
7948
  PointerWorld,
@@ -7723,6 +8003,7 @@ export {
7723
8003
  SnapSource,
7724
8004
  SnapTarget,
7725
8005
  SweepsContained,
8006
+ KeyboardExclusive,
7726
8007
  PresencePeer,
7727
8008
  PresenceInfo,
7728
8009
  PresenceCursor,
@@ -7739,6 +8020,7 @@ export {
7739
8020
  makeVersionGuard,
7740
8021
  WidgetEquipped,
7741
8022
  widgets,
8023
+ renames,
7742
8024
  defineWidget,
7743
8025
  selectedEntities,
7744
8026
  setSelection,
@@ -7827,11 +8109,11 @@ export {
7827
8109
  createCanvasEngine,
7828
8110
  CORE_VERSION,
7829
8111
  All,
7830
- Any5 as Any,
8112
+ Any6 as Any,
7831
8113
  Not7 as Not,
7832
8114
  Related2 as Related,
7833
8115
  createWorld2 as createWorld,
7834
- defineQuery34 as defineQuery,
8116
+ defineQuery36 as defineQuery,
7835
8117
  defineSystem19 as defineSystem,
7836
8118
  defineTickSystem15 as defineTickSystem,
7837
8119
  enumOf8 as enumOf,
@@ -7839,4 +8121,4 @@ export {
7839
8121
  Local2 as Local,
7840
8122
  DurableUndoStatus
7841
8123
  };
7842
- //# sourceMappingURL=chunk-5QY7HK6G.js.map
8124
+ //# sourceMappingURL=chunk-7LZAXQAO.js.map