@bitcobblers/wod-wiki-lang 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browserRuntimeNow-SxxdmtB7.d.cts +2350 -0
- package/dist/browserRuntimeNow-SxxdmtB7.d.ts +2350 -0
- package/dist/chunk-F2TOS4AF.mjs +79 -0
- package/dist/chunk-F2TOS4AF.mjs.map +1 -0
- package/dist/index.cjs +12938 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4076 -0
- package/dist/index.d.ts +4076 -0
- package/dist/index.mjs +12692 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.cjs +842 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +640 -0
- package/dist/react.d.ts +640 -0
- package/dist/react.mjs +741 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +86 -0
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
import { _ as ScriptRuntime, aq as MemoryType, q as IRuntimeBlock, as as MemoryValueOf, ac as DisplayState, at as RoundState, a1 as TimerState, X as IScriptRuntime, F as TypedMemoryReference, a5 as ButtonConfig, K as StackSnapshot } from './browserRuntimeNow-SxxdmtB7.cjs';
|
|
2
|
+
export { az as createBrowserRuntimeNow, aE as getRuntimeNowMs, aH as runtimeNow } from './browserRuntimeNow-SxxdmtB7.cjs';
|
|
3
|
+
import { IMetricSource, IOutputStatement, MetricContainer, TimeSpan } from '@bitcobblers/wod-wiki-core';
|
|
4
|
+
import React$1, { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* useRuntimeExecution - Custom React hook for managing ScriptRuntime execution
|
|
8
|
+
*
|
|
9
|
+
* Encapsulates execution logic, interval management, and lifecycle cleanup.
|
|
10
|
+
*
|
|
11
|
+
* Architecture Decision:
|
|
12
|
+
* - Fixed 20ms tick rate (50 ticks per second)
|
|
13
|
+
* - No speed control (removed for simplicity)
|
|
14
|
+
* - Automatic cleanup on unmount
|
|
15
|
+
* - Reusable across components
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Execution status states
|
|
20
|
+
*/
|
|
21
|
+
type ExecutionStatus = 'idle' | 'running' | 'paused' | 'completed' | 'error';
|
|
22
|
+
/**
|
|
23
|
+
* Return type for useRuntimeExecution hook
|
|
24
|
+
*/
|
|
25
|
+
interface UseRuntimeExecutionReturn {
|
|
26
|
+
status: ExecutionStatus;
|
|
27
|
+
elapsedTime: number;
|
|
28
|
+
stepCount: number;
|
|
29
|
+
startTime: number | null;
|
|
30
|
+
start: () => void;
|
|
31
|
+
pause: () => void;
|
|
32
|
+
stop: () => void;
|
|
33
|
+
reset: () => void;
|
|
34
|
+
step: () => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Manages ScriptRuntime execution lifecycle with fixed 20ms tick rate
|
|
38
|
+
*
|
|
39
|
+
* @param runtime - The ScriptRuntime instance to execute (null if not ready)
|
|
40
|
+
* @returns Object with execution state and control methods
|
|
41
|
+
*/
|
|
42
|
+
declare const useRuntimeExecution: (runtime: ScriptRuntime | null) => UseRuntimeExecutionReturn;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* React hook to subscribe to a specific memory type on a block.
|
|
46
|
+
*
|
|
47
|
+
* Automatically subscribes when the block or type changes, and
|
|
48
|
+
* unsubscribes on cleanup. Returns the current value and updates
|
|
49
|
+
* reactively when behaviors modify the memory.
|
|
50
|
+
*
|
|
51
|
+
* @param block The runtime block to subscribe to (can be undefined)
|
|
52
|
+
* @param type The memory type to subscribe to
|
|
53
|
+
* @returns The current memory value or undefined
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* function TimerComponent({ block }: { block: IRuntimeBlock }) {
|
|
58
|
+
* const timerState = useBlockMemory(block, 'time');
|
|
59
|
+
*
|
|
60
|
+
* if (!timerState) return null;
|
|
61
|
+
*
|
|
62
|
+
* return <div>Direction: {timerState.direction}</div>;
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function useBlockMemory<T extends MemoryType>(block: IRuntimeBlock | undefined, type: T): MemoryValueOf<T> | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Hook for subscribing to timer state from a block.
|
|
69
|
+
*
|
|
70
|
+
* @param block The runtime block
|
|
71
|
+
* @returns The current TimerState or undefined
|
|
72
|
+
*/
|
|
73
|
+
declare function useTimerState(block: IRuntimeBlock | undefined): TimerState | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Hook for subscribing to round state from a block.
|
|
76
|
+
*
|
|
77
|
+
* @param block The runtime block
|
|
78
|
+
* @returns The current RoundState or undefined
|
|
79
|
+
*/
|
|
80
|
+
declare function useRoundState(block: IRuntimeBlock | undefined): RoundState | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Hook for subscribing to display state from a block.
|
|
83
|
+
*
|
|
84
|
+
* @param block The runtime block
|
|
85
|
+
* @returns The current DisplayState or undefined
|
|
86
|
+
*/
|
|
87
|
+
declare function useDisplayState(block: IRuntimeBlock | undefined): DisplayState | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Derived timer display values for UI rendering.
|
|
90
|
+
*/
|
|
91
|
+
interface TimerDisplayValues {
|
|
92
|
+
/** Total elapsed time in milliseconds */
|
|
93
|
+
elapsed: number;
|
|
94
|
+
/** Remaining time in milliseconds (for countdowns) */
|
|
95
|
+
remaining: number | undefined;
|
|
96
|
+
/** Whether the timer is currently running (not paused) */
|
|
97
|
+
isRunning: boolean;
|
|
98
|
+
/** Timer direction */
|
|
99
|
+
direction: 'up' | 'down';
|
|
100
|
+
/** Whether the timer has completed (countdown reached 0) */
|
|
101
|
+
isComplete: boolean;
|
|
102
|
+
/** Formatted time string (MM:SS or HH:MM:SS) */
|
|
103
|
+
formatted: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Hook for derived timer display values.
|
|
107
|
+
*
|
|
108
|
+
* Computes elapsed time, remaining time, and formatted display strings
|
|
109
|
+
* from the raw timer state. Uses requestAnimationFrame for smooth 60fps
|
|
110
|
+
* updates when the timer is running.
|
|
111
|
+
*
|
|
112
|
+
* Consolidated with useTimerElapsed - both now share calculateDuration utility.
|
|
113
|
+
*
|
|
114
|
+
* @param block The runtime block
|
|
115
|
+
* @returns Derived timer display values or null if no timer
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```tsx
|
|
119
|
+
* function TimerDisplay({ block }: { block: IRuntimeBlock }) {
|
|
120
|
+
* const display = useTimerDisplay(block);
|
|
121
|
+
*
|
|
122
|
+
* if (!display) return <div>No timer</div>;
|
|
123
|
+
*
|
|
124
|
+
* return (
|
|
125
|
+
* <div>
|
|
126
|
+
* <span>{display.formatted}</span>
|
|
127
|
+
* {display.direction === 'down' && (
|
|
128
|
+
* <span>{formatTime(display.remaining ?? 0)} remaining</span>
|
|
129
|
+
* )}
|
|
130
|
+
* </div>
|
|
131
|
+
* );
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
declare function useTimerDisplay(block: IRuntimeBlock | undefined): TimerDisplayValues | null;
|
|
136
|
+
/**
|
|
137
|
+
* Derived round display values for UI rendering.
|
|
138
|
+
*/
|
|
139
|
+
interface RoundDisplayValues {
|
|
140
|
+
/** Current round number */
|
|
141
|
+
current: number;
|
|
142
|
+
/** Total rounds (undefined for unbounded) */
|
|
143
|
+
total: number | undefined;
|
|
144
|
+
/** Formatted round label (e.g., "Round 3 of 5") */
|
|
145
|
+
label: string;
|
|
146
|
+
/** Progress as a fraction 0-1 (undefined for unbounded) */
|
|
147
|
+
progress: number | undefined;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Hook for derived round display values.
|
|
151
|
+
*
|
|
152
|
+
* @param block The runtime block
|
|
153
|
+
* @returns Derived round display values or null if no rounds
|
|
154
|
+
*/
|
|
155
|
+
declare function useRoundDisplay(block: IRuntimeBlock | undefined): RoundDisplayValues | null;
|
|
156
|
+
/**
|
|
157
|
+
* Hook for subscribing to the display metrics source from a block.
|
|
158
|
+
*
|
|
159
|
+
* Returns the `IMetricSource` interface from the block's `'metric:display'`
|
|
160
|
+
* memory entry (`DisplayMetricMemory`). The returned source provides
|
|
161
|
+
* precedence-resolved metric that update reactively when the underlying
|
|
162
|
+
* metric memory or runtime state changes.
|
|
163
|
+
*
|
|
164
|
+
* This is the primary hook for UI components that need to render metrics
|
|
165
|
+
* from a runtime block with proper origin precedence (user > runtime > compiler > parser).
|
|
166
|
+
*
|
|
167
|
+
* @param block The runtime block (can be undefined)
|
|
168
|
+
* @returns The IMetricSource for the block, or undefined if no metrics:display memory
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```tsx
|
|
172
|
+
* function BlockView({ block }: { block: IRuntimeBlock }) {
|
|
173
|
+
* const source = useFragmentSource(block);
|
|
174
|
+
* if (!source) return null;
|
|
175
|
+
*
|
|
176
|
+
* const metrics = source.getDisplayMetrics();
|
|
177
|
+
* return <MetricVisualizer metric={metric} />;
|
|
178
|
+
* }
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function useFragmentSource(block: IRuntimeBlock | undefined): IMetricSource | undefined;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Data structure returned by useOutputStatements hook
|
|
185
|
+
* Consolidated from separate implementations in runtime/hooks and clock/hooks
|
|
186
|
+
*/
|
|
187
|
+
interface OutputStatementsData {
|
|
188
|
+
/** All output statements sorted by start time */
|
|
189
|
+
outputs: IOutputStatement[];
|
|
190
|
+
/** Outputs indexed by ID for quick lookup */
|
|
191
|
+
byId: Map<number, IOutputStatement>;
|
|
192
|
+
/** Outputs indexed by sourceBlockKey */
|
|
193
|
+
byBlockKey: Map<string, IOutputStatement[]>;
|
|
194
|
+
/** Segment outputs (timed execution segments) */
|
|
195
|
+
segments: IOutputStatement[];
|
|
196
|
+
/** Completion outputs */
|
|
197
|
+
completions: IOutputStatement[];
|
|
198
|
+
/** Metric outputs */
|
|
199
|
+
metrics: IOutputStatement[];
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* React hook that subscribes to output statement updates from a runtime.
|
|
203
|
+
*
|
|
204
|
+
* Unified hook that works with or without a runtime parameter:
|
|
205
|
+
* - useOutputStatements() - uses runtime from context
|
|
206
|
+
* - useOutputStatements(runtime) - uses provided runtime parameter
|
|
207
|
+
*
|
|
208
|
+
* Returns enriched OutputStatementsData with indexed maps for performance.
|
|
209
|
+
* Consolidated from separate runtime/hooks and clock/hooks implementations.
|
|
210
|
+
*
|
|
211
|
+
* @param runtime Optional runtime instance. If not provided, uses context.
|
|
212
|
+
* @returns OutputStatementsData containing outputs and indexed maps
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* // With context (default)
|
|
217
|
+
* const data = useOutputStatements();
|
|
218
|
+
*
|
|
219
|
+
* // With explicit runtime parameter
|
|
220
|
+
* const data = useOutputStatements(myRuntime);
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare function useOutputStatements(runtime?: IScriptRuntime | null): OutputStatementsData;
|
|
224
|
+
/**
|
|
225
|
+
* Live Tier-2 (running-total) snapshot for display during an active session.
|
|
226
|
+
*
|
|
227
|
+
* Returns the analytics engine's current projection set — totals like total
|
|
228
|
+
* volume / distance / load, recomputed per segment. These values are ephemeral:
|
|
229
|
+
* they are shown live but never persisted; only the finalized values reach the
|
|
230
|
+
* records after the WOD completes. Reuses the output subscription as its change
|
|
231
|
+
* signal (the snapshot is replaced, not appended).
|
|
232
|
+
*/
|
|
233
|
+
declare function useLiveAnalytics(runtime?: IScriptRuntime | null): IOutputStatement[];
|
|
234
|
+
/**
|
|
235
|
+
* Hook to get a specific output by ID
|
|
236
|
+
*/
|
|
237
|
+
declare function useOutputStatement(runtime: IScriptRuntime | null, id: number | null): IOutputStatement | undefined;
|
|
238
|
+
/**
|
|
239
|
+
* Hook to get outputs for a specific block
|
|
240
|
+
*/
|
|
241
|
+
declare function useBlockOutputs(runtime: IScriptRuntime | null, blockKey: string | null): IOutputStatement[];
|
|
242
|
+
/**
|
|
243
|
+
* Hook to compute output hierarchy (parent-child relationships) based on stackLevel
|
|
244
|
+
*/
|
|
245
|
+
declare function useOutputHierarchy(runtime: IScriptRuntime | null): Map<number, number>;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* React hook for subscribing to memory reference changes.
|
|
249
|
+
*
|
|
250
|
+
* This hook automatically manages the subscription lifecycle:
|
|
251
|
+
* - Subscribes when the component mounts or when memoryRef changes
|
|
252
|
+
* - Unsubscribes when the component unmounts or when memoryRef changes
|
|
253
|
+
* - Returns the current value and updates when the memory changes
|
|
254
|
+
*
|
|
255
|
+
* @param memoryRef The memory reference to subscribe to (can be undefined)
|
|
256
|
+
* @returns The current value from the memory reference, or undefined if not available
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```tsx
|
|
260
|
+
* const runtime = useScriptRuntime();
|
|
261
|
+
* const timeSpansRef = runtime.memory.search({
|
|
262
|
+
* type: 'timer-time-spans',
|
|
263
|
+
* ownerId: blockKey
|
|
264
|
+
* })[0] as TypedMemoryReference<TimeSpan[]>;
|
|
265
|
+
*
|
|
266
|
+
* const timeSpans = useMemorySubscription(timeSpansRef);
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
declare function useMemorySubscription<T>(memoryRef: TypedMemoryReference<T> | undefined): T | undefined;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Result of the next-preview resolution.
|
|
273
|
+
*
|
|
274
|
+
* `metrics` contains the display metrics for the next child that
|
|
275
|
+
* will be pushed by the deepest block on the stack that has a
|
|
276
|
+
* `metrics:next` memory location.
|
|
277
|
+
*/
|
|
278
|
+
interface NextPreview {
|
|
279
|
+
/** Fragments describing the next child to be executed */
|
|
280
|
+
metrics: MetricContainer;
|
|
281
|
+
/** The block that owns this preview (the parent that will push the child) */
|
|
282
|
+
block: IRuntimeBlock;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Hook that resolves the "Up Next" preview from the runtime stack.
|
|
286
|
+
*
|
|
287
|
+
* Walks the stack from leaf (index 0) to root, finding the first block
|
|
288
|
+
* that has a non-empty `metrics:next` memory location. This gives the
|
|
289
|
+
* deepest (most specific) preview of what's coming next.
|
|
290
|
+
*
|
|
291
|
+
* The hook subscribes to `metrics:next` memory changes on all stack
|
|
292
|
+
* blocks, so it re-renders when the preview updates (e.g., after a
|
|
293
|
+
* child completes and the next child is queued).
|
|
294
|
+
*
|
|
295
|
+
* @returns NextPreview if any block has a next preview, or null
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```tsx
|
|
299
|
+
* function UpNextCard() {
|
|
300
|
+
* const preview = useNextPreview();
|
|
301
|
+
* if (!preview) return <span>End of session</span>;
|
|
302
|
+
*
|
|
303
|
+
* return <MetricSourceRow metric={preview.metrics} />;
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
declare function useNextPreview(): NextPreview | null;
|
|
308
|
+
|
|
309
|
+
type FragmentSourceStatus = 'pending' | 'active' | 'completed' | 'failed' | 'skipped';
|
|
310
|
+
interface FragmentSourceEntry {
|
|
311
|
+
source: IMetricSource;
|
|
312
|
+
depth: number;
|
|
313
|
+
isLeaf?: boolean;
|
|
314
|
+
isHeader?: boolean;
|
|
315
|
+
isLinked?: boolean;
|
|
316
|
+
status?: FragmentSourceStatus;
|
|
317
|
+
label?: string;
|
|
318
|
+
metricGroups?: any[];
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Represents a timer on the stack with its owning block context.
|
|
322
|
+
*/
|
|
323
|
+
interface StackTimerEntry {
|
|
324
|
+
/** The block that owns this timer */
|
|
325
|
+
block: IRuntimeBlock;
|
|
326
|
+
/** The timer state from block memory */
|
|
327
|
+
timer: TimerState;
|
|
328
|
+
/** Whether this timer is pinned to the primary display */
|
|
329
|
+
isPinned: boolean;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Hook that scans the runtime stack for all blocks with timer memory.
|
|
333
|
+
* Returns timer entries ordered from bottom of stack (index 0) to top.
|
|
334
|
+
*
|
|
335
|
+
* Timer data is read directly from block memory via lock.getMemory('time').
|
|
336
|
+
* When a block is popped from the stack, its memory subscriptions are cleaned
|
|
337
|
+
* up automatically, and the stack event triggers a re-render here.
|
|
338
|
+
*
|
|
339
|
+
* @returns Array of stack timer entries
|
|
340
|
+
*/
|
|
341
|
+
declare function useStackTimers(): StackTimerEntry[];
|
|
342
|
+
/**
|
|
343
|
+
* Determines which timer should be displayed as the primary (big) timer.
|
|
344
|
+
*
|
|
345
|
+
* Pin Resolution Strategy:
|
|
346
|
+
* 1. If the top-of-stack block is a Rest block, its timer is ALWAYS primary.
|
|
347
|
+
* Rest countdowns should be front-and-center so users see time remaining.
|
|
348
|
+
* 2. Otherwise, find the LOWEST (root-closest) block with role === 'primary'.
|
|
349
|
+
* This lets parent blocks (AMRAP, EMOM) keep their timer pinned while
|
|
350
|
+
* child exercises execute beneath them.
|
|
351
|
+
* 3. If no pinned timer exists, use the leaf (top-of-stack) timer.
|
|
352
|
+
*
|
|
353
|
+
* @returns The primary timer entry, or undefined if no timers on stack
|
|
354
|
+
*/
|
|
355
|
+
declare function usePrimaryTimer(): StackTimerEntry | undefined;
|
|
356
|
+
/**
|
|
357
|
+
* Returns all timers that are NOT the primary timer.
|
|
358
|
+
* These are displayed as secondary/context timers in the UI.
|
|
359
|
+
*/
|
|
360
|
+
declare function useSecondaryTimers(): StackTimerEntry[];
|
|
361
|
+
/**
|
|
362
|
+
* Aggregates control buttons from all blocks on the stack.
|
|
363
|
+
*
|
|
364
|
+
* Button Resolution Strategy:
|
|
365
|
+
* - Collect pinned buttons (isPinned === true) from ALL stack levels
|
|
366
|
+
* - Collect non-pinned buttons from the TOP block only
|
|
367
|
+
* - Deduplicate by button ID (pinned take precedence)
|
|
368
|
+
*
|
|
369
|
+
* When a block is popped, its buttons are automatically removed because
|
|
370
|
+
* the stack subscription triggers a re-scan.
|
|
371
|
+
*
|
|
372
|
+
* @returns Array of active button configurations
|
|
373
|
+
*/
|
|
374
|
+
declare function useActiveControls(): ButtonConfig[];
|
|
375
|
+
/**
|
|
376
|
+
* Represents a metrics source on the stack with layout context.
|
|
377
|
+
*
|
|
378
|
+
* Extends the generic FragmentSourceEntry with a block reference for
|
|
379
|
+
* runtime-specific scenarios (accessing memory, dispatching events).
|
|
380
|
+
*/
|
|
381
|
+
interface StackFragmentEntry extends FragmentSourceEntry {
|
|
382
|
+
/** The owning runtime block */
|
|
383
|
+
block: IRuntimeBlock;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Hook that converts the runtime stack into an array of IMetricSource entries.
|
|
387
|
+
*
|
|
388
|
+
* Each block on the stack with a `'metric:display'` memory entry produces a
|
|
389
|
+
* `StackFragmentEntry` containing the `IMetricSource` and layout context
|
|
390
|
+
* (depth, leaf status, label).
|
|
391
|
+
*
|
|
392
|
+
* This is the preferred way for UI components to access metrics data from
|
|
393
|
+
* the stack, replacing `useStackDisplayItems()` which returns `IDisplayItem[]`.
|
|
394
|
+
*
|
|
395
|
+
* @returns Array of stack metrics entries, or undefined if no blocks on stack
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```tsx
|
|
399
|
+
* function StackView() {
|
|
400
|
+
* const entries = useStackFragmentSources();
|
|
401
|
+
* if (!entries) return null;
|
|
402
|
+
*
|
|
403
|
+
* return entries.map(entry => (
|
|
404
|
+
* <MetricVisualizer
|
|
405
|
+
* key={entry.source.id}
|
|
406
|
+
* metrics={entry.source.getDisplayMetrics()}
|
|
407
|
+
* />
|
|
408
|
+
* ));
|
|
409
|
+
* }
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
declare function useStackFragmentSources(): StackFragmentEntry[] | undefined;
|
|
413
|
+
/**
|
|
414
|
+
* Represents a display entry with list-based memory access.
|
|
415
|
+
*
|
|
416
|
+
* Replaces IMetricSource adapter with direct IMetric[][] access.
|
|
417
|
+
*/
|
|
418
|
+
interface StackDisplayEntry {
|
|
419
|
+
/** The owning runtime block */
|
|
420
|
+
block: IRuntimeBlock;
|
|
421
|
+
/** Display rows - each row is an array of metrics */
|
|
422
|
+
displayRows: MetricContainer[];
|
|
423
|
+
/** Display label from block */
|
|
424
|
+
label: string;
|
|
425
|
+
/** Nesting depth for indentation (0 = root level) */
|
|
426
|
+
depth: number;
|
|
427
|
+
/** Whether this is the leaf (most active) entry */
|
|
428
|
+
isLeaf: boolean;
|
|
429
|
+
/** Raw metrics groups from block memory (for backward compatibility) */
|
|
430
|
+
metricGroups?: readonly MetricContainer[];
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Hook that reads list-based memory directly from runtime stack blocks.
|
|
434
|
+
*
|
|
435
|
+
* This is the Phase 3 UI migration hook that consumes the list-based memory
|
|
436
|
+
* API populated by Phase 2 behaviors. It subscribes to all 'metric:display'
|
|
437
|
+
* memory locations and returns display rows without requiring IMetricSource
|
|
438
|
+
* adapter layer.
|
|
439
|
+
*
|
|
440
|
+
* Each block can have multiple 'metric:display' memory locations (non-unique
|
|
441
|
+
* tags in list-based API), where each location stores IMetric[]. These
|
|
442
|
+
* are returned as displayRows: IMetric[][].
|
|
443
|
+
*
|
|
444
|
+
* @returns Array of stack display entries, or undefined if no blocks on stack
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```tsx
|
|
448
|
+
* function StackView() {
|
|
449
|
+
* const entries = useStackDisplayRows();
|
|
450
|
+
* if (!entries) return null;
|
|
451
|
+
*
|
|
452
|
+
* return entries.map(entry => (
|
|
453
|
+
* <div key={entry.block.key.toString()}>
|
|
454
|
+
* {entry.displayRows.map((row, idx) => (
|
|
455
|
+
* <MetricSourceRow key={idx} metrics={row} />
|
|
456
|
+
* ))}
|
|
457
|
+
* </div>
|
|
458
|
+
* ));
|
|
459
|
+
* }
|
|
460
|
+
* ```
|
|
461
|
+
*/
|
|
462
|
+
declare function useStackDisplayRows(): StackDisplayEntry[] | undefined;
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Hook that subscribes to stack snapshots via `runtime.subscribeToStack()`.
|
|
466
|
+
*
|
|
467
|
+
* Returns the latest StackSnapshot, which contains:
|
|
468
|
+
* - `blocks` — current stack (bottom-to-top)
|
|
469
|
+
* - `affectedBlock` — the block that was pushed/popped
|
|
470
|
+
* - `depth` — stack depth after the event
|
|
471
|
+
* - `clockTime` — runtime clock time at event
|
|
472
|
+
* - `type` — 'push' | 'pop' | 'clear' | 'initial'
|
|
473
|
+
*
|
|
474
|
+
* This is the primary hook for UI components that need to react to stack
|
|
475
|
+
* structural changes. For high-frequency timer updates, subscribe to
|
|
476
|
+
* block memory separately.
|
|
477
|
+
*
|
|
478
|
+
* @returns The latest StackSnapshot
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```tsx
|
|
482
|
+
* function StackDisplay() {
|
|
483
|
+
* const snapshot = useStackSnapshot();
|
|
484
|
+
*
|
|
485
|
+
* return (
|
|
486
|
+
* <div>
|
|
487
|
+
* <p>Depth: {snapshot.depth}</p>
|
|
488
|
+
* {snapshot.blocks.map(block => (
|
|
489
|
+
* <div key={block.key.toString()}>{block.label}</div>
|
|
490
|
+
* ))}
|
|
491
|
+
* </div>
|
|
492
|
+
* );
|
|
493
|
+
* }
|
|
494
|
+
* ```
|
|
495
|
+
*/
|
|
496
|
+
declare function useStackSnapshot(): StackSnapshot;
|
|
497
|
+
/**
|
|
498
|
+
* Hook that returns the current stack blocks from the most recent snapshot.
|
|
499
|
+
* Convenience wrapper over useStackSnapshot().
|
|
500
|
+
*
|
|
501
|
+
* @returns Readonly array of blocks currently on the stack
|
|
502
|
+
*/
|
|
503
|
+
declare function useSnapshotBlocks(): readonly IRuntimeBlock[];
|
|
504
|
+
/**
|
|
505
|
+
* Hook that returns the current (top) block on the stack from the snapshot.
|
|
506
|
+
* Returns undefined if the stack is empty.
|
|
507
|
+
*
|
|
508
|
+
* @returns The top block on the stack, or undefined if empty
|
|
509
|
+
*/
|
|
510
|
+
declare function useSnapshotCurrentBlock(): IRuntimeBlock | undefined;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Result from useTimerElapsed hook.
|
|
514
|
+
*/
|
|
515
|
+
interface UseTimerElapsedResult {
|
|
516
|
+
elapsed: number;
|
|
517
|
+
isRunning: boolean;
|
|
518
|
+
timeSpans: readonly TimeSpan[];
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Hook to calculate elapsed time for a timer block by key.
|
|
522
|
+
*
|
|
523
|
+
* This hook uses the unified TimerState from runtime memory to provide
|
|
524
|
+
* real-time elapsed time calculation. It polls for updates when the timer
|
|
525
|
+
* is running to show current time, but only subscribes to memory changes
|
|
526
|
+
* for start/stop/pause/resume events.
|
|
527
|
+
*
|
|
528
|
+
* ## When to Use This Hook
|
|
529
|
+
*
|
|
530
|
+
* Use this hook when your component receives a `blockKey: string` from the
|
|
531
|
+
* display stack system. This is the standard integration pattern for:
|
|
532
|
+
* - ClockAnchor
|
|
533
|
+
* - DigitalClock
|
|
534
|
+
* - Display stack consumers
|
|
535
|
+
*
|
|
536
|
+
* ## When to Use useTimerDisplay Instead
|
|
537
|
+
*
|
|
538
|
+
* If you have direct access to an `IRuntimeBlock` reference (e.g., from
|
|
539
|
+
* `runtime.stack.current()`), prefer `useTimerDisplay(block)` which provides
|
|
540
|
+
* formatted time strings and richer display values.
|
|
541
|
+
*
|
|
542
|
+
* ## Features
|
|
543
|
+
* - Zero polling for completed timers
|
|
544
|
+
* - Subscription-based updates for state changes
|
|
545
|
+
* - 60fps animation frame updates when running
|
|
546
|
+
*
|
|
547
|
+
* @param blockKey The block key to track elapsed time for
|
|
548
|
+
* @returns Object with elapsed time, running state, and time spans
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* ```tsx
|
|
552
|
+
* // Display stack integration (this hook)
|
|
553
|
+
* function KeyBasedTimer({ blockKey }: { blockKey: string }) {
|
|
554
|
+
* const { elapsed, isRunning } = useTimerElapsed(blockKey);
|
|
555
|
+
* const formatted = formatMs(elapsed);
|
|
556
|
+
* return <div className={isRunning ? 'running' : ''}>{formatted}</div>;
|
|
557
|
+
* }
|
|
558
|
+
*
|
|
559
|
+
* // Direct block access (use useTimerDisplay instead)
|
|
560
|
+
* function BlockTimer({ block }: { block: IRuntimeBlock }) {
|
|
561
|
+
* const display = useTimerDisplay(block);
|
|
562
|
+
* return <div>{display?.formatted}</div>;
|
|
563
|
+
* }
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
566
|
+
declare function useTimerElapsed(blockKey: string): UseTimerElapsedResult;
|
|
567
|
+
|
|
568
|
+
interface ScriptRuntimeProviderProps {
|
|
569
|
+
runtime: IScriptRuntime;
|
|
570
|
+
children: ReactNode;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Provides IScriptRuntime context to child components.
|
|
574
|
+
* Must wrap any components that need access to runtime memory or state.
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* ```tsx
|
|
578
|
+
* const runtime = new ScriptRuntime();
|
|
579
|
+
* const script = parseWorkout('For Time: 30 Jumping Jacks');
|
|
580
|
+
* runtime.execute(script);
|
|
581
|
+
*
|
|
582
|
+
* return (
|
|
583
|
+
* <ScriptRuntimeProvider runtime={runtime}>
|
|
584
|
+
* <ClockAnchor blockKey="block-001" />
|
|
585
|
+
* </ScriptRuntimeProvider>
|
|
586
|
+
* );
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
declare const ScriptRuntimeProvider: React.FC<ScriptRuntimeProviderProps>;
|
|
590
|
+
/**
|
|
591
|
+
* Hook to access the IScriptRuntime from context.
|
|
592
|
+
* Must be used within a ScriptRuntimeProvider.
|
|
593
|
+
*
|
|
594
|
+
* @throws Error if called outside ScriptRuntimeProvider
|
|
595
|
+
* @returns IScriptRuntime instance
|
|
596
|
+
*/
|
|
597
|
+
declare function useScriptRuntime(): IScriptRuntime;
|
|
598
|
+
|
|
599
|
+
interface BlockTimerDisplayProps {
|
|
600
|
+
/** The runtime block to display timer for */
|
|
601
|
+
block: IRuntimeBlock | undefined;
|
|
602
|
+
/** Optional CSS class name */
|
|
603
|
+
className?: string;
|
|
604
|
+
/** Show round information if available */
|
|
605
|
+
showRounds?: boolean;
|
|
606
|
+
/** Compact mode for smaller displays */
|
|
607
|
+
compact?: boolean;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* BlockTimerDisplay - Timer display using new behavior-based hooks.
|
|
611
|
+
*
|
|
612
|
+
* This component demonstrates the preferred pattern for displaying timer
|
|
613
|
+
* state from runtime blocks using the new useTimerDisplay and useRoundDisplay
|
|
614
|
+
* hooks.
|
|
615
|
+
*
|
|
616
|
+
* ## Features
|
|
617
|
+
* - 60fps animation for running timers
|
|
618
|
+
* - Automatic format detection (countdown vs countup)
|
|
619
|
+
* - Round display integration
|
|
620
|
+
* - Zero polling for completed timers
|
|
621
|
+
*
|
|
622
|
+
* ## Usage
|
|
623
|
+
*
|
|
624
|
+
* When you have direct access to an IRuntimeBlock (e.g., from the stack),
|
|
625
|
+
* use this component:
|
|
626
|
+
*
|
|
627
|
+
* \\\ sx
|
|
628
|
+
* const block = runtime.stack.current();
|
|
629
|
+
* return <BlockTimerDisplay block={block} showRounds />;
|
|
630
|
+
* \\\
|
|
631
|
+
*
|
|
632
|
+
* For display stack integration where you only have a blockKey string,
|
|
633
|
+
* continue using DigitalClock or ClockAnchor with useTimerElapsed.
|
|
634
|
+
*
|
|
635
|
+
* @see useTimerDisplay
|
|
636
|
+
* @see useRoundDisplay
|
|
637
|
+
*/
|
|
638
|
+
declare const BlockTimerDisplay: React$1.FC<BlockTimerDisplayProps>;
|
|
639
|
+
|
|
640
|
+
export { BlockTimerDisplay, type BlockTimerDisplayProps, type ExecutionStatus, type FragmentSourceEntry, type FragmentSourceStatus, type NextPreview, type OutputStatementsData, type RoundDisplayValues, ScriptRuntimeProvider, type ScriptRuntimeProviderProps, type StackDisplayEntry, type StackFragmentEntry, type StackTimerEntry, type TimerDisplayValues, type UseRuntimeExecutionReturn, type UseTimerElapsedResult, useActiveControls, useBlockMemory, useBlockOutputs, useDisplayState, useFragmentSource, useLiveAnalytics, useMemorySubscription, useNextPreview, useOutputHierarchy, useOutputStatement, useOutputStatements, usePrimaryTimer, useRoundDisplay, useRoundState, useRuntimeExecution, useScriptRuntime, useSecondaryTimers, useSnapshotBlocks, useSnapshotCurrentBlock, useStackDisplayRows, useStackFragmentSources, useStackSnapshot, useStackTimers, useTimerDisplay, useTimerElapsed, useTimerState };
|