@vibecook/ice 0.14.0 → 0.15.0-desk.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 (62) hide show
  1. package/dist/{chunk-ZPUPBULB.js → chunk-52GMQ2BN.js} +1320 -450
  2. package/dist/chunk-52GMQ2BN.js.map +1 -0
  3. package/dist/{chunk-BA7XJC27.js → chunk-K4HUZAYJ.js} +49 -34
  4. package/dist/chunk-K4HUZAYJ.js.map +1 -0
  5. package/dist/{chunk-DYK6KNLG.js → chunk-PFJN3XN2.js} +39 -14
  6. package/dist/chunk-PFJN3XN2.js.map +1 -0
  7. package/dist/{chunk-IBWWLA6D.js → chunk-U4YMA4TJ.js} +6 -5
  8. package/dist/chunk-U4YMA4TJ.js.map +1 -0
  9. package/dist/desk-kit.js +2 -2
  10. package/dist/desk-objects.js +15 -9
  11. package/dist/desk-objects.js.map +1 -1
  12. package/dist/desk.js +31 -3
  13. package/dist/devtools.js +1 -1
  14. package/dist/dom.js +2 -2
  15. package/dist/index.js +1 -1
  16. package/dist/react.js +9 -7
  17. package/dist/react.js.map +1 -1
  18. package/dist/types/packages/core/src/index.d.ts +1 -1
  19. package/dist/types/packages/core/src/interaction/install.d.ts +7 -1
  20. package/dist/types/packages/core/src/systems/held.d.ts +3 -1
  21. package/dist/types/packages/core/src/systems/l1-pick.d.ts +16 -0
  22. package/dist/types/packages/core/src/systems/l2-recognize.d.ts +3 -1
  23. package/dist/types/packages/core/src/systems/press-button.d.ts +25 -0
  24. package/dist/types/packages/core/src/systems/tray.d.ts +3 -0
  25. package/dist/types/packages/desk/src/compose/builder.d.ts +22 -1
  26. package/dist/types/packages/desk/src/compose/marks.d.ts +7 -0
  27. package/dist/types/packages/desk/src/compose/pick.d.ts +1 -1
  28. package/dist/types/packages/desk/src/compose/reflector.d.ts +9 -0
  29. package/dist/types/packages/desk/src/engine/budget.d.ts +5 -0
  30. package/dist/types/packages/desk/src/faults.d.ts +38 -0
  31. package/dist/types/packages/desk/src/ground.d.ts +158 -9
  32. package/dist/types/packages/desk/src/hold/focus.d.ts +1 -1
  33. package/dist/types/packages/desk/src/hold/pose.d.ts +27 -7
  34. package/dist/types/packages/desk/src/host/index.d.ts +1 -1
  35. package/dist/types/packages/desk/src/host/layer.d.ts +110 -4
  36. package/dist/types/packages/desk/src/index.d.ts +5 -2
  37. package/dist/types/packages/desk/src/kind.d.ts +7 -5
  38. package/dist/types/packages/desk/src/kinds/world.d.ts +20 -2
  39. package/dist/types/packages/desk/src/kit/editor.d.ts +3 -1
  40. package/dist/types/packages/desk/src/kit/hold.d.ts +1 -1
  41. package/dist/types/packages/desk/src/missing/layout.d.ts +27 -0
  42. package/dist/types/packages/desk/src/missing/object.d.ts +6 -0
  43. package/dist/types/packages/desk/src/missing/pass.d.ts +39 -0
  44. package/dist/types/packages/desk/src/missing/shaders.d.ts +7 -0
  45. package/dist/types/packages/desk/src/missing/slots.d.ts +8 -0
  46. package/dist/types/packages/desk/src/shaders.gen.d.ts +5 -4
  47. package/dist/types/packages/desk/src/theme.d.ts +22 -0
  48. package/dist/types/packages/desk/src/tray/drawer.d.ts +16 -5
  49. package/dist/types/packages/desk/src/tray/flux.d.ts +4 -1
  50. package/dist/types/packages/desk/src/tray/index.d.ts +1 -1
  51. package/dist/types/packages/desk/src/tray/pass.d.ts +7 -2
  52. package/dist/types/packages/desk/src/tray/specimens.d.ts +21 -6
  53. package/dist/types/packages/dom/src/desk-host.d.ts +15 -2
  54. package/dist/types/packages/dom/src/pointer-adapter.d.ts +6 -0
  55. package/dist/types/packages/objects/src/board/layout.d.ts +1 -1
  56. package/dist/types/packages/objects/src/shaders.gen.d.ts +1 -1
  57. package/dist/types/packages/react/src/selection-menu.d.ts +5 -2
  58. package/package.json +1 -1
  59. package/dist/chunk-BA7XJC27.js.map +0 -1
  60. package/dist/chunk-DYK6KNLG.js.map +0 -1
  61. package/dist/chunk-IBWWLA6D.js.map +0 -1
  62. package/dist/chunk-ZPUPBULB.js.map +0 -1
