Skip to content

Commit 8d87625

Browse files
authored
Merge pull request #323 from githubnext/autoloop/build-tsb-pandas-typescript-migration
[Autoloop: build-tsb-pandas-typescript-migration]
2 parents a7a548e + 0ae2c3f commit 8d87625

107 files changed

Lines changed: 36438 additions & 102 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

biome.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
},
101101
"complexity": {
102102
"useLiteralKeys": "off"
103+
},
104+
"suspicious": {
105+
"noMisplacedAssertion": "off"
103106
}
104107
}
105108
}

playground/arrays.html

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>tsb — pd.arrays: Nullable Typed Extension Arrays</title>
7+
<style>
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+
.subtitle { margin-bottom: 1.5rem; }
43+
44+
#playground-loading {
45+
position: fixed; inset: 0;
46+
background: rgba(13, 17, 23, 0.92);
47+
display: flex; flex-direction: column;
48+
align-items: center; justify-content: center;
49+
z-index: 1000; gap: 1rem;
50+
}
51+
.spinner {
52+
width: 40px; height: 40px;
53+
border: 3px solid var(--border);
54+
border-top-color: var(--accent);
55+
border-radius: 50%;
56+
animation: spin 0.8s linear infinite;
57+
}
58+
@keyframes spin { to { transform: rotate(360deg); } }
59+
#playground-status { color: #8b949e; font-size: 0.95rem; }
60+
61+
.section {
62+
background: var(--surface);
63+
border: 1px solid var(--border);
64+
border-radius: 0.75rem;
65+
padding: 1.5rem;
66+
margin-bottom: 1.5rem;
67+
}
68+
.section p { margin-bottom: 0.75rem; }
69+
70+
.playground-block { margin-top: 0.75rem; }
71+
.playground-header {
72+
display: flex; align-items: center; justify-content: space-between;
73+
background: #1c2128;
74+
border: 1px solid var(--border);
75+
border-bottom: none;
76+
border-radius: 0.5rem 0.5rem 0 0;
77+
padding: 0.4rem 0.75rem;
78+
}
79+
.playground-label {
80+
font-size: 0.75rem; color: #8b949e;
81+
text-transform: uppercase; letter-spacing: 0.05em;
82+
}
83+
.playground-actions { display: flex; gap: 0.5rem; }
84+
.playground-actions button {
85+
background: transparent; color: var(--accent);
86+
border: 1px solid var(--border);
87+
border-radius: 0.35rem;
88+
padding: 0.25rem 0.7rem;
89+
font-size: 0.8rem; cursor: pointer;
90+
font-family: system-ui, sans-serif;
91+
transition: background 0.15s, border-color 0.15s;
92+
}
93+
.playground-actions button:hover:not(:disabled) {
94+
background: rgba(88, 166, 255, 0.1);
95+
border-color: var(--accent);
96+
}
97+
.playground-actions button:disabled { opacity: 0.4; cursor: not-allowed; }
98+
.playground-run { font-weight: 600; }
99+
100+
.playground-editor {
101+
display: block; width: 100%; min-height: 80px;
102+
background: #0d1117; color: var(--text);
103+
border: 1px solid var(--border);
104+
border-top: none; border-bottom: none;
105+
padding: 1rem;
106+
font-family: var(--font-mono);
107+
font-size: 0.875rem; line-height: 1.55;
108+
resize: vertical; outline: none;
109+
tab-size: 2; white-space: pre; overflow-x: auto;
110+
}
111+
.playground-editor:focus {
112+
border-color: var(--accent);
113+
box-shadow: inset 0 0 0 1px var(--accent);
114+
}
115+
116+
.playground-output {
117+
background: #1c2333;
118+
border: 1px solid var(--border);
119+
border-radius: 0 0 0.5rem 0.5rem;
120+
padding: 0.75rem 1rem;
121+
font-family: var(--font-mono);
122+
font-size: 0.85rem; color: #8b949e;
123+
white-space: pre-wrap; min-height: 2rem;
124+
word-break: break-word;
125+
}
126+
.playground-output.active { color: var(--green); border-color: var(--green); }
127+
.playground-output.error { color: var(--red); border-color: var(--red); }
128+
.playground-hint {
129+
font-size: 0.75rem; color: #484f58;
130+
margin-top: 0.35rem; text-align: right;
131+
}
132+
133+
footer {
134+
text-align: center;
135+
padding: 2rem 0;
136+
color: #8b949e;
137+
font-size: 0.85rem;
138+
border-top: 1px solid var(--border);
139+
margin-top: 2rem;
140+
}
141+
</style>
142+
</head>
143+
<body>
144+
145+
<div id="playground-loading">
146+
<div class="spinner"></div>
147+
<div id="playground-status">Initializing playground…</div>
148+
</div>
149+
150+
<a class="back" href="index.html">← Back to roadmap</a>
151+
<h1>pd.arrays: Nullable Typed Extension Arrays</h1>
152+
<p class="subtitle">Nullable typed arrays with three-valued logic — mirrors <code>pandas.arrays</code>
153+
with <code>IntegerArray</code>, <code>FloatingArray</code>, <code>BooleanArray</code>, and <code>StringArray</code>.</p>
154+
155+
<div class="section">
156+
<h2>1 — Quick Start</h2>
157+
<p>All four array types support nullable values, arithmetic, and reductions.</p>
158+
<div class="playground-block">
159+
<div class="playground-header">
160+
<span class="playground-label">TypeScript</span>
161+
<div class="playground-actions">
162+
<button class="playground-run" disabled>▶ Run</button>
163+
<button class="playground-reset">↺ Reset</button>
164+
</div>
165+
</div>
166+
<textarea class="playground-editor" spellcheck="false">import {
167+
IntegerArray,
168+
FloatingArray,
169+
BooleanArray,
170+
StringArray,
171+
} from "tsb";
172+
173+
// Nullable integer array
174+
const ints = IntegerArray.from([1, 2, null, 4, 5], "Int32");
175+
console.log(ints.dtype); // "Int32"
176+
console.log(ints.toArray()); // [1, 2, null, 4, 5]
177+
console.log(ints.sum()); // 12
178+
console.log(ints.fillna(0).toArray()); // [1, 2, 0, 4, 5]
179+
180+
// Nullable float array
181+
const floats = FloatingArray.from([1.5, NaN, 3.0]);
182+
console.log(floats.mean()); // 2.25
183+
184+
// Nullable boolean — three-valued logic
185+
const bools = BooleanArray.from([true, null, false]);
186+
console.log(bools.any()); // true
187+
console.log(bools.all()); // false
188+
189+
// Nullable string array
190+
const strs = StringArray.from(["hello", null, "world"]);
191+
console.log(strs.upper().toArray()); // ["HELLO", null, "WORLD"]
192+
console.log(strs.len().toArray()); // [5, null, 5]</textarea>
193+
<div class="playground-output">Click ▶ Run to execute</div>
194+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
195+
</div>
196+
</div>
197+
198+
<div class="section">
199+
<h2>2 — IntegerArray</h2>
200+
<p>Nullable integer array with configurable dtype (<code>Int8</code>, <code>Int16</code>, <code>Int32</code>, <code>Int64</code>, unsigned variants).</p>
201+
<div class="playground-block">
202+
<div class="playground-header">
203+
<span class="playground-label">TypeScript</span>
204+
<div class="playground-actions">
205+
<button class="playground-run" disabled>▶ Run</button>
206+
<button class="playground-reset">↺ Reset</button>
207+
</div>
208+
</div>
209+
<textarea class="playground-editor" spellcheck="false">import { IntegerArray } from "tsb";
210+
211+
const a = IntegerArray.from([1, 2, null, 4], "Int32");
212+
console.log(a.dtype); // "Int32"
213+
console.log(a.size); // 4
214+
console.log(a.at(2)); // null (NA)
215+
console.log(a.isna()); // [false, false, true, false]
216+
217+
// Arithmetic (NA propagates)
218+
console.log(a.add(10).toArray()); // [11, 12, null, 14]
219+
console.log(a.mul(2).toArray()); // [2, 4, null, 8]
220+
221+
// Reductions
222+
console.log(a.sum()); // 7
223+
console.log(a.mean()); // ~2.33
224+
console.log(a.min()); // 1
225+
console.log(a.max()); // 4</textarea>
226+
<div class="playground-output">Click ▶ Run to execute</div>
227+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
228+
</div>
229+
</div>
230+
231+
<div class="section">
232+
<h2>3 — FloatingArray</h2>
233+
<p>Nullable float array — treats <code>NaN</code> as missing, unlike plain JS numbers.</p>
234+
<div class="playground-block">
235+
<div class="playground-header">
236+
<span class="playground-label">TypeScript</span>
237+
<div class="playground-actions">
238+
<button class="playground-run" disabled>▶ Run</button>
239+
<button class="playground-reset">↺ Reset</button>
240+
</div>
241+
</div>
242+
<textarea class="playground-editor" spellcheck="false">import { FloatingArray } from "tsb";
243+
244+
const f = FloatingArray.from([1.0, 2.5, NaN, 4.5]);
245+
console.log(f.toArray()); // [1.0, 2.5, null, 4.5]
246+
console.log(f.sum()); // 8.0
247+
console.log(f.mean()); // ~2.67
248+
console.log(f.min()); // 1.0
249+
console.log(f.max()); // 4.5
250+
251+
// Arithmetic
252+
console.log(f.add(f).toArray()); // [2.0, 5.0, null, 9.0]
253+
console.log(f.pow(2).toArray()); // [1.0, 6.25, null, 20.25]</textarea>
254+
<div class="playground-output">Click ▶ Run to execute</div>
255+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
256+
</div>
257+
</div>
258+
259+
<div class="section">
260+
<h2>4 — BooleanArray (Three-Valued Logic)</h2>
261+
<p>Implements Kleene three-valued logic: <code>true</code>, <code>false</code>, and <code>null</code> (unknown).</p>
262+
<div class="playground-block">
263+
<div class="playground-header">
264+
<span class="playground-label">TypeScript</span>
265+
<div class="playground-actions">
266+
<button class="playground-run" disabled>▶ Run</button>
267+
<button class="playground-reset">↺ Reset</button>
268+
</div>
269+
</div>
270+
<textarea class="playground-editor" spellcheck="false">import { BooleanArray } from "tsb";
271+
272+
const b = BooleanArray.from([true, null, false]);
273+
console.log(b.any()); // true
274+
console.log(b.all()); // false
275+
console.log(b.sum()); // 1
276+
277+
// Kleene logic
278+
const x = BooleanArray.from([true, false, null, true ]);
279+
const y = BooleanArray.from([true, null, true, false]);
280+
console.log(x.and(y).toArray()); // [true, false, null, false]
281+
console.log(x.or(y).toArray()); // [true, null, true, false]
282+
console.log(x.not().toArray()); // [false, null, true, false]</textarea>
283+
<div class="playground-output">Click ▶ Run to execute</div>
284+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
285+
</div>
286+
</div>
287+
288+
<div class="section">
289+
<h2>5 — StringArray</h2>
290+
<p>Nullable string array with vectorised string methods that skip <code>null</code> values.</p>
291+
<div class="playground-block">
292+
<div class="playground-header">
293+
<span class="playground-label">TypeScript</span>
294+
<div class="playground-actions">
295+
<button class="playground-run" disabled>▶ Run</button>
296+
<button class="playground-reset">↺ Reset</button>
297+
</div>
298+
</div>
299+
<textarea class="playground-editor" spellcheck="false">import { StringArray } from "tsb";
300+
301+
const s = StringArray.from([" Hello ", null, "world"]);
302+
console.log(s.strip().toArray()); // ["Hello", null, "world"]
303+
console.log(s.upper().toArray()); // [" HELLO ", null, "WORLD"]
304+
305+
// Pattern matching → BooleanArray
306+
console.log(s.strip().contains("Hello").toArray()); // [true, null, false]
307+
console.log(s.strip().startswith("H").toArray()); // [true, null, false]
308+
309+
// Lengths → IntegerArray
310+
console.log(s.strip().len().toArray()); // [5, null, 5]</textarea>
311+
<div class="playground-output">Click ▶ Run to execute</div>
312+
<div class="playground-hint">Ctrl+Enter to run · Tab to indent</div>
313+
</div>
314+
</div>
315+
316+
<footer>
317+
<p>
318+
<a href="index.html">tsb playground</a> ·
319+
Built by <a href="https://github.com/githubnext/autoloop">Autoloop</a>
320+
</p>
321+
</footer>
322+
323+
<script type="module" src="playground-runtime.js"></script>
324+
</body>
325+
</html>

0 commit comments

Comments
 (0)