@vibecook/ice 0.15.0 → 0.16.0-portals.2

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 (41) hide show
  1. package/dist/{chunk-644DO6PN.js → chunk-K4SKRVLK.js} +2 -2
  2. package/dist/chunk-K4SKRVLK.js.map +1 -0
  3. package/dist/{chunk-A6PUTIL7.js → chunk-KV6RMWG4.js} +142 -8
  4. package/dist/chunk-KV6RMWG4.js.map +1 -0
  5. package/dist/{chunk-US7WJNR6.js → chunk-NB4ALBIY.js} +349 -66
  6. package/dist/chunk-NB4ALBIY.js.map +1 -0
  7. package/dist/{chunk-SPG45AVV.js → chunk-SHU3HVMF.js} +72 -12
  8. package/dist/chunk-SHU3HVMF.js.map +1 -0
  9. package/dist/desk-kit.js +14 -2
  10. package/dist/desk-objects.js +3 -3
  11. package/dist/desk.js +15 -3
  12. package/dist/devtools.js +1 -1
  13. package/dist/dom.js +2 -2
  14. package/dist/index.js +5 -3
  15. package/dist/react.js +20 -5
  16. package/dist/react.js.map +1 -1
  17. package/dist/types/packages/core/src/catalog/desk.d.ts +36 -1
  18. package/dist/types/packages/core/src/catalog/selection-presence.d.ts +0 -10
  19. package/dist/types/packages/core/src/systems/held.d.ts +10 -3
  20. package/dist/types/packages/core/src/systems/l4-cursor.d.ts +9 -2
  21. package/dist/types/packages/core/src/widget/define-widget.d.ts +16 -22
  22. package/dist/types/packages/desk/src/hold/told.d.ts +15 -0
  23. package/dist/types/packages/desk/src/index.d.ts +1 -1
  24. package/dist/types/packages/desk/src/kind.d.ts +5 -1
  25. package/dist/types/packages/desk/src/kinds/world.d.ts +93 -2
  26. package/dist/types/packages/desk/src/kit/editor.d.ts +9 -1
  27. package/dist/types/packages/desk/src/kit/index.d.ts +1 -0
  28. package/dist/types/packages/desk/src/kit/live.d.ts +260 -0
  29. package/dist/types/packages/desk/src/kit/mips.d.ts +11 -0
  30. package/dist/types/packages/desk/src/kit/wgsl.d.ts +5 -2
  31. package/dist/types/packages/desk/src/object.d.ts +1 -1
  32. package/dist/types/packages/desk/src/still.d.ts +3 -1
  33. package/dist/types/packages/dom/src/input-ownership.d.ts +5 -3
  34. package/dist/types/packages/dom/src/widget-focus.d.ts +2 -2
  35. package/dist/types/packages/objects/src/minimat/layout.d.ts +1 -1
  36. package/dist/types/packages/react/src/keymap.d.ts +9 -3
  37. package/package.json +1 -1
  38. package/dist/chunk-644DO6PN.js.map +0 -1
  39. package/dist/chunk-A6PUTIL7.js.map +0 -1
  40. package/dist/chunk-SPG45AVV.js.map +0 -1
  41. package/dist/chunk-US7WJNR6.js.map +0 -1
@@ -122,7 +122,10 @@ export declare const HeldPointer: import("@vibecook/strata-ecs").Component<impor
122
122
  * a tap that puts it down), on one of the kind's named PARTS (`part`, D3t-b: the kind's own — a
123
123
  * notebook's turn, its click and its drag; never a tap that puts it down) or elsewhere on the object
124
124
  * itself (`object`: two instant taps put it down). `part`: the part it began on ("" — none); `x`/`y`
125
- * where it began (CSS px), the pan it began from, and whether it has moved past the slop.
125
+ * where it began (CSS px), the pan it began from, and whether it has moved past the slop. `count`
126
+ * (design-019 §5, M24 LT2): its CLICK COUNT — 1, then 2, 3… for each primary press that lands within
127
+ * the desk's multi-tap window and slop of the one before (`HeldPressMemo`; a pointerdown's `detail`
128
+ * is 0 in the browser, so the desk counts — by the down events' own times); a middle press's is 1.
126
129
  */
