1// The shared .m files, shown read-only. The editable script in each lab is
2// the filter itself; these are the pieces every lab is allowed to assume.
3import { useState } from 'react'
5const raw = import.meta.glob('../matlab/*.m', { query: '?raw', import: 'default', eager: true }) as Record<
6 string,
7 string
8>
10const FILES = Object.entries(raw)
11 .map(([path, content]) => ({ name: path.slice(path.lastIndexOf('/') + 1), content }))
12 .sort((a, b) => a.name.localeCompare(b.name))
14export default function LibraryView() {
15 const [open, setOpen] = useState<string | null>(FILES[0]?.name ?? null)
16 return (
17 <article className="chapter">
18 <header className="chapter-head">
19 <div className="chapter-part">Reference</div>
20 <h2>The shared MATLAB library</h2>
21 <p className="chapter-blurb">
22 Every lab boots with these function files in its session, alongside the editable script and a driver that
23 reads the controls, computes the exact answer, measures the method against it, and writes the figures and
24 the sound. They are the pieces that would otherwise be repeated in every chapter: reading and writing the
25 page's data, packing a signal for the audio player, the spectral estimates, the Bessel zeros, and the one
26 routine that every measured frequency in the tutorial comes from.
27 </p>
28 </header>
29 <div className="lib-list">
30 {FILES.map((f) => (
31 <div className="lib-file" key={f.name}>
32 <button className="lib-name" onClick={() => setOpen(open === f.name ? null : f.name)}>
33 {open === f.name ? '▾' : '▸'} {f.name}
34 </button>
35 {open === f.name && <pre className="lib-src">{f.content}</pre>}
36 </div>
37 ))}
38 </div>
39 </article>
40 )
41}