@@ -1,12 +1,14 @@
1
- import { type Entity, type FramePickSlot, type HeldPoseSlot, type MarqueeBuffer, type NavFace, type NavGeometrySlot, type PresentationTransitionAdapter, type ReflectorDef, type TrayCategory, type TrayPoseSlot, type TrayScreenFrame, type WidgetType, type World } from "../../../core/src/index";
1
+ import { type Entity, type FramePickSlot, type HeldPoseSlot, type MarqueeBuffer, type NavFace, type NavGeometrySlot, type PointPick, type PresentationTransitionAdapter, type ReflectorDef, type TrayCategory, type TrayPoseSlot, type TrayScreenFrame, type WidgetType, type World } from "../../../core/src/index";
2
2
  import { type Ambient, type AmbientMode, type AmbientPin } from "../compose/ambient";
3
3
  import { type DeskBuilder, type HeldBuild, type HoldPin, type SpatialSource } from "../compose/builder";
4
4
  import { type BudgetStats } from "../engine/budget";
5
5
  import { type RasterQueueStats } from "../engine/rasters";
6
6
  import type { RecordStoreStats } from "../engine/records";
7
+ import { type HoldOptions } from "../hold/pose";
7
8
  import { type SelectionAnchor } from "../compose/marks";
8
9
  import { type DeskReflector, type DeskReflectorStats, type DeskWakes } from "../compose/reflector";
9
- import { Ground, type GroundFrameInputs } from "../ground";
10
+ import { type KindFault } from "../faults";
11
+ import { type CaptureOptions, Ground, type GroundFrameInputs } from "../ground";
10
12
  import type { KindProgram } from "../kind";
11
13
  import type { ObjectFlux } from "../kinds/world";
12
14
  import { type GridConfig } from "../mat/grid";
@@ -23,6 +25,7 @@ import { type MemoryLedger } from "../gpu-memory";
23
25
  import { type GpuProfiler } from "../gpu-profiler";
24
26
  import { type SubmitInstrument } from "../submit-instrument";
25
27
  import type { GroundTheme, Palette } from "../theme";
28
+ import { type TrayOptions } from "../tray/drawer";
26
29
  import type { TrayFluxState, TrayPin } from "../tray/flux";
27
30
  import type { TrayLaid } from "../tray/pass";