127
130
  export declare const HeldPress: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
128
131
  readonly kind: import("@vibecook/strata-ecs").FieldSpec<import("@vibecook/strata-ecs").EnumType<"object" | "pan" | "part" | "desk" | "tool">, true>;
@@ -132,6 +135,7 @@ export declare const HeldPress: import("@vibecook/strata-ecs").Component<import(
132
135
  readonly panX0: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
133
136
  readonly panY0: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
134
137
  readonly moved: import("@vibecook/strata-ecs").FieldSpec<"bool", true>;
138
+ readonly count: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
135
139
  }>, {
136
140
  readonly kind: import("@vibecook/strata-ecs").FieldSpec<import("@vibecook/strata-ecs").EnumType<"object" | "pan" | "part" | "desk" | "tool">, true>;
137
141
  readonly part: import("@vibecook/strata-ecs").FieldSpec<"string", true>;
@@ -140,6 +144,37 @@ export declare const HeldPress: import("@vibecook/strata-ecs").Component<import(
140
144
  readonly panX0: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
141
145
  readonly panY0: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
142
146
  readonly moved: import("@vibecook/strata-ecs").FieldSpec<"bool", true>;
147
+ readonly count: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
148
+ }>;
149
+ /**
150
+ * The last PRIMARY press in hand (design-019 §5, M24 LT2): where it began (CSS px), when (its down event's own time — the frame's
151
+ * `now` for an input with none) and its click count — the next primary press within `GestureSettings.multiTapWindowMs` and
152
+ * `multiTapSlopPx` of it counts on (down to down, any pointer: each touch is a pointer of its own). Cleared when nothing is held.
153
+ */
154
+ export declare const HeldPressMemo: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
155
+ readonly x: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
156
+ readonly y: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
157
+ readonly at: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
158
+ readonly count: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
159
+ }>, {
160
+ readonly x: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
161
+ readonly y: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
162
+ readonly at: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
163
+ readonly count: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
164
+ }>;
165
+ /**
166
+ * Runtime, on a local pointer while an object is held whose kind takes the WHEEL (`OpenBinding.wheel: "kind"` — design-019 §5, M24
167
+ * LT2): the plain wheel's deltas of the last tick that had any, CSS px of the hand, and `seq` — moved once per such tick, so the
168
+ * desk tells the kind each tick's wheel once (`HeldEvent` "wheel"). ⌘/ctrl-wheel and the pinch stay the hand's (they zoom it).
169
+ */
170
+ export declare const HeldWheel: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
171
+ readonly dx: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
172
+ readonly dy: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
173
+ readonly seq: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
174
+ }>, {
175
+ readonly dx: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
176
+ readonly dy: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
177
+ readonly seq: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
143
178
  }>;
144
179
  /** The last instant tap on the held object: where and when — a second within the window puts it down (the notebook's case, generalised). */
145
180
  export declare const HeldTapMemo: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
@@ -19,16 +19,6 @@ export declare const SweepsContained: import("@vibecook/strata-ecs").Tag;
19
19
  * behaviour to read (systems/press-wheel.ts).
20
20
  */
21
21
  export declare const WheelTurns: import("@vibecook/strata-ecs").Tag;
