@demlik/tea 0.7.0 → 0.8.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/chart/index.d.ts +72 -789
- package/dist/chart/index.js +4 -232
- package/dist/chart/index.js.map +1 -1
- package/dist/chart/inspect/index.d.ts +85 -0
- package/dist/chart/inspect/index.js +5 -0
- package/dist/chart/inspect/index.js.map +1 -0
- package/dist/chart/inspect/react.d.ts +112 -0
- package/dist/chart/inspect/react.js +11 -0
- package/dist/chart/inspect/react.js.map +1 -0
- package/dist/chart/inspect/styles.css +286 -0
- package/dist/chart/lane/index.d.ts +361 -0
- package/dist/chart/lane/index.js +9 -0
- package/dist/chart/lane/index.js.map +1 -0
- package/dist/chart/lane/react.d.ts +83 -0
- package/dist/chart/lane/react.js +559 -0
- package/dist/chart/lane/react.js.map +1 -0
- package/dist/chart/lane/styles.css +498 -0
- package/dist/chart/report/index.d.ts +116 -0
- package/dist/chart/report/index.js +32 -0
- package/dist/chart/report/index.js.map +1 -0
- package/dist/chunk-5KJKJOFC.js +758 -0
- package/dist/chunk-5KJKJOFC.js.map +1 -0
- package/dist/chunk-E6GEDSF4.js +307 -0
- package/dist/chunk-E6GEDSF4.js.map +1 -0
- package/dist/chunk-JER5O7PQ.js +416 -0
- package/dist/chunk-JER5O7PQ.js.map +1 -0
- package/dist/chunk-UOC2PL46.js +13 -0
- package/dist/chunk-UOC2PL46.js.map +1 -0
- package/dist/chunk-WRAA7GVZ.js +209 -0
- package/dist/chunk-WRAA7GVZ.js.map +1 -0
- package/dist/chunk-ZCL7SCBK.js +685 -0
- package/dist/chunk-ZCL7SCBK.js.map +1 -0
- package/dist/chunk-ZD6PNZBK.js +457 -0
- package/dist/chunk-ZD6PNZBK.js.map +1 -0
- package/dist/devtools/index.js +2 -207
- package/dist/devtools/index.js.map +1 -1
- package/dist/fold-Blbhru48.d.ts +435 -0
- package/dist/graph-CcjWZVrd.d.ts +923 -0
- package/dist/machine-viz/index.d.ts +18 -1
- package/dist/machine-viz/index.js +2 -8
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/reducer-BqyoVyBG.d.ts +447 -0
- package/dist/run-BVeqJDBF.d.ts +713 -0
- package/dist/samples-DCt6nF8H.d.ts +59 -0
- package/package.json +24 -1
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { useInspectorRuntime } from '../../chunk-JER5O7PQ.js';
|
|
2
|
+
import { replayFeed, runLane, liveFeed, laneView } from '../../chunk-ZCL7SCBK.js';
|
|
3
|
+
import '../../chunk-ZD6PNZBK.js';
|
|
4
|
+
import '../../chunk-5KJKJOFC.js';
|
|
5
|
+
import '../../chunk-E6GEDSF4.js';
|
|
6
|
+
import '../../chunk-UOC2PL46.js';
|
|
7
|
+
import '../../chunk-MUUROGIH.js';
|
|
8
|
+
import '../../chunk-WRAA7GVZ.js';
|
|
9
|
+
import '../../chunk-EWJP3YYP.js';
|
|
10
|
+
import { replay } from '../../chunk-5EHLEUTL.js';
|
|
11
|
+
import '../../chunk-B5VXOFMZ.js';
|
|
12
|
+
import { useMemo, useReducer, useEffect, useRef, useState } from 'react';
|
|
13
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
14
|
+
|
|
15
|
+
function LaneView(props) {
|
|
16
|
+
const feed = useMemo(
|
|
17
|
+
() => replayFeed(props.lane, props.log),
|
|
18
|
+
[props.lane, props.log]
|
|
19
|
+
);
|
|
20
|
+
return /* @__PURE__ */ jsx(
|
|
21
|
+
LanePanels,
|
|
22
|
+
{
|
|
23
|
+
feed,
|
|
24
|
+
title: props.title,
|
|
25
|
+
className: props.className,
|
|
26
|
+
send: null
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
function LiveLaneView(props) {
|
|
31
|
+
const { lane, hands, ctx } = props;
|
|
32
|
+
const [epoch, reset] = useReducer((n) => n + 1, 0);
|
|
33
|
+
const machine = useMemo(
|
|
34
|
+
() => (
|
|
35
|
+
// The one cast, at the construction boundary — `runLane` returns exactly
|
|
36
|
+
// the `init` and `update` a `Machine` is made of, over the lane's own
|
|
37
|
+
// derivations, and `Machine` wants them under the caller's names.
|
|
38
|
+
{ ...runLane(lane, hands) }
|
|
39
|
+
),
|
|
40
|
+
[lane, hands]
|
|
41
|
+
);
|
|
42
|
+
const { rt, rec } = useInspectorRuntime(machine, ctx, epoch);
|
|
43
|
+
if (rt === null) {
|
|
44
|
+
return /* @__PURE__ */ jsx("div", { className: containerClass(props.className), children: /* @__PURE__ */ jsx("div", { className: "tea-lv-boot", children: "booting\u2026" }) });
|
|
45
|
+
}
|
|
46
|
+
return /* @__PURE__ */ jsx(
|
|
47
|
+
LiveLanePanels,
|
|
48
|
+
{
|
|
49
|
+
lane,
|
|
50
|
+
hands,
|
|
51
|
+
samples: props.samples,
|
|
52
|
+
machine,
|
|
53
|
+
runtime: rt,
|
|
54
|
+
rec,
|
|
55
|
+
ctx,
|
|
56
|
+
title: props.title,
|
|
57
|
+
className: props.className,
|
|
58
|
+
onReset: reset
|
|
59
|
+
},
|
|
60
|
+
epoch
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
function LiveLanePanels({
|
|
64
|
+
lane,
|
|
65
|
+
hands,
|
|
66
|
+
samples,
|
|
67
|
+
machine,
|
|
68
|
+
runtime,
|
|
69
|
+
rec,
|
|
70
|
+
ctx,
|
|
71
|
+
title,
|
|
72
|
+
className,
|
|
73
|
+
onReset
|
|
74
|
+
}) {
|
|
75
|
+
const [, bump] = useReducer((n) => n + 1, 0);
|
|
76
|
+
useEffect(() => runtime.subscribe(bump), [runtime]);
|
|
77
|
+
const live = runtime.getState();
|
|
78
|
+
const trace = safeDump(rec, live);
|
|
79
|
+
const tape = useRef(trace);
|
|
80
|
+
tape.current = trace;
|
|
81
|
+
const now = useRef(live);
|
|
82
|
+
now.current = live;
|
|
83
|
+
const total = trace.msgs.length;
|
|
84
|
+
const feed = useMemo(
|
|
85
|
+
() => liveFeed(lane, {
|
|
86
|
+
regionsAt: (n) => regionsOf(
|
|
87
|
+
replayPrefix(machine, tape.current, ctx, n, now.current),
|
|
88
|
+
// a fold that threw leaves the live regions as the honest answer
|
|
89
|
+
regionsOf(now.current, {})
|
|
90
|
+
),
|
|
91
|
+
msgs: tape.current.msgs,
|
|
92
|
+
optsFor: (task) => ({
|
|
93
|
+
...hands[task]?.parts === void 0 ? {} : { parts: hands[task]?.parts },
|
|
94
|
+
...samples?.[task] === void 0 ? {} : { samples: samples[task] }
|
|
95
|
+
})
|
|
96
|
+
}),
|
|
97
|
+
[lane, hands, samples, machine, ctx, total]
|
|
98
|
+
);
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
LanePanels,
|
|
101
|
+
{
|
|
102
|
+
feed,
|
|
103
|
+
title,
|
|
104
|
+
className,
|
|
105
|
+
send: (msg) => runtime.dispatch(msg),
|
|
106
|
+
onReset
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
function containerClass(extra) {
|
|
111
|
+
return `tea-lv${extra ? ` ${extra}` : ""}`;
|
|
112
|
+
}
|
|
113
|
+
var Sep = () => /* @__PURE__ */ jsx("span", { className: "tea-lv-sep", children: " \xB7 " });
|
|
114
|
+
var NO_SEND = "this view was given no way to dispatch";
|
|
115
|
+
function endingWord(view) {
|
|
116
|
+
if (view.terminal === null) return "still running";
|
|
117
|
+
return view.tripped.length > 0 ? "stopped here" : "finished";
|
|
118
|
+
}
|
|
119
|
+
function LanePanels({
|
|
120
|
+
feed,
|
|
121
|
+
title,
|
|
122
|
+
className,
|
|
123
|
+
send,
|
|
124
|
+
onReset
|
|
125
|
+
}) {
|
|
126
|
+
const [at, setAt] = useState(null);
|
|
127
|
+
const cursor = at === null ? feed.total : Math.min(at, feed.total);
|
|
128
|
+
const view = laneView(feed, cursor, title);
|
|
129
|
+
const blocked = view.scrubbed ? `you are looking at step ${view.cursor} of ${view.total}. A button dispatches into the lane as it is NOW \u2014 press \u201Cnow\u201D to get them back.` : view.noDispatch?.why;
|
|
130
|
+
const page = {
|
|
131
|
+
dispatch: send !== null && blocked === void 0 ? { send } : { blocked: blocked ?? NO_SEND },
|
|
132
|
+
foldControls: view.noDispatch !== void 0,
|
|
133
|
+
ended: view.terminal !== null
|
|
134
|
+
};
|
|
135
|
+
return /* @__PURE__ */ jsxs("div", { className: containerClass(className), "data-source": view.source, children: [
|
|
136
|
+
/* @__PURE__ */ jsxs("header", { className: "tea-lv-head", children: [
|
|
137
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-title", children: view.title }),
|
|
138
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
139
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-src", "data-source": view.source, children: view.source }),
|
|
140
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
141
|
+
/* @__PURE__ */ jsxs("span", { className: "tea-lv-now", "data-lane-status": view.status, children: [
|
|
142
|
+
view.terminal === null ? /* @__PURE__ */ jsx("span", { className: "tea-lv-phase", children: view.activePhase ?? "\u2014" }) : /* @__PURE__ */ jsx("span", { className: "tea-lv-terminal", children: view.terminal }),
|
|
143
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
144
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-status", children: endingWord(view) })
|
|
145
|
+
] }),
|
|
146
|
+
view.scrubbed ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
147
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
148
|
+
/* @__PURE__ */ jsxs("span", { className: "tea-lv-warn", children: [
|
|
149
|
+
"time-travelling \u2014 step ",
|
|
150
|
+
view.cursor,
|
|
151
|
+
" of ",
|
|
152
|
+
view.total
|
|
153
|
+
] })
|
|
154
|
+
] }) : null
|
|
155
|
+
] }),
|
|
156
|
+
/* @__PURE__ */ jsxs("p", { className: "tea-lv-lede", children: [
|
|
157
|
+
view.phases.length === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
158
|
+
"A ",
|
|
159
|
+
/* @__PURE__ */ jsx("b", { children: "lane" }),
|
|
160
|
+
" is a run of phases \u2014 this one has a single phase."
|
|
161
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
162
|
+
"A ",
|
|
163
|
+
/* @__PURE__ */ jsx("b", { children: "lane" }),
|
|
164
|
+
" is ",
|
|
165
|
+
view.phases.length,
|
|
166
|
+
" phases that run one after another."
|
|
167
|
+
] }),
|
|
168
|
+
" ",
|
|
169
|
+
"Each phase holds tasks that run ",
|
|
170
|
+
/* @__PURE__ */ jsx("i", { children: "at the same time" }),
|
|
171
|
+
", and every task is one state machine \u2014 the diagram below it is that machine, with the state it is in right now lit up. A phase finishes when all of its tasks finish;",
|
|
172
|
+
" ",
|
|
173
|
+
view.terminal === null ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
174
|
+
"right now ",
|
|
175
|
+
/* @__PURE__ */ jsx("b", { children: view.activePhase }),
|
|
176
|
+
" is the one running."
|
|
177
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
178
|
+
"this lane has ended, on ",
|
|
179
|
+
/* @__PURE__ */ jsx("b", { children: view.terminal }),
|
|
180
|
+
"."
|
|
181
|
+
] })
|
|
182
|
+
] }),
|
|
183
|
+
"blocked" in page.dispatch ? /* @__PURE__ */ jsx("p", { className: "tea-lv-unavailable", "data-unavailable": "dispatch", children: page.dispatch.blocked }) : null,
|
|
184
|
+
/* @__PURE__ */ jsx(StuckPanel, { view }),
|
|
185
|
+
view.phases.map((phase) => /* @__PURE__ */ jsx(PhasePanel, { phase, page }, phase.name)),
|
|
186
|
+
/* @__PURE__ */ jsx(
|
|
187
|
+
TimelinePanel,
|
|
188
|
+
{
|
|
189
|
+
view,
|
|
190
|
+
onScrub: setAt,
|
|
191
|
+
onLive: () => setAt(null),
|
|
192
|
+
onReset
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
] });
|
|
196
|
+
}
|
|
197
|
+
function StuckPanel({ view }) {
|
|
198
|
+
return /* @__PURE__ */ jsxs("section", { className: "tea-lv-panel tea-lv-stuck", children: [
|
|
199
|
+
/* @__PURE__ */ jsxs("h3", { className: "tea-lv-h", children: [
|
|
200
|
+
"1 \xB7 is anything blocked?",
|
|
201
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
202
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-hint", children: "a task nothing can move until someone acts" })
|
|
203
|
+
] }),
|
|
204
|
+
view.stuck.length === 0 ? (
|
|
205
|
+
// Said, never left blank: "nothing is stuck" is an answer, and an empty
|
|
206
|
+
// panel is the reader wondering whether the question was asked.
|
|
207
|
+
/* @__PURE__ */ jsx("p", { className: "tea-lv-none", children: "nothing is stuck \u2014 every task can still move" })
|
|
208
|
+
) : /* @__PURE__ */ jsx("ul", { className: "tea-lv-stucklist", children: view.stuck.map((s) => /* @__PURE__ */ jsxs("li", { "data-stuck": s.reason.kind, "data-task": s.task, children: [
|
|
209
|
+
/* @__PURE__ */ jsx("b", { children: s.task }),
|
|
210
|
+
" ",
|
|
211
|
+
/* @__PURE__ */ jsxs("span", { className: "tea-lv-muted", children: [
|
|
212
|
+
"(",
|
|
213
|
+
s.phase,
|
|
214
|
+
")"
|
|
215
|
+
] }),
|
|
216
|
+
" ",
|
|
217
|
+
"\u2014 ",
|
|
218
|
+
stuckLine(s.reason)
|
|
219
|
+
] }, s.task)) }),
|
|
220
|
+
view.tripped.length === 0 ? null : /* @__PURE__ */ jsxs("p", { className: "tea-lv-tripped", children: [
|
|
221
|
+
"tripped: ",
|
|
222
|
+
view.tripped.join(", ")
|
|
223
|
+
] })
|
|
224
|
+
] });
|
|
225
|
+
}
|
|
226
|
+
function stuckLine(reason) {
|
|
227
|
+
if (reason === null) return "";
|
|
228
|
+
switch (reason.kind) {
|
|
229
|
+
case "tripped":
|
|
230
|
+
return `landed on the error final \`${reason.state}\` \u2014 as finished as a shipped task, and lost`;
|
|
231
|
+
case "dead-end":
|
|
232
|
+
return `\`${reason.state}\` routes no event and is not a final \u2014 nobody can move it`;
|
|
233
|
+
case "budget-spent":
|
|
234
|
+
return `\`${reason.state}\` has spent its retry budget \u2014 the next \`${reason.event}\` is \`${reason.landsOn}\`, not a retry`;
|
|
235
|
+
case "awaiting-world":
|
|
236
|
+
return `\`${reason.state}\` moves only when ${reason.roles.join(" or ")} sends ${reason.events.map((e) => `\`${e}\``).join(" or ")} \u2014 no cmd or sub can arrive here`;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function phaseCount(phase) {
|
|
240
|
+
const n = phase.tasks.length;
|
|
241
|
+
const tasks = `${n} task${n === 1 ? "" : "s"}`;
|
|
242
|
+
switch (phase.standing) {
|
|
243
|
+
case "active":
|
|
244
|
+
return n === 1 ? `${tasks}, running` : `${tasks}, running together`;
|
|
245
|
+
case "complete":
|
|
246
|
+
return `${tasks}, all finished`;
|
|
247
|
+
case "tripped":
|
|
248
|
+
return n === 1 ? `${tasks}, stopped on an error` : `${tasks} \u2014 ${phase.tripped.length} stopped on an error`;
|
|
249
|
+
case "waiting":
|
|
250
|
+
return `${tasks}, not started`;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function PhasePanel({
|
|
254
|
+
phase,
|
|
255
|
+
page
|
|
256
|
+
}) {
|
|
257
|
+
const count = phaseCount(phase);
|
|
258
|
+
return /* @__PURE__ */ jsxs(
|
|
259
|
+
"section",
|
|
260
|
+
{
|
|
261
|
+
className: `tea-lv-panel tea-lv-phase-${phase.standing}`,
|
|
262
|
+
"data-phase": phase.name,
|
|
263
|
+
"data-standing": phase.standing,
|
|
264
|
+
children: [
|
|
265
|
+
/* @__PURE__ */ jsxs("h3", { className: "tea-lv-h", children: [
|
|
266
|
+
phase.index === 0 ? "2 \xB7 " : "",
|
|
267
|
+
phase.name,
|
|
268
|
+
" ",
|
|
269
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-standing", children: phase.standing }),
|
|
270
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
271
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-muted", children: count })
|
|
272
|
+
] }),
|
|
273
|
+
/* @__PURE__ */ jsx("ul", { className: "tea-lv-chips", children: phase.tasks.map((task) => /* @__PURE__ */ jsxs(
|
|
274
|
+
"li",
|
|
275
|
+
{
|
|
276
|
+
className: "tea-lv-chip",
|
|
277
|
+
"data-task": task.task,
|
|
278
|
+
"data-state": task.state,
|
|
279
|
+
"data-end": String(task.endPolarity),
|
|
280
|
+
children: [
|
|
281
|
+
/* @__PURE__ */ jsx("b", { children: task.task }),
|
|
282
|
+
" = ",
|
|
283
|
+
task.state,
|
|
284
|
+
task.endPolarity === "error" ? " (tripped)" : ""
|
|
285
|
+
]
|
|
286
|
+
},
|
|
287
|
+
task.task
|
|
288
|
+
)) }),
|
|
289
|
+
phase.tasks.map((task) => /* @__PURE__ */ jsx(
|
|
290
|
+
TaskPanel,
|
|
291
|
+
{
|
|
292
|
+
task,
|
|
293
|
+
expanded: phase.expanded.includes(task.task),
|
|
294
|
+
alone: phase.tasks.length === 1,
|
|
295
|
+
page
|
|
296
|
+
},
|
|
297
|
+
task.task
|
|
298
|
+
))
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
function waitingLine(task, alone, ended) {
|
|
304
|
+
if (task.waitingOn !== null) return task.waitingOn;
|
|
305
|
+
if (task.endPolarity !== "error") return "nothing \u2014 this task is final";
|
|
306
|
+
const landed = `nothing \u2014 this task landed on the error final \`${task.state}\``;
|
|
307
|
+
if (ended) return `${landed}, which is what stopped the lane`;
|
|
308
|
+
if (alone) return `${landed}, and that trips \`${task.phase}\``;
|
|
309
|
+
return `${landed}, and \`${task.phase}\` will trip the lane once its siblings finish`;
|
|
310
|
+
}
|
|
311
|
+
function TaskPanel({
|
|
312
|
+
task,
|
|
313
|
+
expanded,
|
|
314
|
+
alone,
|
|
315
|
+
page
|
|
316
|
+
}) {
|
|
317
|
+
const [opened, setOpened] = useState(false);
|
|
318
|
+
const showDiagram = expanded || opened;
|
|
319
|
+
const waiting = waitingLine(task, alone, page.ended);
|
|
320
|
+
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
321
|
+
/* @__PURE__ */ jsxs("p", { className: "tea-lv-waiting", children: [
|
|
322
|
+
"waiting on: ",
|
|
323
|
+
waiting
|
|
324
|
+
] }),
|
|
325
|
+
/* @__PURE__ */ jsx(Budget, { task }),
|
|
326
|
+
page.foldControls ? /* @__PURE__ */ jsxs("details", { className: "tea-lv-accepts", children: [
|
|
327
|
+
/* @__PURE__ */ jsxs("summary", { children: [
|
|
328
|
+
"which events this state accepts (",
|
|
329
|
+
task.controls.filter((c) => !c.refused).length,
|
|
330
|
+
" of",
|
|
331
|
+
" ",
|
|
332
|
+
task.controls.length,
|
|
333
|
+
")"
|
|
334
|
+
] }),
|
|
335
|
+
/* @__PURE__ */ jsx("div", { className: "tea-lv-controls", children: task.controls.map((control) => /* @__PURE__ */ jsx(
|
|
336
|
+
Control,
|
|
337
|
+
{
|
|
338
|
+
control,
|
|
339
|
+
dispatch: page.dispatch
|
|
340
|
+
},
|
|
341
|
+
control.event
|
|
342
|
+
)) })
|
|
343
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "tea-lv-controls", children: task.controls.map((control) => /* @__PURE__ */ jsx(
|
|
344
|
+
Control,
|
|
345
|
+
{
|
|
346
|
+
control,
|
|
347
|
+
dispatch: page.dispatch
|
|
348
|
+
},
|
|
349
|
+
control.event
|
|
350
|
+
)) }),
|
|
351
|
+
showDiagram ? /* @__PURE__ */ jsx("pre", { className: "mermaid tea-lv-mermaid", children: task.diagram }, task.diagram) : null
|
|
352
|
+
] });
|
|
353
|
+
if (!expanded) {
|
|
354
|
+
return (
|
|
355
|
+
/* The chip row above already says `task = state` for every task in the
|
|
356
|
+
phase. A collapsed disclosure that repeats it lists each task twice,
|
|
357
|
+
adjacent — which reads as a bug and was one, found by rendering a real
|
|
358
|
+
eight-task phase rather than by any assertion. So the summary says what
|
|
359
|
+
the chip cannot: that there is more here, and whether it has begun. */
|
|
360
|
+
/* @__PURE__ */ jsxs(
|
|
361
|
+
"details",
|
|
362
|
+
{
|
|
363
|
+
className: "tea-lv-task tea-lv-collapsed",
|
|
364
|
+
"data-task": task.task,
|
|
365
|
+
onToggle: (e) => setOpened(e.currentTarget.open),
|
|
366
|
+
children: [
|
|
367
|
+
/* @__PURE__ */ jsxs("summary", { children: [
|
|
368
|
+
/* @__PURE__ */ jsx("b", { children: task.task }),
|
|
369
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
370
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-muted", children: task.moved ? "details" : `still at ${task.state}` })
|
|
371
|
+
] }),
|
|
372
|
+
body
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
return /* @__PURE__ */ jsxs("div", { className: "tea-lv-task", "data-task": task.task, "data-expanded": "true", children: [
|
|
379
|
+
/* @__PURE__ */ jsxs("h4", { className: "tea-lv-taskh", children: [
|
|
380
|
+
/* @__PURE__ */ jsx("b", { children: task.task }),
|
|
381
|
+
" \u2014 ",
|
|
382
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-state", children: task.state }),
|
|
383
|
+
task.endPolarity === "error" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
384
|
+
" ",
|
|
385
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-badge", children: "tripped" })
|
|
386
|
+
] }) : null,
|
|
387
|
+
task.was === void 0 ? null : /* @__PURE__ */ jsxs("span", { className: "tea-lv-muted", children: [
|
|
388
|
+
" \xB7 resumes to ",
|
|
389
|
+
task.was
|
|
390
|
+
] })
|
|
391
|
+
] }),
|
|
392
|
+
body
|
|
393
|
+
] });
|
|
394
|
+
}
|
|
395
|
+
function Budget({ task }) {
|
|
396
|
+
if ("answerable" in task.budget) {
|
|
397
|
+
return /* @__PURE__ */ jsxs(
|
|
398
|
+
"p",
|
|
399
|
+
{
|
|
400
|
+
className: "tea-lv-unavailable",
|
|
401
|
+
"data-unavailable": task.budget.question,
|
|
402
|
+
title: task.budget.why,
|
|
403
|
+
children: [
|
|
404
|
+
"retries: not available \u2014 ",
|
|
405
|
+
task.budget.why
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
if (task.budget.retries === 0) return null;
|
|
411
|
+
return /* @__PURE__ */ jsxs("p", { className: "tea-lv-retries", "data-retries": task.budget.retries, children: [
|
|
412
|
+
"retries: ",
|
|
413
|
+
task.budget.retries,
|
|
414
|
+
"/",
|
|
415
|
+
task.budget.maxRetries,
|
|
416
|
+
task.budget.retries >= task.budget.maxRetries ? " \u2014 spent" : ""
|
|
417
|
+
] });
|
|
418
|
+
}
|
|
419
|
+
function Control({
|
|
420
|
+
control,
|
|
421
|
+
dispatch
|
|
422
|
+
}) {
|
|
423
|
+
const unsendable = "answerable" in control.send;
|
|
424
|
+
const msg = unsendable ? void 0 : control.send;
|
|
425
|
+
const why = unsendable ? control.send.why : void 0;
|
|
426
|
+
const blocked = "blocked" in dispatch ? dispatch.blocked : void 0;
|
|
427
|
+
const sendable = msg !== void 0 && blocked === void 0;
|
|
428
|
+
return /* @__PURE__ */ jsxs(
|
|
429
|
+
"div",
|
|
430
|
+
{
|
|
431
|
+
className: `tea-lv-ev tea-lv-ev-${control.kind}`,
|
|
432
|
+
"data-event": control.event,
|
|
433
|
+
"data-task": control.task,
|
|
434
|
+
"data-status": control.refused ? "refused" : "legal",
|
|
435
|
+
"data-sendable": String(sendable),
|
|
436
|
+
children: [
|
|
437
|
+
/* @__PURE__ */ jsx(
|
|
438
|
+
"button",
|
|
439
|
+
{
|
|
440
|
+
type: "button",
|
|
441
|
+
className: "tea-lv-btn",
|
|
442
|
+
disabled: !sendable,
|
|
443
|
+
title: control.why ?? why ?? blocked ?? control.outcome,
|
|
444
|
+
onClick: () => {
|
|
445
|
+
if (msg !== void 0 && "send" in dispatch) dispatch.send(msg);
|
|
446
|
+
},
|
|
447
|
+
children: control.event
|
|
448
|
+
}
|
|
449
|
+
),
|
|
450
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-to", children: control.refused ? control.why : control.outcome })
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
function TimelinePanel({
|
|
456
|
+
view,
|
|
457
|
+
onScrub,
|
|
458
|
+
onLive,
|
|
459
|
+
onReset
|
|
460
|
+
}) {
|
|
461
|
+
const clockless = "answerable" in view.clock;
|
|
462
|
+
return /* @__PURE__ */ jsxs("section", { className: "tea-lv-panel tea-lv-travel", children: [
|
|
463
|
+
/* @__PURE__ */ jsxs("h3", { className: "tea-lv-h", children: [
|
|
464
|
+
"3 \xB7 what happened, step by step",
|
|
465
|
+
/* @__PURE__ */ jsx(Sep, {}),
|
|
466
|
+
/* @__PURE__ */ jsx("span", { className: "tea-lv-hint", children: "drag to rewind \u2014 everything above moves with it" })
|
|
467
|
+
] }),
|
|
468
|
+
/* @__PURE__ */ jsxs("div", { className: "tea-lv-scrub", children: [
|
|
469
|
+
/* @__PURE__ */ jsx(
|
|
470
|
+
"input",
|
|
471
|
+
{
|
|
472
|
+
type: "range",
|
|
473
|
+
min: 0,
|
|
474
|
+
max: view.total,
|
|
475
|
+
value: view.cursor,
|
|
476
|
+
"aria-label": "step",
|
|
477
|
+
onChange: (e) => onScrub(Number(e.target.value))
|
|
478
|
+
}
|
|
479
|
+
),
|
|
480
|
+
/* @__PURE__ */ jsxs("span", { className: "tea-lv-step", children: [
|
|
481
|
+
view.cursor,
|
|
482
|
+
" / ",
|
|
483
|
+
view.total
|
|
484
|
+
] }),
|
|
485
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: onLive, disabled: !view.scrubbed, children: "now" }),
|
|
486
|
+
onReset === void 0 ? null : /* @__PURE__ */ jsx("button", { type: "button", onClick: onReset, children: "reset" })
|
|
487
|
+
] }),
|
|
488
|
+
clockless ? /* @__PURE__ */ jsxs(
|
|
489
|
+
"p",
|
|
490
|
+
{
|
|
491
|
+
className: "tea-lv-unavailable",
|
|
492
|
+
"data-unavailable": "clock",
|
|
493
|
+
title: view.clock.why,
|
|
494
|
+
children: [
|
|
495
|
+
"when: not available \u2014 ",
|
|
496
|
+
view.clock.why
|
|
497
|
+
]
|
|
498
|
+
}
|
|
499
|
+
) : null,
|
|
500
|
+
view.steps.length === 0 ? /* @__PURE__ */ jsx("p", { className: "tea-lv-none", children: "no steps yet \u2014 every task is where it booted" }) : /* @__PURE__ */ jsxs("table", { className: "tea-lv-steps", children: [
|
|
501
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
502
|
+
/* @__PURE__ */ jsx("th", { children: "#" }),
|
|
503
|
+
clockless ? null : /* @__PURE__ */ jsx("th", { children: "at" }),
|
|
504
|
+
/* @__PURE__ */ jsx("th", { children: "task" }),
|
|
505
|
+
/* @__PURE__ */ jsx("th", { children: "event" }),
|
|
506
|
+
/* @__PURE__ */ jsx("th", { children: "from \u2192 to" })
|
|
507
|
+
] }) }),
|
|
508
|
+
/* @__PURE__ */ jsx("tbody", { children: view.steps.map((step) => /* @__PURE__ */ jsxs(
|
|
509
|
+
"tr",
|
|
510
|
+
{
|
|
511
|
+
"data-step": step.index,
|
|
512
|
+
"data-refused": step.refused ? "true" : void 0,
|
|
513
|
+
children: [
|
|
514
|
+
/* @__PURE__ */ jsx("td", { children: step.index + 1 }),
|
|
515
|
+
clockless ? null : /* @__PURE__ */ jsx("td", { children: view.clock[step.index] }),
|
|
516
|
+
/* @__PURE__ */ jsx("td", { children: step.task }),
|
|
517
|
+
/* @__PURE__ */ jsx("td", { children: step.event }),
|
|
518
|
+
/* @__PURE__ */ jsx("td", { children: step.refused ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
519
|
+
step.from,
|
|
520
|
+
" \u2014 refused, nothing moved"
|
|
521
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
522
|
+
step.from,
|
|
523
|
+
" \u2192 ",
|
|
524
|
+
step.to
|
|
525
|
+
] }) })
|
|
526
|
+
]
|
|
527
|
+
},
|
|
528
|
+
step.index
|
|
529
|
+
)) })
|
|
530
|
+
] })
|
|
531
|
+
] });
|
|
532
|
+
}
|
|
533
|
+
function regionsOf(state, fallback) {
|
|
534
|
+
if (typeof state !== "object" || state === null) return fallback;
|
|
535
|
+
const regions = state.regions;
|
|
536
|
+
return typeof regions === "object" && regions !== null ? regions : fallback;
|
|
537
|
+
}
|
|
538
|
+
function safeDump(rec, live) {
|
|
539
|
+
try {
|
|
540
|
+
return rec.dump();
|
|
541
|
+
} catch {
|
|
542
|
+
return { loaded: null, msgs: [], finalState: live };
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
function replayPrefix(machine, trace, ctx, n, live) {
|
|
546
|
+
try {
|
|
547
|
+
return replay(machine, {
|
|
548
|
+
msgs: trace.msgs.slice(0, n),
|
|
549
|
+
ctx,
|
|
550
|
+
loaded: trace.loaded
|
|
551
|
+
}).state;
|
|
552
|
+
} catch {
|
|
553
|
+
return live;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export { LaneView, LiveLaneView };
|
|
558
|
+
//# sourceMappingURL=react.js.map
|
|
559
|
+
//# sourceMappingURL=react.js.map
|