@msb235/blits 0.11.0 → 0.12.1

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 (78) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/dist/arcs.d.ts +40 -0
  3. package/dist/arcs.js +241 -0
  4. package/dist/chain.d.ts +6 -1
  5. package/dist/chain.js +33 -13
  6. package/dist/channels.d.ts +2 -0
  7. package/dist/channels.js +12 -1
  8. package/dist/clone.js +16 -4
  9. package/dist/cue.js +11 -2
  10. package/dist/departed.d.ts +5 -1
  11. package/dist/departed.js +71 -27
  12. package/dist/easing.d.ts +12 -1
  13. package/dist/easing.js +7 -1
  14. package/dist/everyone.d.ts +14 -1
  15. package/dist/everyone.js +27 -2
  16. package/dist/fade.js +3 -3
  17. package/dist/fill.js +16 -9
  18. package/dist/fit.d.ts +8 -1
  19. package/dist/fit.js +7 -3
  20. package/dist/fold.js +69 -13
  21. package/dist/gather.js +38 -7
  22. package/dist/handle.d.ts +2 -0
  23. package/dist/handle.js +8 -0
  24. package/dist/held.d.ts +5 -2
  25. package/dist/held.js +6 -3
  26. package/dist/history.d.ts +19 -2
  27. package/dist/history.js +149 -31
  28. package/dist/hosts.js +27 -11
  29. package/dist/index.d.ts +4 -1
  30. package/dist/index.js +2 -0
  31. package/dist/lanes.d.ts +23 -7
  32. package/dist/lanes.js +36 -2
  33. package/dist/lean.js +2 -2
  34. package/dist/marks.js +3 -0
  35. package/dist/mixer.d.ts +16 -1
  36. package/dist/mixer.js +60 -30
  37. package/dist/move.js +7 -2
  38. package/dist/numbers.d.ts +5 -1
  39. package/dist/numbers.js +4 -0
  40. package/dist/owner.js +6 -1
  41. package/dist/place.d.ts +8 -0
  42. package/dist/place.js +16 -8
  43. package/dist/project.js +3 -3
  44. package/dist/qualify.d.ts +10 -0
  45. package/dist/qualify.js +52 -1
  46. package/dist/reading.d.ts +2 -1
  47. package/dist/reading.js +2 -1
  48. package/dist/record.d.ts +6 -0
  49. package/dist/record.js +1 -0
  50. package/dist/restored.d.ts +67 -18
  51. package/dist/restored.js +159 -49
  52. package/dist/revive.d.ts +1 -0
  53. package/dist/revive.js +1 -0
  54. package/dist/roster.js +2 -1
  55. package/dist/seek.js +72 -18
  56. package/dist/shared.d.ts +1 -1
  57. package/dist/shared.js +1 -1
  58. package/dist/spans.d.ts +5 -0
  59. package/dist/spans.js +75 -5
  60. package/dist/store.d.ts +2 -0
  61. package/dist/store.js +4 -0
  62. package/dist/touch.js +3 -2
  63. package/dist/transport.js +6 -1
  64. package/dist/types/arc.d.ts +55 -0
  65. package/dist/types/arc.js +1 -0
  66. package/dist/types/mix.d.ts +24 -0
  67. package/dist/types/voice.d.ts +10 -1
  68. package/dist/types/watch.d.ts +126 -0
  69. package/dist/types/watch.js +1 -0
  70. package/dist/types.d.ts +2 -0
  71. package/dist/voice.d.ts +37 -6
  72. package/dist/voice.js +17 -0
  73. package/dist/watch.d.ts +28 -0
  74. package/dist/watch.js +467 -0
  75. package/dist/weigh.d.ts +13 -2
  76. package/dist/weigh.js +10 -3
  77. package/docs/schema.html +39 -3
  78. package/package.json +5 -4
package/dist/transport.js CHANGED
@@ -8,6 +8,7 @@ import { projectAll } from './project.js';
8
8
  import { scoredDrop, scoredJoin } from './scored.js';
9
9
  import { seek } from './seek.js';