22
- /**
23
- * `interaction.keyboard: "exclusive"` (design-007 §3.1, petitions I1/I4): while
24
- * a node inside this widget holds browser focus, the engine's keyboard surfaces
25
- * (keymap shortcuts, the adapter's Space pan modifier) stand down. The ROUTING
26
- * truth is the DOM — the dom-widgets reflector writes a `data-canvas-keyboard`
27
- * marker on the widget host and the keymap/adapter read the event-target chain
28
- * against `document.activeElement`; this tag is the ECS-side mirror of the
29
- * declaration (queryable by devtools/presence), never a routing input.
30
- */
31
- export declare const KeyboardExclusive: import("@vibecook/strata-ecs").Tag;
32
22
  /**
33
23
  * Marks an ephemeral presence-peer entity (design-001 §5.6). Rides the presence
34
24
  * blob so remote peers project it — a peer query is `[PresencePeer, Not(Local)]`
@@ -28,11 +28,16 @@
28
28
  * PARTS (D3t-b: any part but `content` and `frame`, the object itself): that press is the KIND's
29
29
  * (`HeldPress` `part`, with the part it began on — a notebook's turn: two clicks there turn two pages);
30
30
  * - every route above is the PRIMARY button's (petition I28, press-button.ts): a secondary press — and a middle one with nothing
31
- * to pan — is a point in the hand as on the desk: it keeps no `HeldPress`, so it puts nothing down, works no part, lays no stroke.
31
+ * to pan — is a point in the hand as on the desk: it keeps no `HeldPress`, so it puts nothing down, works no part, lays no stroke;
32
+ * - (design-019 §5, M24 LT2) a primary press is COUNTED — `HeldPress.count`, 1, 2, 3… within the multi-tap window and slop of the
33
+ * last (`HeldPressMemo`, by the down events' own times): the platform's `detail` is 0 on a pointerdown, so the desk counts; and a
34
+ * kind that takes the wheel (`OpenBinding.wheel: "kind"` — its type's `heldWheel`) has a plain wheel written to `HeldWheel` for it
35
+ * instead of panning the hand — ⌘/ctrl and the pinch zoom the hand as ever, and past 0.72× still put it down.
32
36
  * The ways back are OPS (`ops.putDown`, structural) and a system may not run them mid-tick: it writes
33
37
  * the one-tick `HeldIntent` and the facade applies it after the step (D2b's `NavIntent`, same shape).
34
38
  * Nothing here reads a kind: the seam gives a frame and (D3t-a) the part under a point; the tool in
35
- * hand is core's `HeldTool`.
39
+ * hand is core's `HeldTool`, the wheel's owner the widget type's `heldWheel`. The kind is TOLD its input by the desk, which folds
40
+ * `HeldPointer`, `HeldPress` and `HeldWheel` into its `held` events (desk/hold/told.ts) — never a second input path.
36
41
  */
37
42
  import type { Entity, System, World } from "@vibecook/strata-ecs";
38
43
  /** The held object's frame ON SCREEN as the renderer drew it this frame (CSS px): its centre, half extents, its scale (CSS px per object unit), and whether the pickup has settled (the wheel waits for it). */
