semiotic 3.8.1 → 3.8.3

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.
Files changed (178) hide show
  1. package/CLAUDE.md +3 -1
  2. package/README.md +54 -52
  3. package/ai/behaviorContracts.cjs +9 -0
  4. package/ai/dist/mcp-server.js +142 -13
  5. package/ai/schema.json +616 -42
  6. package/ai/surface-manifest.json +1 -1
  7. package/ai/system-prompt.md +5 -2
  8. package/dist/chunk-OrdinalBrushOverlay-PXHQYDB2.module.min.js +2 -0
  9. package/dist/chunk-XYBrushOverlay-ECZJJLAJ.module.min.js +1 -0
  10. package/dist/chunk-XYBrushOverlay-EP2SV3UI.module.min.js +2 -0
  11. package/dist/chunk-chunk-255KDHW5.module.min.js +1 -0
  12. package/dist/chunk-chunk-2CCFBTQC.module.min.js +2 -0
  13. package/dist/chunk-chunk-2CXCXRB4.module.min.js +1 -0
  14. package/dist/chunk-chunk-2JGJ5GUG.module.min.js +2 -0
  15. package/dist/chunk-chunk-2RXP3FS3.module.min.js +1 -0
  16. package/dist/chunk-chunk-2WVCH4PL.module.min.js +1 -0
  17. package/dist/chunk-chunk-4TMZXLCR.module.min.js +1 -0
  18. package/dist/chunk-chunk-5APBQXZA.module.min.js +1 -0
  19. package/dist/chunk-chunk-5RKXZQ2P.module.min.js +1 -0
  20. package/dist/chunk-chunk-5UKL5W76.module.min.js +2 -0
  21. package/dist/chunk-chunk-6HSGDMTA.module.min.js +2 -0
  22. package/dist/chunk-chunk-7FW6EGLP.module.min.js +2 -0
  23. package/dist/chunk-chunk-7OEOSCBP.module.min.js +1 -0
  24. package/dist/chunk-chunk-A63CTACR.module.min.js +2 -0
  25. package/dist/chunk-chunk-ANYDWOZF.module.min.js +1 -0
  26. package/dist/chunk-chunk-AZJUDQRM.module.min.js +2 -0
  27. package/dist/chunk-chunk-B6V35LMY.module.min.js +2 -0
  28. package/dist/chunk-chunk-BOSVL645.module.min.js +2 -0
  29. package/dist/chunk-chunk-CA3YDW6F.module.min.js +1 -0
  30. package/dist/chunk-chunk-CP3EN6KZ.module.min.js +1 -0
  31. package/dist/chunk-chunk-DSNGDNJY.module.min.js +1 -0
  32. package/dist/chunk-chunk-EMO5NUGE.module.min.js +2 -0
  33. package/dist/chunk-chunk-F25UA5HT.module.min.js +1 -0
  34. package/dist/chunk-chunk-FRIO6MCV.module.min.js +1 -0
  35. package/dist/chunk-chunk-FYY2ACNJ.module.min.js +2 -0
  36. package/dist/chunk-chunk-G7WFWHAD.module.min.js +2 -0
  37. package/dist/chunk-chunk-GMQ5AYTD.module.min.js +1 -0
  38. package/dist/chunk-chunk-GWSWSPXN.module.min.js +1 -0
  39. package/dist/chunk-chunk-I6C3KR5H.module.min.js +2 -0
  40. package/dist/chunk-chunk-IP2UE74X.module.min.js +1 -0
  41. package/dist/chunk-chunk-J3ELI22J.module.min.js +1 -0
  42. package/dist/chunk-chunk-J3QOW4OE.module.min.js +0 -0
  43. package/dist/chunk-chunk-J3XWETBJ.module.min.js +2 -0
  44. package/dist/chunk-chunk-J5RL6GXU.module.min.js +2 -0
  45. package/dist/chunk-chunk-JCG72SGW.module.min.js +2 -0
  46. package/dist/{semiotic-ai-chunk-OG7BQUUW.module.min.js → chunk-chunk-JJ2OOIET.module.min.js} +0 -1
  47. package/dist/chunk-chunk-JNCHKRIR.module.min.js +2 -0
  48. package/dist/chunk-chunk-KTWEBFMX.module.min.js +2 -0
  49. package/dist/chunk-chunk-L3H6DQCR.module.min.js +2 -0
  50. package/dist/chunk-chunk-M337NY6L.module.min.js +1 -0
  51. package/dist/chunk-chunk-M7VYYHCE.module.min.js +2 -0
  52. package/dist/chunk-chunk-MC35ILYP.module.min.js +2 -0
  53. package/dist/chunk-chunk-N72SWNBV.module.min.js +1 -0
  54. package/dist/chunk-chunk-OBQRFTIL.module.min.js +2 -0
  55. package/dist/chunk-chunk-OQTLSTGI.module.min.js +2 -0
  56. package/dist/chunk-chunk-Q2YADC2V.module.min.js +2 -0
  57. package/dist/chunk-chunk-QRIBHZYW.module.min.js +1 -0
  58. package/dist/chunk-chunk-QSQVBIJA.module.min.js +1 -0
  59. package/dist/chunk-chunk-RCF52Z42.module.min.js +2 -0
  60. package/dist/chunk-chunk-ROP4HI7H.module.min.js +2 -0
  61. package/dist/chunk-chunk-RZH7VZYS.module.min.js +2 -0
  62. package/dist/chunk-chunk-SA3D43RA.module.min.js +2 -0
  63. package/dist/chunk-chunk-SANERMIZ.module.min.js +2 -0
  64. package/dist/chunk-chunk-SIRIJ3DY.module.min.js +1 -0
  65. package/dist/chunk-chunk-SV4XAZ3Q.module.min.js +1 -0
  66. package/dist/chunk-chunk-U66USBWU.module.min.js +1 -0
  67. package/dist/chunk-chunk-UHSZEB74.module.min.js +1 -0
  68. package/dist/chunk-chunk-VVCA3DB7.module.min.js +1 -0
  69. package/dist/chunk-chunk-WCX6U47H.module.min.js +2 -0
  70. package/dist/chunk-chunk-XEVJDUTH.module.min.js +1 -0
  71. package/dist/chunk-chunk-XQYVEKEJ.module.min.js +2 -0
  72. package/dist/chunk-chunk-Y6AXCRVO.module.min.js +1 -0
  73. package/dist/chunk-chunk-YCQYG6J5.module.min.js +2 -0
  74. package/dist/chunk-chunk-YHNZCPOZ.module.min.js +2 -0
  75. package/dist/chunk-chunk-YWZB3KPI.module.min.js +2 -0
  76. package/dist/chunk-chunk-ZCNBUZPL.module.min.js +2 -0
  77. package/dist/chunk-statisticalOverlays-6MVAK5RW.module.min.js +2 -0
  78. package/dist/components/charts/custom/XYCustomChart.d.ts +3 -0
  79. package/dist/components/charts/physics/PhysicalFlowChart.d.ts +7 -0
  80. package/dist/components/charts/realtime/RealtimeHistogram.d.ts +5 -6
  81. package/dist/components/charts/realtime/temporalHistogramConfig.d.ts +11 -0
  82. package/dist/components/charts/shared/areaSeriesData.d.ts +15 -0
  83. package/dist/components/charts/shared/auditAccessibilityText.d.ts +13 -0
  84. package/dist/components/charts/shared/chartMode.d.ts +67 -0
  85. package/dist/components/charts/shared/colorUtils.d.ts +8 -0
  86. package/dist/components/charts/shared/geoStyleDefaults.d.ts +3 -0
  87. package/dist/components/charts/shared/hooks.d.ts +13 -80
  88. package/dist/components/charts/shared/useChartSetup.d.ts +3 -0
  89. package/dist/components/charts/shared/useCustomChartSetup.d.ts +3 -0
  90. package/dist/components/charts/shared/useXYLineStyle.d.ts +3 -2
  91. package/dist/components/charts/shared/xyLineStyle.d.ts +21 -0
  92. package/dist/components/charts/xy/LineChart.d.ts +3 -0
  93. package/dist/components/legendLayout.d.ts +31 -0
  94. package/dist/components/server/serverChartConfigShared.d.ts +29 -0
  95. package/dist/components/server/serverChartConfigs.d.ts +2 -13
  96. package/dist/components/server/serverChartConfigsXY.d.ts +3 -0
  97. package/dist/components/server/serverGaugeOverlay.d.ts +28 -0
  98. package/dist/components/server/staticLegend.d.ts +7 -1
  99. package/dist/components/server/staticSVGChrome.d.ts +60 -2
  100. package/dist/components/stream/GeoPipelineStore.d.ts +2 -0
  101. package/dist/components/stream/GeoSVGOverlay.d.ts +2 -0
  102. package/dist/components/stream/OrdinalBrushOverlay.d.ts +1 -2
  103. package/dist/components/stream/OrdinalBrushOverlayLazy.d.ts +9 -0
  104. package/dist/components/stream/SceneToSVG.d.ts +8 -6
  105. package/dist/components/stream/SceneToSVGGeo.d.ts +10 -0
  106. package/dist/components/stream/SceneToSVGNetwork.d.ts +12 -0
  107. package/dist/components/stream/XYBrushOverlayLazy.d.ts +17 -0
  108. package/dist/components/stream/canvasBackground.d.ts +7 -0
  109. package/dist/components/stream/networkTypes.d.ts +2 -4
  110. package/dist/components/stream/renderBackend.d.ts +14 -0
  111. package/dist/components/stream/sceneToSVGShared.d.ts +51 -0
  112. package/dist/components/types/legendTypes.d.ts +16 -3
  113. package/dist/controls.min.js +1 -1
  114. package/dist/controls.module.min.js +1 -1
  115. package/dist/geo.min.js +1 -1
  116. package/dist/geo.module.min.js +1 -1
  117. package/dist/network.min.js +1 -1
  118. package/dist/network.module.min.js +1 -1
  119. package/dist/ordinal.min.js +1 -1
  120. package/dist/ordinal.module.min.js +1 -1
  121. package/dist/physics-matter.min.js +1 -1
  122. package/dist/physics-matter.module.min.js +1 -1
  123. package/dist/physics-rapier.min.js +1 -1
  124. package/dist/physics-rapier.module.min.js +1 -1
  125. package/dist/physics.min.js +1 -1
  126. package/dist/physics.module.min.js +1 -1
  127. package/dist/realtime.min.js +1 -1
  128. package/dist/realtime.module.min.js +1 -1
  129. package/dist/rough.min.js +1 -1
  130. package/dist/rough.module.min.js +1 -1
  131. package/dist/semiotic-ai-core.min.js +1 -1
  132. package/dist/semiotic-ai-core.module.min.js +1 -1
  133. package/dist/semiotic-ai.min.js +1 -1
  134. package/dist/semiotic-ai.module.min.js +1 -1
  135. package/dist/semiotic-data.min.js +1 -1
  136. package/dist/semiotic-data.module.min.js +1 -1
  137. package/dist/semiotic-experimental.min.js +1 -1
  138. package/dist/semiotic-experimental.module.min.js +1 -1
  139. package/dist/semiotic-realtime-core.min.js +1 -1
  140. package/dist/semiotic-realtime-core.module.min.js +1 -1
  141. package/dist/semiotic-realtime-react.min.js +1 -1
  142. package/dist/semiotic-realtime-react.module.min.js +1 -1
  143. package/dist/semiotic-recipes-core.min.js +1 -1
  144. package/dist/semiotic-recipes-core.module.min.js +1 -1
  145. package/dist/semiotic-recipes-react.min.js +1 -1
  146. package/dist/semiotic-recipes-react.module.min.js +1 -1
  147. package/dist/semiotic-recipes.min.js +1 -1
  148. package/dist/semiotic-recipes.module.min.js +1 -1
  149. package/dist/semiotic-server-edge.min.js +1 -1
  150. package/dist/semiotic-server-edge.module.min.js +1 -1
  151. package/dist/semiotic-server-node.min.js +1 -1
  152. package/dist/semiotic-server-node.module.min.js +1 -1
  153. package/dist/semiotic-themes-core.min.js +1 -1
  154. package/dist/semiotic-themes-core.module.min.js +1 -1
  155. package/dist/semiotic-themes-react.min.js +1 -1
  156. package/dist/semiotic-themes-react.module.min.js +1 -1
  157. package/dist/semiotic-themes.min.js +1 -1
  158. package/dist/semiotic-themes.module.min.js +1 -1
  159. package/dist/semiotic-utils-core.min.js +1 -1
  160. package/dist/semiotic-utils-core.module.min.js +1 -1
  161. package/dist/semiotic-utils-react.min.js +1 -1
  162. package/dist/semiotic-utils-react.module.min.js +1 -1
  163. package/dist/semiotic-utils.min.js +1 -1
  164. package/dist/semiotic-utils.module.min.js +1 -1
  165. package/dist/semiotic-value.min.js +1 -1
  166. package/dist/semiotic-value.module.min.js +1 -1
  167. package/dist/semiotic.min.js +1 -1
  168. package/dist/semiotic.module.min.js +1 -1
  169. package/dist/server.min.js +1 -1
  170. package/dist/server.module.min.js +1 -1
  171. package/dist/xy.min.js +1 -1
  172. package/dist/xy.module.min.js +1 -1
  173. package/package.json +4 -4
  174. package/dist/semiotic-ai-statisticalOverlays-CY4WKR4A.module.min.js +0 -2
  175. package/dist/semiotic-chunk-3FSVZ46U.module.min.js +0 -2
  176. package/dist/semiotic-statisticalOverlays-UOMSFKVJ.module.min.js +0 -2
  177. package/dist/xy-chunk-IWD6IB6V.module.min.js +0 -2
  178. package/dist/xy-statisticalOverlays-7RWG6LJT.module.min.js +0 -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` (108KB gz), `semiotic/ordinal` (88KB gz), `semiotic/network` (93KB gz), `semiotic/geo` (66KB gz), `semiotic/realtime` (119KB gz), `semiotic/realtime/core` (118KB gz), `semiotic/realtime/react` (1KB gz), `semiotic/server` (124KB gz), `semiotic/server/node` (124KB gz), `semiotic/server/edge` (123KB gz), `semiotic/utils` (59KB gz), `semiotic/utils/core` (58KB gz), `semiotic/utils/react` (4KB gz), `semiotic/recipes` (53KB gz), `semiotic/recipes/core` (52KB gz), `semiotic/recipes/react` (1KB gz), `semiotic/themes` (6KB gz), `semiotic/themes/core` (6KB gz), `semiotic/themes/react` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (6KB gz), `semiotic/physics` (104KB gz), `semiotic/physics/matter` (1KB gz), `semiotic/physics/rapier` (1KB gz), `semiotic/ai` (394KB gz), `semiotic/ai/core` (67KB gz), `semiotic/controls` (10KB gz), `semiotic/rough` (3KB gz). Full `semiotic` is 251KB gz.
7
+ - **Use sub-path imports** — `semiotic/xy` (136KB gz), `semiotic/ordinal` (116KB gz), `semiotic/network` (122KB gz), `semiotic/geo` (95KB gz), `semiotic/realtime` (148KB gz), `semiotic/realtime/core` (143KB gz), `semiotic/realtime/react` (1KB gz), `semiotic/server` (134KB gz), `semiotic/server/node` (134KB gz), `semiotic/server/edge` (157KB gz), `semiotic/utils` (75KB gz), `semiotic/utils/core` (74KB gz), `semiotic/utils/react` (6KB gz), `semiotic/recipes` (75KB gz), `semiotic/recipes/core` (74KB gz), `semiotic/recipes/react` (2KB gz), `semiotic/themes` (7KB gz), `semiotic/themes/core` (7KB gz), `semiotic/themes/react` (6KB gz), `semiotic/data` (4KB gz), `semiotic/value` (8KB gz), `semiotic/physics` (133KB gz), `semiotic/physics/matter` (1KB gz), `semiotic/physics/rapier` (1KB gz), `semiotic/ai` (430KB gz), `semiotic/ai/core` (68KB gz), `semiotic/controls` (12KB gz), `semiotic/rough` (3KB gz). Full `semiotic` is 347KB 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
 
@@ -339,6 +339,8 @@ Interface for proposing/scoring variants beyond `capability.variants`. The built
339
339
 
340
340
  These rules are generated from `ai/behaviorContracts.cjs` and are consumed by `semiotic-ai --doctor`, MCP resources, and docs checks.
341
341
 
342
+ - **Accessible chart text uses direct chart props** (`accessibility.description-props`): High-level charts expose title for the visible name, description for a concise accessible description, summary for a screen-reader-only takeaway and interaction guidance, and accessibleTable for the data-table fallback.
343
+ Agent action: Put title, description, summary, and accessibleTable directly on the chart component when they appear in its schema. For generated L1–L3 description or a navigable chart tree, use ChartContainer with chartConfig plus describe and/or navigable; do not invent frameProps fields.
342
344
  - **Data required by usage mode** (`props.data-required-by-usage-mode`): Static usage (`renderChart`, MCP previews, SSR snapshots, and copy/paste examples with immediate data) requires data in props. React push mode selects live ingestion by omitting data and mutating through a ref.
343
345
  Agent action: Pass usageMode="push" to `semiotic-ai --doctor` when validating ref-based JSX with no data prop. Keep usageMode="static" or omit it for renderChart/MCP/static configs where data must be present.
344
346
  - **Categorical color precedence** (`color.category-precedence`): When colorBy is set, CategoryColorProvider/LinkedCharts category maps win for mapped categories. Unmapped categories fall back to explicit colorScheme, then ThemeProvider colors.categorical, then the built-in categorical fallback.
package/README.md CHANGED
@@ -16,14 +16,16 @@ AI coding assistants generate correct chart code on the first try.
16
16
  <img src="./docs/public/assets/img/semiotic-release-dashboard.svg" alt="Semiotic release dashboard showing chart count, bundle sizes, capability coverage, chart families, and documentation growth" width="100%">
17
17
  <!-- semiotic-readme-dashboard:end -->
18
18
 
19
- ## What's New in 3.8.1
19
+ ## What's New in 3.8.3
20
20
 
21
- 3.8.1 makes the hosted MCP rendering path release-ready:
21
+ 3.8.3 aligns browser and server rendering while tightening the docs release gate:
22
22
 
23
- - Stateless HTTP requests no longer cancel rendering after a completed request body.
24
- - Hosted `createChart` now has verified SVG and render evidence with `render-proven` status.
25
- - `GET /health` is the sole supported MCP health endpoint; nightly remains `main`-based while
26
- stable deployments are pinned to published releases.
23
+ - Static SVG rendering now shares chart defaults, legend layout, color behavior, and specialized
24
+ chart paths with the browser renderers.
25
+ - SSR parity coverage compares semantic chart output and targeted rendered geometry without
26
+ maintaining a second, redundant visual-snapshot matrix.
27
+ - Two new narrative examples—Earthquakes and Europa Languages—exercise geographic and network
28
+ visualization paths, and every example source route is smoke-tested in CI.
27
29
 
28
30
  ```jsx