10
10
  import { hostAt, record, replay, tapeOf } from './tape.js';
11
+ import { gave, historyFor } from './watch.js';
11
12
  /** How far the tape's reach moves before it is pruned again, ms of mix time. */
12
13
  const TAPE_STEP_MS = 1000;
13
14
  /** Whether a change made in frame `seq` falls inside `cut`; `early` for one made before the frame was read. */
@@ -337,5 +338,9 @@ export function announce(transport, name, opts, slot, mix) {
337
338
  * @category mix
338
339
  */
339
340
  export function transport(opts = {}) {
340
- return new Transport(opts.history, true);
341
+ const { history, added } = historyFor(opts);
342
+ const t = new Transport(history, true);
343
+ if (added)
344
+ gave(t);
345
+ return t;
341
346
  }
@@ -0,0 +1,55 @@
1
+ import type { Handle, OwnerSpec, VoiceSpec } from './voice.js';
2
+ /**
3
+ * One voice of an arc's part: a voice's spec, less what the arc sets for it. The arc places it,
4
+ * fades it across each boundary by `blend`, and holds its first and last frames for the blend.
5
+ *
6
+ * @category score
7
+ */
8
+ export interface ArcVoice<I, O, H = unknown> extends Omit<VoiceSpec<I, O, H>, 'owner' | 'start' | 'anchor' | 'freeze' | 'fade' | 'faster' | 'slower' | 'overlap' | 'ballast' | 'priority' | 'earliest' | 'rank'> {
9
+ /**
10
+ * How long the part holds the arc, ms on the arc's clock. Default: the patch's duration times
11
+ * its passes, which leaves out a `stagger`, so a part whose last subject lands later says so here.
12
+ */
13
+ duration?: number;
14
+ }
15
+ /**
16
+ * One part of an arc: a voice, or several layered together that play as one and last as long as
17
+ * the longest.
18
+ *
19
+ * @category score
20
+ */
21
+ export type ArcPart<I, O, H = unknown> = ArcVoice<I, O, H> | readonly ArcVoice<I, O, H>[];
22
+ /**
23
+ * What `arc` takes: an owner over three parts that hand over in order, `enter`, `active` and
24
+ * `exit`, any of which may be left out.
25
+ *
26
+ * @category score
27
+ */
28
+ export interface ArcSpec<I, O, H = unknown> extends Omit<OwnerSpec<I, H>, 'freeze'> {
29
+ /** What plays as it arrives. Its end is the arc's `in` mark. */
30
+ enter?: ArcPart<I, O, H>;
31
+ /** What plays between the two, over the hold. Its end is the arc's `coast` mark. */
32
+ active?: ArcPart<I, O, H>;
33
+ /** What plays as it leaves. Its start is the arc's `out` mark, and its end the arc's `end`. */
34
+ exit?: ArcPart<I, O, H>;
35
+ /**
36
+ * How long `active` plays, ms on the arc's clock, looping for it unless its `loop` says how many
37
+ * passes; or `'open'`, until `release`. Default: `active`'s own length, held open where it loops
38
+ * for good, and 0 with no `active`.
39
+ */
40
+ hold?: number | 'open';
41
+ /** A crossfade across each boundary, ms, half before it and half after. Default 0. */
42
+ blend?: number;
43
+ }
44
+ /**
45
+ * An arc's handle: an owner's, and the release of its hold. `fade` takes it out with no exit.
46
+ *
47
+ * @category score
48
+ */
49
+ export interface ArcHandle<I = unknown> extends Handle<I> {
50
+ /**
51
+ * Ends the hold now and plays the exit, its blend starting here; where the enter is still
52
+ * playing, the exit follows it. Nothing once the exit has begun or the arc is fading.
53
+ */
54
+ release(): void;
55
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { ArcHandle, ArcSpec } from './arc.js';
1
2
  import type { Kit } from './channel.js';
2
3
  import type { HistoryOptions, Tape } from './history.js';
3
4
  import type { Patch, Sent, Signal } from './patch.js';
@@ -52,6 +53,11 @@ export interface MixOptions<H = unknown> {
52
53
  * string or number subject is its own key; with a store, an object subject needs this.
53
54
  */
54
55
  keyOf?(subject: never): string | number;
56
+ /**
57
+ * What a debugger calls a subject (see `watched`); where it gives nothing, the subject's own
58
+ * `name` or `id`, a DOM element's tag, id and classes, or its class and a number.
59
+ */
60
+ labelOf?(subject: never): string | undefined;
55
61
  /**
56
62
  * Whether a channel may run as a lane: computed for every subject at once in flat arrays, when
57
63
  * every voice writing it can run that way. On by default; what a host reads is the same either
@@ -146,6 +152,18 @@ export interface Mix<I, O, H = unknown> {
146
152
  * turns it once it plays.
147
153
  */
148
154
  span(spec: SpanSpec<I, H>): SpanHandle<I>;
155
+ /**
156
+ * Cues an arc: an owner holding three parts that hand over in order on its clock, `enter`, then
157
+ * `active` for the `hold`, then `exit`, each a voice or several layered. Its marks are its own:
158
+ * `start` as the enter begins, `in` as it ends, `coast` as the hold ends and `out` as the exit
159
+ * begins, which are one time, and `end` as the exit ends, where it leaves and `done` resolves.
160
+ * While the hold is open, `coast`, `out` and `end` are unknown until `release` fixes them. Each
161
+ * part shows its first and last frames through the blends either side of it, and a part left
162
+ * out leaves its time to the one before it. Its `fade` takes it out with no exit. An arc with a
163
+ * finite hold may sit in a span. Throws for a `rate` below 0, a hold below 0, and an `enter` or
164
+ * `exit` that never ends.
165
+ */
166
+ arc(spec: ArcSpec<I, O, H>): ArcHandle<I>;
149
167
  /**
150
168
  * The host reports the clock, once a frame. Nothing advances at the call. Throws for a timestamp
151
169
  * earlier than the last sync's, short of a `rebase`: the host's clock only goes forward, and
@@ -295,6 +313,12 @@ export interface Mix<I, O, H = unknown> {
295
313
  * A frame loop sleeping on `inert` subscribes here to wake.
296
314
  */
297
315
  onWake(fn: () => void): () => void;
316
+ /**
317
+ * Takes the mix off the list debuggers read (see `watched`), for a host done with it, where it
318
+ * would otherwise stay until collected. Stops every watcher, and frees a hold no other listed mix
319
+ * on its transport shares. It still plays if synced.
320
+ */
321
+ close(): void;
298
322
  /** Fades every voice out: over `over` when given, over each voice's own `fade.out` otherwise. */
299
323
  mute(opts?: {
300
324
  over?: number;
@@ -3,7 +3,7 @@ import type { Motion, Value } from '../motion.js';
3
3
  import type { Described } from './history.js';
4
4
  import type { Doubt } from './mix.js';
5
5
  import type { Easing, Patch, Signal } from './patch.js';
6
- import type { Hit, Placement } from './place.js';
6
+ import type { Anchor, Hit, Placement } from './place.js';
7
7
  /**
8
8
  * A voice's own ramps in and out, in ms, and the curve both take.
9
9
  *
@@ -31,6 +31,15 @@ export interface SpanHints {
31
31
  ballast?: boolean;
32
32
  /** How hard its own length holds against the span's budget. Default `weak`. */
33
33
  priority?: Strength;
34
+ /**
35
+ * The soonest it may start: a time on the span's clock, or an anchor. The fit never places it
36
+ * sooner, and the children after it are laid out from where it starts. One already past when it is
37
+ * cued places it there, partway through. One whose anchor has no answer yet waits, and under `queue` or
38
+ * `stagger` so does every child after it.
39
+ */
40
+ earliest?: number | Anchor;
41
+ /** Where it plays among the span's children still to start: lower first, ties as cued. Default 0. */
42
+ rank?: number;
34
43
  }
35
44
  /**
36
45
  * What `cue` takes: a patch, and the clock, weight and reach it plays with.
@@ -0,0 +1,126 @@
1
+ import type { HistoryOptions } from './history.js';
2
+ import type { Mix } from './mix.js';
3
+ import type { Sent } from './patch.js';
4
+ import type { Handle } from './voice.js';
5
+ /**
6
+ * Every mix made on the page, for a debugger: shared by every copy of blits loaded, so a mix one
7
+ * copy made is listed by another. `watched()` returns it.
8
+ *
9
+ * @category mix
10
+ */
11
+ export interface Registry {
12
+ /** The mixes still alive, in the order they were made. */
13
+ entries(): Watched[];
14
+ /** Hears each mix made, and each one collected, by its entry's `id`. Returns an unsubscribe. */
15
+ on(fn: (change: {
16
+ kind: 'add';
17
+ entry: Watched;
18
+ } | {
19
+ kind: 'gone';
20
+ id: number;
21
+ }) => void): () => void;
22
+ /**
23
+ * The history a mix made from now on keeps when its options name none and it is on no
24
+ * transport, so a debugger present before the page's mixes can scrub them. Undefined by default.
25
+ */
26
+ history: HistoryOptions | undefined;
27
+ }
28
+ /**
29
+ * One mix as a debugger sees it. Built by the copy of blits that made the mix, so a debugger
30
+ * reads mixes from other releases through it alike.
31
+ *
32
+ * @category mix
33
+ */
34
+ export interface Watched<I = unknown, O = unknown> {
35
+ /** Numbers mixes in the order they were made, across copies; what a `gone` change names. */
36
+ readonly id: number;
37
+ /** The release of the copy that made it. */
38
+ readonly release: string;
39
+ readonly name: string | undefined;
40
+ readonly mix: Mix<I, O>;
41
+ /** What history it keeps, and whether the registry's `history` gave it; undefined for none. */
42
+ readonly history: {
43
+ readonly ms: number;
44
+ readonly tape: boolean;
45
+ readonly added: boolean;
46
+ } | undefined;
47
+ /** The earliest mix time `read` reaches back to: `mix.now` without history. */
48
+ readonly reach: number;
49
+ /** The kit's channel names, in kit order. */
50
+ readonly channels: readonly string[];
51
+ /** What a voice was cued with that its handle does not carry; undefined for a handle not on this mix. */
52
+ voice(handle: Handle<I>): {
53
+ readonly name: string | undefined;
54
+ readonly tags: readonly string[];
55
+ } | undefined;
56
+ /** What to call a subject: the mix's `labelOf`, else a guess from the subject itself. */
57
+ label(subject: I): string;
58
+ /**
59
+ * Calls `fn` with each frame the host read, once the next one begins. While anyone watches, the
60
+ * mix records what `probe`, `pull` and `drain` give the host, and nothing else changes. Returns
61
+ * a function that stops watching.
62
+ */
63
+ watch(fn: (frame: WatchedFrame<I, O>) => void): () => void;
64
+ /** The subjects its voices still playing name, and those the host read in the last two frames while watched. */
65
+ subjects(): I[];
66
+ /**
67
+ * One subject's pose at mix time `at`, default now, read through `project`, which moves nothing:
68
+ * never a probe. A time behind now needs history that reaches it.
69
+ */
70
+ read(subject: I, at?: number): O;
71
+ /** Takes the clock from the host: see `Hold`. Throws while another hold has it. */
72
+ hold(): Hold;
73
+ }
74
+ /**
75
+ * What the host read in one frame.
76
+ *
77
+ * @category mix
78
+ */
79
+ export interface WatchedFrame<I, O> {
80
+ seq: number;
81
+ /** The mix clock the frame stood at. */
82
+ now: number;
83
+ /** The host's timestamp at the frame's sync. */
84
+ timestamp: number;
85
+ /** Each probe, in order, with a copy of the pose it returned. */
86
+ probed: {
87
+ subject: I;
88
+ pose: O;
89
+ }[];
90
+ /** Each pull, with copies of the columns it wrote. */
91
+ pulled: {
92
+ subjects: I[];
93
+ columns: Record<string, Float64Array>;
94
+ }[];
95
+ /** What `drain` handed the host. */
96
+ sent: Sent<I, unknown>[];
97
+ voices: Handle<I>[];
98
+ }
99
+ /**
100
+ * A mix's clock in a debugger's hands, and every mix's on the same transport. The host's `sync`
101
+ * still begins each frame, but the frame's gap counts at `rate`, so the mix moves at `rate` times
102
+ * its own rate; the host's own clock calls (`seek`, `rate`, `ramp`, `rebase`) wait for `free`.
103
+ * Nothing done through a hold is recorded on the tape or in the mix's rate, and each change wakes
104
+ * a host sleeping on `inert`.
105
+ *
106
+ * @category mix
107
+ */
108
+ export interface Hold {
109
+ readonly mixes: Mix<unknown, unknown>[];
110
+ /** The mix clock. */
111
+ readonly now: number;
112
+ /** The earliest mix time `seek` reaches: `now` without history and a tape. */
113
+ readonly reach: number;
114
+ /** How much of each of the host's frames the held mix plays; 0 pauses it. Starts at 0. */
115
+ rate: number;
116
+ /** Moves the mixes to mix time `to`, back within `reach` or ahead. */
117
+ seek(to: number): void;
118
+ /** Plays the mixes `ms` of mix time further on, in one frame. */
119
+ step(ms: number): void;
120
+ /**
121
+ * Gives the clock back: the host's next sync carries on from where the hold left the mix, and
122
+ * its clock calls made meanwhile are made, in order. A call made while the tape holds later
123
+ * calls acts on the mix but is not recorded, so those calls still play.
124
+ */
125
+ free(): void;
126
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type * from './types/arc.js';
1
2
  export type * from './types/channel.js';
2
3
  export type * from './types/history.js';
3
4
  export type * from './types/mix.js';
@@ -5,3 +6,4 @@ export type * from './types/patch.js';
5
6
  export type * from './types/place.js';
6
7
  export type * from './types/transport.js';
7
8
  export type * from './types/voice.js';
9
+ export type * from './types/watch.js';
package/dist/voice.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Arc } from './arcs.js';
1
2
  import type { Blend } from './blend.js';
2
3
  import { type Clock } from './clock.js';
3
4
  import { type Curve } from './easing.js';
@@ -7,6 +8,7 @@ import { Named } from './named.js';
7
8
  import type { Past } from './origin.js';
8
9
  import { Holding } from './owner.js';
9
10
  import { type Built, intosOf, type Scratch } from './patch.js';
11
+ import type { Stamp } from './restored.js';
10
12
  import type { Fitting } from './spans.js';
11
13
  import { Store } from './store.js';
12
14
  import type { Anchor, Channel, FadeSpec, Handle, Patch, Setting, VoiceSpec } from './types.js';
@@ -54,6 +56,21 @@ export interface Ahead<S> {
54
56
  ticks: number;
55
57
  /** Undefined until a record has stepped on from the copy. */
56
58
  state: S | undefined;
59
+ /**
60
+ * The state the record a seek replaced had stepped on to from the copy, at `leftTicks`; undefined
61
+ * until one had.
62
+ */
63
+ leftTicks: number;
64
+ left: S | undefined;
65
+ }
66
+ /** A copy of a record kept under `history`, by the mix time and frame it was taken at. */
67
+ export interface Snap<S> {
68
+ at: number;
69
+ seq: number;
70
+ held: Subject<S>;
71
+ ahead?: Ahead<S>;
72
+ /** Set where another record's list holds it too, so a seek cutting it from one lets go of it. */
73
+ shared?: true;
57
74
  }
58
75
  /** Everything one voice holds for one subject, chained through the next voice that reaches it. */
59
76
  export interface Subject<S> {
@@ -100,12 +117,7 @@ export interface Subject<S> {
100
117
  /** Kept state a history store gave back, which each owner takes in turn on its first keep. */
101
118
  unkept?: unknown[];
102
119
  /** Under `history`, copies of this record by the mix time they were taken, oldest first. */
103
- snaps?: {
104
- at: number;
105
- seq: number;
106
- held: Subject<S>;
107
- ahead?: Ahead<S>;
108
- }[];
120
+ snaps?: Snap<S>[];
109
121
  /** In a projection: where this record started from, and whether nothing known could be. */
110
122
  from?: number;
111
123
  unknown?: boolean;
@@ -136,6 +148,8 @@ export interface Subject<S> {
136
148
  /** A motion voice's number for this subject in its patch, good while `freed` is the patch's own. */
137
149
  run: number;
138
150
  freed: number;
151
+ /** In a voice's store once a seek has gone back, the stamp of the seek it was last put back or written at. */
152
+ restored: Stamp | null;
139
153
  }
140
154
  /** A voice's clock, weight and fade from one mix time on, kept under `history`. */
141
155
  export interface Controls extends Clock {
@@ -152,6 +166,8 @@ export interface Controls extends Clock {
152
166
  outOver: number;
153
167
  outSet: boolean;
154
168
  rebuilds: number;
169
+ /** An arc's hold. */
170
+ hold: number;
155
171
  /** How many of the voice's past clocks it had then. */
156
172
  past: number;
157
173
  /** Shows in its own frame: made by a sync, or before anything read the mix that frame. */
@@ -236,6 +252,8 @@ export declare class Voice<I, O> {
236
252
  rebuilds: number;
237
253
  /** Whether its span's last fit jumped it to its end, which leaves it no time in that fit. */
238
254
  skipped: boolean;
255
+ /** What its `earliest` answered at its span's last fit, span ms; NaN while unknown or absent. */
256
+ floorSeen: number;
239
257
  /** Whether its patch has kept state on a record through `setting.keep`, which makes it stateful. */
240
258
  keeping: boolean;
241
259
  /** Subjects fading out of this voice alone, by the ramp each started; null while none are. */
@@ -330,12 +348,19 @@ export declare class Voice<I, O> {
330
348
  of: Blend<I, O>;
331
349
  i: number;
332
350
  } | null;
351
+ /**
352
+ * Copies the latest seek back cut from its records' lists that no other list holds, for the
353
+ * copies its probes keep next to be written over; null until a seek cuts one.
354
+ */
355
+ spares: Snap<unknown>[] | null;
333
356
  /** The one record of every subject it does not reach. */
334
357
  unreached: Subject<unknown> | null;
335
358
  /** By subject number, a bit set where `unreached` stands for the subject; null until one is. */
336
359
  unreachedBits: Uint32Array | null;
337
360
  /** Whether one record stands for every subject: see `shares` in `everyone.ts`. */
338
361
  sharing: boolean;
362
+ /** The frames it has played sharing it. */
363
+ shared: number;
339
364
  /** That record, null until a chain first asks and once the voice shares no more. */
340
365
  everyone: Subject<unknown> | null;
341
366
  /** While sharing, by subject number: a bit where a chain has asked about the subject. */
@@ -356,6 +381,12 @@ export declare class Voice<I, O> {
356
381
  holding: Holding<Voice<I, O>> | null;
357
382
  /** For a span, its budget and how its children were last fitted; null for any other voice. */
358
383
  fitting: Fitting | null;
384
+ /** For an arc, how its parts are laid out; null for any other voice. */
385
+ arc: Arc | null;
386
+ /** For an arc, how long its hold lasts, ms on its clock: Infinity while open. */
387
+ hold: number;
388
+ /** For a voice an arc holds, which part it plays: 0 enter, 1 active, 2 exit; -1 for any other. */
389
+ part: number;
359
390
  /**
360
391
  * `done` and `played`, made when first asked for, already settled if the voice is: most hosts
361
392
  * never await either, and a mix may hold tens of thousands of voices.
package/dist/voice.js CHANGED
@@ -143,6 +143,8 @@ export class Voice {
143
143
  rebuilds = 0;
144
144
  /** Whether its span's last fit jumped it to its end, which leaves it no time in that fit. */
145
145
  skipped = false;
146
+ /** What its `earliest` answered at its span's last fit, span ms; NaN while unknown or absent. */
147
+ floorSeen = Number.NaN;
146
148
  /** Whether its patch has kept state on a record through `setting.keep`, which makes it stateful. */
147
149
  keeping = false;
148
150
  /** Subjects fading out of this voice alone, by the ramp each started; null while none are. */
@@ -236,12 +238,19 @@ export class Voice {
236
238
  ownKept = null;
237
239
  /** The blend it is a member of, and which. */
238
240
  blend = null;
241
+ /**
242
+ * Copies the latest seek back cut from its records' lists that no other list holds, for the
243
+ * copies its probes keep next to be written over; null until a seek cuts one.
244
+ */
245
+ spares = null;
239
246
  /** The one record of every subject it does not reach. */
240
247
  unreached = null;
241
248
  /** By subject number, a bit set where `unreached` stands for the subject; null until one is. */
242
249
  unreachedBits = null;
243
250
  /** Whether one record stands for every subject: see `shares` in `everyone.ts`. */
244
251
  sharing = false;
252
+ /** The frames it has played sharing it. */
253
+ shared = 0;
245
254
  /** That record, null until a chain first asks and once the voice shares no more. */
246
255
  everyone = null;
247
256
  /** While sharing, by subject number: a bit where a chain has asked about the subject. */
@@ -262,6 +271,12 @@ export class Voice {
262
271
  holding;
263
272
  /** For a span, its budget and how its children were last fitted; null for any other voice. */
264
273
  fitting = null;
274
+ /** For an arc, how its parts are laid out; null for any other voice. */
275
+ arc = null;
276
+ /** For an arc, how long its hold lasts, ms on its clock: Infinity while open. */
277
+ hold = 0;
278
+ /** For a voice an arc holds, which part it plays: 0 enter, 1 active, 2 exit; -1 for any other. */
279
+ part = -1;
265
280
  /**
266
281
  * `done` and `played`, made when first asked for, already settled if the voice is: most hosts
267
282
  * never await either, and a mix may hold tens of thousands of voices.
@@ -365,6 +380,7 @@ export class Voice {
365
380
  this.outOver = c.outOver;
366
381
  this.outSet = c.outSet;
367
382
  this.rebuilds = c.rebuilds;
383
+ this.hold = c.hold;
368
384
  const clocks = this.clocks;
369
385
  if (clocks !== null && clocks.length !== c.past)
370
386
  this.clocks = c.past === 0 ? null : clocks.slice(0, c.past);
@@ -578,6 +594,7 @@ export class Voice {
578
594
  outOver: this.outOver,
579
595
  outSet: this.outSet,
580
596
  rebuilds: this.rebuilds,
597
+ hold: this.hold,
581
598
  past: this.clocks?.length ?? 0,
582
599
  });
583
600
  }
@@ -0,0 +1,28 @@
1
+ import type { Mixer } from './mixer.js';
2
+ import type { MixOptions, Registry } from './types.js';
3
+ type Any = Mixer<unknown, unknown>;
4
+ /**
5
+ * Every mix made on the page, shared by every copy of blits loaded: what a debugger reads to find
6
+ * them. See `Registry`.
7
+ *
8
+ * @category mix
9
+ */
10
+ export declare function watched(): Registry;
11
+ /**
12
+ * The history a mix or transport made with `opts` keeps: its own, or with none named and no
13
+ * transport, the registry's default. Reads the registry only where one was made.
14
+ */
15
+ export declare function historyFor(opts: {
16
+ history?: MixOptions['history'];
17
+ transport?: unknown;
18
+ }): {
19
+ history: MixOptions['history'];
20
+ added: boolean;
21
+ };
22
+ /** Marks a transport whose history the registry's default gave. */
23
+ export declare function gave(transport: object): void;
24
+ /** Lists a mix the host made, under an entry this copy builds. */
25
+ export declare function register(mix: Any): void;
26
+ /** Unlists a mix, telling every listener it is gone; one not listed is left alone. */
27
+ export declare function unregister(mix: Any): void;
28
+ export {};