@@ -47,11 +52,13 @@ export interface HeldScreenFrame {
47
52
  /**
48
53
  * The pose seam: the renderer's word on where the held object is — `undefined` before its first frame — and (D3t-a) which of
49
54
  * its kind's parts is under a point of the object's own frame (its `hit` on the geometry it drew: the board's melamine
50
- * `content`, its `frame`), null over nothing; absent = no parts ("content" inside the frame).
55
+ * `content`, its `frame`), null over nothing; absent = no parts ("content" inside the frame). `cursor` (design-019 §5, M24 LT2):
56
+ * the kind's cursor over one of its NAMED parts (its `open.cursor`) — L4 shows it above its own; undefined: L4's.
51
57
  */
52
58
  export interface HeldPoseSource {
53
59
  frame(entity: Entity): HeldScreenFrame | undefined;
54
60
  part?(entity: Entity, x: number, y: number): string | null;
61
+ cursor?(entity: Entity, part: string): string | undefined;
55
62
  }
56
63
  /** The stack's slot for the pose source — a mutable box, so the renderer can arrive after install (as `framePick`). */
57
64
  export interface HeldPoseSlot {
@@ -12,7 +12,10 @@
12
12
  * everything but the hand's. (design-018 §5: the lip's "pointer" retired with its handle — the drawer's handle is the app's DOM bar.)
13
13
  * Above all of them (design-015 §8, D3t-a): with an object IN HAND, the mode in hand's own
14
14
  * `cursor` (its `HeldToolDef.cursor` — "none" where the tool draws itself: the board's marker) while
15
- * the mouse is over the object's drawing surface (`HeldPointer.part` "content") or presses the tool.
15
+ * the mouse is over the object's drawing surface (`HeldPointer.part` "content") or presses the tool —
16
+ * and (design-019 §5, M24 LT2) over one of the kind's NAMED parts, the KIND's cursor when it names one:
17
+ * the pose seam's `cursor` (its `open.cursor` — a link's `pointer`, a text field's `text`), asked each
18
+ * run while the mouse is over such a part; undefined there falls to the rest, as ever.
16
19
  *
17
20
  * Scheduled on the `CanvasSurface` anchor query (exactly one such entity,
18
21
  * guaranteed by install — the same idiom `pointerIngest` uses in l0-input.ts)
@@ -24,6 +27,10 @@
24
27
  * cursor reflector is the only consumer (core never touches DOM).
25
28
  */
26
29
  import type { System, World } from "@vibecook/strata-ecs";
27
- export declare function createCursorSync(world: World): System & {
30
+ import type { HeldPoseSlot } from "./held";
31
+ /** `pose`: the stack's held pose slot (`installInteractionStack`'s `heldPose`) — the kind's cursor in hand rides it (M24 LT2). */
32
+ export declare function createCursorSync(world: World, opts?: {
33
+ readonly pose?: HeldPoseSlot;
34
+ }): System & {
28
35
  readCursor(): string;
29
36
  };
@@ -113,24 +113,6 @@ export interface WidgetInteraction {
113
113
  * that pointer is the widget's, never the camera's; its deltas add up in the pointer's `PressWheel`. Default false.
114
114
  */
115
115
  readonly wheelTurns?: boolean;
116
- /**
117
- * Keyboard claim (design-007 §3.1, petitions I1/I4). `"exclusive"`: while a
118
- * node inside this widget's claim holds browser focus, the engine keymap and
119
- * the adapter's Space pan modifier stand down — keys flow to the widget's own
120
- * handlers (the engine stops competing; it never delivers behavior). The claim
121
- * is a `data-canvas-keyboard` host in screen space (the desk's one focused
122
- * editor carries it), and plain wheel over its scrollable content cedes to
123
- * native scroll (ctrl/pinch stays canvas zoom always). Default `"shared"`.
124
- */
125
- readonly keyboard?: "shared" | "exclusive";
126
- /**
127
- * Escape ownership under an exclusive claim (design-007 §3.3 / §7-Q1).
128
- * `"release"` (default): Escape is the engine-reserved release gesture — it
129
- * blurs the widget; the NEXT Escape, with focus gone, cancels gestures.
130
- * `"widget"`: even Escape flows to the widget (vim-grade terminals); release
131
- * is click-away or `blurFocus()`. Ignored unless `keyboard: "exclusive"`.
132
- */
133
- readonly keyboardEscape?: "release" | "widget";
134
116
  }
135
117
  export interface WidgetDef {
136
118
  readonly type: string;
@@ -174,6 +156,18 @@ export interface WidgetDef {
174
156
  readonly heldTools?: readonly HeldToolDef[];
175
157
  /** The mode in hand when the object is picked up, from its props (the board: its capped marker's ink). Default: the first mode, else none. */
176
158
  readonly heldTool?: (props: Readonly<Record<string, unknown>>) => string;
159
+ /**
160
+ * The WHEEL in hand (design-019 §5, M24 LT2 — the desk's `defineObject` passes its kind's `open.wheel`): `"hand"` (the default — a
161
+ * plain wheel moves the object once brought close) or `"kind"` — a plain wheel is the kind's (core writes it to the pointer's
162
+ * `HeldWheel`, the desk tells the kind); ⌘/ctrl-wheel and the pinch zoom the hand either way. Refused on anything that does not open.
163
+ */
164
+ readonly heldWheel?: "hand" | "kind";
165
+ /**
166
+ * ESCAPE in hand (design-019 §5, M24 LT2 — the kind's `open.escape`): `"desk"` (the default — Esc puts the object down) or `"kind"` —
167
+ * Esc is the kind's (a source that owns it: a terminal), and the keymap never puts the object down for it: Done, a click off it or
168
+ * the pinch do. Refused on anything that does not open.
169
+ */
170
+ readonly heldEscape?: "desk" | "kind";
177
171
  /**
178
172
  * The acts the SELECTION MENU offers for a selection of this type's objects (design-016 §5 · K-L2, K8a — widget/menu-actions.ts):
179
173
  * each an id, a label, a glyph and an op; the menu shows one when every selected object's type declares it, and
@@ -325,10 +319,10 @@ export interface WidgetType {
325
319
  readonly provides: readonly string[];
326
320
  /** Fixed nested-frame binding and ingress/portal metadata, when a container. */
327
321
  readonly container: WidgetContainerEntry | undefined;
328
- /** Keyboard claim (design-007): the dom layer reads THIS (registry truth), not the tag. */
329
- readonly keyboard: "shared" | "exclusive";
330
- /** Escape ownership under an exclusive claim ("release" = engine-reserved). */
331
- readonly keyboardEscape: "release" | "widget";
322
+ /** The plain wheel's owner in hand (M24 LT2): `"hand"` unless the object's kind takes it — core's held input reads THIS. */
323
+ readonly heldWheel: "hand" | "kind";
324
+ /** Escape's owner in hand (M24 LT2): `"desk"` unless the object's kind owns it — the keymap reads THIS. */
325
+ readonly heldEscape: "desk" | "kind";
332
326
  /** May instances be dropped INTO an accepting container (design-015 §9; `"never"` = a root object always, D-D18)? The drop system reads THIS. */
333
327
  readonly drop: "into" | "never";
334
328
  readonly migrate: Readonly<Record<number, (prev: Record<string, unknown>) => Record<string, unknown>>>;
@@ -0,0 +1,15 @@
1
+ import { type Entity, type World } from "../../../core/src/index";
2
+ import type { HeldEvent } from "../kinds/world";
3
+ /** One object's events for one frame. */
4
+ export interface HeldTold {
5
+ readonly entity: Entity;
6
+ readonly events: readonly HeldEvent[];
7
+ }
8
+ export interface HeldFold {
9
+ /**
10
+ * This frame's events — for the object in hand when something happened, and for the object the hand just LET GO of when a press of
11
+ * its kind was still down (its `up`, where the pointer was last). Empty when nothing happened or nothing is held.
12
+ */
13
+ step(): readonly HeldTold[];
14
+ }
15
+ export declare function createHeldFold(world: World): HeldFold;
@@ -4,7 +4,7 @@ export * from "./host/index";
4
4
  export * from "./compose/index";
5
5
  export * from "./kit/index";
6
6
  export * from "./object";
7
- export { type DataChildren, FLUX_REST, type HeldContext, type HeldReadoutContext, type HeldToolDef, type InsideContext, isObjectKind, type KindDriver, type KindDriverHost, type KindHost, type KindLocal, numberProp, type ObjectContext, type ObjectDomHost, type ObjectFlux, type ObjectHit, type ObjectHost, type ObjectKind, type ObjectRect, type OpenBinding, rectFrame, rectOf, type RungContext, type StratumName, stringProp } from "./kinds/world";
7
+ export { type DataChildren, FLUX_REST, type HeldContext, type HeldCursorContext, type HeldEvent, type HeldReadoutContext, type HeldToolDef, type InsideContext, isObjectKind, type KindDriver, type KindDriverHost, type KindHost, type KindLocal, numberProp, type ObjectContext, type ObjectDomHost, type ObjectFlux, type ObjectHit, type ObjectHost, type ObjectKind, type ObjectRect, type OpenBinding, rectFrame, rectOf, type RungContext, type StratumName, stringProp } from "./kinds/world";
8
8
  export { carryOf, focusOf, HELD_USER_REST, type HeldPose, type HeldUser, type HeldViewport, heldCamera, heldFrame, heldPose, HOLD, type HoldOptions, type HoldReserves, type HomePose, homePose, isNarrow, type ReadingTarget, readingTarget } from "./hold/pose";
9
9
  export { NO_DOCS, type TypingDocs, type WritableSession, writable } from "./docs";
10
10
  export { createKindFaults, faultText, KIND_MISSING, KIND_STRIKES, type KindFault, type KindFaults } from "./faults";
@@ -87,7 +87,11 @@ export interface KindPass<R = unknown> {
87
87
  * its own before the frame's, as the whiteboard's stamps and drying do). Returns the count that will draw.
88
88
  */
89
89
  prepare(encoder: GPUCommandEncoder, slot: SlotContext, records: readonly R[], extra?: KindExtra): number;
90
- /** Draw records [first, end) — indices into this frame's `records` — in their order, into the open pass. */
90
+ /**
91
+ * Draw records [first, end) — indices into this frame's `records` — in their order, into the open pass: with as many of the kind's
92
+ * own pipelines as it draws them with (a LIGHT pipeline multiplies what lies below the run, and nothing in the hand target — the
93
+ * header's light pass).
94
+ */
91
95
  drawRange(pass: GPURenderPassEncoder, first: number, end: number): void;
92
96
  /**
93
97
  * The kind's persistent record store's counters (design-015 §4.3; D6) — records packed and uploaded, draw lists rewritten — a
@@ -61,6 +61,43 @@ export type { HeldToolDef } from "../../../core/src/index";
61
61
  export interface HeldReadoutContext extends Pick<HeldToolApi, "world" | "entity" | "props"> {
62
62
  readonly local: unknown;
63
63
  }
64
+ /** What a kind's `open.cursor` reads (design-019 §5, M24 LT2): the object in hand, the NAMED part under the mouse, the kind's state on this desk. */
65
+ export interface HeldCursorContext {
66
+ readonly entity: Entity;
67
+ readonly part: string;
68
+ readonly local: unknown;
69
+ }
70
+ /**
71
+ * One thing the HAND did with the object in hand, TOLD to its kind (design-019 §5, M24 LT2 — `KindLocal.held`), in the held extent's
72
+ * own units, centred (as core's `HeldPointer` is: the open extent, through the pose the renderer drew). A kind reaches the desk through
73
+ * `/desk`, `/desk/kit` and `/desk/engine` alone, so it is TOLD its input — it never reads core's pointer components.
74
+ * - `pointer`: the `down`, each frame's `move` (one sample a frame — the ingest folds a frame's moves) and the `up` of a press ON the
75
+ * object — on one of the kind's named parts (the kind's own: never a tap that puts it down), on its `content` or `frame` (two instant
76
+ * taps there still put it down — the hand's rule), with a mode in hand on its surface — and the pointer's moves between presses, over
77
+ * the object or off it. `part`: the kind's own `hit` under it (null over nothing); `button` the one pressed or released (0 — a press in
78
+ * hand is the primary's, petition I28; −1 on a move); `buttons` the mask held (a primary press's never empty); `count` the press's
79
+ * click count (core's `HeldPress.count`: 1, 2, 3… within the desk's multi-tap window and slop; 0 on a move). A press the HAND takes —
80
+ * a pan (the middle button, Space), a press on the soft desk — is never told, nor its moves; a press of the kind's still down when the
81
+ * hand lets go is told its `up` where the pointer was last.
82
+ * - `wheel`: a plain wheel while the object is in hand and its kind takes the wheel (`OpenBinding.wheel: "kind"`) — the frame's deltas, CSS
83
+ * px of the hand, at the pointer's point over the object or off it (the kind decides what lands on it).
84
+ */
85
+ export type HeldEvent = {
86
+ readonly type: "pointer";
87
+ readonly phase: "down" | "move" | "up";
88
+ readonly x: number;
89
+ readonly y: number;
90
+ readonly part: ObjectHit | null;
91
+ readonly button: number;
92
+ readonly buttons: number;
93
+ readonly count: number;
94
+ } | {
95
+ readonly type: "wheel";
96
+ readonly x: number;
97
+ readonly y: number;
98
+ readonly dx: number;
99
+ readonly dy: number;
100
+ };
64
101
  /**
65
102
  * The kind's OPENING (design-015 §8; D4b) — what "pick it up" means for this kind. `extent`: the OPEN rect in the object's
66
103
  * own desk units, centred as its rect is and UNTURNED (the builder turns it with the object): a notebook's spread (twice the
@@ -93,6 +130,27 @@ export interface OpenBinding {
93
130
  * word draws nothing of the desk).
94
131
  */
95
132
  readonly readout?: string | ((ctx: HeldReadoutContext) => string | undefined);
133
+ /**
134
+ * The WHEEL in hand (design-019 §5, M24 LT2): `"hand"` (the default — a plain wheel moves the object once brought close) or `"kind"`
135
+ * — a plain wheel while it is held is the kind's, told as a `HeldEvent` "wheel" with its point (a page scrolls); the hand never pans
136
+ * for it. ⌘-wheel and the pinch still zoom the hand, and past 0.72× still put it down. Carried onto the widget type (`heldWheel`) by
137
+ * `defineObject`, where core's held input reads it.
138
+ */
139
+ readonly wheel?: "hand" | "kind";
140
+ /**
141
+ * The CURSOR in hand (design-019 §5, M24 LT2): asked while the object is held and the mouse is over one of the kind's NAMED parts
142
+ * (any but `content` and `frame`) — a link's `pointer`, a text field's `text`, from what its source says (`LiveInfo.cursor`); the
143
+ * desk shows it above its own (core's L4), written to the container only when it changes. `undefined` or "": the desk's own. One
144
+ * that throws is a strike against the kind (petition I24) and the desk's own is shown.
145
+ */
146
+ cursor?(ctx: HeldCursorContext): string | undefined;
147
+ /**
148
+ * ESCAPE in hand (design-019 §5, M24 LT2): `"desk"` (the default — Esc puts the object down, in one press even while its kind leases
149
+ * the editor) or `"kind"` — Esc is the kind's (a source that owns it: a terminal; its lease takes the key): the keymap never puts the
150
+ * object down for it nor blurs the editor, and the hand is put down by Done, a click off it, or the pinch. Carried onto the widget
151
+ * type (`heldEscape`) by `defineObject`, where the keymap reads it.
152
+ */
153
+ readonly escape?: "desk" | "kind";
96
154
  }
97
155
  /**
98
156
  * What the builder hands the object IN HAND (D4b, beside its flux): the carry amount `e` (0 on the desk … 1 in hand — the
@@ -154,8 +212,9 @@ export interface KindHost {
154
212
  * decoder `PICTURE_DECODER`, the app's byte store `BLOB_STORE`, anything in `deskLayer({ services })`) and what any object's DOM
155
213
  * half lends (`ObjectHost.lend` — the desk calendar's `PRINT_RASTER`): `use(key)` answers it, or undefined when nothing on this
156
214
  * desk lends it (in Node the oracle pins committed rasters and tiles). Absent: a bare host (a test) — no services at all.
157
- * D-K8a.1: the desk's OWN doors stay fields of this host — `pass`, `children`, `drawn`, `budget`, `rasters`, `remake`, `wake`: the
158
- * builder's word, its budget, its queue and its loop, made by the desk for each kind and never lent, replaced or taken by a kind.
215
+ * D-K8a.1: the desk's OWN doors stay fields of this host — `pass`, `children`, `drawn`, `budget`, `rasters`, `remake`, `wake`,
216
+ * `redraw`, `keyOf`, `frames`: the builder's word, its budget, its queue, its loop and the document's keys, made by the desk for each
217
+ * kind and never lent, replaced or taken by a kind.
159
218
  */
160
219
  use?<T>(key: ServiceKey<T>): T | undefined;
161
220
  /** An object's DATA children (D3w, design-015 §5.1 — a board's strokes, a pad's events and pins); absent = none (a test, the oracle). */
@@ -186,6 +245,31 @@ export interface KindHost {
186
245
  * kind never polls for what an arrival can tell it. Absent (a bare host, the oracle): its tick is asked every frame.
187
246
  */
188
247
  readonly wake?: (() => void) | undefined;
248
+ /**
249
+ * DRAW AGAIN, REMAKE NOTHING (design-019 §3.3, M24 LT1): the next frame is encoded again and no record is remade — what a kind
250
+ * asks when something its pass reads changed under records that stand (a live face's texture took a frame: `LiveFace.take`
251
+ * answered true). Called in the kind's tick (whose answer is then FALSE — true would remake every record of the kind) or from
252
+ * outside a frame; either way the frame is drawn and a sleeping loop wakes for it — the reflector dirtied as a driver's and a DOM
253
+ * half's `wake` dirty it. Absent (a bare host): nothing to draw; a still's (`createStill`) does nothing — its one frame follows.
254
+ */
255
+ readonly redraw?: (() => void) | undefined;
256
+ /**
257
+ * THE OBJECT'S DURABLE KEY (design-019 §3.5, M24 LT1): strata's durable entity key (`DurableStore.keyOf`, strata §14.3) — minted
258
+ * ONCE for the entity by the peer whose transaction made it (`<peer>-<n>`: a peer's counter resumes past its own keys, so a key
259
+ * is never minted twice) and carried in the document as the entity's own key, so every peer projects the entity under it and a
260
+ * reload binds it to its new runtime handle: the same on every peer and across reloads, where the `Entity` is neither. A host
261
+ * names an outside surface by it (a page re-attached on reload, not restarted). Undefined for a runtime-only entity (a tray's
262
+ * insert ghost, a specimen) and with no document. Absent (a bare host): none known.
263
+ */
264
+ readonly keyOf?: ((e: Entity) => string | undefined) | undefined;
265
+ /**
266
+ * THE DESK'S FRAMES (design-019 §3.4, M24 LT1): how many frames this desk has drawn — the reflector's count
267
+ * (`DeskLayerHandle.redraws()`), moving once per frame drawn and never for a capture. A kind with no records in a slot is never
268
+ * prepared, and a kind is ticked on steps that draw nothing (an input step), so "my pass was not asked" means "not drawn" only when
269
+ * a frame WAS drawn: what a kind that folds its prepares per frame reads for that boundary (`createSight(host.frames)`). Absent (a
270
+ * bare host, a still): every step is taken as a frame.
271
+ */
272
+ readonly frames?: (() => number) | undefined;
189
273
  }
190
274
  /**
191
275
  * An object's DATA children as its kind reads them (D3w): entities `ChildOf` the object, never members of the desk's
@@ -240,6 +324,13 @@ export interface KindLocal {
240
324
  veils?(): ReadonlySet<Entity>;
241
325
  /** The kind's word on a raster it charged to the budget (D6): true = on screen this frame, never evicted now. */
242
326
  keeps?(key: string): boolean;
327
+ /**
328
+ * The HAND's input while `e` is IN HAND (design-019 §5, M24 LT2 — `HeldEvent`): called once a frame something happened, after the
329
+ * drivers and before the kinds' ticks, with the frame's events in order. The desk derives them from what core writes (`HeldPointer`,
330
+ * `HeldPress`, `HeldWheel`) — never a second input path — so a kind's DOM half and its world half see one hand. A kind that keeps a
331
+ * driver of its own (the calendar's hand) may read core's facts instead. One that throws is a strike against the kind (petition I24).
332
+ */
333
+ held?(e: Entity, events: readonly HeldEvent[]): void;
243
334
  dispose?(): void;
244
335
  }
245
336
  /** What a kind's `rung` reads (K6b): the object as the builder holds it, its SLOT's zoom (an inside's is its host's face's) and the dpr, and its kind's state on this desk. */
@@ -39,8 +39,16 @@ export interface EditorLease {
39
39
  * (a peer's, an undo) reaches the platform's field; `null`: keep the field's own (a session is open — the field is the truth).
40
40
  */
41
41
  value(): string | null;
42
- /** The platform's value after an input event. */
42
+ /** The platform's value after an input event (while a composition runs, only for a lease that declares no `compose`). */
43
43
  input(value: string): void;
44
+ /**
45
+ * The IME's COMPOSITION as it runs (design-019 §5, M24 LT2 — the preedit a remote page's IME is driven by): told once as it starts
46
+ * (`""`, 0) and after each update the platform applies — the composition's text and the caret within it. A lease that declares it is
47
+ * told the composition INSTEAD of `input` values while one runs; absent, it sees the field's values as ever (the preedit inside them).
48
+ */
49
+ compose?(text: string, caret: number): void;
50
+ /** The composition COMMITTED (`compositionend`'s data, M24 LT2) — the text it ended with ("" when it was cancelled). */
51
+ commit?(text: string): void;
44
52
  /** A key the lease takes: true — handled (the editor prevents its default, so the keymap stands down). */
45
53
  keydown(ev: KeyboardEvent): boolean;
46
54
  /** The caret moved (a selection change, a tap, a value the world moved): its index. */
@@ -7,6 +7,7 @@ export * from "./hold";
7
7
  export * from "./inside";
8
8
  export * from "./layer";
9
9
  export * from "./light";
10
+ export * from "./live";
10
11
  export * from "./mesh";
11
12
  export * from "./mips";
12
13
  export * from "./nav";