29
31
  import { LineChart } from "semiotic/xy"
@@ -370,35 +372,35 @@ The numbers below are **first-party artifact cost**: the gzip size of Semiotic's
370
372
 
371
373
  | Entry Point | gzip | What's inside |
372
374
  |---|---|---|
373
- | `semiotic/xy` | **108 KB** | LineChart, AreaChart, Scatterplot, Heatmap, + 8 more XY charts |
374
- | `semiotic/ordinal` | **88 KB** | BarChart, PieChart, BoxPlot, Histogram, + 11 more categorical charts |
375
- | `semiotic/network` | **93 KB** | ForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more |
376
- | `semiotic/geo` | **66 KB** | ChoroplethMap, FlowMap, DistanceCartogram, ProportionalSymbolMap |
377
- | `semiotic/realtime` | **119 KB** | RealtimeLineChart, RealtimeHistogram, + 4 streaming charts |
378
- | `semiotic/realtime/core` | **118 KB** | Streaming chart types, HOCs, and buffer helpers |
375
+ | `semiotic/xy` | **136 KB** | LineChart, AreaChart, Scatterplot, Heatmap, + 8 more XY charts |
376
+ | `semiotic/ordinal` | **116 KB** | BarChart, PieChart, BoxPlot, Histogram, + 11 more categorical charts |
377
+ | `semiotic/network` | **122 KB** | ForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more |
378
+ | `semiotic/geo` | **95 KB** | ChoroplethMap, FlowMap, DistanceCartogram, ProportionalSymbolMap |
379
+ | `semiotic/realtime` | **148 KB** | RealtimeLineChart, RealtimeHistogram, + 4 streaming charts |
380
+ | `semiotic/realtime/core` | **143 KB** | Streaming chart types, HOCs, and buffer helpers |
379
381
  | `semiotic/realtime/react` | **1 KB** | Stream status and synced push hooks |
