semiotic 3.7.0 → 3.7.2
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/CLAUDE.md +3 -2
- package/README.md +46 -7
- package/ai/behaviorContracts.cjs +19 -9
- package/ai/cli.js +15 -0
- package/ai/dist/mcp-server.js +583 -66
- package/ai/schema.json +1 -1
- package/ai/system-prompt.md +3 -3
- package/dist/components/AccessibleNavTree.d.ts +2 -1
- package/dist/components/Annotation.d.ts +1 -1
- package/dist/components/CategoryColors.d.ts +1 -1
- package/dist/components/ChartGrid.d.ts +1 -1
- package/dist/components/ContextLayout.d.ts +1 -1
- package/dist/components/DataSummaryContext.d.ts +1 -1
- package/dist/components/DetailsPanel.d.ts +1 -1
- package/dist/components/Legend.d.ts +3 -2
- package/dist/components/LinkedCharts.d.ts +1 -1
- package/dist/components/ThemeProvider.d.ts +1 -1
- package/dist/components/Tooltip/FlippingTooltip.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +2 -2
- package/dist/components/ai/qualityScorecard.d.ts +11 -0
- package/dist/components/charts/geo/ChoroplethMap.d.ts +2 -1
- package/dist/components/charts/network/CirclePack.d.ts +2 -1
- package/dist/components/charts/network/OrbitDiagram.d.ts +1 -1
- package/dist/components/charts/network/TreeDiagram.d.ts +2 -1
- package/dist/components/charts/network/Treemap.d.ts +2 -1
- package/dist/components/charts/realtime/RealtimeHistogram.d.ts +1 -1
- package/dist/components/charts/shared/ChartError.d.ts +2 -1
- package/dist/components/charts/shared/withChartWrapper.d.ts +1 -1
- package/dist/components/charts/xy/MinimapChart.d.ts +2 -1
- package/dist/components/charts/xy/ScatterplotMatrix.d.ts +2 -1
- package/dist/components/semiotic-server.d.ts +2 -1
- package/dist/components/server/renderEvidence.d.ts +92 -0
- package/dist/components/server/renderToStaticSVG.d.ts +14 -1
- package/dist/components/stream/AccessibleDataTable.d.ts +5 -5
- package/dist/components/stream/FocusRing.d.ts +2 -1
- package/dist/components/stream/MarginalGraphics.d.ts +2 -1
- package/dist/components/stream/NetworkCanvasHitTester.d.ts +3 -2
- package/dist/components/stream/NetworkPipelineStore.d.ts +46 -1
- package/dist/components/stream/NetworkSVGOverlay.d.ts +2 -1
- package/dist/components/stream/OrdinalBrushOverlay.d.ts +19 -1
- package/dist/components/stream/OrdinalSVGOverlay.d.ts +2 -2
- package/dist/components/stream/PipelineStore.d.ts +6 -0
- package/dist/components/stream/SVGOverlay.d.ts +3 -2
- package/dist/components/stream/StalenessBadge.d.ts +19 -0
- package/dist/components/stream/XYBrushOverlay.d.ts +21 -1
- package/dist/components/stream/quadtreeHitTest.d.ts +7 -1
- package/dist/geo.min.js +1 -1
- package/dist/geo.module.min.js +1 -1
- package/dist/network.min.js +1 -1
- package/dist/network.module.min.js +1 -1
- package/dist/ordinal.min.js +1 -1
- package/dist/ordinal.module.min.js +1 -1
- package/dist/realtime.min.js +1 -1
- package/dist/realtime.module.min.js +1 -1
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-server.d.ts +2 -1
- package/dist/semiotic-themes.min.js +1 -1
- package/dist/semiotic-themes.module.min.js +1 -1
- package/dist/semiotic-utils.min.js +1 -1
- package/dist/semiotic-utils.module.min.js +1 -1
- package/dist/semiotic-value.min.js +1 -1
- package/dist/semiotic-value.module.min.js +1 -1
- package/dist/semiotic.min.js +1 -1
- package/dist/semiotic.module.min.js +1 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +2 -2
package/CLAUDE.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- Install: `npm install semiotic`
|
|
5
5
|
<!-- semiotic-bundle-sizes:start -->
|
|
6
6
|
<!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
|
|
7
|
-
- **Use sub-path imports** — `semiotic/xy` (90KB gz), `semiotic/ordinal` (74KB gz), `semiotic/network` (68KB gz), `semiotic/geo` (55KB gz), `semiotic/realtime` (95KB gz), `semiotic/server` (
|
|
7
|
+
- **Use sub-path imports** — `semiotic/xy` (90KB gz), `semiotic/ordinal` (74KB gz), `semiotic/network` (68KB gz), `semiotic/geo` (55KB gz), `semiotic/realtime` (95KB gz), `semiotic/server` (128KB gz), `semiotic/utils` (38KB gz), `semiotic/recipes` (9KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (6KB gz), `semiotic/ai` (250KB gz). Full `semiotic` is 203KB gz.
|
|
8
8
|
<!-- semiotic-bundle-sizes:end -->
|
|
9
9
|
- CLI: `npx semiotic-ai [--schema|--compact|--examples|--doctor|--audit-a11y]` · MCP: `npx semiotic-mcp`
|
|
10
10
|
|
|
@@ -160,9 +160,10 @@ Also: **ScatterplotMatrix**, **ChartContainer** (`title`, `subtitle`, `actions`)
|
|
|
160
160
|
HOC charts render SVG automatically in server environments. For standalone generation:
|
|
161
161
|
|
|
162
162
|
```ts
|
|
163
|
-
import { renderChart, renderToImage, renderToAnimatedGif, renderDashboard } from "semiotic/server"
|
|
163
|
+
import { renderChart, renderChartWithEvidence, renderToImage, renderToAnimatedGif, renderDashboard } from "semiotic/server"
|
|
164
164
|
|
|
165
165
|
const svg = renderChart("BarChart", { data, categoryAccessor, valueAccessor, theme: "tufte", showLegend, showGrid, annotations })
|
|
166
|
+
const { svg: svg2, evidence } = renderChartWithEvidence("BarChart", { data, categoryAccessor, valueAccessor }) // evidence: { markCount, markCountByType, empty, xDomain?, yDomain?, categories?, nodeCount?, edgeCount?, annotationCount, ariaLabel, warnings } — ground truth from the rendered scene; check `evidence.empty`/`markCount` instead of parsing SVG. MCP renderChart returns the same block.
|
|
166
167
|
const png = await renderToImage("LineChart", { ... }, { format: "png", scale: 2 }) // requires sharp
|
|
167
168
|
const gif = await renderToAnimatedGif("line", data, { xAccessor, yAccessor, theme: "dark" }, { fps: 12, transitionFrames: 4, decay: { type: "linear" } }) // requires sharp + gifenc
|
|
168
169
|
const dashboard = renderDashboard([{ component: "BarChart", props }, { component: "PieChart", colSpan: 2, props }], { title, theme, layout: { columns: 2 } })
|
package/README.md
CHANGED
|
@@ -12,6 +12,18 @@ Simple charts in 5 lines. Network graphs, streaming data, and coordinated
|
|
|
12
12
|
dashboards when you need them. Structured schemas and an MCP server so
|
|
13
13
|
AI coding assistants generate correct chart code on the first try.
|
|
14
14
|
|
|
15
|
+
## What's New in 3.7.2
|
|
16
|
+
|
|
17
|
+
3.7.2 is a deployment and docs-polish patch release:
|
|
18
|
+
|
|
19
|
+
- `semiotic-mcp --http` now runs in stateless Streamable HTTP mode, with JSON responses,
|
|
20
|
+
health endpoints, optional `MCP_ALLOWED_HOSTS` host-header protection, and serverless-friendly
|
|
21
|
+
request teardown.
|
|
22
|
+
- `deploy/cloud-run` contains a minimal Google Cloud Run wrapper for publishing the MCP server as a
|
|
23
|
+
public read-only connector for ChatGPT, Claude, and other MCP clients.
|
|
24
|
+
- The Accessibility docs' visible navigation tree and bidirectional BarChart examples now honor
|
|
25
|
+
dark mode, and the contested-annotations blog demo renders its editorial-status callouts reliably.
|
|
26
|
+
|
|
15
27
|
```jsx
|
|
16
28
|
import { LineChart } from "semiotic/xy"
|
|
17
29
|
|
|
@@ -35,11 +47,11 @@ generate correct code without examples.
|
|
|
35
47
|
Semiotic ships with everything an AI coding assistant needs to generate
|
|
36
48
|
correct visualizations without trial and error:
|
|
37
49
|
|
|
38
|
-
- **`semiotic/ai`** — a single import with the 47-chart capability catalog (XY, ordinal, network, realtime, geo, value), optimized for LLM code generation.
|
|
50
|
+
- **`semiotic/ai`** — a single import with the 47-chart capability catalog (XY, ordinal, network, realtime, geo, value), optimized for LLM code generation. Note: the published entry files are pre-bundled, so importing one chart from `semiotic/ai` still ships most of the bundle — treat it as a codegen/tooling surface and use family subpaths (`semiotic/xy`, `semiotic/geo`, `semiotic/value`, …) in production code, at roughly half the single-chart cost.
|
|
39
51
|
- **`ai/schema.json`** — machine-readable prop schemas for every component
|
|
40
52
|
- **`npx semiotic-mcp`** — an MCP server for tool-based chart rendering in any MCP client
|
|
41
53
|
- **`npx semiotic-ai --doctor`** — validate component + props JSON from the command line with typo suggestions and anti-pattern detection
|
|
42
|
-
- **`diagnoseConfig(component, props)`** — programmatic anti-pattern detector with
|
|
54
|
+
- **`diagnoseConfig(component, props)`** — programmatic anti-pattern detector with actionable fixes, spanning validation, encoding, accessibility, and misleading-design (deception) checks
|
|
43
55
|
- **`CLAUDE.md`** — instruction files auto-synced for Claude, Cursor, Copilot, Windsurf, and Cline
|
|
44
56
|
- **`llms.txt`** — machine-readable documentation following the emerging standard
|
|
45
57
|
|
|
@@ -320,13 +332,13 @@ Semiotic ships 12 entry points. **Don't import from `"semiotic"` unless you need
|
|
|
320
332
|
| `semiotic/network` | **68 KB** | ForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more |
|
|
321
333
|
| `semiotic/geo` | **55 KB** | ChoroplethMap, FlowMap, DistanceCartogram, ProportionalSymbolMap |
|
|
322
334
|
| `semiotic/realtime` | **95 KB** | RealtimeLineChart, RealtimeHistogram, + 4 streaming charts |
|
|
323
|
-
| `semiotic/server` | **
|
|
324
|
-
| `semiotic/utils` | **
|
|
335
|
+
| `semiotic/server` | **128 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
|
|
336
|
+
| `semiotic/utils` | **38 KB** | ThemeProvider, validators, serialization — no chart components |
|
|
325
337
|
| `semiotic/recipes` | **9 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
|
|
326
338
|
| `semiotic/themes` | **4 KB** | Theme presets only (tufte, carbon, etc.) |
|
|
327
339
|
| `semiotic/data` | **3 KB** | bin, rollup, groupBy, pivot, fromVegaLite |
|
|
328
340
|
| `semiotic/value` | **6 KB** | BigNumber — focal-value KPI / scorecard (SingleValueFrame POC) |
|
|
329
|
-
| `semiotic/ai` | **
|
|
341
|
+
| `semiotic/ai` | **250 KB** | All 47 schema-backed charts + validation — optimized for LLM code generation |
|
|
330
342
|
| `semiotic` | **203 KB** | Everything below (full bundle) |
|
|
331
343
|
|
|
332
344
|
<!-- semiotic-bundle-sizes:end -->
|
|
@@ -411,13 +423,20 @@ Add to your MCP client config (e.g. `claude_desktop_config.json` for Claude Desk
|
|
|
411
423
|
}
|
|
412
424
|
```
|
|
413
425
|
|
|
414
|
-
No API keys or authentication required. The server runs locally via stdio. HTTP mode is also available for inspectors and
|
|
426
|
+
No API keys or authentication required. The server runs locally via stdio. HTTP mode is also available for inspectors, web clients, and ChatGPT Apps SDK experiments: `npx semiotic-mcp --http --port 3001`. In 3.7.2 HTTP mode is stateless: each request gets a fresh read-only MCP server + transport, so it can autoscale on serverless hosts without sticky sessions.
|
|
427
|
+
|
|
428
|
+
For ChatGPT developer mode, expose the HTTP endpoint over HTTPS with a tunnel and create a connector that points at `https://<your-tunnel>/mcp`. The experimental Apps SDK surface is `renderInteractiveChart`, which returns a `text/html;profile=mcp-app` widget template plus a hidden SVG payload rendered by Semiotic on the MCP server.
|
|
429
|
+
|
|
430
|
+
For a hosted deployment, see `deploy/cloud-run`. The wrapper runs the published `semiotic-mcp`
|
|
431
|
+
binary, exposes `/mcp` plus health endpoints, and supports `MCP_ALLOWED_HOSTS` for production
|
|
432
|
+
host-header allowlisting.
|
|
415
433
|
|
|
416
434
|
### Tools
|
|
417
435
|
|
|
418
436
|
| Tool | Description |
|
|
419
437
|
|------|-------------|
|
|
420
|
-
| **`renderChart`** | Render a Semiotic chart to static SVG. Supports the components returned by `getSchema` that are marked `[renderable]`. Pass `{ component: "LineChart", props: { data: [...], xAccessor: "x", yAccessor: "y" } }`. Returns SVG string or validation errors with fix suggestions. |
|
|
438
|
+
| **`renderChart`** | Render a Semiotic chart to static SVG. Supports the components returned by `getSchema` that are marked `[renderable]`. Pass `{ component: "LineChart", props: { data: [...], xAccessor: "x", yAccessor: "y" } }`. Returns SVG string plus a "Render evidence" JSON block (mark counts by scene type, resolved axis domains, empty flag, annotation count, accessible name) so agents can verify the chart drew data marks, or validation errors with fix suggestions. |
|
|
439
|
+
| **`renderInteractiveChart`** | Render a static-data chart as a ChatGPT Apps widget. Uses the same Semiotic server render path as `renderChart`, then hydrates an iframe UI with fit, zoom, data, hover, and render-evidence controls. |
|
|
421
440
|
| **`getSchema`** | Return the prop schema for a specific component. Pass `{ component: "LineChart" }` to get its props, or omit `component` to list all 47 chart schemas. Components marked `[renderable]` are available through `renderChart`; realtime charts require a browser/live environment. |
|
|
422
441
|
| **`suggestChart`** | Legacy sample-row recommender. Pass `{ data: [{...}, ...] }` with 1–5 sample objects plus optional broad intent/capability filters. |
|
|
423
442
|
| **`suggestCharts`** | Capability-based recommender for bounded row data. Returns ranked chart suggestions with scores, reasons, caveats, import paths, and ready-to-use props. |
|
|
@@ -439,6 +458,7 @@ No API keys or authentication required. The server runs locally via stdio. HTTP
|
|
|
439
458
|
| **`semiotic://behavior-contracts`** | Agent-visible semantic rules for color precedence, required prop combinations, push refs, and renderability. |
|
|
440
459
|
| **`semiotic://system-prompt`** | Compact AI instructions with import rules, chart props, SSR guidance, and pitfalls. |
|
|
441
460
|
| **`semiotic://examples`** | Copy-paste chart examples by data shape. |
|
|
461
|
+
| **`ui://semiotic/chart-widget.html`** | ChatGPT Apps / MCP Apps widget template used by `renderInteractiveChart`. |
|
|
442
462
|
|
|
443
463
|
### Prompts
|
|
444
464
|
|
|
@@ -490,6 +510,25 @@ Args: {
|
|
|
490
510
|
→ Returns: <svg>...</svg>
|
|
491
511
|
```
|
|
492
512
|
|
|
513
|
+
### Example: render a ChatGPT Apps widget
|
|
514
|
+
|
|
515
|
+
```
|
|
516
|
+
Tool: renderInteractiveChart
|
|
517
|
+
Args: {
|
|
518
|
+
"component": "BarChart",
|
|
519
|
+
"props": {
|
|
520
|
+
"title": "Revenue by Quarter",
|
|
521
|
+
"data": [
|
|
522
|
+
{ "quarter": "Q1", "revenue": 120 },
|
|
523
|
+
{ "quarter": "Q2", "revenue": 180 }
|
|
524
|
+
],
|
|
525
|
+
"categoryAccessor": "quarter",
|
|
526
|
+
"valueAccessor": "revenue"
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
→ Returns: structured chart summary for the model + hidden SVG/widget metadata for ChatGPT.
|
|
530
|
+
```
|
|
531
|
+
|
|
493
532
|
### Example: diagnose a broken config
|
|
494
533
|
|
|
495
534
|
```
|
package/ai/behaviorContracts.cjs
CHANGED
|
@@ -15,13 +15,17 @@ const DOC_MARKER_START = "<!-- semiotic-behavior-contracts:start -->"
|
|
|
15
15
|
const DOC_MARKER_END = "<!-- semiotic-behavior-contracts:end -->"
|
|
16
16
|
|
|
17
17
|
// Components whose static config requires `data` are derived from
|
|
18
|
-
// `ai/schema.json` rather than maintained as a hand-curated list.
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
18
|
+
// `ai/schema.json` rather than maintained as a hand-curated list.
|
|
19
|
+
//
|
|
20
|
+
// A component needs data in STATIC usage if its schema declares a `data` input
|
|
21
|
+
// prop — NOT merely if `data` is in the `required` array. `required` lists the
|
|
22
|
+
// semantic accessors a chart needs (highAccessor, subcategoryAccessor, series,
|
|
23
|
+
// …), and several data-driven charts don't put `data` itself there:
|
|
24
|
+
// CandlestickChart, MultiAxisLineChart, QuadrantChart, DifferenceChart,
|
|
25
|
+
// LikertChart, and SwimlaneChart. Keying off `required.includes("data")` missed
|
|
26
|
+
// exactly those — they'd render blank with no data yet passed --doctor / MCP
|
|
27
|
+
// diagnoseConfig as "OK" in static mode. Keying off the presence of a `data`
|
|
28
|
+
// property catches them (and still includes the charts that DO list `data`).
|
|
25
29
|
//
|
|
26
30
|
// `STATIC_DATA_COMPONENTS` stays exported as a Set for test/legacy callers
|
|
27
31
|
// that probe the surface, and is rebuilt from disk at module load time.
|
|
@@ -41,8 +45,10 @@ function loadStaticDataComponentsFromSchema() {
|
|
|
41
45
|
const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8"))
|
|
42
46
|
const out = new Set()
|
|
43
47
|
for (const tool of schema.tools || []) {
|
|
44
|
-
const
|
|
45
|
-
if
|
|
48
|
+
const properties = tool.function?.parameters?.properties || {}
|
|
49
|
+
// Data-driven if the schema declares a `data` input prop, regardless of
|
|
50
|
+
// whether `data` appears in `required` (see note above).
|
|
51
|
+
if ("data" in properties) out.add(tool.function.name)
|
|
46
52
|
}
|
|
47
53
|
if (out.size > 0) return out
|
|
48
54
|
} catch {
|
|
@@ -114,6 +120,10 @@ const PUSH_MODE_COMPONENTS = [
|
|
|
114
120
|
"Scatterplot",
|
|
115
121
|
"BubbleChart",
|
|
116
122
|
"ConnectedScatterplot",
|
|
123
|
+
"CandlestickChart",
|
|
124
|
+
"MultiAxisLineChart",
|
|
125
|
+
"QuadrantChart",
|
|
126
|
+
"DifferenceChart",
|
|
117
127
|
"BarChart",
|
|
118
128
|
"StackedBarChart",
|
|
119
129
|
"GroupedBarChart",
|
package/ai/cli.js
CHANGED
|
@@ -163,6 +163,21 @@ function validatePropsWithSchema(componentName, props, usageMode = "static") {
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
// Array-shape charts that declare a `data` schema prop need it in static
|
|
167
|
+
// usage even when "data" isn't in `required` (those lists hold semantic
|
|
168
|
+
// accessors). Without this, --doctor passed dataless static CandlestickChart /
|
|
169
|
+
// MultiAxisLineChart / QuadrantChart / DifferenceChart / SwimlaneChart /
|
|
170
|
+
// LikertChart configs that render blank. dataRequiredForUsageMode is true for
|
|
171
|
+
// them in static and false in push, mirroring the MCP diagnoseConfig path.
|
|
172
|
+
if (
|
|
173
|
+
"data" in properties &&
|
|
174
|
+
!required.includes("data") &&
|
|
175
|
+
dataRequiredForUsageMode(component.name, usageMode) &&
|
|
176
|
+
(props.data === undefined || props.data === null)
|
|
177
|
+
) {
|
|
178
|
+
errors.push(`"data" is required for ${component.name}.`)
|
|
179
|
+
}
|
|
180
|
+
|
|
166
181
|
for (const [propName, value] of Object.entries(props)) {
|
|
167
182
|
if (value === undefined || value === null) continue
|
|
168
183
|
const propSchema = properties[propName]
|