Skip to content

Commit 7322d3b

Browse files
authored
Merge pull request #70 from githubnext/copilot/fix-interactive-playgrounds
Standardize all playground pages to consistent interactive format
2 parents c8543cf + f4ea0f6 commit 7322d3b

18 files changed

Lines changed: 6293 additions & 2396 deletions

playground/cat_accessor.html

Lines changed: 367 additions & 107 deletions
Large diffs are not rendered by default.

playground/csv.html

Lines changed: 376 additions & 136 deletions
Large diffs are not rendered by default.

playground/cum_ops.html

Lines changed: 375 additions & 127 deletions
Large diffs are not rendered by default.

playground/datetime_accessor.html

Lines changed: 402 additions & 198 deletions
Large diffs are not rendered by default.

playground/describe.html

Lines changed: 379 additions & 136 deletions
Large diffs are not rendered by default.

playground/elem_ops.html

Lines changed: 366 additions & 134 deletions
Large diffs are not rendered by default.

playground/ewm.html

Lines changed: 479 additions & 285 deletions
Large diffs are not rendered by default.

playground/index.html

Lines changed: 51 additions & 51 deletions
Large diffs are not rendered by default.

playground/json.html

Lines changed: 376 additions & 139 deletions
Large diffs are not rendered by default.

playground/melt.html

