@ox-content/code-play 3.0.0-alpha.1 → 3.0.0-alpha.10
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/README.md +19 -6
- package/dist/browser.mjs +481 -57
- package/dist/client.mjs +189 -28
- package/dist/client.mjs.map +1 -1
- package/dist/config.d.mts +15 -2
- package/dist/config.d.mts.map +1 -1
- package/dist/hydrate.d.mts +3 -2
- package/dist/hydrate.d.mts.map +1 -1
- package/dist/hydrate.mjs +2 -2
- package/dist/hydrate2.d.mts +2 -2
- package/dist/hydrate2.mjs +295 -32
- package/dist/hydrate2.mjs.map +1 -1
- package/dist/index.d.mts +24 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/payload.mjs +10 -2
- package/dist/payload.mjs.map +1 -1
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin2.mjs +378 -144
- package/dist/plugin2.mjs.map +1 -1
- package/package.json +1 -1
package/dist/hydrate2.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as errorResult, i as errorMessage, n as createCodePlay, o as JS_SANDBOX_FLAGS, u as selectStream } from "./client.mjs";
|
|
2
|
-
import { a as escapeHtml,
|
|
2
|
+
import { a as escapeHtml, h as resolveLanguage, t as decodePayload } from "./payload.mjs";
|
|
3
3
|
//#region src/hydrate-action.ts
|
|
4
4
|
function readPlayPayload(encoded) {
|
|
5
5
|
try {
|
|
@@ -18,12 +18,39 @@ async function runPlayAction(input) {
|
|
|
18
18
|
input.setBusy(false);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
function idleRunActionState() {
|
|
22
|
+
return { phase: "idle" };
|
|
23
|
+
}
|
|
24
|
+
function runningRunActionState(action, startedAtMs = Date.now()) {
|
|
25
|
+
return {
|
|
26
|
+
phase: "running",
|
|
27
|
+
action,
|
|
28
|
+
startedAtMs
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function resultRunActionState(action, result, finishedAtMs = Date.now()) {
|
|
32
|
+
return {
|
|
33
|
+
phase: result.status === "offline" ? "offline" : result.status === "ok" || result.status === "cancelled" ? "result" : "error",
|
|
34
|
+
action,
|
|
35
|
+
result,
|
|
36
|
+
message: result.diagnostics[0]?.message,
|
|
37
|
+
finishedAtMs
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function errorRunActionState(action, error, finishedAtMs = Date.now()) {
|
|
41
|
+
return {
|
|
42
|
+
phase: "error",
|
|
43
|
+
action,
|
|
44
|
+
message: errorMessage(error),
|
|
45
|
+
finishedAtMs
|
|
46
|
+
};
|
|
47
|
+
}
|
|
21
48
|
//#endregion
|
|
22
49
|
//#region src/styles.ts
|
|
23
50
|
const CODE_PLAY_STYLES = `
|
|
24
51
|
.ox-code-play {
|
|
25
52
|
border: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 16%, transparent));
|
|
26
|
-
border-radius:
|
|
53
|
+
border-radius: 8px;
|
|
27
54
|
background: var(--octc-color-bg-alt, var(--octc-color-bg, Canvas));
|
|
28
55
|
color: var(--octc-color-text, CanvasText);
|
|
29
56
|
overflow: hidden;
|
|
@@ -37,22 +64,89 @@ const CODE_PLAY_STYLES = `
|
|
|
37
64
|
padding: 0.6rem 0.8rem;
|
|
38
65
|
border-bottom: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 12%, transparent));
|
|
39
66
|
}
|
|
67
|
+
.ox-code-play__summary {
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
flex: 1 1 12rem;
|
|
70
|
+
min-width: 9rem;
|
|
71
|
+
gap: 0.45rem;
|
|
72
|
+
align-items: baseline;
|
|
73
|
+
}
|
|
40
74
|
.ox-code-play__lang {
|
|
41
75
|
font: 600 0.8rem/1.2 ui-sans-serif, system-ui, sans-serif;
|
|
42
|
-
margin-right: auto;
|
|
43
76
|
color: var(--octc-color-text, CanvasText);
|
|
44
77
|
}
|
|
78
|
+
.ox-code-play__title {
|
|
79
|
+
min-width: 0;
|
|
80
|
+
overflow-wrap: anywhere;
|
|
81
|
+
font: 500 0.78rem/1.25 ui-sans-serif, system-ui, sans-serif;
|
|
82
|
+
opacity: 0.72;
|
|
83
|
+
}
|
|
84
|
+
.ox-code-play__status {
|
|
85
|
+
min-width: 5.25rem;
|
|
86
|
+
text-align: center;
|
|
87
|
+
border: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 16%, transparent));
|
|
88
|
+
border-radius: 6px;
|
|
89
|
+
padding: 0.18rem 0.5rem;
|
|
90
|
+
font: 650 0.68rem/1.25 ui-sans-serif, system-ui, sans-serif;
|
|
91
|
+
color: var(--octc-color-text, CanvasText);
|
|
92
|
+
background: var(--octc-color-bg, Canvas);
|
|
93
|
+
}
|
|
94
|
+
.ox-code-play[data-ox-run-state="running"] .ox-code-play__status {
|
|
95
|
+
color: var(--octc-color-primary, var(--octc-accent, #4f46e5));
|
|
96
|
+
}
|
|
97
|
+
.ox-code-play[data-ox-run-state="error"] .ox-code-play__status,
|
|
98
|
+
.ox-code-play[data-ox-run-state="offline"] .ox-code-play__status {
|
|
99
|
+
color: var(--octc-danger, #b42318);
|
|
100
|
+
}
|
|
45
101
|
.ox-code-play__toolbar button {
|
|
46
102
|
appearance: none;
|
|
47
103
|
border: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 20%, transparent));
|
|
48
104
|
background: color-mix(in srgb, var(--octc-color-text, CanvasText) 8%, transparent);
|
|
49
105
|
color: var(--octc-color-text, CanvasText);
|
|
50
|
-
border-radius:
|
|
106
|
+
border-radius: 8px;
|
|
51
107
|
padding: 0.25rem 0.75rem;
|
|
52
108
|
font: 600 0.75rem/1.4 ui-sans-serif, system-ui, sans-serif;
|
|
53
109
|
cursor: pointer;
|
|
54
110
|
}
|
|
55
111
|
.ox-code-play__toolbar button:disabled { opacity: 0.55; cursor: progress; }
|
|
112
|
+
.ox-code-play__toolbar button:focus-visible,
|
|
113
|
+
.ox-code-play__tabs button:focus-visible,
|
|
114
|
+
.ox-code-play__field input:focus-visible,
|
|
115
|
+
.ox-code-play__field select:focus-visible,
|
|
116
|
+
.ox-code-play__panel:focus-visible {
|
|
117
|
+
outline: 2px solid var(--octc-color-primary, var(--octc-accent, #4f46e5));
|
|
118
|
+
outline-offset: 2px;
|
|
119
|
+
}
|
|
120
|
+
.ox-code-play__runtime {
|
|
121
|
+
display: flex;
|
|
122
|
+
flex-wrap: wrap;
|
|
123
|
+
gap: 0.45rem;
|
|
124
|
+
align-items: center;
|
|
125
|
+
padding: 0.55rem 0.8rem;
|
|
126
|
+
border-bottom: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 10%, transparent));
|
|
127
|
+
background: color-mix(in srgb, var(--octc-color-text, CanvasText) 4%, transparent);
|
|
128
|
+
}
|
|
129
|
+
.ox-code-play__runtime-chip {
|
|
130
|
+
display: inline-grid;
|
|
131
|
+
gap: 0.1rem;
|
|
132
|
+
min-width: 7.5rem;
|
|
133
|
+
padding: 0.35rem 0.5rem;
|
|
134
|
+
border: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 14%, transparent));
|
|
135
|
+
border-radius: 6px;
|
|
136
|
+
background: var(--octc-color-bg, Canvas);
|
|
137
|
+
}
|
|
138
|
+
.ox-code-play__runtime-chip span {
|
|
139
|
+
font: 600 0.62rem/1.1 ui-sans-serif, system-ui, sans-serif;
|
|
140
|
+
text-transform: uppercase;
|
|
141
|
+
letter-spacing: 0.04em;
|
|
142
|
+
opacity: 0.62;
|
|
143
|
+
}
|
|
144
|
+
.ox-code-play__runtime-chip strong {
|
|
145
|
+
font: 650 0.78rem/1.2 ui-sans-serif, system-ui, sans-serif;
|
|
146
|
+
}
|
|
147
|
+
.ox-code-play__runtime-chip--ok strong { color: var(--octc-color-primary, var(--octc-accent, #4f46e5)); }
|
|
148
|
+
.ox-code-play__runtime-chip--warn strong { color: var(--octc-warning, #b54708); }
|
|
149
|
+
.ox-code-play__runtime-chip--muted strong { opacity: 0.72; }
|
|
56
150
|
.ox-code-play .ox-code { margin: 0; }
|
|
57
151
|
.ox-code-play__source pre { margin: 0; border: 0; border-radius: 0; }
|
|
58
152
|
.ox-code-play__tabs {
|
|
@@ -66,7 +160,7 @@ const CODE_PLAY_STYLES = `
|
|
|
66
160
|
background: transparent;
|
|
67
161
|
color: var(--octc-color-text, CanvasText);
|
|
68
162
|
padding: 0.35rem 0.55rem;
|
|
69
|
-
border-radius:
|
|
163
|
+
border-radius: 6px 6px 0 0;
|
|
70
164
|
font: 600 0.75rem/1.2 ui-sans-serif, system-ui, sans-serif;
|
|
71
165
|
cursor: pointer;
|
|
72
166
|
}
|
|
@@ -93,7 +187,7 @@ const CODE_PLAY_STYLES = `
|
|
|
93
187
|
.ox-code-play__field input, .ox-code-play__field select {
|
|
94
188
|
font: inherit;
|
|
95
189
|
padding: 0.3rem 0.45rem;
|
|
96
|
-
border-radius:
|
|
190
|
+
border-radius: 6px;
|
|
97
191
|
border: 1px solid var(--octc-color-border, color-mix(in srgb, currentColor 18%, transparent));
|
|
98
192
|
background: var(--octc-color-bg, Canvas);
|
|
99
193
|
color: var(--octc-color-text, CanvasText);
|
|
@@ -188,42 +282,127 @@ function renderPlayUi(state) {
|
|
|
188
282
|
if (preset === "headless") return "";
|
|
189
283
|
const panel = state.panel ?? "stdio";
|
|
190
284
|
const canTypecheck = state.payload.capabilities.typecheck;
|
|
285
|
+
const runState = state.runState ?? (state.busy ? {
|
|
286
|
+
phase: "running",
|
|
287
|
+
action: "execute"
|
|
288
|
+
} : idleRunActionState());
|
|
289
|
+
const isBusy = Boolean(state.busy) || runState.phase === "running";
|
|
191
290
|
const tabs = renderTabs(state, panel);
|
|
192
291
|
const viewers = state.payload.viewers;
|
|
193
|
-
|
|
292
|
+
const label = widgetLabel(state.payload, definition);
|
|
293
|
+
return `<div class="ox-code-play ox-code-play--${preset}" data-ox-code-play-ui data-ox-run-state="${runState.phase}" role="region" aria-label="${escapeHtml(label)}" aria-busy="${isBusy ? "true" : "false"}">
|
|
194
294
|
<div class="ox-code-play__toolbar">
|
|
195
|
-
<span class="ox-code-play__lang">${escapeHtml(definition?.name ?? state.payload.language)}</span>
|
|
196
|
-
<
|
|
197
|
-
|
|
198
|
-
|
|
295
|
+
<span class="ox-code-play__summary"><span class="ox-code-play__lang">${escapeHtml(definition?.name ?? state.payload.language)}</span>${state.payload.title ? `<span class="ox-code-play__title">${escapeHtml(state.payload.title)}</span>` : ""}</span>
|
|
296
|
+
<span class="ox-code-play__status" data-ox-status role="status" aria-live="polite">${renderRunStatusText(runState)}</span>
|
|
297
|
+
<button type="button" data-ox-action="run" aria-label="${escapeHtml(`Run ${label}`)}"${actionButtonAttrs("run", Boolean(state.busy))}>Run</button>
|
|
298
|
+
${canTypecheck ? `<button type="button" data-ox-action="typecheck" aria-label="${escapeHtml(`Typecheck ${label}`)}"${actionButtonAttrs("typecheck", Boolean(state.busy))}>Typecheck</button>` : ""}
|
|
299
|
+
<button type="button" data-ox-action="cancel" aria-label="${escapeHtml(`Cancel ${label}`)}"${actionButtonAttrs("cancel", Boolean(state.busy))}>Cancel</button>
|
|
199
300
|
</div>
|
|
301
|
+
${renderRuntimeStrip(state.payload, definition)}
|
|
200
302
|
<div class="ox-code-play__source"></div>
|
|
201
303
|
${tabs}
|
|
202
|
-
${viewers.stdio ?
|
|
203
|
-
${viewers.stderr ?
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
304
|
+
${viewers.stdio ? renderPanel("stdio", "Stdio", panel, preset, `${renderDiagnosticsHtml(state.result)}${renderStdioHtml(state.result?.stdio ?? [])}`) : ""}
|
|
305
|
+
${viewers.stderr ? renderPanel("stderr", "Stderr", panel, preset, renderStderrHtml(state.result)) : ""}
|
|
306
|
+
${viewers.config ? renderPanel("config", "Config", panel, preset, renderConfigHtml(definition?.configSchema ?? [], state.payload.config)) : ""}
|
|
307
|
+
${viewers.provenance ? renderPanel("provenance", "Provenance", panel, preset, renderProvenanceHtml(state.result?.provenance)) : ""}
|
|
308
|
+
${viewers.timing ? renderPanel("timing", "Timing", panel, preset, renderTimingHtml(state.result?.timing)) : ""}
|
|
207
309
|
</div>`;
|
|
208
310
|
}
|
|
311
|
+
function renderRunStatusText(state) {
|
|
312
|
+
if (state.phase === "running") return state.action === "typecheck" ? "Typechecking" : "Running";
|
|
313
|
+
if (state.phase === "offline") return "Offline";
|
|
314
|
+
if (state.phase === "error") {
|
|
315
|
+
if (state.result?.status === "timeout") return "Timed out";
|
|
316
|
+
if (state.result?.status === "unsupported") return "Unsupported";
|
|
317
|
+
return "Error";
|
|
318
|
+
}
|
|
319
|
+
if (state.phase === "result") {
|
|
320
|
+
if (state.result?.status === "cancelled") return "Cancelled";
|
|
321
|
+
return "Done";
|
|
322
|
+
}
|
|
323
|
+
return "Ready";
|
|
324
|
+
}
|
|
325
|
+
function renderRuntimeStrip(payload, definition) {
|
|
326
|
+
const runtime = runtimeLabel(payload, definition);
|
|
327
|
+
const executor = executorLabel(payload, definition);
|
|
328
|
+
const checks = payload.capabilities.typecheck ? "Typecheck ready" : "Run only";
|
|
329
|
+
return `<div class="ox-code-play__runtime" aria-label="Code Play runtime">${[
|
|
330
|
+
runtimeChip("Runtime", runtime.label, runtime.kind),
|
|
331
|
+
runtimeChip("Executor", executor.label, executor.kind),
|
|
332
|
+
runtimeChip("Checks", checks, payload.capabilities.typecheck ? "ok" : "muted")
|
|
333
|
+
].join("")}</div>`;
|
|
334
|
+
}
|
|
335
|
+
function runtimeLabel(payload, definition) {
|
|
336
|
+
switch (definition?.backend) {
|
|
337
|
+
case "javascript": return {
|
|
338
|
+
label: "Browser sandbox",
|
|
339
|
+
kind: "ok"
|
|
340
|
+
};
|
|
341
|
+
case "typescript": return {
|
|
342
|
+
label: "TypeScript sandbox",
|
|
343
|
+
kind: "ok"
|
|
344
|
+
};
|
|
345
|
+
case "framework": return {
|
|
346
|
+
label: `${definition.name} iframe preview`,
|
|
347
|
+
kind: "ok"
|
|
348
|
+
};
|
|
349
|
+
case "rust-playground": return {
|
|
350
|
+
label: "Rust Playground",
|
|
351
|
+
kind: payload.endpoints?.rust ? "ok" : "warn"
|
|
352
|
+
};
|
|
353
|
+
case "go-playground": return {
|
|
354
|
+
label: "Go Playground",
|
|
355
|
+
kind: payload.endpoints?.go ? "ok" : "warn"
|
|
356
|
+
};
|
|
357
|
+
case "remote": return payload.endpoint ? {
|
|
358
|
+
label: "Piston-compatible",
|
|
359
|
+
kind: "ok"
|
|
360
|
+
} : {
|
|
361
|
+
label: "Endpoint missing",
|
|
362
|
+
kind: "warn"
|
|
363
|
+
};
|
|
364
|
+
default: return {
|
|
365
|
+
label: definition?.name ?? payload.language,
|
|
366
|
+
kind: "muted"
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function executorLabel(payload, definition) {
|
|
371
|
+
if (!payload.capabilities.execute) return {
|
|
372
|
+
label: "Disabled",
|
|
373
|
+
kind: "warn"
|
|
374
|
+
};
|
|
375
|
+
if (definition?.backend === "remote" && !payload.endpoint) return {
|
|
376
|
+
label: "Configure endpoint",
|
|
377
|
+
kind: "warn"
|
|
378
|
+
};
|
|
379
|
+
return {
|
|
380
|
+
label: "On demand",
|
|
381
|
+
kind: "ok"
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function runtimeChip(label, value, kind) {
|
|
385
|
+
return `<span class="ox-code-play__runtime-chip ox-code-play__runtime-chip--${kind}"><span>${escapeHtml(label)}</span><strong>${escapeHtml(value)}</strong></span>`;
|
|
386
|
+
}
|
|
209
387
|
function renderTabs(state, panel) {
|
|
210
388
|
if (state.payload.ui === "compact") return "";
|
|
211
389
|
const viewers = state.payload.viewers;
|
|
212
390
|
const buttons = [
|
|
213
|
-
viewers.stdio ? tab("stdio", "
|
|
214
|
-
viewers.stderr ? tab("stderr", "
|
|
215
|
-
viewers.config ? tab("config", "
|
|
216
|
-
viewers.provenance ? tab("provenance", "
|
|
217
|
-
viewers.timing ? tab("timing", "
|
|
391
|
+
viewers.stdio ? tab("stdio", "Stdio", panel) : "",
|
|
392
|
+
viewers.stderr ? tab("stderr", "Stderr", panel) : "",
|
|
393
|
+
viewers.config ? tab("config", "Config", panel) : "",
|
|
394
|
+
viewers.provenance ? tab("provenance", "Provenance", panel) : "",
|
|
395
|
+
viewers.timing ? tab("timing", "Timing", panel) : ""
|
|
218
396
|
].filter(Boolean).join("");
|
|
219
397
|
return buttons ? `<div class="ox-code-play__tabs" role="tablist">${buttons}</div>` : "";
|
|
220
398
|
}
|
|
221
399
|
function tab(id, label, selected) {
|
|
222
|
-
|
|
400
|
+
const isSelected = selected === id;
|
|
401
|
+
return `<button type="button" role="tab" data-ox-panel="${id}" aria-selected="${isSelected ? "true" : "false"}" tabindex="${isSelected ? "0" : "-1"}">${label}</button>`;
|
|
223
402
|
}
|
|
224
403
|
function actionButtonAttrs(action, busy) {
|
|
225
404
|
const state = actionBusyState(action, busy);
|
|
226
|
-
return `${state.disabled ? " disabled" : ""}${state.hidden ? " hidden" : ""}`;
|
|
405
|
+
return `${state.disabled ? " disabled aria-disabled=\"true\"" : ""}${state.hidden ? " hidden" : ""}`;
|
|
227
406
|
}
|
|
228
407
|
function actionBusyState(action, busy) {
|
|
229
408
|
if (action === "cancel") return {
|
|
@@ -240,15 +419,30 @@ function applyActionBusy(root, busy) {
|
|
|
240
419
|
const state = actionBusyState(button.dataset.oxAction ?? "", busy);
|
|
241
420
|
button.disabled = state.disabled;
|
|
242
421
|
button.hidden = state.hidden;
|
|
422
|
+
button.setAttribute("aria-disabled", state.disabled ? "true" : "false");
|
|
243
423
|
}
|
|
424
|
+
for (const widget of queryPlayWidgets(root)) widget.setAttribute("aria-busy", busy ? "true" : "false");
|
|
425
|
+
}
|
|
426
|
+
function renderPanel(id, label, current, preset, html) {
|
|
427
|
+
return `<div class="ox-code-play__panel" role="tabpanel" tabindex="0" aria-label="${escapeHtml(label)}" data-panel="${id}"${hidden(current, id, preset)}>${html}</div>`;
|
|
244
428
|
}
|
|
245
429
|
function hidden(current, id, preset) {
|
|
246
430
|
if (preset === "compact" && (id === "stdio" || id === "stderr")) return "";
|
|
247
431
|
return current === id ? "" : " hidden";
|
|
248
432
|
}
|
|
433
|
+
function widgetLabel(payload, definition) {
|
|
434
|
+
const language = definition?.name ?? payload.language;
|
|
435
|
+
return payload.title ? `${payload.title} (${language})` : `${language} Code Play`;
|
|
436
|
+
}
|
|
437
|
+
function queryPlayWidgets(root) {
|
|
438
|
+
const widgets = [...root.querySelectorAll(".ox-code-play")];
|
|
439
|
+
if (typeof HTMLElement !== "undefined" && root instanceof HTMLElement && root.matches(".ox-code-play")) widgets.unshift(root);
|
|
440
|
+
return widgets;
|
|
441
|
+
}
|
|
249
442
|
//#endregion
|
|
250
443
|
//#region src/hydrate.ts
|
|
251
444
|
const STYLE_ID = "ox-code-play-styles";
|
|
445
|
+
let widgetId = 0;
|
|
252
446
|
function hydrateCodePlay(root = defaultRoot(), options = {}) {
|
|
253
447
|
ensureStyles();
|
|
254
448
|
const client = options.client ?? createCodePlayFromPayloads(root);
|
|
@@ -261,7 +455,7 @@ function mountCodePlay(element, options = {}) {
|
|
|
261
455
|
const payload = readPlayPayload(element.getAttribute("data-ox-code-play") ?? "");
|
|
262
456
|
if (!payload || payload.ui === "headless") return;
|
|
263
457
|
const client = options.client ?? createCodePlay({
|
|
264
|
-
languages: { [payload.language]:
|
|
458
|
+
languages: { [payload.language]: languageEnableFromPayload(payload) },
|
|
265
459
|
endpoints: payload.endpoints
|
|
266
460
|
});
|
|
267
461
|
const source = element.innerHTML;
|
|
@@ -273,7 +467,9 @@ function mountCodePlay(element, options = {}) {
|
|
|
273
467
|
if (sourceSlot) sourceSlot.innerHTML = source;
|
|
274
468
|
element.replaceChildren(widget);
|
|
275
469
|
element.dataset.oxCodePlayMounted = "true";
|
|
470
|
+
element.removeAttribute("inert");
|
|
276
471
|
bindWidget(element, payload, client);
|
|
472
|
+
prepareA11y(element);
|
|
277
473
|
}
|
|
278
474
|
function bindWidget(element, payload, client) {
|
|
279
475
|
let current = payload;
|
|
@@ -288,6 +484,9 @@ function bindWidget(element, payload, client) {
|
|
|
288
484
|
runButton?.addEventListener("click", () => void run("execute"));
|
|
289
485
|
checkButton?.addEventListener("click", () => void run("typecheck"));
|
|
290
486
|
cancelButton?.addEventListener("click", () => session.cancel());
|
|
487
|
+
element.addEventListener("keydown", (event) => {
|
|
488
|
+
if (event.target instanceof HTMLElement && event.target.matches("[role=\"tab\"]")) handleTabKeydown(element, event);
|
|
489
|
+
});
|
|
291
490
|
element.addEventListener("click", (event) => {
|
|
292
491
|
const target = event.target;
|
|
293
492
|
if (!(target instanceof HTMLElement)) return;
|
|
@@ -306,13 +505,20 @@ function bindWidget(element, payload, client) {
|
|
|
306
505
|
async function run(action) {
|
|
307
506
|
await runPlayAction({
|
|
308
507
|
action: () => action === "typecheck" ? session.typecheck() : session.run(),
|
|
309
|
-
setBusy: (busy) =>
|
|
310
|
-
|
|
311
|
-
|
|
508
|
+
setBusy: (busy) => {
|
|
509
|
+
applyActionBusy(element, busy);
|
|
510
|
+
if (busy) paintRunState(element, runningRunActionState(action));
|
|
511
|
+
},
|
|
512
|
+
onResult: (result) => paintResult(element, current, result, action),
|
|
513
|
+
onError: (error) => {
|
|
514
|
+
paintRunState(element, errorRunActionState(action, error));
|
|
515
|
+
paintResult(element, current, errorResult(errorMessage(error)), action);
|
|
516
|
+
}
|
|
312
517
|
});
|
|
313
518
|
}
|
|
314
519
|
}
|
|
315
|
-
function paintResult(element, _payload, result) {
|
|
520
|
+
function paintResult(element, _payload, result, action) {
|
|
521
|
+
paintRunState(element, resultRunActionState(action, result));
|
|
316
522
|
const stdio = element.querySelector("[data-panel=\"stdio\"]");
|
|
317
523
|
if (stdio) {
|
|
318
524
|
stdio.innerHTML = `${renderDiagnosticsHtml(result)}${renderStdioHtml(result.stdio)}`;
|
|
@@ -333,11 +539,27 @@ function paintResult(element, _payload, result) {
|
|
|
333
539
|
if (timing) timing.innerHTML = renderTimingHtml(result.timing);
|
|
334
540
|
const stderr = element.querySelector("[data-panel=\"stderr\"]");
|
|
335
541
|
if (stderr) stderr.innerHTML = renderStderrHtml(result);
|
|
336
|
-
showPanel(element,
|
|
542
|
+
showPanel(element, resultPanelToShow(result, Boolean(stderr)));
|
|
543
|
+
}
|
|
544
|
+
function paintRunState(element, state) {
|
|
545
|
+
const widget = element.querySelector(".ox-code-play");
|
|
546
|
+
widget?.setAttribute("data-ox-run-state", state.phase);
|
|
547
|
+
widget?.setAttribute("aria-busy", state.phase === "running" ? "true" : "false");
|
|
548
|
+
const status = element.querySelector("[data-ox-status]");
|
|
549
|
+
if (status) status.textContent = renderRunStatusText(state);
|
|
550
|
+
}
|
|
551
|
+
function resultPanelToShow(result, hasStderrPanel) {
|
|
552
|
+
if (!hasStderrPanel) return "stdio";
|
|
553
|
+
if (result.diagnostics.some((diagnostic) => diagnostic.severity === "error") || result.status !== "ok" && Boolean(result.stderr)) return "stderr";
|
|
554
|
+
return "stdio";
|
|
337
555
|
}
|
|
338
556
|
function showPanel(element, panel) {
|
|
339
557
|
const compact = Boolean(element.querySelector(".ox-code-play--compact"));
|
|
340
|
-
for (const tab of element.querySelectorAll("[data-ox-panel]"))
|
|
558
|
+
for (const tab of element.querySelectorAll("[data-ox-panel]")) {
|
|
559
|
+
const selected = tab.getAttribute("data-ox-panel") === panel;
|
|
560
|
+
tab.setAttribute("aria-selected", selected ? "true" : "false");
|
|
561
|
+
tab.tabIndex = selected ? 0 : -1;
|
|
562
|
+
}
|
|
341
563
|
for (const node of element.querySelectorAll(".ox-code-play__panel")) {
|
|
342
564
|
const id = node.dataset.panel;
|
|
343
565
|
if (compact && (id === "stdio" || id === "stderr")) {
|
|
@@ -347,6 +569,38 @@ function showPanel(element, panel) {
|
|
|
347
569
|
node.hidden = id !== panel;
|
|
348
570
|
}
|
|
349
571
|
}
|
|
572
|
+
function handleTabKeydown(element, event) {
|
|
573
|
+
if (![
|
|
574
|
+
"ArrowLeft",
|
|
575
|
+
"ArrowRight",
|
|
576
|
+
"Home",
|
|
577
|
+
"End"
|
|
578
|
+
].includes(event.key)) return;
|
|
579
|
+
const tabs = [...element.querySelectorAll("[data-ox-panel]")];
|
|
580
|
+
const current = tabs.indexOf(event.target);
|
|
581
|
+
if (current === -1) return;
|
|
582
|
+
event.preventDefault();
|
|
583
|
+
const next = tabs[event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : event.key === "ArrowRight" ? (current + 1) % tabs.length : (current - 1 + tabs.length) % tabs.length];
|
|
584
|
+
const panel = next?.dataset.oxPanel;
|
|
585
|
+
if (!next || !panel) return;
|
|
586
|
+
showPanel(element, panel);
|
|
587
|
+
next.focus();
|
|
588
|
+
}
|
|
589
|
+
function prepareA11y(element) {
|
|
590
|
+
const widget = element.querySelector(".ox-code-play");
|
|
591
|
+
if (!widget) return;
|
|
592
|
+
if (!widget.id) widget.id = `ox-code-play-${++widgetId}`;
|
|
593
|
+
for (const tab of element.querySelectorAll("[data-ox-panel]")) {
|
|
594
|
+
const panelName = tab.dataset.oxPanel;
|
|
595
|
+
const panel = panelName ? element.querySelector(`[data-panel="${panelName}"]`) : null;
|
|
596
|
+
if (!panelName || !panel) continue;
|
|
597
|
+
tab.id ||= `${widget.id}-${panelName}-tab`;
|
|
598
|
+
panel.id ||= `${widget.id}-${panelName}-panel`;
|
|
599
|
+
tab.setAttribute("aria-controls", panel.id);
|
|
600
|
+
panel.setAttribute("aria-labelledby", tab.id);
|
|
601
|
+
panel.removeAttribute("aria-label");
|
|
602
|
+
}
|
|
603
|
+
}
|
|
350
604
|
function readForm(form) {
|
|
351
605
|
const data = new FormData(form);
|
|
352
606
|
const config = {};
|
|
@@ -359,7 +613,7 @@ function createCodePlayFromPayloads(root) {
|
|
|
359
613
|
let endpoints;
|
|
360
614
|
for (const element of queryWidgets(root)) try {
|
|
361
615
|
const payload = decodePayload(element.getAttribute("data-ox-code-play") ?? "");
|
|
362
|
-
languages[payload.language] =
|
|
616
|
+
languages[payload.language] = languageEnableFromPayload(payload);
|
|
363
617
|
endpoints = payload.endpoints ?? endpoints;
|
|
364
618
|
} catch {}
|
|
365
619
|
return createCodePlay({
|
|
@@ -367,6 +621,15 @@ function createCodePlayFromPayloads(root) {
|
|
|
367
621
|
endpoints
|
|
368
622
|
});
|
|
369
623
|
}
|
|
624
|
+
function languageEnableFromPayload(payload) {
|
|
625
|
+
const enable = {
|
|
626
|
+
execute: payload.capabilities.execute,
|
|
627
|
+
typecheck: payload.capabilities.typecheck,
|
|
628
|
+
config: payload.config
|
|
629
|
+
};
|
|
630
|
+
if (payload.endpoint) enable.endpoint = payload.endpoint;
|
|
631
|
+
return enable;
|
|
632
|
+
}
|
|
370
633
|
function queryWidgets(root) {
|
|
371
634
|
return [...root.querySelectorAll("[data-ox-code-play]")];
|
|
372
635
|
}
|
|
@@ -382,6 +645,6 @@ function defaultRoot() {
|
|
|
382
645
|
return document;
|
|
383
646
|
}
|
|
384
647
|
//#endregion
|
|
385
|
-
export {
|
|
648
|
+
export { runPlayAction as _, renderRunStatusText as a, renderProvenanceHtml as c, renderTimingHtml as d, CODE_PLAY_STYLES as f, resultRunActionState as g, readPlayPayload as h, renderPlayUi as i, renderStderrHtml as l, idleRunActionState as m, mountCodePlay as n, renderConfigHtml as o, errorRunActionState as p, resultPanelToShow as r, renderDiagnosticsHtml as s, hydrateCodePlay as t, renderStdioHtml as u, runningRunActionState as v };
|
|
386
649
|
|
|
387
650
|
//# sourceMappingURL=hydrate2.mjs.map
|