380
- | `semiotic/server` | **124 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
381
- | `semiotic/server/node` | **124 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
382
- | `semiotic/server/edge` | **123 KB** | renderChart, renderChartWithEvidence, renderToStaticSVG, renderDashboard |
383
- | `semiotic/utils` | **59 KB** | ThemeProvider, validators, serialization — no chart components |
384
- | `semiotic/utils/core` | **58 KB** | Theme helpers and serialization utilities |
385
- | `semiotic/utils/react` | **4 KB** | ThemeProvider, useTheme, useReducedMotion, useHighContrast, useStreamStatus |
386
- | `semiotic/recipes` | **53 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
387
- | `semiotic/recipes/core` | **52 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
388
- | `semiotic/recipes/react` | **1 KB** | Glyph and React layout-selection helpers |
389
- | `semiotic/themes` | **6 KB** | Theme presets only (tufte, carbon, etc.) |
390
- | `semiotic/themes/core` | **6 KB** | Theme presets and token helpers |
391
- | `semiotic/themes/react` | **4 KB** | ThemeProvider/useTheme and hooks |
392
- | `semiotic/data` | **3 KB** | bin, rollup, groupBy, pivot, fromVegaLite |
393
- | `semiotic/value` | **6 KB** | BigNumber — focal-value KPI / scorecard (SingleValueFrame POC) |
394
- | `semiotic/physics` | **104 KB** | GaltonBoardChart, EventDropChart, PhysicsPileChart, CollisionSwarmChart, PhysicalFlowChart, PhysicsCustomChart |
382
+ | `semiotic/server` | **134 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
383
+ | `semiotic/server/node` | **134 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
384
+ | `semiotic/server/edge` | **157 KB** | renderChart, renderChartWithEvidence, renderToStaticSVG, renderDashboard |
385
+ | `semiotic/utils` | **75 KB** | ThemeProvider, validators, serialization — no chart components |
386
+ | `semiotic/utils/core` | **74 KB** | Theme helpers and serialization utilities |
387
+ | `semiotic/utils/react` | **6 KB** | ThemeProvider, useTheme, useReducedMotion, useHighContrast, useStreamStatus |
388
+ | `semiotic/recipes` | **75 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
389
+ | `semiotic/recipes/core` | **74 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
390
+ | `semiotic/recipes/react` | **2 KB** | Glyph and React layout-selection helpers |
391
+ | `semiotic/themes` | **7 KB** | Theme presets only (tufte, carbon, etc.) |
392
+ | `semiotic/themes/core` | **7 KB** | Theme presets and token helpers |
393
+ | `semiotic/themes/react` | **6 KB** | ThemeProvider/useTheme and hooks |
394
+ | `semiotic/data` | **4 KB** | bin, rollup, groupBy, pivot, fromVegaLite |
395
+ | `semiotic/value` | **8 KB** | BigNumber — focal-value KPI / scorecard (SingleValueFrame POC) |
396
+ | `semiotic/physics` | **133 KB** | GaltonBoardChart, EventDropChart, PhysicsPileChart, CollisionSwarmChart, PhysicalFlowChart, PhysicsCustomChart |
395
397
  | `semiotic/physics/matter` | **1 KB** | Matter.js migration helpers + optional peer guard (no chart components) |
