@vibecook/ice 0.15.0-desk.4 → 0.15.0-desk.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-M7E6E7K5.js → chunk-7XSZRL74.js} +2 -2
- package/dist/{chunk-PFJN3XN2.js → chunk-CAJ64OD6.js} +231 -43
- package/dist/chunk-CAJ64OD6.js.map +1 -0
- package/dist/{chunk-E5ADZNMK.js → chunk-G3LDSWL4.js} +71 -12
- package/dist/chunk-G3LDSWL4.js.map +1 -0
- package/dist/{chunk-JS6PG6YD.js → chunk-RE4GDHFJ.js} +13 -1
- package/dist/chunk-RE4GDHFJ.js.map +1 -0
- package/dist/{chunk-I53CLMYG.js → chunk-WWFLFPSG.js} +48 -9
- package/dist/chunk-WWFLFPSG.js.map +1 -0
- package/dist/desk-kit.js +3 -3
- package/dist/desk-objects.js +7 -7
- package/dist/desk-objects.js.map +1 -1
- package/dist/desk.js +4 -4
- package/dist/devtools.js +2 -2
- package/dist/dom.js +3 -3
- package/dist/index.js +12 -2
- package/dist/kernel.js +5 -1
- package/dist/react.js +3 -3
- package/dist/types/packages/core/src/catalog/desk.d.ts +19 -1
- package/dist/types/packages/core/src/catalog/pointer.d.ts +7 -0
- package/dist/types/packages/core/src/catalog/selection-presence.d.ts +11 -1
- package/dist/types/packages/core/src/engine/frame-control.d.ts +14 -0
- package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +13 -0
- package/dist/types/packages/core/src/index.d.ts +2 -2
- package/dist/types/packages/core/src/input/queue.d.ts +5 -1
- package/dist/types/packages/core/src/ops/tray.d.ts +20 -1
- package/dist/types/packages/core/src/presence/index.d.ts +2 -2
- package/dist/types/packages/core/src/presence/presence-kit.d.ts +14 -0
- package/dist/types/packages/core/src/presence/publish.d.ts +7 -0
- package/dist/types/packages/core/src/presence/remote-cursors.d.ts +17 -2
- package/dist/types/packages/core/src/systems/tray.d.ts +13 -1
- package/dist/types/packages/desk/src/compose/index.d.ts +2 -1
- package/dist/types/packages/desk/src/compose/reflector.d.ts +6 -0
- package/dist/types/packages/desk/src/ground.d.ts +11 -3
- package/dist/types/packages/desk/src/host/layer.d.ts +49 -3
- package/dist/types/packages/desk/src/marks/layout.d.ts +8 -0
- package/dist/types/packages/desk/src/still.d.ts +13 -1
- package/dist/types/packages/dom/src/desk-host.d.ts +5 -0
- package/dist/types/packages/dom/src/pointer-adapter.d.ts +18 -3
- package/dist/types/packages/kernel/src/coords.d.ts +32 -1
- package/package.json +1 -1
- package/dist/chunk-E5ADZNMK.js.map +0 -1
- package/dist/chunk-I53CLMYG.js.map +0 -1
- package/dist/chunk-JS6PG6YD.js.map +0 -1
- package/dist/chunk-PFJN3XN2.js.map +0 -1
- /package/dist/{chunk-M7E6E7K5.js.map → chunk-7XSZRL74.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
defineQuery,
|
|
13
13
|
field,
|
|
14
14
|
init
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-CAJ64OD6.js";
|
|
16
16
|
|
|
17
17
|
// ../desk/src/lattice/lod.ts
|
|
18
18
|
var BASE_SPACING = 20;
|
|
@@ -2399,4 +2399,4 @@ export {
|
|
|
2399
2399
|
writeChanged,
|
|
2400
2400
|
lineWeight
|
|
2401
2401
|
};
|
|
2402
|
-
//# sourceMappingURL=chunk-
|
|
2402
|
+
//# sourceMappingURL=chunk-7XSZRL74.js.map
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
visibleRect,
|
|
28
28
|
wireCubic,
|
|
29
29
|
zoomAtPoint
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-RE4GDHFJ.js";
|
|
31
31
|
|
|
32
32
|
// ../core/src/boot/hmr.ts
|
|
33
33
|
function defineSchemaOnce(key, build2) {
|
|
@@ -571,6 +571,9 @@ function createFrameControl(world) {
|
|
|
571
571
|
const listeners = /* @__PURE__ */ new Set();
|
|
572
572
|
let settleLeft = 0;
|
|
573
573
|
let parked = false;
|
|
574
|
+
const parkListeners = /* @__PURE__ */ new Set();
|
|
575
|
+
let heardParked = false;
|
|
576
|
+
let parkOwed = false;
|
|
574
577
|
const sources = /* @__PURE__ */ new Map();
|
|
575
578
|
const wakeListeners = /* @__PURE__ */ new Set();
|
|
576
579
|
const wakeCounts = {};
|
|
@@ -593,6 +596,41 @@ function createFrameControl(world) {
|
|
|
593
596
|
for (const r of reporters.values()) if (r.busy()) names.push(r.name);
|
|
594
597
|
return names;
|
|
595
598
|
};
|
|
599
|
+
const announcePark = (on) => {
|
|
600
|
+
if (heardParked === on) return;
|
|
601
|
+
heardParked = on;
|
|
602
|
+
for (const fn of [...parkListeners]) {
|
|
603
|
+
if (heardParked !== on) return;
|
|
604
|
+
try {
|
|
605
|
+
fn(on);
|
|
606
|
+
} catch (err) {
|
|
607
|
+
console.error("[ice] frame.onParked \u2014 a listener threw; the gate stands", err);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
const claim = () => {
|
|
612
|
+
if (freezes.size === 0) return true;
|
|
613
|
+
if (!parked && settleLeft <= 0) {
|
|
614
|
+
parked = true;
|
|
615
|
+
if (devGuardsEnabled()) {
|
|
616
|
+
console.warn(
|
|
617
|
+
`ice: frame.freeze \u2014 settle cap (${SETTLE_CAP} frames) reached with reporters still busy: ${busyNames().join(", ")}. Parking on a possibly unsettled frame.`
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (parked) {
|
|
622
|
+
if (heardParked) return false;
|
|
623
|
+
parkOwed = false;
|
|
624
|
+
announcePark(true);
|
|
625
|
+
return parked ? false : claim();
|
|
626
|
+
}
|
|
627
|
+
settleLeft -= 1;
|
|
628
|
+
if (busyNames().length === 0) {
|
|
629
|
+
parked = true;
|
|
630
|
+
parkOwed = true;
|
|
631
|
+
}
|
|
632
|
+
return true;
|
|
633
|
+
};
|
|
596
634
|
return {
|
|
597
635
|
freeze(name) {
|
|
598
636
|
const token = Symbol(name);
|
|
@@ -609,12 +647,15 @@ function createFrameControl(world) {
|
|
|
609
647
|
if (released) return;
|
|
610
648
|
released = true;
|
|
611
649
|
freezes.delete(token);
|
|
612
|
-
|
|
650
|
+
const open = freezes.size === 0;
|
|
651
|
+
if (open) {
|
|
613
652
|
settleLeft = 0;
|
|
614
653
|
parked = false;
|
|
654
|
+
parkOwed = false;
|
|
615
655
|
}
|
|
616
656
|
sync();
|
|
617
657
|
announce();
|
|
658
|
+
if (open) announcePark(false);
|
|
618
659
|
};
|
|
619
660
|
},
|
|
620
661
|
isFrozen: () => freezes.size > 0,
|
|
@@ -631,28 +672,19 @@ function createFrameControl(world) {
|
|
|
631
672
|
};
|
|
632
673
|
},
|
|
633
674
|
settling: () => busyNames(),
|
|
634
|
-
claimStep
|
|
635
|
-
if (freezes.size === 0) return true;
|
|
636
|
-
if (parked) return false;
|
|
637
|
-
if (settleLeft <= 0) {
|
|
638
|
-
parked = true;
|
|
639
|
-
if (devGuardsEnabled()) {
|
|
640
|
-
console.warn(
|
|
641
|
-
`ice: frame.freeze \u2014 settle cap (${SETTLE_CAP} frames) reached with reporters still busy: ${busyNames().join(", ")}. Parking on a possibly unsettled frame.`
|
|
642
|
-
);
|
|
643
|
-
}
|
|
644
|
-
return false;
|
|
645
|
-
}
|
|
646
|
-
settleLeft -= 1;
|
|
647
|
-
if (busyNames().length === 0) parked = true;
|
|
648
|
-
return true;
|
|
649
|
-
},
|
|
675
|
+
claimStep: claim,
|
|
650
676
|
onChange(fn) {
|
|
651
677
|
listeners.add(fn);
|
|
652
678
|
return () => {
|
|
653
679
|
listeners.delete(fn);
|
|
654
680
|
};
|
|
655
681
|
},
|
|
682
|
+
onParked(fn) {
|
|
683
|
+
parkListeners.add(fn);
|
|
684
|
+
return () => {
|
|
685
|
+
parkListeners.delete(fn);
|
|
686
|
+
};
|
|
687
|
+
},
|
|
656
688
|
wake(reason) {
|
|
657
689
|
if (inStep) return;
|
|
658
690
|
wakeCounts[reason] = (wakeCounts[reason] ?? 0) + 1;
|
|
@@ -722,6 +754,10 @@ function createFrameControl(world) {
|
|
|
722
754
|
},
|
|
723
755
|
leaveStep() {
|
|
724
756
|
inStep = false;
|
|
757
|
+
if (parkOwed) {
|
|
758
|
+
parkOwed = false;
|
|
759
|
+
announcePark(true);
|
|
760
|
+
}
|
|
725
761
|
},
|
|
726
762
|
stepping: () => inStep,
|
|
727
763
|
sleepStats: () => ({ asleep, sleeps, wakes: { ...wakeCounts }, timed, steps })
|
|
@@ -1371,7 +1407,14 @@ var Tray = defineComponent("Tray", {
|
|
|
1371
1407
|
* `setTrayCategory` (the bar's chips, the desk handle's door) and `trayLay` — which lays only that category's entries, zeroes the
|
|
1372
1408
|
* scroll and the band when it moves, and falls back to all ("") when the frame hangs none of it.
|
|
1373
1409
|
*/
|
|
1374
|
-
category: field3("string", { default: "" })
|
|
1410
|
+
category: field3("string", { default: "" }),
|
|
1411
|
+
/**
|
|
1412
|
+
* Petition I37 — THE KEYBOARD FOCUS on the board: the type of the specimen it is on ("" — none), a fact of the view like `hover`.
|
|
1413
|
+
* Its writer is the op `focusTray` (next/prev/first/last along the lay's order, or a type by its id); `trayLay` scrolls the
|
|
1414
|
+
* specimen it moves to into the board's face, and lets it go when what it was on is laid no more (a category, a frame). The
|
|
1415
|
+
* renderer draws no ring for it: a host does, from the desk handle's `TrayAnchor.focused`.
|
|
1416
|
+
*/
|
|
1417
|
+
focus: field3("string", { default: "" })
|
|
1375
1418
|
});
|
|
1376
1419
|
var TrayIntent = defineResource(
|
|
1377
1420
|
"TrayIntent",
|
|
@@ -1394,7 +1437,8 @@ var TrayContent = defineComponent("TrayContent", {
|
|
|
1394
1437
|
width: field3("f64", { default: 0 }),
|
|
1395
1438
|
bottom: field3("f64", { default: 0 }),
|
|
1396
1439
|
laid: field3("u32", { default: 0 }),
|
|
1397
|
-
present: field3("string", { default: "[]" })
|
|
1440
|
+
present: field3("string", { default: "[]" }),
|
|
1441
|
+
order: field3("string", { default: "[]" })
|
|
1398
1442
|
});
|
|
1399
1443
|
var Specimen = defineTag("Specimen");
|
|
1400
1444
|
var TrayPress = defineComponent("TrayPress", {
|
|
@@ -1646,6 +1690,7 @@ var PointerPart = defineComponent("PointerPart", { part: field7("string", { defa
|
|
|
1646
1690
|
var PartTap = defineResource("PartTap", { seq: "u32", target: "eid", part: "string" });
|
|
1647
1691
|
var WheelHandled = defineTag("WheelHandled");
|
|
1648
1692
|
var OverInteractive = defineTag("OverInteractive");
|
|
1693
|
+
var PointerOutside = defineTag("PointerOutside");
|
|
1649
1694
|
var LocalPointer = defineTag("LocalPointer");
|
|
1650
1695
|
var PointerWorld = defineComponent("PointerWorld", {
|
|
1651
1696
|
x: field7("f64", { default: 0 }),
|
|
@@ -1691,7 +1736,9 @@ var PresenceInfo = defineComponent("PresenceInfo", { name: "string", color: "str
|
|
|
1691
1736
|
var PresenceCursor = defineComponent("PresenceCursor", {
|
|
1692
1737
|
x: field9("f64", { default: 0 }),
|
|
1693
1738
|
y: field9("f64", { default: 0 }),
|
|
1694
|
-
device: enumOf6(["mouse", "touch", "pen"])
|
|
1739
|
+
device: enumOf6(["mouse", "touch", "pen"]),
|
|
1740
|
+
away: field9("bool", { default: false }),
|
|
1741
|
+
canvas: field9("string", { default: "" })
|
|
1695
1742
|
});
|
|
1696
1743
|
var SelectionSummary = defineComponent("SelectionSummary", {
|
|
1697
1744
|
count: field9("u16", { default: 0 }),
|
|
@@ -8132,7 +8179,9 @@ function createSelectionChromeSystem(world) {
|
|
|
8132
8179
|
},
|
|
8133
8180
|
{
|
|
8134
8181
|
name: "selectionChrome",
|
|
8135
|
-
|
|
8182
|
+
// orderIndependent (petition I34): its writes land on its OWN handle pool alone — rows disjoint from every other derive
|
|
8183
|
+
// writer of Position/Size (the tray's lay writes the tray's specimens alone)
|
|
8184
|
+
access: { write: [Position, Size], orderIndependent: [Position, Size] },
|
|
8136
8185
|
// Run while there is a selection to mirror OR a pool still to reap.
|
|
8137
8186
|
runIf: () => world.firstOf(selectedQ2) !== void 0 || handleEntities.length > 0
|
|
8138
8187
|
}
|
|
@@ -8951,6 +9000,8 @@ function createTrayLay(world, opts) {
|
|
|
8951
9000
|
let rangeKey = "";
|
|
8952
9001
|
let laidTray;
|
|
8953
9002
|
let laidCategory = "";
|
|
9003
|
+
let focusedFor = "";
|
|
9004
|
+
let laidTypes = [];
|
|
8954
9005
|
const clampToRange = (ctx, tray, frame2, bottom) => {
|
|
8955
9006
|
if (frame2.face === void 0) return;
|
|
8956
9007
|
const range = trayScrollMax(bottom, frame2.face - (frame2.foot ?? 0), frame2.pitch);
|
|
@@ -8961,18 +9012,48 @@ function createTrayLay(world, opts) {
|
|
|
8961
9012
|
rangeKey = key;
|
|
8962
9013
|
if (t.scroll > range) ctx.edit(tray).set(Tray, { ...t, scroll: range });
|
|
8963
9014
|
};
|
|
9015
|
+
const focusInView = (ctx, tray, frame2, bottom) => {
|
|
9016
|
+
const t = ctx.read(tray, Tray);
|
|
9017
|
+
const focus = t.focus ?? "";
|
|
9018
|
+
if (focus !== "" && !laidTypes.includes(focus)) {
|
|
9019
|
+
focusedFor = "";
|
|
9020
|
+
ctx.edit(tray).set(Tray, { ...t, focus: "" });
|
|
9021
|
+
return;
|
|
9022
|
+
}
|
|
9023
|
+
if (focus === focusedFor) return;
|
|
9024
|
+
if (focus === "") {
|
|
9025
|
+
focusedFor = "";
|
|
9026
|
+
return;
|
|
9027
|
+
}
|
|
9028
|
+
const hung = specimensOf(world, tray).find((e) => world.get(e, PrefabId)?.id === focus);
|
|
9029
|
+
if (hung === void 0) return;
|
|
9030
|
+
const at = ctx.get(hung, Position);
|
|
9031
|
+
const size = ctx.get(hung, Size);
|
|
9032
|
+
if (at === void 0 || size === void 0) return;
|
|
9033
|
+
focusedFor = focus;
|
|
9034
|
+
if (frame2.face === void 0) return;
|
|
9035
|
+
const top = frame2.head ?? 0;
|
|
9036
|
+
const showing = frame2.face - (frame2.foot ?? 0) - top;
|
|
9037
|
+
let scroll = t.scroll;
|
|
9038
|
+
if (at.y < scroll + top || size.h > showing) scroll = at.y - top;
|
|
9039
|
+
else if (at.y + size.h > scroll + top + showing) scroll = at.y + size.h - top - showing;
|
|
9040
|
+
scroll = Math.min(Math.max(scroll, 0), trayScrollMax(bottom, frame2.face - (frame2.foot ?? 0), frame2.pitch));
|
|
9041
|
+
if (scroll !== t.scroll || t.stretch !== 0) ctx.edit(tray).set(Tray, { ...t, scroll, stretch: 0 });
|
|
9042
|
+
};
|
|
8964
9043
|
return defineTickSystem9(
|
|
8965
9044
|
(ctx) => {
|
|
8966
9045
|
const tray = world.firstOf(trayQ2);
|
|
8967
9046
|
if (tray === void 0 || !ctx.isAlive(tray)) return;
|
|
8968
|
-
const
|
|
8969
|
-
|
|
9047
|
+
const source = opts.pose.current;
|
|
9048
|
+
const frame2 = source?.frame();
|
|
9049
|
+
if (source === null || source === void 0 || frame2 === void 0 || !(frame2.w > 0) || !(frame2.pitch > 0)) return;
|
|
8970
9050
|
const content = ctx.get(tray, TrayContent);
|
|
8971
9051
|
const policy = opts.placement;
|
|
8972
9052
|
const inside = policy === void 0 ? void 0 : currentNavFrame(world);
|
|
8973
9053
|
const root = world.getResource(BoardRoot)?.root;
|
|
8974
9054
|
const takes = (type) => policy === void 0 ? true : inside !== void 0 ? policy.canIngress(type, inside) : root === void 0 || policy.canPlace === void 0 || policy.canPlace(type, root);
|
|
8975
|
-
const
|
|
9055
|
+
const draws = (type) => source.draws === void 0 || source.draws(type);
|
|
9056
|
+
const types = hungTypes(world).filter((t2) => takes(t2.type) && draws(t2.type));
|
|
8976
9057
|
const t = ctx.read(tray, Tray);
|
|
8977
9058
|
const asked = t.category ?? "";
|
|
8978
9059
|
const category = asked !== "" && !types.some((q) => categoryOf(q) === asked) ? "" : asked;
|
|
@@ -8981,6 +9062,7 @@ function createTrayLay(world, opts) {
|
|
|
8981
9062
|
const key = `${tray}|${content?.laid ?? 0}|${frame2.w}|${frame2.pitch}|${types.map((q) => q.type).join(",")}|${category}`;
|
|
8982
9063
|
if (key === laidKey) {
|
|
8983
9064
|
clampToRange(ctx, tray, frame2, content?.bottom ?? 0);
|
|
9065
|
+
focusInView(ctx, tray, frame2, content?.bottom ?? 0);
|
|
8984
9066
|
return;
|
|
8985
9067
|
}
|
|
8986
9068
|
const shown = category === "" ? types : types.filter((q) => categoryOf(q) === category);
|
|
@@ -9010,15 +9092,20 @@ function createTrayLay(world, opts) {
|
|
|
9010
9092
|
ctx.setRelation(spawned, ChildOf, tray, "last");
|
|
9011
9093
|
}
|
|
9012
9094
|
for (const e of have.values()) ctx.destroy(e);
|
|
9013
|
-
const next2 = { width: frame2.w, bottom: layout.bottom, laid: (content?.laid ?? 0) + 1, present: JSON.stringify(presentOf(types)) };
|
|
9095
|
+
const next2 = { width: frame2.w, bottom: layout.bottom, laid: (content?.laid ?? 0) + 1, present: JSON.stringify(presentOf(types)), order: JSON.stringify(layout.placed.map((q) => q.type)) };
|
|
9014
9096
|
if (content === void 0) ctx.addComponent(tray, TrayContent, next2);
|
|
9015
9097
|
else ctx.edit(tray).set(TrayContent, next2);
|
|
9016
9098
|
laidKey = `${tray}|${next2.laid}|${frame2.w}|${frame2.pitch}|${types.map((q) => q.type).join(",")}|${category}`;
|
|
9017
9099
|
laidTray = tray;
|
|
9018
9100
|
laidCategory = category;
|
|
9101
|
+
laidTypes = layout.placed.map((q) => q.type);
|
|
9019
9102
|
clampToRange(ctx, tray, frame2, layout.bottom);
|
|
9103
|
+
focusInView(ctx, tray, frame2, layout.bottom);
|
|
9020
9104
|
},
|
|
9021
|
-
|
|
9105
|
+
// Petition I34: in derive, after `trayInput` (react) by the phase — the lay reads back what the input wrote this tick, so the two
|
|
9106
|
+
// `Tray` writers are ORDERED, never attested. `Position`/`Size` it writes on the tray's specimens alone, rows disjoint from the
|
|
9107
|
+
// selection chrome's handle pool (its derive co-writer) — that, and only that, is attested.
|
|
9108
|
+
{ name: "trayLay", access: { write: [Position, Size, TrayContent, Tray], orderIndependent: [Position, Size] } }
|
|
9022
9109
|
);
|
|
9023
9110
|
}
|
|
9024
9111
|
|
|
@@ -9044,7 +9131,7 @@ var write = (world, patch) => {
|
|
|
9044
9131
|
const e = ensureTray(world);
|
|
9045
9132
|
const cur = world.read(e, Tray);
|
|
9046
9133
|
const next2 = { ...cur, ...patch };
|
|
9047
|
-
if (next2.open !== cur.open || next2.scroll !== cur.scroll || next2.stretch !== cur.stretch || next2.hover !== cur.hover || next2.category !== cur.category) world.edit(e).set(Tray, next2);
|
|
9134
|
+
if (next2.open !== cur.open || next2.scroll !== cur.scroll || next2.stretch !== cur.stretch || next2.hover !== cur.hover || next2.category !== cur.category || next2.focus !== cur.focus) world.edit(e).set(Tray, next2);
|
|
9048
9135
|
};
|
|
9049
9136
|
function openTray(world) {
|
|
9050
9137
|
if (heldEntity(world) !== void 0) return false;
|
|
@@ -9065,6 +9152,31 @@ function toggleTray(world) {
|
|
|
9065
9152
|
function scrollTray(world, scroll) {
|
|
9066
9153
|
write(world, { scroll, stretch: 0 });
|
|
9067
9154
|
}
|
|
9155
|
+
function trayHung(world) {
|
|
9156
|
+
const e = world.firstOf(trayQ3);
|
|
9157
|
+
const raw = e === void 0 ? void 0 : world.get(e, TrayContent)?.order;
|
|
9158
|
+
if (raw === void 0 || raw === null || raw === "") return [];
|
|
9159
|
+
const list = JSON.parse(raw);
|
|
9160
|
+
return Array.isArray(list) ? list.filter((q) => typeof q === "string") : [];
|
|
9161
|
+
}
|
|
9162
|
+
function trayFocus(world) {
|
|
9163
|
+
const e = world.firstOf(trayQ3);
|
|
9164
|
+
return e === void 0 ? "" : world.get(e, Tray)?.focus ?? "";
|
|
9165
|
+
}
|
|
9166
|
+
function focusTray(world, to) {
|
|
9167
|
+
const order = trayHung(world);
|
|
9168
|
+
const cur = trayFocus(world);
|
|
9169
|
+
const i = order.indexOf(cur);
|
|
9170
|
+
const last = order.length - 1;
|
|
9171
|
+
let next2;
|
|
9172
|
+
if (to === "first") next2 = order[0] ?? "";
|
|
9173
|
+
else if (to === "last") next2 = order[last] ?? "";
|
|
9174
|
+
else if (to === "next") next2 = order[i < 0 ? 0 : Math.min(i + 1, last)] ?? "";
|
|
9175
|
+
else if (to === "prev") next2 = order[i < 0 ? last : Math.max(i - 1, 0)] ?? "";
|
|
9176
|
+
else next2 = order.includes(to) ? to : cur;
|
|
9177
|
+
write(world, { focus: next2 });
|
|
9178
|
+
return next2;
|
|
9179
|
+
}
|
|
9068
9180
|
function trayCategory(world) {
|
|
9069
9181
|
const e = world.firstOf(trayQ3);
|
|
9070
9182
|
return e === void 0 ? "" : world.get(e, Tray)?.category ?? "";
|
|
@@ -9332,6 +9444,7 @@ function createL0Systems(world, queue) {
|
|
|
9332
9444
|
wentCancelled: false,
|
|
9333
9445
|
handled: false,
|
|
9334
9446
|
overInteractive: void 0,
|
|
9447
|
+
outside: false,
|
|
9335
9448
|
mods: { shift: ev.mods.shift, ctrl: ev.mods.ctrl, alt: ev.mods.alt, meta: ev.mods.meta },
|
|
9336
9449
|
wheelDx: 0,
|
|
9337
9450
|
wheelDy: 0,
|
|
@@ -9361,6 +9474,7 @@ function createL0Systems(world, queue) {
|
|
|
9361
9474
|
s.hasWheel = true;
|
|
9362
9475
|
if (ev.wheelHandled === true) s.wheelHandled = true;
|
|
9363
9476
|
}
|
|
9477
|
+
s.outside = ev.kind === "leave";
|
|
9364
9478
|
if (ev.surfaceHandled === true) s.handled = true;
|
|
9365
9479
|
if (ev.overInteractive !== void 0) s.overInteractive = ev.overInteractive;
|
|
9366
9480
|
}
|
|
@@ -9386,6 +9500,7 @@ function createL0Systems(world, queue) {
|
|
|
9386
9500
|
if (s.handled) ctx.addTag(spawned, HandledByWidget);
|
|
9387
9501
|
if (s.wheelHandled) ctx.addTag(spawned, WheelHandled);
|
|
9388
9502
|
if (s.overInteractive === true) ctx.addTag(spawned, OverInteractive);
|
|
9503
|
+
if (s.outside) ctx.addTag(spawned, PointerOutside);
|
|
9389
9504
|
byId.set(id, spawned);
|
|
9390
9505
|
continue;
|
|
9391
9506
|
}
|
|
@@ -9415,6 +9530,10 @@ function createL0Systems(world, queue) {
|
|
|
9415
9530
|
if (s.overInteractive) ctx.addTag(existing, OverInteractive);
|
|
9416
9531
|
else ctx.removeTag(existing, OverInteractive);
|
|
9417
9532
|
}
|
|
9533
|
+
if (s.outside !== ctx.hasTag(existing, PointerOutside)) {
|
|
9534
|
+
if (s.outside) ctx.addTag(existing, PointerOutside);
|
|
9535
|
+
else ctx.removeTag(existing, PointerOutside);
|
|
9536
|
+
}
|
|
9418
9537
|
}
|
|
9419
9538
|
bumpVersion(world, PointerVersion);
|
|
9420
9539
|
},
|
|
@@ -10990,7 +11109,8 @@ function installInteractionStack(engine, opts = {}) {
|
|
|
10990
11109
|
// which now narrow-phases wire entries against wireSync's cached cubics.
|
|
10991
11110
|
// pressWheel beside it (D3t-a): a press holding a `WheelTurns` widget takes its pointer's wheel from both wheel consumers too.
|
|
10992
11111
|
// trayInput right after the hand's (design-017 §4, K3): the pegboard drawer's wheel, its board and its inert desk, in the same vocabulary
|
|
10993
|
-
|
|
11112
|
+
// (its lay is derived from what it writes — at the head of derive, below)
|
|
11113
|
+
engine.addSystems("react", createHeldInput(world, { pose: heldPose }), createTrayInput(world, { pose: trayPose }), createPressWheel(world), pick.spatialSync, wireSync, pick.picking),
|
|
10994
11114
|
engine.addSystems("ctl:spawn", l2.cancelSweep, l2.recognizerSpawn, l2.wheelSpawn, l2.recognizerIntegrity),
|
|
10995
11115
|
engine.addSystems(
|
|
10996
11116
|
"ctl:recognize",
|
|
@@ -11031,7 +11151,12 @@ function installInteractionStack(engine, opts = {}) {
|
|
|
11031
11151
|
// in derive; ports must be indexed before chrome/next-frame picking read it),
|
|
11032
11152
|
// selectionChrome BEFORE cursor (handles spawn at the derive flush so cursor
|
|
11033
11153
|
// + next frame's spatialSync see them).
|
|
11034
|
-
|
|
11154
|
+
// trayLay at the HEAD of derive (petition I34): it reads back the drawer's facts trayInput wrote in react this tick — its clamp
|
|
11155
|
+
// judges this tick's band, a category move starts the board at its top over this tick's wheel — so it is ORDERED after the input
|
|
11156
|
+
// by the phase, never attested (both wrote `Tray` in react, and strata's dev build warned on every engine). Its specimens are
|
|
11157
|
+
// derived state, spawned at the derive flush for the renderer; the selection chrome, the other Position/Size writer here,
|
|
11158
|
+
// writes rows disjoint from them, and both attest it.
|
|
11159
|
+
engine.addSystems("derive", createTrayLay(world, { pose: trayPose, placement: opts.placement }), ports, createSelectionChromeSystem(world), cursor),
|
|
11035
11160
|
// insertGhostReap AFTER recognizerReap: it reads terminal phase tags on
|
|
11036
11161
|
// capturing recognizers pre-flush (deferred destroys land at the group
|
|
11037
11162
|
// boundary), and its own despawns must not race the marker sweep.
|
|
@@ -14114,7 +14239,7 @@ function attachPresence(world, opts) {
|
|
|
14114
14239
|
const source = new LoroEphemeralSnapshot(loro);
|
|
14115
14240
|
const onRemote = opts.onRemote;
|
|
14116
14241
|
const stopRemote = onRemote === void 0 ? void 0 : loro.subscribe((ev) => {
|
|
14117
|
-
if (ev.by !== "local") onRemote();
|
|
14242
|
+
if (ev.by !== "local" && (ev.added.length > 0 || ev.updated.length > 0 || ev.removed.length > 0)) onRemote();
|
|
14118
14243
|
});
|
|
14119
14244
|
const outbound = /* @__PURE__ */ new Set();
|
|
14120
14245
|
const eph = createEphemeralStore(source, {
|
|
@@ -14137,6 +14262,8 @@ function attachPresence(world, opts) {
|
|
|
14137
14262
|
});
|
|
14138
14263
|
let localPeer = spawnLocalPeer();
|
|
14139
14264
|
let detached = false;
|
|
14265
|
+
let awayReason = null;
|
|
14266
|
+
const awayHeard = /* @__PURE__ */ new Set();
|
|
14140
14267
|
let healQueued = false;
|
|
14141
14268
|
const stopResetHeal = world.observe({
|
|
14142
14269
|
onReset: () => {
|
|
@@ -14171,6 +14298,19 @@ function attachPresence(world, opts) {
|
|
|
14171
14298
|
outbound.delete(fn);
|
|
14172
14299
|
};
|
|
14173
14300
|
},
|
|
14301
|
+
setAway(reason) {
|
|
14302
|
+
if (reason !== null && typeof reason !== "string") throw new Error(`ice: presence setAway \u2014 the reason is a string or null (got ${String(reason)})`);
|
|
14303
|
+
if (detached || reason === awayReason) return;
|
|
14304
|
+
awayReason = reason;
|
|
14305
|
+
for (const fn of [...awayHeard]) fn(reason);
|
|
14306
|
+
},
|
|
14307
|
+
away: () => awayReason,
|
|
14308
|
+
onAway(fn) {
|
|
14309
|
+
awayHeard.add(fn);
|
|
14310
|
+
return () => {
|
|
14311
|
+
awayHeard.delete(fn);
|
|
14312
|
+
};
|
|
14313
|
+
},
|
|
14174
14314
|
detach() {
|
|
14175
14315
|
if (detached) return;
|
|
14176
14316
|
detached = true;
|
|
@@ -14182,6 +14322,7 @@ function attachPresence(world, opts) {
|
|
|
14182
14322
|
}
|
|
14183
14323
|
attachment.detach();
|
|
14184
14324
|
outbound.clear();
|
|
14325
|
+
awayHeard.clear();
|
|
14185
14326
|
stopRemote?.();
|
|
14186
14327
|
loro.destroy();
|
|
14187
14328
|
}
|
|
@@ -14193,6 +14334,11 @@ import { defineQuery as defineQuery47 } from "@vibecook/strata-ecs";
|
|
|
14193
14334
|
var SELECTION_KEY_CAP = 32;
|
|
14194
14335
|
var COUNT_MAX = 65535;
|
|
14195
14336
|
var localMouseQ = defineQuery47([Pointer, LocalPointer, PointerWorld]);
|
|
14337
|
+
function presenceCanvasOf(world, peerId, keyOf) {
|
|
14338
|
+
const frame2 = currentNavFrame(world);
|
|
14339
|
+
if (frame2 === void 0 || frame2 === world.getResource(BoardRoot)?.root) return "";
|
|
14340
|
+
return keyOf?.(frame2) ?? `~${peerId}/${frame2}`;
|
|
14341
|
+
}
|
|
14196
14342
|
function createPresencePublish(world, session, opts = {}) {
|
|
14197
14343
|
const { eph } = session;
|
|
14198
14344
|
const keyOf = opts.keyOf;
|
|
@@ -14214,18 +14360,26 @@ function createPresencePublish(world, session, opts = {}) {
|
|
|
14214
14360
|
publishSelection(world);
|
|
14215
14361
|
};
|
|
14216
14362
|
function publishCursor(w) {
|
|
14217
|
-
let
|
|
14363
|
+
let mouse;
|
|
14218
14364
|
w.query(localMouseQ).each((b) => {
|
|
14219
14365
|
for (const r of b) {
|
|
14220
|
-
if (
|
|
14366
|
+
if (mouse !== void 0) break;
|
|
14221
14367
|
const e = b.entity(r);
|
|
14222
14368
|
if (w.read(e, Pointer).device !== "mouse") continue;
|
|
14223
14369
|
const pw = w.read(e, PointerWorld);
|
|
14224
|
-
|
|
14370
|
+
mouse = { x: pw.x, y: pw.y, outside: w.hasTag(e, PointerOutside) };
|
|
14225
14371
|
}
|
|
14226
14372
|
});
|
|
14227
|
-
|
|
14228
|
-
if (
|
|
14373
|
+
const at = mouse ?? (cursorPresent ? lastCursor : void 0);
|
|
14374
|
+
if (at === void 0) return;
|
|
14375
|
+
const cursor = {
|
|
14376
|
+
x: at.x,
|
|
14377
|
+
y: at.y,
|
|
14378
|
+
device: "mouse",
|
|
14379
|
+
away: mouse?.outside === true || session.away() !== null,
|
|
14380
|
+
canvas: presenceCanvasOf(w, session.peerId, keyOf)
|
|
14381
|
+
};
|
|
14382
|
+
if (cursorPresent && lastCursor !== void 0 && cursorEquals(lastCursor, cursor)) {
|
|
14229
14383
|
return;
|
|
14230
14384
|
}
|
|
14231
14385
|
if (cursorPresent) eph.edit(localPeer).set(PresenceCursor, cursor);
|
|
@@ -14280,6 +14434,9 @@ function createPresencePublish(world, session, opts = {}) {
|
|
|
14280
14434
|
lastSummary = summary;
|
|
14281
14435
|
}
|
|
14282
14436
|
}
|
|
14437
|
+
function cursorEquals(a, b) {
|
|
14438
|
+
return a.x === b.x && a.y === b.y && a.device === b.device && a.away === b.away && a.canvas === b.canvas;
|
|
14439
|
+
}
|
|
14283
14440
|
function summaryEquals(a, b) {
|
|
14284
14441
|
return a.count === b.count && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h && a.keys === b.keys;
|
|
14285
14442
|
}
|
|
@@ -14288,16 +14445,18 @@ function summaryEquals(a, b) {
|
|
|
14288
14445
|
import { Not as Not8, defineQuery as defineQuery48, defineTickSystem as defineTickSystem17 } from "@vibecook/strata-ecs";
|
|
14289
14446
|
import { Local as Local2 } from "@vibecook/strata-ecs";
|
|
14290
14447
|
var remotePeerCursorsQ = defineQuery48([PresenceCursor, PresencePeer, Not8(Local2)]);
|
|
14291
|
-
function createRemoteCursorsRig(world) {
|
|
14448
|
+
function createRemoteCursorsRig(world, opts = {}) {
|
|
14292
14449
|
const pool = /* @__PURE__ */ new Map();
|
|
14293
14450
|
const system = defineTickSystem17(
|
|
14294
14451
|
(ctx) => {
|
|
14295
14452
|
const live = /* @__PURE__ */ new Set();
|
|
14453
|
+
const here = presenceCanvasOf(world, opts.peerId ?? "", opts.keyOf);
|
|
14296
14454
|
ctx.query(remotePeerCursorsQ).each((b) => {
|
|
14297
14455
|
for (const r of b) {
|
|
14298
14456
|
const peer = b.entity(r);
|
|
14299
|
-
live.add(peer);
|
|
14300
14457
|
const pc = ctx.read(peer, PresenceCursor);
|
|
14458
|
+
if (pc.away || (pc.canvas ?? "") !== here) continue;
|
|
14459
|
+
live.add(peer);
|
|
14301
14460
|
const entry = pool.get(peer);
|
|
14302
14461
|
if (entry === void 0) {
|
|
14303
14462
|
const cursor = ctx.spawn({
|
|
@@ -14345,14 +14504,23 @@ function createRemoteCursorsRig(world) {
|
|
|
14345
14504
|
}
|
|
14346
14505
|
};
|
|
14347
14506
|
}
|
|
14348
|
-
function createRemoteCursorsSystem(world) {
|
|
14349
|
-
return createRemoteCursorsRig(world).system;
|
|
14507
|
+
function createRemoteCursorsSystem(world, opts = {}) {
|
|
14508
|
+
return createRemoteCursorsRig(world, opts).system;
|
|
14350
14509
|
}
|
|
14351
14510
|
function installPresence(engine, session, opts = {}) {
|
|
14352
|
-
const
|
|
14353
|
-
const
|
|
14511
|
+
const publish = createPresencePublish(engine.world, session, opts);
|
|
14512
|
+
const removePublish = engine.onPublish(publish);
|
|
14513
|
+
let installed = true;
|
|
14514
|
+
const stopAway = session.onAway(() => {
|
|
14515
|
+
queueMicrotask(() => {
|
|
14516
|
+
if (installed && !engine.frame.stepping()) publish(engine.world);
|
|
14517
|
+
});
|
|
14518
|
+
});
|
|
14519
|
+
const rig = createRemoteCursorsRig(engine.world, { peerId: session.peerId, ...opts.keyOf !== void 0 ? { keyOf: opts.keyOf } : {} });
|
|
14354
14520
|
const removeSystem = engine.addSystems("present", rig.system);
|
|
14355
14521
|
return () => {
|
|
14522
|
+
installed = false;
|
|
14523
|
+
stopAway();
|
|
14356
14524
|
removePublish();
|
|
14357
14525
|
removeSystem();
|
|
14358
14526
|
rig.reap();
|
|
@@ -16247,6 +16415,21 @@ function createCanvasEngine(opts = {}) {
|
|
|
16247
16415
|
}
|
|
16248
16416
|
return spawned;
|
|
16249
16417
|
},
|
|
16418
|
+
layFromTray(type, at) {
|
|
16419
|
+
if (typeof at?.x !== "number" || typeof at.y !== "number" || !Number.isFinite(at.x) || !Number.isFinite(at.y)) {
|
|
16420
|
+
throw new Error(`ice: ops.layFromTray \u2014 the point is ${JSON.stringify(at) ?? String(at)}: { x, y }, a world point of the current frame, two finite numbers.`);
|
|
16421
|
+
}
|
|
16422
|
+
if (heldNow() !== void 0 || !trayHung(world).includes(type)) return void 0;
|
|
16423
|
+
const widget = catalog.widget(type);
|
|
16424
|
+
const entry = widget?.tray;
|
|
16425
|
+
if (widget === void 0 || entry === void 0) return void 0;
|
|
16426
|
+
const { w, h } = widget.defaultSize;
|
|
16427
|
+
const props = trayTakeProps(entry);
|
|
16428
|
+
const laid = ops.spawnWidget(type, { x: at.x - w / 2, y: at.y - h / 2, w, h, ...props !== void 0 ? { props } : {} });
|
|
16429
|
+
ops.setSelection([laid]);
|
|
16430
|
+
closeTray(world);
|
|
16431
|
+
return laid;
|
|
16432
|
+
},
|
|
16250
16433
|
insertByDrag(type, o) {
|
|
16251
16434
|
requireWritable("insertByDrag");
|
|
16252
16435
|
const targetFrame = requireCurrentFrame("insertByDrag");
|
|
@@ -16812,6 +16995,7 @@ export {
|
|
|
16812
16995
|
PartTap,
|
|
16813
16996
|
WheelHandled,
|
|
16814
16997
|
OverInteractive,
|
|
16998
|
+
PointerOutside,
|
|
16815
16999
|
LocalPointer,
|
|
16816
17000
|
PointerWorld,
|
|
16817
17001
|
Keyboard,
|
|
@@ -16974,6 +17158,9 @@ export {
|
|
|
16974
17158
|
closeTray,
|
|
16975
17159
|
toggleTray,
|
|
16976
17160
|
scrollTray,
|
|
17161
|
+
trayHung,
|
|
17162
|
+
trayFocus,
|
|
17163
|
+
focusTray,
|
|
16977
17164
|
trayCategory,
|
|
16978
17165
|
setTrayCategory,
|
|
16979
17166
|
trayCategories,
|
|
@@ -17023,6 +17210,7 @@ export {
|
|
|
17023
17210
|
attachBroadcastRelay,
|
|
17024
17211
|
DEFAULT_PRESENCE_TTL_MS,
|
|
17025
17212
|
attachPresence,
|
|
17213
|
+
presenceCanvasOf,
|
|
17026
17214
|
createPresencePublish,
|
|
17027
17215
|
createRemoteCursorsSystem,
|
|
17028
17216
|
installPresence,
|
|
@@ -17047,4 +17235,4 @@ export {
|
|
|
17047
17235
|
Local3 as Local,
|
|
17048
17236
|
DurableUndoStatus
|
|
17049
17237
|
};
|
|
17050
|
-
//# sourceMappingURL=chunk-
|
|
17238
|
+
//# sourceMappingURL=chunk-CAJ64OD6.js.map
|