Lines changed: 275 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,200 @@
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>tsb — melt</title>
7-
<script src="playground-runtime.js"></script>
87
<style>
9-
body { font-family: system-ui, sans-serif; max-width: 860px; margin: 2rem auto; padding: 0 1rem; color: #1a1a1a; }
10-
h1 { font-size: 2rem; margin-bottom: .25rem; }
11-
.subtitle { color: #555; margin-bottom: 2rem; }
12-
section { margin-bottom: 2.5rem; }
13-
h2 { font-size: 1.25rem; border-bottom: 2px solid #e0e0e0; padding-bottom: .35rem; margin-bottom: 1rem; }
14-
pre { background: #f5f5f5; border-radius: 6px; padding: 1rem; overflow-x: auto; font-size: .875rem; }
15-
code { font-family: "JetBrains Mono", "Fira Code", monospace; }
16-
.output { background: #eaf7ea; border-left: 4px solid #4caf50; padding: .75rem 1rem; border-radius: 0 6px 6px 0; margin-top: .5rem; font-size: .875rem; white-space: pre; font-family: monospace; }
17-
.note { background: #fff8e1; border-left: 4px solid #ffc107; padding: .6rem 1rem; border-radius: 0 6px 6px 0; font-size: .9rem; margin: .75rem 0; }
18-
nav { margin-bottom: 1.5rem; font-size: .9rem; color: #555; }
19-
nav a { color: #0366d6; text-decoration: none; }
20-
nav a:hover { text-decoration: underline; }
8+
:root {
9+
--bg: #0d1117;
10+
--surface: #161b22;
11+
--border: #30363d;
12+
--text: #e6edf3;
13+
--accent: #58a6ff;
14+
--green: #3fb950;
15+
--orange: #d29922;
16+
--red: #f85149;
17+
--font-mono: "Cascadia Code", "Fira Code", "JetBrains Mono", monospace;
18+
}
19+
* { box-sizing: border-box; margin: 0; padding: 0; }
20+
body {
21+
background: var(--bg);
22+
color: var(--text);
23+
font-family: system-ui, -apple-system, sans-serif;
24+
line-height: 1.6;
25+
padding: 2rem;
26+
max-width: 900px;
27+
margin: 0 auto;
28+
}
29+
a { color: var(--accent); }
30+
h1 { color: var(--accent); margin-bottom: 0.5rem; }
31+
h2 { margin-top: 0; margin-bottom: 0.5rem; font-size: 1.25rem; }
32+
p { color: #8b949e; margin-bottom: 1rem; }
33+
code {
34+
font-family: var(--font-mono);
35+
font-size: 0.875em;
36+
background: var(--surface);
37+
border: 1px solid var(--border);
38+
border-radius: 0.3rem;
39+
padding: 0.1rem 0.4rem;
40+
}
41+
.back { margin-bottom: 2rem; display: inline-block; }
42+
#playground-loading {
43+
position: fixed;
44+
inset: 0;
45+
background: rgba(13, 17, 23, 0.92);
46+
display: flex;
47+
flex-direction: column;
48+
align-items: center;
49+
justify-content: center;
50+
z-index: 1000;
51+
gap: 1rem;
52+
}
53+
.spinner {
54+
width: 40px; height: 40px;
55+
border: 3px solid var(--border);
56+
border-top-color: var(--accent);
57+
border-radius: 50%;
58+
animation: spin 0.8s linear infinite;
59+
}
60+
@keyframes spin { to { transform: rotate(360deg); } }
61+
#playground-status { color: #8b949e; font-size: 0.95rem; }
62+
.section {
63+
background: var(--surface);
64+
border: 1px solid var(--border);
65+
border-radius: 0.75rem;
66+
padding: 1.5rem;
67+
margin-bottom: 1.5rem;
68+
}
69+
.section p { margin-bottom: 0.75rem; }
70+
.playground-block { margin-top: 0.75rem; }
71+
.playground-header {
72+
display: flex;
73+
align-items: center;
74+
justify-content: space-between;
75+
background: #1c2128;
76+
border: 1px solid var(--border);
77+
border-bottom: none;
78+
border-radius: 0.5rem 0.5rem 0 0;
79+
padding: 0.4rem 0.75rem;
80+
}
81+
.playground-label {
82+
font-size: 0.75rem;
83+
color: #8b949e;
84+
text-transform: uppercase;
85+
letter-spacing: 0.05em;
86+
}
87+
.playground-actions { display: flex; gap: 0.5rem; }
88+
.playground-actions button {
89+
background: transparent;
90+
color: var(--accent);
91+
border: 1px solid var(--border);
92+
border-radius: 0.35rem;
93+
padding: 0.25rem 0.7rem;
94+
font-size: 0.8rem;
95+
cursor: pointer;
96+
font-family: system-ui, sans-serif;
97+
transition: background 0.15s, border-color 0.15s;
98+
}
99+
.playground-actions button:hover:not(:disabled) {
100+
background: rgba(88, 166, 255, 0.1);
101+
border-color: var(--accent);
102+
}
103+
.playground-actions button:disabled { opacity: 0.4; cursor: not-allowed; }
104+
.playground-run { font-weight: 600; }
105+
.playground-editor {
106+
display: block;
107+
width: 100%;
108+
min-height: 80px;
109+
background: #0d1117;
110+
color: var(--text);
111+
border: 1px solid var(--border);
112+
border-top: none;
113+
border-bottom: none;
114+
padding: 1rem;
115+
font-family: var(--font-mono);
116+
font-size: 0.875rem;
117+
line-height: 1.55;
118+
resize: vertical;
119+
outline: none;
120+
tab-size: 2;
121+
white-space: pre;
122+
overflow-x: auto;
123+
}
124+
.playground-editor:focus {
125+
border-color: var(--accent);
126+
box-shadow: inset 0 0 0 1px var(--accent);
127+
}
128+
.playground-output {
129+
background: #1c2333;
130+
border: 1px solid var(--border);
131+
border-radius: 0 0 0.5rem 0.5rem;
132+
padding: 0.75rem 1rem;
133+
font-family: var(--font-mono);
134+
font-size: 0.85rem;
135+
color: #8b949e;
136+
white-space: pre-wrap;
137+
min-height: 2rem;
138+
word-break: break-word;
139+
}
140+
.playground-output.active { color: var(--green); border-color: var(--green); }
141+
.playground-output.error { color: var(--red); border-color: var(--red); }
142+
.playground-hint {
143+
font-size: 0.75rem;
144+
color: #484f58;
145+
margin-top: 0.35rem;
146+
text-align: right;
147+
}
148+
.api-reference-code {
149+
background: var(--bg);
150+
border: 1px solid var(--border);
151+
border-radius: 0.5rem;
152+
padding: 1rem;
153+
font-family: var(--font-mono);
154+
font-size: 0.85rem;
155+
color: #8b949e;
156+
overflow-x: auto;
157+
margin-top: 0.5rem;
158+
}
159+
.api-reference-code code {
160+
background: none;
161+
border: none;
162+
padding: 0;
163+
}
164+
footer {
165+
text-align: center;
166+
padding: 2rem 0;
167+
color: #8b949e;
168+
font-size: 0.85rem;
169+
border-top: 1px solid var(--border);
170+
margin-top: 2rem;
171+
}
21172
</style>
22173
</head>
23174
<body>
24-
<nav><a href="index.html">← tsb playground</a></nav>
25-
<h1>melt — Wide to Long</h1>
26-
<p class="subtitle">Unpivot a DataFrame from wide format to long format — mirrors <code>pandas.melt()</code> / <code>DataFrame.melt()</code>.</p>
175+
<div id="playground-loading">
176+
<div class="spinner"></div>
177+
<div id="playground-status">Initializing playground…</div>
178+
</div>
179+
<a class="back" href="index.html">← Back to roadmap</a>
180+
<h1>🔄 melt — Interactive Playground</h1>
181+
<p>Unpivot a DataFrame from wide format to long format — mirrors
182+
<code>pandas.melt()</code> / <code>DataFrame.melt()</code>.<br>
183+
<strong style="color: var(--text);">Edit any code block below and press ▶ Run
184+
(or Ctrl+Enter) to execute it live in your browser.</strong>
185+
</p>
27186

28-
<section>
29-
<h2>1 — Basic melt</h2>
30-
<p>Melt all value columns into a single <code>variable</code> / <code>value</code> pair.</p>
31-
<pre><code id="ex1-code">import { DataFrame, melt } from "tsb";
187+
<!-- 1 · Basic melt -->
188+
<div class="section">
189+
<h2>1 · Basic melt</h2>
190+
<p>Melt all value columns into a single <code>variable</code> / <code>value</code>
191+
pair.</p>
192+
<div class="playground-block">
193+
<div class="playground-header">
194+
<span class="playground-label">TypeScript</span>
195+
<div class="playground-actions">
196+
<button class="playground-run" disabled>▶ Run</button>
197+
<button class="playground-reset">↺ Reset</button>
198+
</div>
199+
</div>
200+
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";
32201

33202
const df = DataFrame.fromColumns({
34203
A: [1, 2, 3],
@@ -37,16 +206,26 @@ <h2>1 — Basic melt</h2>
37206
});
38207

39208
const long = melt(df);
40-
console.log(long.toRecords());
41-
// [{ variable: "A", value: 1 }, { variable: "A", value: 2 }, ...]
42-
</code></pre>
43-
<div class="output" id="ex1-out">▶ run</div>
44-
</section>
209+
console.log(long.toRecords());</textarea>
210+
<div class="playground-output">Click ▶ Run to execute</div>
211+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
212+
</div>
213+
</div>
45214

46-
<section>
47-
<h2>2 — Preserve identifier columns</h2>
48-
<p>Use <code>id_vars</code> to keep columns as identifiers that are repeated for each melted row.</p>
49-
<pre><code id="ex2-code">import { DataFrame, melt } from "tsb";
215+
<!-- 2 · Preserve identifier columns -->
216+
<div class="section">
217+
<h2>2 · Preserve identifier columns</h2>
218+
<p>Use <code>id_vars</code> to keep columns as identifiers that are repeated for
219+
each melted row.</p>
220+
<div class="playground-block">
221+
<div class="playground-header">
222+
<span class="playground-label">TypeScript</span>
223+
<div class="playground-actions">
224+
<button class="playground-run" disabled>▶ Run</button>
225+
<button class="playground-reset">↺ Reset</button>
226+
</div>
227+
</div>
228+
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";
50229

51230
const df = DataFrame.fromColumns({
52231
id: ["alice", "bob", "carol"],
@@ -55,16 +234,30 @@ <h2>2 — Preserve identifier columns</h2>
55234
mar: [120, 210, 140],
56235
});
57236

58-
const long = melt(df, { id_vars: "id", var_name: "month", value_name: "sales" });
59-
console.log(long.toRecords());
60-
</code></pre>
61-
<div class="output" id="ex2-out">▶ run</div>
62-
</section>
237+
const long = melt(df, {
238+
id_vars: "id",
239+
var_name: "month",
240+
value_name: "sales",
241+
});
242+
console.log(long.toRecords());</textarea>
243+
<div class="playground-output">Click ▶ Run to execute</div>
244+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
245+
</div>
246+
</div>
63247

64-
<section>
65-
<h2>3 — Selective value columns</h2>
66-
<p>Use <code>value_vars</code> to specify which columns to unpivot.</p>
67-
<pre><code id="ex3-code">import { DataFrame, melt } from "tsb";
248+
<!-- 3 · Selective value columns -->
249+
<div class="section">
250+
<h2>3 · Selective value columns</h2>
251+
<p>Use <code>value_vars</code> to specify which columns to unpivot.</p>
252+
<div class="playground-block">
253+
<div class="playground-header">
254+
<span class="playground-label">TypeScript</span>
255+
<div class="playground-actions">
256+
<button class="playground-run" disabled>▶ Run</button>
257+
<button class="playground-reset">↺ Reset</button>
258+
</div>
259+
</div>
260+
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";
68261

69262
const df = DataFrame.fromColumns({
70263
name: ["Alice", "Bob"],
@@ -73,22 +266,31 @@ <h2>3 — Selective value columns</h2>
73266
grade: ["B", "A"],
74267
});
75268

76-
// Only melt score columns, keep name
77269
const long = melt(df, {
78270
id_vars: "name",
79271
value_vars: ["score1", "score2"],
80272
var_name: "test",
81273
value_name: "score",
82274
});
83-
console.log(long.toRecords());
84-
</code></pre>
85-
<div class="output" id="ex3-out">▶ run</div>
86-
</section>
275+
console.log(long.toRecords());</textarea>
276+
<div class="playground-output">Click ▶ Run to execute</div>
277+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
278+
</div>
279+
</div>
87280

88-
<section>
89-
<h2>4 — Multiple id columns</h2>
90-
<p>Pass an array to <code>id_vars</code> to use multiple identifier columns.</p>
91-
<pre><code id="ex4-code">import { DataFrame, melt } from "tsb";
281+
<!-- 4 · Multiple id columns -->
282+
<div class="section">
283+
<h2>4 · Multiple id columns</h2>
284+
<p>Pass an array to <code>id_vars</code> to use multiple identifier columns.</p>
285+
<div class="playground-block">
286+
<div class="playground-header">
287+
<span class="playground-label">TypeScript</span>
288+
<div class="playground-actions">
289+
<button class="playground-run" disabled>▶ Run</button>
290+
<button class="playground-reset">↺ Reset</button>
291+
</div>
292+
</div>
293+
<textarea class="playground-editor" spellcheck="false">import { DataFrame, melt } from "tsb";
92294

93295
const df = DataFrame.fromColumns({
94296
year: [2022, 2023],
@@ -102,28 +304,32 @@ <h2>4 — Multiple id columns</h2>
102304
var_name: "quarter",
103305
value_name: "revenue",
104306
});
105-
console.log(long.toRecords());
106-
</code></pre>
107-
<div class="output" id="ex4-out">▶ run</div>
108-
</section>
307+
console.log(long.toRecords());</textarea>
308+
<div class="playground-output">Click ▶ Run to execute</div>
309+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
310+
</div>
311+
</div>
109312

110-
<script>
111-
window.addEventListener("load", () => {
112-
document.querySelectorAll(".output").forEach((el) => {
113-
const id = el.id.replace("-out", "-code");
114-
const code = document.getElementById(id)?.textContent ?? "";
115-
el.textContent = "▶ click to run";
116-
el.style.cursor = "pointer";
117-
el.addEventListener("click", () => {
118-
el.textContent = "Running…";
119-
try {
120-
window.runTsb?.(code, (result) => { el.textContent = result; });
121-
} catch (e) {
122-
el.textContent = String(e);
123-
}
124-
});
125-
});
126-
});
127-
</script>
313+
<!-- API Reference -->
314+
<div class="section">
315+
<h2>API Reference</h2>
316+
<p>Unpivot a DataFrame from wide to long format. Columns not specified as
317+
<code>id_vars</code> or <code>value_vars</code> are melted into
318+
<code>variable</code> / <code>value</code> pairs.</p>
319+
<pre class="api-reference-code"><code>melt(df: DataFrame, options?: {
320+
id_vars?: string | string[], // columns to keep as identifiers
321+
value_vars?: string | string[], // columns to unpivot (default: all non-id)
322+
var_name?: string, // name for the variable column (default: "variable")
323+
value_name?: string, // name for the value column (default: "value")
324+
}): DataFrame</code></pre>
325+
</div>
326+
327+
<footer>
328+
<p>
329+
<a href="index.html">tsb playground</a> ·
330+
Built by <a href="https://github.com/githubnext/autoloop">Autoloop</a>
331+
</p>
332+
</footer>
333+
<script type="module" src="playground-runtime.js"></script>
128334
</body>
129335
</html>

0 commit comments

Comments
 (0)