typebulb 0.14.3 → 0.14.5
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 +93 -1
- package/dist/agents/claude/client.js +1 -1
- package/dist/index.js +137 -137
- package/dist/servers.js +59 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -219,7 +219,7 @@ The agent mirror turns that block into a live, sandboxed app, with a *breakout
|
|
|
219
219
|
|
|
220
220
|
The host owns a bulb's **width**; you own its **height**.
|
|
221
221
|
|
|
222
|
-
**Width is the host's.** Standalone, a bulb fills its browser window; in the agent mirror, an embed fits the conversation column by default, with a per-embed *spread* toggle to the full transcript width — and a cap so a tall embed doesn't run away down the transcript. Don't set a width or guess how much room you'll get.
|
|
222
|
+
**Width is the host's.** Standalone, a bulb fills its browser window; in the agent mirror, an embed fits the conversation column by default, with a per-embed *spread* toggle to the full transcript width — and a cap so a tall embed doesn't run away down the transcript. Don't set a width or guess how much room you'll get. `max-width` is the one width worth setting — a readability cap that only declines excess, so it's safe at any granted width. It's also what *spread* runs into: a dense visualization that earns the full transcript width should omit it.
|
|
223
223
|
|
|
224
224
|
**Height follows your content.** Set a height that adapts — content-driven or viewport-filling — never a fixed pixel value, which neither grows to fill a broken-out window nor shrinks to its content. Prose, a form, a chart flow to their natural height: set none. A full-bleed surface with no natural height of its own gets `height: 100dvh` **and** a pixel floor like `min-height: 420px`. Both are needed — `100dvh` fills its own window if the bulb is broken out, and the floor holds a definite band when embedded. Without the floor a bare `100dvh` collapses to zero embedded, because the mirror sizes an embed to its content height and `100dvh` gives it nothing to measure against.
|
|
225
225
|
|
|
@@ -251,6 +251,7 @@ The host owns a bulb's **width**; you own its **height**.
|
|
|
251
251
|
- **`tb.theme` drives the `html[data-theme]` attribute** — style off that selector (`html[data-theme="dark"] { … }`); don't read `tb.theme` to branch your rendering.
|
|
252
252
|
- **`color-scheme` is set for you** — the host always applies `html[data-theme="dark"] { color-scheme: dark }` / `html[data-theme="light"] { color-scheme: light }` on top of your `styles.css`.
|
|
253
253
|
- **Math (KaTeX) renders in your replies** — write inline `$…$` / display `$$…$$` (prefer `$y = x^2$` over inline-code or a Unicode `y = x²`). The mirror's KaTeX renders only in prose and doesn't reach inside a fenced block (bulb, mermaid, svg, code).
|
|
254
|
+
- **Charts: prefer a bulb over mermaid's `xychart`** unless a static, unlabeled bar or line is enough — start from the [Charts](#charts) skeleton.
|
|
254
255
|
- **`tb.json<T>(n)` is generic** — `tb.json<Album[]>(0)` returns typed parsed JSON; `tb.data(n)` returns the raw string.
|
|
255
256
|
- **`tb.proxy()` is for same-origin Web Worker / WASM loads** — e.g. ffmpeg or tesseract: `tb.proxy("https://unpkg.com/...")` routes the CDN URL through the local server's origin.
|
|
256
257
|
- **Prefer an `index.html` fragment** over a full HTML document — usually just the mount stub (`<div id="root"></div>`).
|
|
@@ -350,6 +351,97 @@ const { text } = await tb.ai({
|
|
|
350
351
|
|
|
351
352
|
Provider support varies — the level is mapped to provider-specific parameters (e.g. Anthropic's adaptive thinking, OpenAI's reasoning effort).
|
|
352
353
|
|
|
354
|
+
## Charts
|
|
355
|
+
|
|
356
|
+
Mermaid's `xychart-beta` is static, unlabeled bars and lines — no tooltips, no legend, no other chart types. Anything more is a bulb. Start from this skeleton:
|
|
357
|
+
|
|
358
|
+
````markdown
|
|
359
|
+
---
|
|
360
|
+
format: typebulb/v1
|
|
361
|
+
name: Revenue vs Cost
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
**code.tsx**
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
import React from "react"
|
|
368
|
+
import { createRoot } from "react-dom/client"
|
|
369
|
+
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
|
|
370
|
+
ResponsiveContainer } from "recharts"
|
|
371
|
+
|
|
372
|
+
type Point = { month: string; revenue: number; cost: number }
|
|
373
|
+
const data = tb.json<Point[]>(0)
|
|
374
|
+
|
|
375
|
+
function App() {
|
|
376
|
+
return (
|
|
377
|
+
<div className="wrap">
|
|
378
|
+
<h1>Revenue vs Cost</h1>
|
|
379
|
+
<ResponsiveContainer width="100%" height={320}>
|
|
380
|
+
<LineChart data={data}>
|
|
381
|
+
<CartesianGrid stroke="currentColor" strokeOpacity={0.1} />
|
|
382
|
+
<XAxis dataKey="month" stroke="currentColor" tick={{ fill: "currentColor", fontSize: 12 }} />
|
|
383
|
+
<YAxis stroke="currentColor" tick={{ fill: "currentColor", fontSize: 12 }} />
|
|
384
|
+
<Tooltip contentStyle={{ background: "Canvas", color: "CanvasText",
|
|
385
|
+
border: "1px solid currentColor", borderRadius: 6 }} />
|
|
386
|
+
<Legend wrapperStyle={{ fontSize: 13 }} />
|
|
387
|
+
<Line dataKey="revenue" stroke="#14b8a6" strokeWidth={2} />
|
|
388
|
+
<Line dataKey="cost" stroke="#e11d48" strokeWidth={2} />
|
|
389
|
+
</LineChart>
|
|
390
|
+
</ResponsiveContainer>
|
|
391
|
+
</div>
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
createRoot(document.getElementById("root")!).render(<App />)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**index.html**
|
|
399
|
+
|
|
400
|
+
```html
|
|
401
|
+
<div id="root"></div>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**styles.css**
|
|
405
|
+
|
|
406
|
+
```css
|
|
407
|
+
.wrap {
|
|
408
|
+
max-width: 720px; /* readability cap — omit when the chart earns spread width */
|
|
409
|
+
margin: 0 auto; /* horizontal centering only */
|
|
410
|
+
padding: 24px 16px; /* vertical space as padding, never margin (see Sizing) */
|
|
411
|
+
font: 14px system-ui, sans-serif;
|
|
412
|
+
}
|
|
413
|
+
h1 { font-size: 18px; margin: 0 0 12px; }
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**data.txt**
|
|
417
|
+
|
|
418
|
+
```txt
|
|
419
|
+
[
|
|
420
|
+
{ "month": "Jan", "revenue": 12, "cost": 8 },
|
|
421
|
+
{ "month": "Feb", "revenue": 14, "cost": 9 },
|
|
422
|
+
{ "month": "Mar", "revenue": 11, "cost": 10 },
|
|
423
|
+
{ "month": "Apr", "revenue": 17, "cost": 10 },
|
|
424
|
+
{ "month": "May", "revenue": 21, "cost": 12 },
|
|
425
|
+
{ "month": "Jun", "revenue": 24, "cost": 12 }
|
|
426
|
+
]
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**config.json**
|
|
430
|
+
|
|
431
|
+
```json
|
|
432
|
+
{
|
|
433
|
+
"description": "Monthly revenue vs cost as a two-series line chart.",
|
|
434
|
+
"dependencies": {
|
|
435
|
+
"react": "^19.2.7",
|
|
436
|
+
"react-dom": "^19.2.7",
|
|
437
|
+
"recharts": "^3.8.1"
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
````
|
|
442
|
+
|
|
443
|
+
The non-obvious bits: axes and grid off `currentColor` (light/dark with zero theme JS), the tooltip on `Canvas`/`CanvasText` system colors, and an explicit height on `ResponsiveContainer` — a chart has no natural height; the root still sizes to content. For point-dense marks (thousands of scatter dots or bars) or types recharts lacks (heatmap, candlestick, gauge), use `echarts` (canvas) instead.
|
|
444
|
+
|
|
353
445
|
## License
|
|
354
446
|
|
|
355
447
|
MIT
|