396
398
  | `semiotic/physics/rapier` | **1 KB** | Rapier peer guard + adapter decision metadata (no chart components) |
397
- | `semiotic/ai` | **394 KB** | All schema-backed charts + validation — optimized for LLM code generation |
398
- | `semiotic/ai/core` | **67 KB** | suggestCharts, validateProps, describeChart, repairChartConfig, tool adapters — no chart components |
399
- | `semiotic/controls` | **10 KB** | DirectManipulationControl, CircularBrush, MobileStandardControls, auditVisualizationControls — no frame renderer |
399
+ | `semiotic/ai` | **430 KB** | All schema-backed charts + validation — optimized for LLM code generation |
400
+ | `semiotic/ai/core` | **68 KB** | suggestCharts, validateProps, describeChart, repairChartConfig, tool adapters — no chart components |
401
+ | `semiotic/controls` | **12 KB** | DirectManipulationControl, CircularBrush, MobileStandardControls, auditVisualizationControls — no frame renderer |
400
402
  | `semiotic/rough` | **3 KB** | Optional deterministic Rough.js paint backend — exact Semiotic geometry remains authoritative |
401
- | `semiotic` | **251 KB** | Everything below (full bundle) |
403
+ | `semiotic` | **347 KB** | Everything below (full bundle) |
402
404
 