28
31
  export interface DeskLayerOptions {
@@ -43,6 +46,27 @@ export interface DeskLayerOptions {
43
46
  readonly ambientIdleMs?: number;
44
47
  /** The root's grid at the mount: the mat's config (its gobo, its rulers) and the lattice's fade-in. */
45
48
  readonly grid?: GridConfig;
49
+ /**
50
+ * THE HAND as the host's chrome needs it (petition I20), read at the mount: the held object's reading fit keeps `top` CSS px under
51
+ * the view's top (`HOLD.top`, 56 — a phone keeps `HOLD.topPhone`) and `band` above its foot (`HOLD.band`, 72 — the held bar's band),
52
+ * and the held bar travels `travelMs` (M1; the bar is the host's — the anchor carries it, `HeldAnchor.travelMs`; absent, the bar's
53
+ * own). Each a finite number ≥ 0; absent, `HOLD`'s.
54
+ */
55
+ readonly hold?: HoldOptions;
56
+ /**
57
+ * THE DRAWER as the host's chrome needs it (petition I21), read at the mount: its `foot` inset, CSS px (0) — the pegboard's laid
58
+ * content ends this far above the board's bottom edge (the face's clip ends there, the veil lays the plain board over it and feathers
59
+ * out over `DRAWER.fade` above it — the header's mirror), where a host's line floats over the board; the scroll's range grows by it,
60
+ * so the last line is still reached; the board runs to its edge. A finite number ≥ 0; absent, 0.
61
+ */
62
+ readonly tray?: TrayOptions;
63
+ /**
64
+ * THE ROOM'S OTHER PEOPLE (petition I26), read at the mount: `false` — the host draws its peers itself (VibeField draws each by
65
+ * face, from `usePresencePeers`), so the host the layer is mounted in (`@ice/dom`'s `createDeskHost`, `<Desk>`) mounts no remote
66
+ * cursors — no plane, no reflector; the layer says so on its handle (`DeskLayerHandle.cursors`). The presence session,
67
+ * `usePresencePeers` and the local OS and open-hand cursors are untouched. Absent or `true`, the host draws them, as ever.
68
+ */
69
+ readonly cursors?: boolean;
46
70
  /** The objects' springs (springs.ts `SPRINGS`): the builder reads these numbers every frame, so a host that keeps the object may tune them live (the dev panel — D5a). */
47
71
  readonly springs?: ObjectSprings;
48
72
  /** The device pixel ratio the canvas is capped at (2). */
@@ -105,10 +129,17 @@ export interface MatPin extends AmbientPin {
105
129
  * nobody captured (out of memory, a validation or an internal error): the desk still draws what it can, but a frame — or every frame,
106
130
  * an attachment left invalid — may be lost, and the state never reads `ready` again on its own (D7); `failed` — no desk (refused, or
107
131
  * the device lost). `message` names the cause.
132
+ *
133
+ * `faults` (petition I24) — the KINDS this desk draws as MISSING, each its name and why, in the order they went: refused at create (a
134
+ * pass that would not compile, a pipeline that failed validation) or quarantined at three strikes (a `resolve`, `record`, `chip`, `hit`,
135
+ * `tick` or `due` that threw — src/faults.ts). Absent while none is. One kind's fault is that kind's: the state does not move for it
136
+ * (`ready` stays `ready`), its objects wear the desk's missing face, nothing of it is called again. Each is said ONCE — the status
137
+ * moves when a kind goes missing (`onStatus` hears it; a kind refused at the boot rides the boot's own `ready`), never again for it.
108
138
  */
109
139
  export interface DeskLayerStatus {
110
140
  readonly state: "pending" | "ready" | "degraded" | "failed";
111
141
  readonly message?: string;
142
+ readonly faults?: readonly KindFault[];
112
143
  }
113
144
  /** The mount context — the fields of `@ice/dom`'s `LayerContext` this layer reads, mirrored structurally (dom never imports the desk). */
114
145
  export interface DeskLayerContext {
@@ -117,6 +148,11 @@ export interface DeskLayerContext {
117
148
  };
118
149
  readonly world: World;
119
150
  readonly framePick?: FramePickSlot;
151
+ /**
152
+ * The interaction stack's exact pick out of the tick (`stack.pickAt`, petition I27 — what a press at a screen point would touch now,
153
+ * through `framePick` above): the handle's `pick` answers a host through it. Absent (a bare host), `pick` answers null.
154
+ */
155
+ readonly pickAt?: (sx: number, sy: number) => PointPick | undefined;
120
156
  /** The nav geometry seam (design-015 §9, D2b): the desk sets its word on its containers' drawn faces here, clears it at dispose. */
121
157
  readonly navGeometry?: NavGeometrySlot;
122
158
  /** The held pose seam (design-015 §8, D4b): the desk publishes where the object in hand is ON SCREEN as it drew it; core's held input maps every pointer through it. */
@@ -154,6 +190,26 @@ export interface SelectionSource {
154
190
  anchor(): SelectionAnchor;
155
191
  subscribe(listener: () => void): () => void;
156
192
  }
193
+ /**
194
+ * The object under a screen point as the desk's own pick resolves it (petition I27 — `DeskLayerHandle.pick`): what a press there
195
+ * touches, so what a primary click there selects — the host selects it through the engine's ops (`ops.setSelection([entity])`) and
196
+ * reads its acts off the selection's anchor.
197
+ */
198
+ export interface PickResult {
199
+ readonly entity: Entity;
200
+ /** Its object type (its `PrefabId`) — what the host names it by and finds its type with (`engine.catalog.widget(type)`). */
201
+ readonly type: string;
202
+ /**
203
+ * The canvas it lies in — the frame the pick is made in: the board root on the root desk, the container entered (a mini mat whose
204
+ * desk is the view); `NO_ENTITY` in a world with no document.
205
+ */
206
+ readonly canvas: Entity;
207
+ /**
208
+ * Its kind's PART under the point (design-014): `""` the object itself — its body or its frame, which a click selects; a named part
209
+ * (the calendar's roll, corner and foot) is the kind's own — a click there works the part and selects nothing.
210
+ */
211
+ readonly part: string;
212
+ }
157
213
  /**
158
214
  * The desk's MAIN-THREAD time (D6): every flush of the layer's reflector — the kinds' ticks, the pull, the build and the
159
215
  * render when a frame is due — counted and timed since the mount; `frames` are the flushes that drew, `frameMs` their share.
@@ -168,6 +224,20 @@ export interface DeskLayerPerf {
168
224
  readonly kindTicks: Readonly<Record<string, number>>;
169
225
  /** The drivers asked (`idle`, then `follow`): none on a step a registered time alone started (K7a). */
170
226
  readonly driverAsks: number;
227
+ /** The mount's own cost as its boot went (petition I25). */
228
+ readonly boot: DeskLayerBoot;
229
+ }
230
+ /**
231
+ * THE MOUNT'S COST (petition I25 — a desk's kinds are compiled at its mount, so a host that changes them remounts, and may veil it):
232
+ * the boot's milestones, ms since the mount (the factory's call, on `performance.now()`'s clock), each absent until it happens — for
233
+ * good on a boot that failed. `device`: the device in hand (the adapter and the device asked for, or the engine's adopted); `compiled`:
234
+ * the passes compiled (`Ground.create` resolved — the status `ready`); `presented`: the first frame's GPU work done
235
+ * (`queue.onSubmittedWorkDone()` after its submit — the compositor's from then).
236
+ */
237
+ export interface DeskLayerBoot {
238
+ readonly device?: number;
239
+ readonly compiled?: number;
240
+ readonly presented?: number;
171
241
  }
172
242
  /**
173
243
  * The pegboard tray's door (design-017; K3) — the app's `a` and a rig's hand: the facts through core's tray ops (the one writer beside
@@ -288,6 +358,11 @@ export interface DeskLayerHandle {
288
358
  available(): boolean;
289
359
  };
290
360
  dispose(): void;
361
+ /**
362
+ * Whether the host mounts the room's other people's cursors (petition I26): `deskLayer({ cursors })` as read at the mount, `true`
363
+ * when absent — `@ice/dom`'s `createDeskHost` reads it off the handle (its structural `LayerHandle.cursors`) before it registers them.
364
+ */
365
+ readonly cursors: boolean;
291
366
  /** The canvas in the ground slot. */
292
367
  readonly canvas: HTMLCanvasElement;
293
368
  /** The device is acquired and `Ground.create` resolved. */
@@ -304,6 +379,35 @@ export interface DeskLayerHandle {
304
379
  ground(): Ground | null;
305
380
  /** The theme changed (and, with it, the palette): the looks are remade, the next frame re-renders. */
306
381
  setTheme(theme: GroundTheme, palette?: Palette): void;
382
+ /**
383
+ * THE CAPTURE DOOR (petition I23 — the covers' still, the thumbnails, "Send to…"): the desk as the LAST PRESENTED frame showed
384
+ * it — the same camera, theme, selection marks, hand and tray (what to hide is the host's, by its own doors, before the call) —
385
+ * as an `ImageBitmap` of `rect` (CSS px of the view; the whole view when absent) at the view's dpr × `scale` (1; a thumbnail
386
+ * asks 0.25). Inside: that frame's inputs drawn ONCE MORE into a readable texture at the asked size and read back
387
+ * (`Ground.capture`) — never a copy kept of every frame, never a frame: the swap chain is not touched, the loop is not woken, no
388
+ * frame is counted (`redraws()`, `perf().frames`), and the memory ledger shows the still and its readback as a `capture` line of
389
+ * its own while they live and nothing after. Taken while the frame gate holds (`engine.frame.freeze`), it is the parked frame;
390
+ * live, the most recent. `undefined`, never a throw, while `status()` is `failed` or `degraded`, before the first frame has been
391
+ * presented, or when the device is lost mid-copy (a malformed option throws at the call). Captures serialize; one asked for the
392
+ * same picture (equal options, no frame since) while another is in flight resolves to that one's bitmap.
393
+ */
394
+ capture(opts?: CaptureOptions): Promise<ImageBitmap | undefined>;
395
+ /**
396
+ * THE DESK'S PICK (petition I27 — a host's right-click selects the object under the pointer before it grows the menu): the object
397
+ * at `point` (CSS px of the view, the container's top-left at 0, 0 — a pointer event's client point less the container's rect) as
398
+ * the desk's own pick resolves it. Inside: the interaction stack's exact pick (`stack.pickAt`, through the mount context) — the one
399
+ * body a press's `TouchesExact` is written by, never a second hit path — so the answer is what a primary click there selects: the
400
+ * topmost object by stratum and sibling order through its kind's mirror on the last frame's geometry, its PART reported; on a live
401
+ * mini mat's face the mini mat (its inside's objects are no members of this frame — entered, they pick with it as their canvas).
402
+ * Synchronous; reads the last frame's world — no redraw, no wake, no write; it never selects (the host decides). `null` over the
403
+ * bare mat and its rulers (printed on it), over what is not an object (a resize handle), while an object is in hand or the
404
+ * pegboard drawer is out (the desk inert to the pointer — D4b, design-017 §4), before the first frame, and while `status()` is
405
+ * `pending` or `failed` (`degraded` picks: the desk still draws, a click still selects). A point that is not two finite numbers throws.
406
+ */
407
+ pick(point: {
408
+ readonly x: number;
409
+ readonly y: number;
410
+ }): PickResult | null;
307
411
  /** The mat's config over the current one (the rulers, the gobo): the root's grid. */
308
412
  configureMat(mat: Partial<MatConfig>): void;
309
413
  /** The lattice's fade-in window. */
@@ -365,7 +469,7 @@ export interface DeskLayerHandle {
365
469
  ambient(): Ambient;
366
470
  /** The submit instrument on the layer's device — installed the first time it is asked for (K2, D-K2.1: never asked, the queue carries no wrapper), counting from then; undefined before the device. */
367
471
  submits(): SubmitInstrument | undefined;
368
- /** The layer's own main-thread time since the mount (D6, design-015 §11.4's idle gate): a rig diffs two readings. */
472
+ /** The layer's own main-thread time since the mount (D6, design-015 §11.4's idle gate): a rig diffs two readings. And the boot's milestones (`boot`, petition I25). */
369
473
  perf(): DeskLayerPerf;
370
474
  /** The raster budget's ledger (D6): what the kinds' caches hold, by owner, against the cap; the evictions so far. */
371
475
  memory(): BudgetStats;
@@ -387,7 +491,9 @@ export interface DeskLayerHandle {
387
491
  /**
388
492
  * The desk's registered wake taken apart (K7a — "why is the desk awake?"): when each part is next due, on `performance.now()`'s
389
493
  * clock (`Infinity`: never on its own) — the reflector's, the drivers' (now while one follows), a kind woken, each kind's `due`,
390
- * the tray's layers' let-go (`tray`, K7a over K5a) and the raster queue's waiting asks (`rasters`, K6b: now while any wait).
494
+ * the tray's layers' let-go (`tray`, K7a over K5a) and the raster queue's waiting asks (`rasters`, K6b: now while any wait). A
495
+ * MISSING kind (petition I24) is a row of `kinds` whatever it declares: `KIND_MISSING` (−1 — no time; it is never due, nothing of
496
+ * it runs), and `at` never counts it.
391
497
  */
392
498
  due(now: number): {
393
499
  readonly at: number;
@@ -4,9 +4,12 @@ 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 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
- export { carryOf, focusOf, HELD_USER_REST, type HeldPose, type HeldUser, type HeldViewport, heldCamera, heldFrame, heldPose, HOLD, type HomePose, homePose, isNarrow, type ReadingTarget, readingTarget } from "./hold/pose";
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";
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
+ export { createKindFaults, faultText, KIND_MISSING, KIND_STRIKES, type KindFault, type KindFaults } from "./faults";
11
+ export { MISSING_KIND, MISSING_OBJECT } from "./missing/object";
12
+ export { isMissingRecord, missingFace, type MissingRecord } from "./missing/layout";
10
13
  export * from "./theme";
11
14
  export * from "./shaders";
12
15
  export { BLUE_NOISE_SIZE, blueNoise } from "./assets/blue-noise.gen";
@@ -23,12 +23,14 @@ export declare const STRATA: readonly StratumName[];
23
23
  */
24
24
  /**
25
25
  * The render a slot is prepared for (D7): the FRAME (the desk as it is), the COPY (the desk behind a carried object, made once
26
- * per stamp and blurred), or the HAND (K9 R4 — the carried object alone, prepared EVERY frame of the carry while the copy
27
- * stands). A pass that keeps state per render keeps the copy's apart; a pass whose residency asks are per prepare (the
28
- * pictures' details, the boards' pool) re-asks what it has bound under the hand, else the tick's step — seeing only the hand's
29
- * asks — would free every other detail on the desk behind it, a softness pop at every put-down.
26
+ * per stamp and blurred), the HAND (K9 R4 — the carried object alone, prepared EVERY frame of the carry while the copy
27
+ * stands), or a CAPTURE (petition I23, `ground.ts` `captureFrame` — the last presented frame's inputs drawn ONCE MORE into a
28
+ * readable texture at the asked scale, outside any frame; the desk's own frame stands as drawn). A pass that keeps state per
29
+ * render keeps the copy's apart; a pass whose residency asks are per prepare (the pictures' details, the boards' pool) re-asks
30
+ * what it has bound under the hand AND under a capture, else the tick's step — seeing only the hand's asks, or a thumbnail's
31
+ * coarser ones — would free every other detail on the desk behind it, a softness pop at every put-down.
30
32
  */
31
- export type RenderTarget = "frame" | "copy" | "hand";
33
+ export type RenderTarget = "frame" | "copy" | "hand" | "capture";
32
34
  export interface SlotContext {
33
35
  /** The slot's camera and box (CSS px) and the device pixel ratio. */
34
36
  readonly view: View & {
@@ -1,4 +1,4 @@
1
- import type { Component, Entity, HeldToolDef, Relation, Tag, WidgetType, World } from "../../../core/src/index";
1
+ import type { Component, Entity, HeldToolApi, HeldToolDef, Relation, Tag, WidgetType, World } from "../../../core/src/index";
2
2
  import type { TypingDocs } from "../docs";
3
3
  import type { RasterBudget } from "../engine/budget";
4
4
  import type { RasterQueue } from "../engine/rasters";
@@ -53,6 +53,14 @@ export type ObjectHit = "content" | "frame" | (string & {});
53
53
  * or — no `kind` — declared only (dim; a later slice builds it). `glyph` names one of the bar's.
54
54
  */
55
55
  export type { HeldToolDef } from "../../../core/src/index";
56
+ /**
57
+ * What a kind's `open.readout` reads (petition I22): the READ side of what its held tools' acts are handed (core's `HeldToolApi` —
58
+ * the world, the object in hand, its props as the world holds them now) and the kind's own state on this desk (`local`, as `page`
59
+ * and `openness` read it: the spread a turn is heading for, the time a clock's hands show). A readout never writes.
60
+ */
61
+ export interface HeldReadoutContext extends Pick<HeldToolApi, "world" | "entity" | "props"> {
62
+ readonly local: unknown;
63
+ }
56
64
  /**
57
65
  * The kind's OPENING (design-015 §8; D4b) — what "pick it up" means for this kind. `extent`: the OPEN rect in the object's
58
66
  * own desk units, centred as its rect is and UNTURNED (the builder turns it with the object): a notebook's spread (twice the
@@ -64,7 +72,8 @@ export type { HeldToolDef } from "../../../core/src/index";
64
72
  * two-page extent that opens one page at a time on a portrait phone (Q-p); `page`: which of its two is in view there — 0 the
65
73
  * right (the default) … 1 the left, flux the view glides by (D3t-b: the notebook reads page by page). `tools`: the held bar's
66
74
  * slots (D3t-a: live — a mode or an action each); `tool`: the mode in hand when it is picked up, from its props (default: the first mode);
67
- * `swatches`: the colour a slot shows instead of its glyph (the board's four inks — the product's palette, through the look).
75
+ * `swatches`: the colour a slot shows instead of its glyph (the board's four inks — the product's palette, through the look), read
76
+ * with the anchor as `readout` is — a throw leaves the slots their glyphs, said once, never a strike (petition I24).
68
77
  */
69
78
  export interface OpenBinding {
70
79
  extent(ctx: Pick<ObjectContext, "rect" | "props">): ObjectRect;
@@ -75,6 +84,15 @@ export interface OpenBinding {
75
84
  readonly tools?: readonly HeldToolDef[];
76
85
  tool?(props: Readonly<Record<string, unknown>>): string;
77
86
  swatches?(look: unknown): Readonly<Record<string, string>>;
87
+ /**
88
+ * The kind's WORD IN HAND (petition I22 — MC-D9's readouts): where the hand is, said beside its tools — the notebook's "Page 2",
89
+ * the calendar's "September", a clock's time. A string, or read each time the selection's anchor is recomposed (the pickup, a
90
+ * mode taken up, a held tool's act run — every frame drawn while it is held) and surfaced as `HeldAnchor.readout`; `undefined`
91
+ * or "" — no word. A readout that throws is caught at the kind's boundary: the anchor keeps the tools and carries no word, and the
92
+ * desk says so once — never a strike against the kind (petition I24: the anchor is read at the host's rate and only in hand, and a
93
+ * word draws nothing of the desk).
94
+ */
95
+ readonly readout?: string | ((ctx: HeldReadoutContext) => string | undefined);
78
96
  }
79
97
  /**
80
98
  * What the builder hands the object IN HAND (D4b, beside its flux): the carry amount `e` (0 on the desk … 1 in hand — the
@@ -26,7 +26,8 @@ export interface EditorPlace {
26
26
  }
27
27
  /**
28
28
  * A LEASE on the ONE editor (D3t-c; K8a — any kind's): while lent, the textarea's value, keys, caret and blur are the lease's, and
29
- * it says where the textarea stands; another lease, a blur, `release`, or `live()` answering false ends it (`ended`).
29
+ * it says where the textarea stands; another lease, a blur, `release`, `live()` answering false or the editor's `dispose` (the desk
30
+ * unmounted — petition I25) ends it (`ended`).
30
31
  */
31
32
  export interface EditorLease {
32
33
  /** The TEXT PART this lease writes — its kind's declared `TextPart.part` ("note.body", "calendar.line"): what `lease()` names. */
@@ -74,6 +75,7 @@ export interface DeskEditor {
74
75
  readonly h: number;
75
76
  readonly angle: number;
76
77
  } | null;
78
+ /** The editor goes with its desk: a lease still held ends first (`ended` — a typing session commits), then the textarea leaves. */
77
79
  dispose(): void;
78
80
  }
79
81
  /**
@@ -1 +1 @@
1
- export { carryOf, HOLD, readingTarget } from "../hold/pose";
1
+ export { carryOf, HOLD, type HoldReserves, readingTarget } from "../hold/pose";
@@ -0,0 +1,27 @@
1
+ import type { ObjectRect } from "../kinds/world";
2
+ import { type GroundTheme, type RGB } from "../theme";
3
+ /** The face's record as the pass's WGSL reads it (shaders/missing/missing-pass.wgsl). */
4
+ export declare const MissingFace: import("../engine").StructDef<"rect" | "ink" | "shape" | "mix">;
5
+ /** What the missing face draws for one object: its box, its ink and its fade. `missing` brands it — the pass draws nothing else. */
6
+ export interface MissingRecord {
7
+ readonly missing: true;
8
+ readonly cx: number;
9
+ readonly cy: number;
10
+ readonly hx: number;
11
+ readonly hy: number;
12
+ readonly ink: RGB;
13
+ readonly fade: number;
14
+ }
15
+ /** Is this record the missing face's? (A kind's own record handed to its missing pass — the frame before a quarantine took — is not.) */
16
+ export declare const isMissingRecord: (r: unknown) => r is MissingRecord;
17
+ /** The face of an object whose box is `rect` (centred, world units) under `theme`, at `fade` (1 whole … 0 gone). */
18
+ export declare function missingFace(rect: ObjectRect, theme: Pick<GroundTheme, "name">, fade?: number): MissingRecord;
19
+ /** The record's values by field — a record that is not the face's packs as nothing (fade 0: the vertex stage collapses it). */
20
+ export declare function missingValues(r: unknown): {
21
+ rect: number[];
22
+ ink: number[];
23
+ mix: number[];
24
+ shape: number[];
25
+ };
26
+ /** The face's pick: the object itself (`content` — a tap selects it, a drag moves it) anywhere in its box; else a miss. */
27
+ export declare function missingHit(g: ObjectRect, wx: number, wy: number): "content" | null;
@@ -0,0 +1,6 @@
1
+ import type { ObjectKind, ObjectRect } from "../kinds/world";
2
+ import { type MissingRecord } from "./layout";
3
+ /** The name an object whose type has no kind is drawn under (a kind may not take it — ground.ts). */
4
+ export declare const MISSING_KIND = "desk.missing";
5
+ /** The missing face's kind: its program (the ground's own — never registered) and its world half. */
6
+ export declare const MISSING_OBJECT: ObjectKind<ObjectRect, MissingRecord>;
@@ -0,0 +1,39 @@
1
+ import { type RecordStoreStats } from "../engine/records";
2
+ import type { KindExtra, KindPass, SlotContext } from "../kind";
3
+ import type { MatPass } from "../kit/view";
4
+ import type { ShaderText } from "../shaders";
5
+ export declare class MissingPass implements KindPass<unknown> {
6
+ readonly name = "desk/missing";
7
+ private store;
8
+ private group;
9
+ private boundStore;
10
+ private boundAssets;
11
+ private count;
12
+ private readonly device;
13
+ private readonly shared;
14
+ private readonly mat;
15
+ private constructor();
16
+ /**
17
+ * The root's pass on `mat`, made NOW (no await — a quarantine asks for it mid-frame): its layout and its one pipeline (it is lit by
18
+ * nothing — the same in every slot). The desk's own WGSL, composed from the host's text; WebGPU compiles it before its first draw.
19
+ */
20
+ static make(device: GPUDevice, format: GPUTextureFormat, mat: MatPass, text?: ShaderText): MissingPass;
21
+ /** A slot's own faces on the shared pipeline, through `mat`'s view block. */
22
+ spawn(mat: MatPass): MissingPass;
23
+ prepare(_encoder: GPUCommandEncoder, _slot: SlotContext, records: readonly unknown[], extra?: KindExtra): number;
24
+ private rebind;
25
+ drawRange(pass: GPURenderPassEncoder, first: number, end: number): void;
26
+ /** The store's counters (a rig's witness) — nothing until the slot's first face. */
27
+ records(): RecordStoreStats;
28
+ dispose(): void;
29
+ }
30
+ /** A desk's missing faces (petition I24): a slot's own on its mat, at its first ask — the pipeline made at the desk's first. */
31
+ export interface MissingFaces {
32
+ /** A slot's faces on `mat` (the desk's pipeline made now if this is the first). */
33
+ spawn(mat: MatPass): KindPass;
34
+ /** Has the desk made its pipeline (a face was ever asked for)? */
35
+ readonly made: boolean;
36
+ dispose(): void;
37
+ }
38
+ /** The missing faces of a desk on `device` — nothing made until the first `spawn` (then the pipeline, on the root's `mat`). */
39
+ export declare function missingFaces(device: GPUDevice, format: GPUTextureFormat, mat: MatPass, text?: ShaderText): MissingFaces;
@@ -0,0 +1,7 @@
1
+ import type { ComposeOptions } from "../engine/shader";
2
+ import { type ShaderText } from "../shaders";
3
+ export declare const MISSING_SHADER_FILES: {
4
+ readonly entry: "missing/missing-pass.wgsl";
5
+ };
6
+ /** The missing face's program for a host's shader text (default: the desk's generated module). */
7
+ export declare function missingShaders(text?: ShaderText): ComposeOptions;
@@ -0,0 +1,8 @@
1
+ import type { KindPass } from "../kind";
2
+ import type { SlotSet } from "../ground";
3
+ import type { MissingFaces } from "./pass";
4
+ /**
5
+ * Kind `name`'s entry in `s` becomes the desk's missing faces on the slot's mat (`faces` — the root's), under the kind's name and
6
+ * stratum. Returns the pass the entry held (the caller lets it go), or undefined when the slot holds no such kind, or the desk no faces.
7
+ */
8
+ export declare function swapToMissing(s: SlotSet, name: string, faces: MissingFaces | undefined): KindPass | undefined;