403
405
  <!-- semiotic-bundle-sizes:end -->
404
406
 
@@ -419,33 +421,33 @@ Method: fresh `npm pack --ignore-scripts` tarball → temporary consumer → min
419
421
 
420
422
  | Public named import | Runtime | gzip cold-consumer bundle |
421
423
  |---|---:|---:|
422
- | `import { LineChart } from "semiotic"` | browser | **281.3 KiB** |
423
- | `import { LineChart } from "semiotic/xy"` | browser | **143.8 KiB** |
424
- | `import { BarChart } from "semiotic/ordinal"` | browser | **119.1 KiB** |
425
- | `import { SankeyDiagram } from "semiotic/network"` | browser | **124.4 KiB** |
426
- | `import { RealtimeLineChart } from "semiotic/realtime"` | browser | **163.5 KiB** |
427
- | `import { RingBuffer } from "semiotic/realtime/core"` | browser | **163.4 KiB** |
424
+ | `import { LineChart } from "semiotic"` | browser | **146.9 KiB** |
425
+ | `import { LineChart } from "semiotic/xy"` | browser | **146.9 KiB** |
426
+ | `import { BarChart } from "semiotic/ordinal"` | browser | **121.4 KiB** |
427
+ | `import { SankeyDiagram } from "semiotic/network"` | browser | **126.0 KiB** |
428
+ | `import { RealtimeLineChart } from "semiotic/realtime"` | browser | **120.8 KiB** |
429
+ | `import { RingBuffer } from "semiotic/realtime/core"` | browser | **168.9 KiB** |
428
430
  | `import { useStreamStatus } from "semiotic/realtime/react"` | browser | **0.6 KiB** |
429
- | `import { GaltonBoardChart } from "semiotic/physics"` | browser | **113.6 KiB** |
431
+ | `import { GaltonBoardChart } from "semiotic/physics"` | browser | **115.8 KiB** |
430
432
  | `import { MATTER_PHYSICS_CAPABILITIES } from "semiotic/physics/matter"` | browser | **0.2 KiB** |
431
433
  | `import { RAPIER_PHYSICS_CAPABILITIES } from "semiotic/physics/rapier"` | browser | **0.2 KiB** |
432
- | `import { renderChart } from "semiotic/server"` | node | **164.7 KiB** |
433
- | `import { generateFrameSVGs } from "semiotic/server/edge"` | node | **79.9 KiB** |
434
- | `import { renderToImage } from "semiotic/server/node"` | node | **165.1 KiB** |
435
- | `import { suggestCharts } from "semiotic/ai"` | browser | **413.4 KiB** |
436
- | `import { suggestCharts } from "semiotic/ai/core"` | browser | **30.6 KiB** |
434
+ | `import { renderChart } from "semiotic/server"` | node | **177.0 KiB** |
435
+ | `import { generateFrameSVGs } from "semiotic/server/edge"` | node | **84.3 KiB** |
436
+ | `import { renderToImage } from "semiotic/server/node"` | node | **177.5 KiB** |
437
+ | `import { suggestCharts } from "semiotic/ai"` | browser | **205.8 KiB** |
438
+ | `import { suggestCharts } from "semiotic/ai/core"` | browser | **31.1 KiB** |
437
439
  | `import { bin } from "semiotic/data"` | browser | **0.4 KiB** |
438
- | `import { ChoroplethMap } from "semiotic/geo"` | browser | **104.1 KiB** |
440
+ | `import { ChoroplethMap } from "semiotic/geo"` | browser | **105.6 KiB** |
439
441
  | `import { createRoughRenderMode } from "semiotic/rough"` | browser | **3.3 KiB** |
440
442
  | `import { resolveThemePreset } from "semiotic/themes"` | browser | **3.4 KiB** |
441
443
  | `import { resolveThemePreset } from "semiotic/themes/core"` | browser | **3.4 KiB** |
442
444
  | `import { ThemeProvider } from "semiotic/themes/react"` | browser | **4.4 KiB** |
443
- | `import { validateProps } from "semiotic/utils"` | browser | **7.9 KiB** |
444
- | `import { smartTickFormat } from "semiotic/utils/core"` | browser | **2.1 KiB** |
445
- | `import { useReducedMotion } from "semiotic/utils/react"` | browser | **1.8 KiB** |
446
- | `import { waffleLayout } from "semiotic/recipes"` | browser | **1.3 KiB** |
447
- | `import { waffleLayout } from "semiotic/recipes/core"` | browser | **1.3 KiB** |
448
- | `import { Glyph } from "semiotic/recipes/react"` | browser | **0.9 KiB** |
445
+ | `import { validateProps } from "semiotic/utils"` | browser | **6.4 KiB** |
446
+ | `import { smartTickFormat } from "semiotic/utils/core"` | browser | **0.2 KiB** |
447
+ | `import { useReducedMotion } from "semiotic/utils/react"` | browser | **0.3 KiB** |
448
+ | `import { waffleLayout } from "semiotic/recipes"` | browser | **2.5 KiB** |
449
+ | `import { waffleLayout } from "semiotic/recipes/core"` | browser | **2.5 KiB** |
450
+ | `import { Glyph } from "semiotic/recipes/react"` | browser | **0.8 KiB** |
449
451
  | `import { BigNumber } from "semiotic/value"` | browser | **5.9 KiB** |
450
452
  | `import { DirectManipulationControl } from "semiotic/controls"` | browser | **1.3 KiB** |
451
453
 
@@ -459,9 +461,9 @@ import { SankeyDiagram } from "semiotic/network"
459
461
  import { ChoroplethMap } from "semiotic/geo"
460
462
  ```
461
463
 
462
- **Tree-shaking**: Each sub-path is a separate, pre-bundled artifact marked `"sideEffects": false`, so importing from `semiotic/xy` never pulls in `semiotic/ordinal` or `semiotic/network`. Note the boundary: within a family artifact the charts are **already combined into one module**, so importing only `LineChart` from `semiotic/xy` still loads the whole XY family artifact (≈98 KB gz) bundlers cannot tree-shake individual charts back out of a pre-bundled family. Cross-family separation is real; per-chart separation within a family is not (granular per-chart entries are planned). Pick the narrowest sub-path for your charts.
464
+ **Tree-shaking & multi-subpath imports**: Family entries (`semiotic/xy`, `semiotic/network`, `semiotic/ai`, …) are built as one ESM graph with **shared chunks**. Stream frames, renderers, and other common code ship once and are imported by every entry that needs them — so combining `semiotic/ai` + `semiotic/xy` + `semiotic/network` does **not** mean paying for three full copies of the runtime. The package is marked `"sideEffects": false`, so modern bundlers keep only the named exports you retain (e.g. `LineChart` + `suggestCharts`). Prefer family subpaths for clarity; import AI helpers from `semiotic/ai` or the lighter `semiotic/ai/core` when you do not need the chart catalog.
463
465
 
464
- **When to use `"semiotic"`**: Only if your app uses charts from 3+ categories (XY + ordinal + network) and you'd rather have one import than three. The full bundle is roughly the sum of every sub-path bundle above see the `semiotic` row of the table for the current number.
466
+ **When to use `"semiotic"`**: Fine when you want one import for mixed families. With shared chunks it is no longer “sum every subpath” the cold-consumer table above is the better guide for a single named import, and multi-family apps should not see the old double-pay tax.
465
467
 
466
468
  ## TypeScript
467
469
 
@@ -147,6 +147,15 @@ const PUSH_MODE_COMPONENTS = [
147
147
  const STATIC_DATA_COMPONENTS = loadStaticDataComponentsFromSchema()
148
148
 
149
149
  const BEHAVIOR_CONTRACTS = [
150
+ {
151
+ id: "accessibility.description-props",
152
+ category: "accessibility",
153
+ title: "Accessible chart text uses direct chart props",
154
+ severity: "warning",
155
+ appliesTo: {},
156
+ summary: "High-level charts expose title for the visible name, description for a concise accessible description, summary for a screen-reader-only takeaway and interaction guidance, and accessibleTable for the data-table fallback.",
157
+ agentAction: "Put title, description, summary, and accessibleTable directly on the chart component when they appear in its schema. For generated L1–L3 description or a navigable chart tree, use ChartContainer with chartConfig plus describe and/or navigable; do not invent frameProps fields.",
158
+ },
150
159
  {
151
160
  id: "props.data-required-by-usage-mode",
152
161
  category: "required-props",
@@ -7559,6 +7559,15 @@ var require_behaviorContracts = __commonJS({
7559
7559
  ];
7560
7560
  var STATIC_DATA_COMPONENTS = loadStaticDataComponentsFromSchema();
7561
7561
  var BEHAVIOR_CONTRACTS2 = [
7562
+ {
7563
+ id: "accessibility.description-props",
7564
+ category: "accessibility",
7565
+ title: "Accessible chart text uses direct chart props",
7566
+ severity: "warning",
7567
+ appliesTo: {},
7568
+ summary: "High-level charts expose title for the visible name, description for a concise accessible description, summary for a screen-reader-only takeaway and interaction guidance, and accessibleTable for the data-table fallback.",
7569
+ agentAction: "Put title, description, summary, and accessibleTable directly on the chart component when they appear in its schema. For generated L1\u2013L3 description or a navigable chart tree, use ChartContainer with chartConfig plus describe and/or navigable; do not invent frameProps fields."
7570
+ },
7562
7571
  {
7563
7572
  id: "props.data-required-by-usage-mode",
7564
7573
  category: "required-props",
@@ -33769,12 +33778,60 @@ function buildInfoForProfile(profile) {
33769
33778
  function profileResult(result) {
33770
33779
  return { ...result, surfaceVersion: SURFACE_VERSION };
33771
33780
  }
33781
+ function schemaAccessibilityGuidance(entry) {
33782
+ const properties = entry?.parameters?.properties ?? {};
33783
+ const directProps = Object.fromEntries(
33784
+ ["title", "description", "summary", "accessibleTable"].filter((name) => properties[name]).map((name) => [name, properties[name]])
33785
+ );
33786
+ return {
33787
+ directProps,
33788
+ chartContainer: {
33789
+ component: "ChartContainer",
33790
+ requires: ["chartConfig"],
33791
+ titleProp: "title",
33792
+ subtitleProp: "subtitle",
33793
+ describeProp: "describe",
33794
+ navigableProp: "navigable",
33795
+ description: "Use ChartContainer with chartConfig plus describe for a generated L1\u2013L3 description and navigable for a screen-reader navigation tree."
33796
+ }
33797
+ };
33798
+ }
33799
+ function accessibilityRecommendation(component, props, data) {
33800
+ const directProps = schemaAccessibilityGuidance(schemaByComponent[component]).directProps;
33801
+ const recommendation = {};
33802
+ const categoryAccessor = typeof props.categoryAccessor === "string" ? props.categoryAccessor : void 0;
33803
+ const valueAccessor = typeof props.valueAccessor === "string" ? props.valueAccessor : void 0;
33804
+ if (directProps.description && typeof props.description !== "string") {
33805
+ recommendation.description = categoryAccessor && valueAccessor ? `${component} comparing ${valueAccessor} by ${categoryAccessor}.` : `${component} chart.`;
33806
+ }
33807
+ if (directProps.summary && typeof props.summary !== "string") {
33808
+ const numericRows = categoryAccessor && valueAccessor ? data.map((row) => ({ category: row[categoryAccessor], value: row[valueAccessor] })).filter((row) => typeof row.value === "number" && Number.isFinite(row.value)) : [];
33809
+ const highest = numericRows.reduce(
33810
+ (current, row) => !current || row.value > current.value ? row : current,
33811
+ void 0
33812
+ );
33813
+ recommendation.summary = highest ? `${String(highest.category)} is highest at ${highest.value}. Use arrow keys to move between chart marks.` : "Use arrow keys to move between chart marks.";
33814
+ }
33815
+ return Object.keys(recommendation).length > 0 ? {
33816
+ location: "direct-component-props",
33817
+ props: recommendation,
33818
+ chartContainer: schemaAccessibilityGuidance(schemaByComponent[component]).chartContainer
33819
+ } : void 0;
33820
+ }
33772
33821
  async function getSchemaHandler(args) {
33773
33822
  const component = args.component;
33823
+ const availableComponents = allComponentNames.map((name) => ({
33824
+ name,
33825
+ renderable: metadataForComponent(name).renderable
33826
+ }));
33774
33827
  if (!component) {
33775
- const list = allComponentNames.map((name) => metadataForComponent(name).renderable ? `${name} [renderable]` : name);
33828
+ const list = availableComponents.map(
33829
+ ({ name, renderable: renderable2 }) => renderable2 ? `${name} [renderable]` : name
33830
+ );
33776
33831
  return {
33777
- content: [{ type: "text", text: `Available components (${allComponentNames.length}):
33832
+ content: [{
33833
+ type: "text",
33834
+ text: `Available components (${allComponentNames.length}):
33778
33835
  ${list.join(", ")}
33779
33836
 
33780
33837
  Components marked [renderable] can be rendered to SVG via renderChart (pass theme parameter for styled output). Others (Realtime*) require a browser environment.
@@ -33783,27 +33840,55 @@ For full agent context, read MCP resources: semiotic://schema, semiotic://compon
33783
33840
 
33784
33841
  All charts support CSS custom properties for theming (--semiotic-bg, --semiotic-text, --semiotic-grid, etc.) and <ThemeProvider>. Use COLOR_BLIND_SAFE_CATEGORICAL (import from semiotic/themes) for accessible color palettes.
33785
33842
 
33786
- Pass { component: '<name>' } to get the prop schema for a specific component.` }]
33843
+ Pass { component: '<name>' } to get the prop schema for a specific component.`
33844
+ }],
33845
+ structuredContent: profileResult({
33846
+ status: "component-list",
33847
+ availableComponents
33848
+ })
33787
33849
  };
33788
33850
  }
33789
33851
  const entry = schemaByComponent[component];
33790
33852
  if (!entry) {
33791
33853
  const available = Object.keys(schemaByComponent).sort();
33792
33854
  return {
33793
- content: [{ type: "text", text: `Unknown component "${component}". Available: ${available.join(", ")}` }],
33855
+ content: [{
33856
+ type: "text",
33857
+ text: `Unknown component "${component}". Available: ${available.join(", ")}`
33858
+ }],
33859
+ structuredContent: profileResult({
33860
+ status: "unknown-component",
33861
+ component,
33862
+ availableComponents
33863
+ }),
33794
33864
  isError: true
33795
33865
  };
33796
33866
  }
33797
- const renderableNote = metadataForComponent(component).renderable ? "This component can be rendered to SVG via renderChart." : "This component requires a browser environment and cannot be rendered via renderChart.";
33798
- const contracts = behaviorContractsFor({ component, props: {} });
33867
+ const renderable = metadataForComponent(component).renderable;
33868
+ const renderableNote = renderable ? "This component can be rendered to SVG via renderChart." : "This component requires a browser environment and cannot be rendered via renderChart.";
33869
+ const contracts = behaviorContractsFor({
33870
+ component,
33871
+ props: {}
33872
+ });
33799
33873
  const contractText = contracts.length > 0 ? `
33800
33874
 
33801
33875
  Behavior contracts:
33802
33876
  ${JSON.stringify(contracts, null, 2)}` : "";
33803
33877
  return {
33804
- content: [{ type: "text", text: `${renderableNote}
33878
+ content: [{
33879
+ type: "text",
33880
+ text: `${renderableNote}
33805
33881
 
33806
- ${JSON.stringify(entry, null, 2)}${contractText}` }]
33882
+ ${JSON.stringify(entry, null, 2)}${contractText}`
33883
+ }],
33884
+ structuredContent: profileResult({
33885
+ status: "component-schema",
33886
+ component,
33887
+ renderable,
33888
+ schema: entry,
33889
+ accessibility: schemaAccessibilityGuidance(entry),
33890
+ behaviorContracts: contracts
33891
+ })
33807
33892
  };
33808
33893
  }
33809
33894
  var SUGGEST_INTENT_ALIASES = {
@@ -34645,9 +34730,17 @@ async function improveChartHandler(args) {
34645
34730
  const repair = (0, import_ai3.repairChartConfig)(args.component, data, { intent });
34646
34731
  const capability = (0, import_ai3.getCapability)(args.component);
34647
34732
  const variants = capability ? (0, import_ai3.proposeVariant)(args.component, capability, { profile: (0, import_ai3.profileData)(data), intent }) : [];
34733
+ const accessibility = accessibilityRecommendation(args.component, args.props, data);
34648
34734
  return {
34649
34735
  content: [{ type: "text", text: `Improvement analysis for ${args.component}: ${diagnosis.diagnoses.length} diagnosis item(s), repair status ${repair.status}, ${variants.length} variant proposal(s).` }],
34650
- structuredContent: profileResult({ status: repair.status === "ok" ? "reviewed" : "repair-needed", component: args.component, diagnostics: diagnosis.diagnoses, repair, variants })
34736
+ structuredContent: profileResult({
34737
+ status: repair.status === "ok" ? "reviewed" : "repair-needed",
34738
+ component: args.component,
34739
+ diagnostics: diagnosis.diagnoses,
34740
+ repair,
34741
+ variants,
34742
+ ...accessibility ? { accessibilityRecommendation: accessibility } : {}
34743
+ })
34651
34744
  };
34652
34745
  }
34653
34746
  async function explainChartHandler(args) {
@@ -34659,8 +34752,8 @@ async function explainChartHandler(args) {
34659
34752
  }
34660
34753
  async function auditChartHandler(args) {
34661
34754
  const diagnosis = (0, import_ai3.diagnoseConfig)(args.component, args.props);
34662
- const accessibility = (0, import_ai3.auditAccessibility)(args.component, args.props, { inChartContainer: true, describe: true, navigable: true });
34663
- const mobile = (0, import_ai3.auditMobileVisualization)(args.component, args.props, { viewportWidth: args.viewportWidth, inChartContainer: true });
34755
+ const accessibility = (0, import_ai3.auditAccessibility)(args.component, args.props);
34756
+ const mobile = (0, import_ai3.auditMobileVisualization)(args.component, args.props, { viewportWidth: args.viewportWidth });
34664
34757
  const blocking = diagnosis.diagnoses.some((item) => item.severity === "error") || !accessibility.ok || !mobile.ok;
34665
34758
  return {
34666
34759
  content: [{ type: "text", text: `Audit for ${args.component}: ${blocking ? "blocking findings need attention" : "no blocking findings"}.` }],
@@ -34859,7 +34952,19 @@ function createServer2(profile = "developer", options = {}) {
34859
34952
  title: "Improve an existing chart",
34860
34953
  description: "Diagnose a chart configuration, assess data fit, and propose repairs or variants.",
34861
34954
  inputSchema: { component: external_exports3.string(), props: external_exports3.record(external_exports3.string(), external_exports3.unknown()), data: external_exports3.array(external_exports3.record(external_exports3.string(), external_exports3.unknown())).optional(), intent: external_exports3.union([external_exports3.string(), external_exports3.array(external_exports3.string())]).optional() },
34862
- outputSchema: { status: external_exports3.enum(["reviewed", "repair-needed"]), component: external_exports3.string(), surfaceVersion: external_exports3.string() },
34955
+ outputSchema: {
34956
+ status: external_exports3.enum(["reviewed", "repair-needed"]),
34957
+ component: external_exports3.string(),
34958
+ diagnostics: external_exports3.array(external_exports3.unknown()),
34959
+ repair: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
34960
+ variants: external_exports3.array(external_exports3.unknown()),
34961
+ accessibilityRecommendation: external_exports3.object({
34962
+ location: external_exports3.literal("direct-component-props"),
34963
+ props: external_exports3.record(external_exports3.string(), external_exports3.string()),
34964
+ chartContainer: external_exports3.record(external_exports3.string(), external_exports3.unknown())
34965
+ }).optional(),
34966
+ surfaceVersion: external_exports3.string()
34967
+ },
34863
34968
  annotations: READ_ONLY_TOOL_ANNOTATIONS
34864
34969
  }, improveChartHandler);
34865
34970
  srv.registerTool("explainChart", {
@@ -34879,7 +34984,31 @@ function createServer2(profile = "developer", options = {}) {
34879
34984
  srv.registerTool("getChartSchema", {
34880
34985
  title: "Get a chart schema",
34881
34986
  description: "Return canonical Semiotic prop-schema guidance for code editing and advanced configuration.",
34882
- inputSchema: { component: external_exports3.string().optional() },
34987
+ inputSchema: {
34988
+ component: external_exports3.string().optional()
34989
+ },
34990
+ outputSchema: {
34991
+ status: external_exports3.enum([
34992
+ "component-list",
34993
+ "component-schema",
34994
+ "unknown-component"
34995
+ ]),
34996
+ component: external_exports3.string().optional(),
34997
+ renderable: external_exports3.boolean().optional(),
34998
+ availableComponents: external_exports3.array(
34999
+ external_exports3.object({
35000
+ name: external_exports3.string(),
35001
+ renderable: external_exports3.boolean()
35002
+ })
35003
+ ).optional(),
35004
+ schema: external_exports3.record(external_exports3.string(), external_exports3.unknown()).optional(),
35005
+ accessibility: external_exports3.object({
35006
+ directProps: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
35007
+ chartContainer: external_exports3.record(external_exports3.string(), external_exports3.unknown())
35008
+ }).optional(),
35009
+ behaviorContracts: external_exports3.array(external_exports3.unknown()).optional(),
35010
+ surfaceVersion: external_exports3.string()
35011
+ },
34883
35012
  annotations: READ_ONLY_TOOL_ANNOTATIONS
34884
35013
  }, getSchemaHandler);
34885
35014
  return srv;