semiotic 3.8.0 → 3.8.1

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 (234) hide show
  1. package/CLAUDE.md +12 -9
  2. package/README.md +39 -39
  3. package/ai/dist/mcp-server.js +98 -17
  4. package/ai/schema.json +1 -1
  5. package/ai/surface-manifest.json +3 -2
  6. package/ai/system-prompt.md +3 -2
  7. package/dist/__tests__/scenarios/mcpProtocolTypes.d.ts +20 -0
  8. package/dist/components/AccessibleNavTree.d.ts +7 -1
  9. package/dist/components/ai/chartClinicMetadata.generated.d.ts +15 -0
  10. package/dist/components/ai/useNavigationSync.d.ts +17 -2
  11. package/dist/components/chartContainerMobile.d.ts +9 -0
  12. package/dist/components/charts/geo/ChoroplethMap.d.ts +19 -2
  13. package/dist/components/charts/geo/DistanceCartogram.d.ts +14 -2
  14. package/dist/components/charts/geo/FlowMap.d.ts +10 -6
  15. package/dist/components/charts/geo/ProportionalSymbolMap.d.ts +14 -2
  16. package/dist/components/charts/index.d.ts +6 -0
  17. package/dist/components/charts/network/ChordDiagram.d.ts +9 -1
  18. package/dist/components/charts/network/ForceDirectedGraph.d.ts +11 -0
  19. package/dist/components/charts/network/SankeyDiagram.d.ts +9 -1
  20. package/dist/components/charts/ordinal/BarChart.d.ts +21 -0
  21. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +11 -0
  22. package/dist/components/charts/ordinal/StackedBarChart.d.ts +11 -0
  23. package/dist/components/charts/physics/CollisionSwarmChart.d.ts +7 -0
  24. package/dist/components/charts/physics/EventDropChart.d.ts +7 -0
  25. package/dist/components/charts/physics/GaltonBoardChart.d.ts +8 -0
  26. package/dist/components/charts/physics/PhysicsCustomChart.d.ts +4 -25
  27. package/dist/components/charts/physics/PhysicsPileChart.d.ts +7 -0
  28. package/dist/components/charts/physics/physicsChartShared.d.ts +17 -1
  29. package/dist/components/charts/physics/physicsCustomLayout.d.ts +32 -0
  30. package/dist/components/charts/shared/AnnotationLabel.d.ts +88 -0
  31. package/dist/components/charts/shared/annotationActivation.d.ts +35 -0
  32. package/dist/components/charts/shared/annotationLabelLayout.d.ts +5 -0
  33. package/dist/components/charts/shared/annotationRules.d.ts +2 -1
  34. package/dist/components/charts/shared/chartSelectionUtils.d.ts +4 -0
  35. package/dist/components/charts/shared/chartSpecCore.d.ts +3 -3
  36. package/dist/components/charts/shared/datumTypes.d.ts +2 -0
  37. package/dist/components/charts/shared/diagnoseAnnotationChecks.d.ts +2 -0
  38. package/dist/components/charts/shared/formatUtils.d.ts +3 -3
  39. package/dist/components/charts/shared/hatchFill.d.ts +87 -0
  40. package/dist/components/charts/shared/hooks.d.ts +7 -6
  41. package/dist/components/charts/shared/knownChartComponents.d.ts +9 -0
  42. package/dist/components/charts/shared/leastSquaresRegression.d.ts +16 -0
  43. package/dist/components/charts/shared/mergeShapeStyle.d.ts +3 -2
  44. package/dist/components/charts/shared/semanticInteractions.d.ts +42 -0
  45. package/dist/components/charts/shared/sparseArray.d.ts +1 -1
  46. package/dist/components/charts/shared/streamPropsHelpers.d.ts +6 -4
  47. package/dist/components/charts/shared/styleRules.d.ts +205 -0
  48. package/dist/components/charts/shared/tooltipUtils.d.ts +22 -9
  49. package/dist/components/charts/shared/types.d.ts +9 -6
  50. package/dist/components/charts/shared/useAreaSeriesSetup.d.ts +16 -2
  51. package/dist/components/charts/shared/useChartSetup.d.ts +2 -2
  52. package/dist/components/charts/shared/useCustomChartSetup.d.ts +3 -0
  53. package/dist/components/charts/shared/useFrameImperativeHandle.d.ts +1 -2
  54. package/dist/components/charts/shared/useLikertAggregation.d.ts +4 -4
  55. package/dist/components/charts/shared/useOrdinalBrush.d.ts +2 -1
  56. package/dist/components/charts/shared/useOrdinalPieceStyle.d.ts +24 -1
  57. package/dist/components/charts/shared/useStreamingLegend.d.ts +1 -1
  58. package/dist/components/charts/shared/useXYLineStyle.d.ts +10 -0
  59. package/dist/components/charts/shared/useXYPointStyle.d.ts +19 -1
  60. package/dist/components/charts/shared/validateChartData.d.ts +7 -5
  61. package/dist/components/charts/shared/validationMap.d.ts +11 -2
  62. package/dist/components/charts/shared/validationMap.generated.d.ts +6 -0
  63. package/dist/components/charts/shared/withChartWrapper.d.ts +4 -3
  64. package/dist/components/charts/value/targetPresentation.d.ts +22 -0
  65. package/dist/components/charts/value/types.d.ts +5 -6
  66. package/dist/components/charts/xy/AreaChart.d.ts +8 -0
  67. package/dist/components/charts/xy/BubbleChart.d.ts +9 -0
  68. package/dist/components/charts/xy/ConnectedScatterplot.d.ts +7 -0
  69. package/dist/components/charts/xy/DifferenceChart.d.ts +1 -52
  70. package/dist/components/charts/xy/Heatmap.d.ts +2 -2
  71. package/dist/components/charts/xy/LineChart.d.ts +11 -0
  72. package/dist/components/charts/xy/QuadrantChart.d.ts +7 -0
  73. package/dist/components/charts/xy/Scatterplot.d.ts +10 -0
  74. package/dist/components/charts/xy/StackedAreaChart.d.ts +7 -0
  75. package/dist/components/charts/xy/differenceSegments.d.ts +49 -0
  76. package/dist/components/charts/xy/scatterplotMatrixInteractionTypes.d.ts +12 -0
  77. package/dist/components/controls/SentenceFilter.d.ts +97 -0
  78. package/dist/components/data/fromVegaLite.d.ts +19 -9
  79. package/dist/components/rough/createRoughRenderMode.d.ts +46 -0
  80. package/dist/components/semiotic-ai.d.ts +3 -1
  81. package/dist/components/semiotic-controls.d.ts +2 -0
  82. package/dist/components/semiotic-geo.d.ts +4 -0
  83. package/dist/components/semiotic-network.d.ts +4 -0
  84. package/dist/components/semiotic-ordinal.d.ts +6 -0
  85. package/dist/components/semiotic-physics.d.ts +4 -0
  86. package/dist/components/semiotic-rough.d.ts +4 -0
  87. package/dist/components/semiotic-utils-core.d.ts +4 -0
  88. package/dist/components/semiotic-xy.d.ts +4 -0
  89. package/dist/components/semiotic.d.ts +9 -1
  90. package/dist/components/server/optionalImageTypes.d.ts +37 -0
  91. package/dist/components/server/serverChartConfigShared.d.ts +9 -5
  92. package/dist/components/server/serverChartConfigs.d.ts +4 -4
  93. package/dist/components/server/staticAnnotations.d.ts +6 -3
  94. package/dist/components/server/staticLegend.d.ts +1 -1
  95. package/dist/components/server/staticNetwork.d.ts +4 -4
  96. package/dist/components/server/staticSVGChrome.d.ts +2 -2
  97. package/dist/components/store/ObservationStore.d.ts +21 -1
  98. package/dist/components/stream/AccessibleDataTable.d.ts +4 -10
  99. package/dist/components/stream/AriaLiveTooltip.d.ts +9 -0
  100. package/dist/components/stream/CanvasHitTester.d.ts +4 -4
  101. package/dist/components/stream/DataSourceAdapter.d.ts +1 -1
  102. package/dist/components/stream/FrameRuntime.d.ts +57 -0
  103. package/dist/components/stream/GeoParticlePool.d.ts +1 -1
  104. package/dist/components/stream/GeoPipelineStore.d.ts +43 -12
  105. package/dist/components/stream/GeoSVGOverlay.d.ts +64 -0
  106. package/dist/components/stream/NetworkCanvasHitTester.d.ts +2 -1
  107. package/dist/components/stream/NetworkPipelineStore.d.ts +24 -21
  108. package/dist/components/stream/NetworkSSRFrame.d.ts +17 -0
  109. package/dist/components/stream/NetworkSVGOverlay.d.ts +6 -0
  110. package/dist/components/stream/OrdinalCanvasHitTester.d.ts +2 -2
  111. package/dist/components/stream/OrdinalPipelineStore.d.ts +13 -13
  112. package/dist/components/stream/OrdinalSVGOverlay.d.ts +9 -1
  113. package/dist/components/stream/OrdinalStyleResolver.d.ts +12 -0
  114. package/dist/components/stream/ParticlePool.d.ts +1 -1
  115. package/dist/components/stream/PipelineStore.d.ts +12 -16
  116. package/dist/components/stream/SVGOverlay.d.ts +6 -0
  117. package/dist/components/stream/SceneGraph.d.ts +3 -3
  118. package/dist/components/stream/accessorUtils.d.ts +2 -2
  119. package/dist/components/stream/annotationAccessorResolver.d.ts +2 -2
  120. package/dist/components/stream/frameGraphics.d.ts +4 -0
  121. package/dist/components/stream/frameKeyboardNavigation.d.ts +45 -0
  122. package/dist/components/stream/geoPipelineHelpers.d.ts +3 -3
  123. package/dist/components/stream/geoPipelineUpdateResults.d.ts +34 -0
  124. package/dist/components/stream/geoSceneBuilder.d.ts +16 -0
  125. package/dist/components/stream/geoTypes.d.ts +48 -15
  126. package/dist/components/stream/hitTestUtils.d.ts +2 -2
  127. package/dist/components/stream/hoverUtils.d.ts +4 -2
  128. package/dist/components/stream/layouts/forceLayoutWorkerClient.d.ts +1 -0
  129. package/dist/components/stream/layouts/hierarchyUtils.d.ts +2 -2
  130. package/dist/components/stream/networkCustomLayoutRunner.d.ts +23 -0
  131. package/dist/components/stream/networkCustomRestyle.d.ts +15 -0
  132. package/dist/components/stream/networkFrameAnimation.d.ts +7 -0
  133. package/dist/components/stream/networkFrameHandleTypes.d.ts +39 -0
  134. package/dist/components/stream/networkFrameObservations.d.ts +15 -0
  135. package/dist/components/stream/networkFramePaint.d.ts +11 -2
  136. package/dist/components/stream/networkInteractionTypes.d.ts +26 -0
  137. package/dist/components/stream/networkPipelineConfig.d.ts +2 -2
  138. package/dist/components/stream/networkPipelineUpdateResults.d.ts +38 -0
  139. package/dist/components/stream/networkTypes.d.ts +37 -56
  140. package/dist/components/stream/ordinalCanvasRenderers.d.ts +2 -2
  141. package/dist/components/stream/ordinalPipelineUpdateResults.d.ts +20 -1
  142. package/dist/components/stream/ordinalSceneBuilders/types.d.ts +2 -2
  143. package/dist/components/stream/ordinalTypes.d.ts +30 -3
  144. package/dist/components/stream/physics/PhysicsPipelineStore.d.ts +2 -0
  145. package/dist/components/stream/physics/PhysicsSVGOverlay.d.ts +6 -0
  146. package/dist/components/stream/physics/StreamPhysicsTypes.d.ts +21 -6
  147. package/dist/components/stream/physics/physicsFrameObservations.d.ts +19 -0
  148. package/dist/components/stream/physics/physicsFrameSetup.d.ts +4 -0
  149. package/dist/components/stream/physics/physicsPipelineUpdateResults.d.ts +19 -1
  150. package/dist/components/stream/physics/usePhysicsFrameLifecyclePolicy.d.ts +3 -1
  151. package/dist/components/stream/pipelineConfig.d.ts +4 -2
  152. package/dist/components/stream/pipelineDecay.d.ts +2 -2
  153. package/dist/components/stream/pipelinePulse.d.ts +2 -2
  154. package/dist/components/stream/pipelineStoreUpdateResults.d.ts +23 -2
  155. package/dist/components/stream/pipelineTransitions.d.ts +1 -1
  156. package/dist/components/stream/pipelineUpdateContract.d.ts +7 -0
  157. package/dist/components/stream/pipelineUpdateStore.d.ts +21 -0
  158. package/dist/components/stream/renderBackend.d.ts +27 -0
  159. package/dist/components/stream/renderers/canvasRenderHelpers.d.ts +15 -1
  160. package/dist/components/stream/renderers/geoCanvasRenderer.d.ts +3 -2
  161. package/dist/components/stream/renderers/networkParticleRenderer.d.ts +1 -1
  162. package/dist/components/stream/sceneRenderBackendTypes.d.ts +28 -0
  163. package/dist/components/stream/sceneRevisionDiagnostics.d.ts +31 -4
  164. package/dist/components/stream/streamSemanticTypes.d.ts +16 -0
  165. package/dist/components/stream/streamThemeTypes.d.ts +14 -0
  166. package/dist/components/stream/svgOverlayUtils.d.ts +10 -0
  167. package/dist/components/stream/test-utils/frameScheduler.d.ts +12 -0
  168. package/dist/components/stream/test-utils/revisionConsumption.d.ts +13 -0
  169. package/dist/components/stream/titleLayout.d.ts +31 -0
  170. package/dist/components/stream/types.d.ts +30 -65
  171. package/dist/components/stream/useCanvasFrameHost.d.ts +71 -0
  172. package/dist/components/stream/useFrame.d.ts +23 -0
  173. package/dist/components/stream/useLegendCategoryEmission.d.ts +3 -3
  174. package/dist/components/stream/useSemanticFrameInteractions.d.ts +22 -0
  175. package/dist/components/stream/useUpdateResultSnapshot.d.ts +7 -0
  176. package/dist/components/stream/xyFrameAxisTypes.d.ts +50 -0
  177. package/dist/components/stream/xySceneBuilders/types.d.ts +6 -5
  178. package/dist/controls.min.js +1 -1
  179. package/dist/controls.module.min.js +1 -1
  180. package/dist/forceLayoutWorker.js +1 -1
  181. package/dist/geo.min.js +1 -1
  182. package/dist/geo.module.min.js +1 -1
  183. package/dist/network.min.js +1 -1
  184. package/dist/network.module.min.js +1 -1
  185. package/dist/ordinal.min.js +1 -1
  186. package/dist/ordinal.module.min.js +1 -1
  187. package/dist/physics.min.js +1 -1
  188. package/dist/physics.module.min.js +1 -1
  189. package/dist/physicsWorker.js +1 -1
  190. package/dist/realtime.min.js +1 -1
  191. package/dist/realtime.module.min.js +1 -1
  192. package/dist/rough.min.js +1 -0
  193. package/dist/rough.module.min.js +1 -0
  194. package/dist/semiotic-ai-core.min.js +1 -1
  195. package/dist/semiotic-ai-core.module.min.js +1 -1
  196. package/dist/semiotic-ai.d.ts +3 -1
  197. package/dist/semiotic-ai.min.js +1 -1
  198. package/dist/semiotic-ai.module.min.js +1 -1
  199. package/dist/semiotic-controls.d.ts +2 -0
  200. package/dist/semiotic-data.min.js +1 -1
  201. package/dist/semiotic-data.module.min.js +1 -1
  202. package/dist/semiotic-experimental.min.js +1 -1
  203. package/dist/semiotic-experimental.module.min.js +1 -1
  204. package/dist/semiotic-geo.d.ts +4 -0
  205. package/dist/semiotic-network.d.ts +4 -0
  206. package/dist/semiotic-ordinal.d.ts +6 -0
  207. package/dist/semiotic-physics.d.ts +4 -0
  208. package/dist/semiotic-realtime-core.min.js +1 -1
  209. package/dist/semiotic-realtime-core.module.min.js +1 -1
  210. package/dist/semiotic-realtime-react.min.js +1 -1
  211. package/dist/semiotic-realtime-react.module.min.js +1 -1
  212. package/dist/semiotic-rough.d.ts +4 -0
  213. package/dist/semiotic-server-edge.min.js +1 -1
  214. package/dist/semiotic-server-edge.module.min.js +1 -1
  215. package/dist/semiotic-server-node.min.js +1 -1
  216. package/dist/semiotic-server-node.module.min.js +1 -1
  217. package/dist/semiotic-utils-core.d.ts +4 -0
  218. package/dist/semiotic-utils-core.min.js +1 -1
  219. package/dist/semiotic-utils-core.module.min.js +1 -1
  220. package/dist/semiotic-utils.min.js +1 -1
  221. package/dist/semiotic-utils.module.min.js +1 -1
  222. package/dist/semiotic-value.min.js +1 -1
  223. package/dist/semiotic-value.module.min.js +1 -1
  224. package/dist/semiotic-xy.d.ts +4 -0
  225. package/dist/semiotic.d.ts +9 -1
  226. package/dist/semiotic.min.js +1 -1
  227. package/dist/semiotic.module.min.js +1 -1
  228. package/dist/server.min.js +1 -1
  229. package/dist/server.module.min.js +1 -1
  230. package/dist/test-utils/capturedFrameProps.d.ts +67 -0
  231. package/dist/test-utils/frameMock.d.ts +12 -9
  232. package/dist/xy.min.js +1 -1
  233. package/dist/xy.module.min.js +1 -1
  234. package/package.json +26 -7
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` (101KB gz), `semiotic/ordinal` (82KB gz), `semiotic/network` (85KB gz), `semiotic/geo` (62KB gz), `semiotic/realtime` (111KB gz), `semiotic/realtime/core` (110KB gz), `semiotic/realtime/react` (1KB gz), `semiotic/server` (189KB gz), `semiotic/server/node` (189KB gz), `semiotic/server/edge` (188KB gz), `semiotic/utils` (71KB gz), `semiotic/utils/core` (70KB 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` (98KB gz), `semiotic/physics/matter` (1KB gz), `semiotic/physics/rapier` (1KB gz), `semiotic/ai` (394KB gz), `semiotic/ai/core` (79KB gz), `semiotic/controls` (5KB gz). Full `semiotic` is 258KB gz.
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.
8
8
  <!-- semiotic-bundle-sizes:end -->
9
9
  - CLI: `npx semiotic-ai [--schema|--compact|--examples|--doctor|--audit-a11y]` · MCP: `npx semiotic-mcp`
10
10
 
@@ -20,11 +20,11 @@ HOC Charts (simple, default) → Stream Frames (full control). Use HOCs unless y
20
20
 
21
21
  ## XY Charts (`semiotic/xy`)
22
22
 
23
- **LineChart** — `data`, `xAccessor` ("x"), `yAccessor` ("y"), `lineBy`, `lineDataAccessor`, `colorBy`, `colorScheme`, `curve`, `lineWidth` (2), `showPoints`, `pointRadius` (3), `fillArea` (boolean|string[]), `areaOpacity` (0.3), `lineGradient`, `anomaly`, `forecast`, `band` ({y0Accessor, y1Accessor, style?, perSeries?, interactive?} or array for fan charts; participates in yExtent; non-interactive by default), `directLabel`, `gapStrategy`, `xScaleType`/`yScaleType` ("linear"|"log"|"time"), `tooltip="multi"` for hover-anywhere
23
+ **LineChart** — `data`, `xAccessor` ("x"), `yAccessor` ("y"), `lineBy`, `lineDataAccessor`, `colorBy`, `colorScheme`, `curve`, `lineWidth` (2), `showPoints`, `pointRadius` (3), `fillArea` (boolean|string[]), `areaOpacity` (0.3), `lineGradient`, `anomaly`, `forecast`, `band` ({y0Accessor, y1Accessor, style?, perSeries?, interactive?} or array for fan charts; participates in yExtent; non-interactive by default), `directLabel`, `gapStrategy`, `xScaleType`/`yScaleType` ("linear"|"log"|"time"), `styleRules` (per-series), `tooltip="multi"` for hover-anywhere
24
24
  **AreaChart** — LineChart props + `areaBy`, `y0Accessor`, `gradientFill`, `areaOpacity` (0.7), `showLine` (true), `band`, `tooltip="multi"`
25
25
  **DifferenceChart** — Two-series A/B. Fills between with `seriesAColor` where A>B, `seriesBColor` where B>A; crossovers interpolated. `data`, `xAccessor`, `seriesAAccessor` ("a"), `seriesBAccessor` ("b"), `seriesALabel`/`seriesBLabel`, `seriesAColor` (var(--semiotic-danger))/`seriesBColor` (var(--semiotic-info)), `showLines` (true), `lineWidth` (1.5), `showPoints` (false), `pointRadius` (3), `curve` ("linear"), `areaOpacity` (0.6), `gradientFill`, `xExtent`/`yExtent`, `pointIdAccessor`, `windowSize`. Push via `ref.push({x,a,b})`. Accessor outputs coerce through `toNumber`.
26
26
  **StackedAreaChart** — flat array + `areaBy` (required), `colorBy`, `normalize`, `baseline` ("zero"|"wiggle" streamgraph|"silhouette" centered), `stackOrder` ("key"|"insideOut"|"asc"|"desc"). Streamgraph: `baseline="wiggle"` + `stackOrder="insideOut"`. `baseline` ⊥ `normalize`. No `lineBy`. `tooltip="multi"` interpolates between samples.
27
- **Scatterplot** — `xAccessor`, `yAccessor`, `colorBy`, `sizeBy`, `sizeRange`, `symbolBy` (categorical field → glyph **shape**: each mark becomes a d3-shape glyph; size still tracks `sizeBy`/`pointRadius`), `symbolMap` ({category → shape}; unmapped auto-assign — pass it for legend-matchable shapes), `pointRadius` (5), `pointOpacity` (0.8), `marginalGraphics`, `regression` (boolean | "linear"|"polynomial"|"loess" | RegressionConfig — sugar for trend overlay)
27
+ **Scatterplot** — `xAccessor`, `yAccessor`, `colorBy`, `sizeBy`, `sizeRange`, `symbolBy` (categorical field → glyph **shape**: each mark becomes a d3-shape glyph; size still tracks `sizeBy`/`pointRadius`), `symbolMap` ({category → shape}; unmapped auto-assign — pass it for legend-matchable shapes), `pointRadius` (5), `pointOpacity` (0.8), `marginalGraphics`, `styleRules` (per-point; `axis:"x"`/`"y"` thresholds), `regression` (boolean | "linear"|"polynomial"|"loess" | RegressionConfig — sugar for trend overlay)
28
28
  **BubbleChart** — Scatterplot + `sizeBy` (required), `sizeRange` ([5,40]), `regression`
29
29
  **ConnectedScatterplot** — + `orderAccessor`, `regression`
30
30
  **QuadrantChart** — Scatterplot + `quadrants`, `xCenter`, `yCenter`
@@ -36,9 +36,9 @@ HOC Charts (simple, default) → Stream Frames (full control). Use HOCs unless y
36
36
 
37
37
  ## Ordinal Charts (`semiotic/ordinal`)
38
38
 
39
- **BarChart** — `categoryAccessor`, `valueAccessor`, `orientation`, `colorBy`, `sort`, `barPadding` (40), `roundedTop`, `gradientFill` (true | {topOpacity, bottomOpacity} | {colorStops}; tip→base), `regression`
40
- **StackedBarChart** — + `stackBy` (required), `normalize`, `sort` (false default — insertion order)
41
- **GroupedBarChart** — + `groupBy` (required), `barPadding` (60), `sort` (false default)
39
+ **BarChart** — `categoryAccessor`, `valueAccessor`, `orientation`, `colorBy`, `sort`, `barPadding` (40), `roundedTop`, `gradientFill` (true | {topOpacity, bottomOpacity} | {colorStops}; tip→base), `styleRules`, `regression`
40
+ **StackedBarChart** — + `stackBy` (required), `normalize`, `sort` (false default — insertion order), `styleRules`
41
+ **GroupedBarChart** — + `groupBy` (required), `barPadding` (60), `sort` (false default), `styleRules`
42
42
  **SwarmPlot** — `colorBy`, `sizeBy`, `symbolBy` (categorical field → glyph shape, like Scatterplot), `symbolMap`, `pointRadius`, `pointOpacity`
43
43
  **BoxPlot** — + `showOutliers`, `outlierRadius`
44
44
  **Histogram** — + `bins` (25), `relative`. Always horizontal.
@@ -54,9 +54,11 @@ HOC Charts (simple, default) → Stream Frames (full control). Use HOCs unless y
54
54
 
55
55
  All ordinal: `colorBy`, `colorScheme`, `categoryFormat` (string|ReactNode), `showCategoryTicks` (true).
56
56
 
57
+ **`styleRules`** (declarative threshold-aware styling — **every chart family**) — an ordered `StyleRule[]` where each `{ when, style }` matching a mark contributes its style, merged in list order so **the last applicable rule wins per property** (CSS-cascade model). Wired on: **ordinal** BarChart/StackedBarChart/GroupedBarChart (bars/segments); **XY** LineChart/AreaChart/StackedAreaChart (per-series) + Scatterplot/BubbleChart/QuadrantChart/ConnectedScatterplot (per-point); **network** ForceDirectedGraph/SankeyDiagram/ChordDiagram (nodes); **geo** ChoroplethMap (features) + ProportionalSymbolMap/DistanceCartogram (symbols); **physics** GaltonBoardChart/PhysicsPileChart/CollisionSwarmChart/EventDropChart (particles). `when` = predicate `(datum, ctx) => boolean`, a declarative threshold (`{ axis?: "x"|"y"|"value", field?, gt, gte, lt, lte, eq, ne, within:[min,max], outside, in:[...] }`), or `true`/omitted (always). `ctx` channels by family: bars `{ value, category }`; XY `{ value(=y), x, y }` (use `axis:"x"`/`"y"` to target either axis regardless of accessor field name); network/geo/physics `{ value, category }` (category = the colorBy/group). A rule's `style.fill` may be a color string or a **`HatchFill`** descriptor (`{ type:"hatch", background?, stroke?, spacing?, angle?, lineWidth?, lineOpacity? }`) resolving to a `CanvasPattern` on canvas and an SVG `<pattern>` in SSR — one declaration, both backends. Precedence: top-level primitives > per-mark style fn (`pieceStyle`/`pointStyle`/`nodeStyle`) > `styleRules` > base `colorBy`/`color`/theme. Works through `renderChart`/MCP for all wired families (use the declarative-threshold form, not predicates, when the config must serialize). `HatchFill` is also a `band`/`x-band` annotation `fill` and any scene `style.fill`. Caveats: line/area rules resolve per-series (sample datum, not per-vertex); network hierarchy charts (Tree/Treemap/CirclePack/Orbit) are NOT wired (their `colorByDepth` owns fill); MultiAxisLineChart/MinimapChart/CandlestickChart not wired. Exported from `semiotic` + each family entry + `semiotic/utils`: `StyleRule`, `resolveStyleRules`, `matchesThreshold`, `makeRuleValueResolver`, `makeXYRuleContext`, `makeNodeRuleContext`, `composeStyleRules`, `HatchFill`, `isHatchFill`. See `/features/style-rules`.
58
+
57
59
  ## Network Charts (`semiotic/network`)
58
60
 
59
- **ForceDirectedGraph** — `nodes`, `edges`, `nodeIDAccessor`, `sourceAccessor`, `targetAccessor`, `colorBy`, `nodeSize`, `nodeSizeRange`, `edgeWidth`, `iterations` (300), `forceStrength` (0.1 — link-attraction multiplier), `layoutExecution` ("auto" default | "worker" | "sync" — auto runs big layouts in a Web Worker by estimated cost, sync fallback everywhere), `layoutLoadingContent` (ReactNode while worker layout pends; `false` suppresses), `onLayoutStateChange` (`"pending"|"ready"|"error"`), `showLabels`, `nodeLabel`
61
+ **ForceDirectedGraph** — `nodes`, `edges`, `nodeIDAccessor`, `sourceAccessor`, `targetAccessor`, `colorBy`, `nodeSize`, `nodeSizeRange`, `edgeWidth`, `iterations` (300), `forceStrength` (0.1 — link-attraction multiplier), `layoutExecution` ("auto" default | "worker" | "sync" — auto runs big layouts in a Web Worker by estimated cost, sync fallback everywhere), `layoutLoadingContent` (ReactNode while worker layout pends; `false` suppresses), `onLayoutStateChange` (`"pending"|"ready"|"error"`), `showLabels`, `nodeLabel`, `styleRules` (style groups of nodes — rules see the raw node; `ctx.category` = colorBy group)
60
62
  **SankeyDiagram** — `edges`, `nodes`, `valueAccessor`, `nodeIdAccessor`, `colorBy`, `edgeColorBy`, `orientation`, `nodeAlign`, `nodeWidth`, `nodePaddingRatio`, `showLabels`
61
63
  **ProcessSankey** — temporal sankey with real time x-axis. `nodes`, `edges` (each with `startTime`/`endTime`), `domain` (req `[t0, t1]`), `axisTicks?`, `xExtentAccessor` (optional `[start, end]` lifetime per node), `colorBy`/`colorScheme`/`showLegend`/`legendPosition`, `pairing` ("value"|"temporal"), `packing` ("off"|"reuse"), `laneOrder` ("crossing-min"|"inside-out"|"crossing-min+inside-out"|"insertion"), `lifetimeMode` ("full"|"half"), `ribbonLane` ("source"|"target"|"both"), `showLaneRails`, `showLabels` (true), `showQualityReadout`, `showParticles` + `particleStyle`, `timeFormat`/`valueFormat`, push API via ref. Static-graph cycles OK as long as edges move forward in time. Use ProcessSankey for time-stamped events; SankeyDiagram for static snapshots.
62
64
  **ChordDiagram** — `edges`, `nodes`, `valueAccessor`, `edgeColorBy`, `padAngle`, `showLabels`
@@ -69,7 +71,7 @@ All ordinal: `colorBy`, `colorScheme`, `categoryFormat` (string|ReactNode), `sho
69
71
 
70
72
  Import from `semiotic/geo` only — avoids d3-geo in non-geo bundles.
71
73
 
72
- **ChoroplethMap** — `areas` (GeoJSON Feature[] or "world-110m"), `valueAccessor`, `colorScheme`, `projection` ("equalEarth"), `graticule`, `tooltip`, `showLegend`
74
+ **ChoroplethMap** — `areas` (GeoJSON Feature[] or "world-110m"), `valueAccessor`, `colorScheme`, `projection` ("equalEarth"), `graticule`, `tooltip`, `showLegend`, `styleRules` (flag features — rules see the feature with `properties` flattened; `fill` may be a HatchFill)
73
75
  **ProportionalSymbolMap** — `points`, `xAccessor` ("lon"), `yAccessor` ("lat"), `sizeBy`, `sizeRange`, `colorBy`, `areas?`
74
76
  **FlowMap** — `flows`, `nodes`, `valueAccessor`, `edgeColorBy`, `lineType`, `showParticles`
75
77
  **DistanceCartogram** — `points`, `center`, `costAccessor`, `strength`, `showRings`
@@ -82,7 +84,7 @@ Import from `semiotic/physics` only — not re-exported from the root `semiotic`
82
84
 
83
85
  Process/arrival/distribution charts backed by `StreamPhysicsFrame`. The settled projection is the chart; motion is explanatory context. Use when the movement has data semantics, not as decoration.
84
86
 
85
- **GaltonBoardChart** — `data`, `valueAccessor` ("value"), `bins` (21), `mode` ("sample"|"mechanical"), `pegRows`, `mechanicalCount`, `branchProbability`, `ballRadius`, `colorBy`, `seed`, `size`/`width`/`height`, `paused`, `frameProps`. Renders a deterministic Galton/Plinko-style distribution that settles into bins; mechanical mode can generate a seeded no-data demonstration.
87
+ **GaltonBoardChart** — `data`, `valueAccessor` ("value"), `bins` (21), `mode` ("sample"|"mechanical"), `pegRows`, `mechanicalCount`, `branchProbability`, `ballRadius`, `colorBy`, `styleRules` (per-particle; `ctx.category` = colorBy group), `seed`, `size`/`width`/`height`, `paused`, `frameProps`. Renders a deterministic Galton/Plinko-style distribution that settles into bins; mechanical mode can generate a seeded no-data demonstration.
86
88
  **EventDropChart** — `data`, `timeAccessor` ("time"), `arrivalAccessor` ("arrivalTime"), `windows` ({size}), `watermark` ({delay}|fn), `timeScale`, `ballRadius`, `colorBy`, `seed`, `size`, `paused`, `frameProps`. Use for event-time arrival, lateness, and watermark-window stories.
87
89
  **PhysicsPileChart** — `data`, `categoryAccessor` ("category"), `valueAccessor` ("value"), `mode` ("sample"|"mechanical"), `mechanicalCount`, `mechanicalCategories`, `unitValue` (1), `ballRadius`, `colorBy`, `seed`, `showProjection`, `size`, `paused`, `frameProps`. Unitizes values into repeated bodies that settle into category piles; mechanical mode can generate a seeded no-data capacity sketch; the default projection overlay keeps exact totals readable.
88
90
  **CollisionSwarmChart** — `data`, `xAccessor` ("x"), optional `groupAccessor`, `radiusAccessor`, `pointRadius`, `xExtent`, `collisionIterations`, `settle`, `showProjection`, `colorBy`, `seed`, `size`, `paused`, `frameProps`. Uses springs plus collisions to separate overlapping dots while preserving the quantitative axis and optional group lanes.
@@ -227,6 +229,7 @@ All HOCs accept `annotations`. Coordinates use data field names.
227
229
  **Reference lines**: `y-threshold` (`value`, `label`, `color`, `labelPosition`), `x-threshold`, `band` (`y0`, `y1`), `x-band` (`x0`, `x1`, `fill`, `fillOpacity` — full-height vertical region for eras/phases; skipped when either bound is missing)
228
230
  **Ordinal**: `category-highlight`
229
231
  **Enclosures**: `enclose`, `rect-enclose`, `highlight`
232
+ **Label backgrounds**: every region-bounding annotation (`y-threshold`, `x-threshold`, `band`, `x-band`, `enclose`, `rect-enclose`, `category-highlight`) accepts `labelBackground` for a legibility backdrop behind the label text — `"halo"`/`true` (stroke halo in the plot bg; default for threshold/band labels), `"box"` (semitransparent rounded panel), `"none"`/`false` (plain), or a config `{ type: "halo"|"box", fill?, opacity? (0.85), padding? ({x,y}), radius? (3), stroke?, haloWidth? (3) }`. One shared renderer (`AnnotationLabel`) drives client + SSR, so it works on every frame and in server SVG. `band`/`x-band` `fill` also accepts a `HatchFill` for hatched regions.
230
233
  **Statistical**: `trend`, `envelope`, `anomaly-band`, `forecast`
231
234
  **Streaming anchors**: `"fixed" | "latest" | "sticky" | "semantic"` — also exposed as `lifecycle.anchor` on the `semiotic/ai` annotation lifecycle. `"semantic"` is typed but currently falls back to fixed positioning; stableId-based re-resolution remains open.
232
235
  **Hierarchy**: any annotation accepts `emphasis: "primary" | "secondary"` across XY, ordinal, network, geo, and static SVG rendering. `secondary` dims (opacity 0.6) and yields z-order; `primary` paints at full weight and on top. Type-agnostic, no-op when unset; class hooks `annotation-emphasis--{primary|secondary}` for further styling.
package/README.md CHANGED
@@ -16,16 +16,14 @@ 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.0
19
+ ## What's New in 3.8.1
20
20
 
21
- 3.8.0 makes chart status, layout, and review workflows more explicit:
21
+ 3.8.1 makes the hosted MCP rendering path release-ready:
22
22
 
23
- - `ChartContainer` notifications add a non-intrusive bell/popover for chart-level findings.
24
- - ForceDirectedGraph can run expensive layouts in a Web Worker with synchronous SSR/hydration parity.
25
- - `x-band` annotations, minimum-width interval lanes, and custom-layout readback make dense,
26
- time-oriented charts easier to inspect.
27
- - The DataPitfalls bridge and GoFish DisplayList adapter remain experimental and are exposed from
28
- `semiotic/experimental` with `unstable_` names.
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.
29
27
 
30
28
  ```jsx
31
29
  import { LineChart } from "semiotic/xy"
@@ -372,18 +370,18 @@ The numbers below are **first-party artifact cost**: the gzip size of Semiotic's
372
370
 
373
371
  | Entry Point | gzip | What's inside |
374
372
  |---|---|---|
375
- | `semiotic/xy` | **101 KB** | LineChart, AreaChart, Scatterplot, Heatmap, + 8 more XY charts |
376
- | `semiotic/ordinal` | **82 KB** | BarChart, PieChart, BoxPlot, Histogram, + 11 more categorical charts |
377
- | `semiotic/network` | **85 KB** | ForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more |
378
- | `semiotic/geo` | **62 KB** | ChoroplethMap, FlowMap, DistanceCartogram, ProportionalSymbolMap |
379
- | `semiotic/realtime` | **111 KB** | RealtimeLineChart, RealtimeHistogram, + 4 streaming charts |
380
- | `semiotic/realtime/core` | **110 KB** | Streaming chart types, HOCs, and buffer helpers |
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 |
381
379
  | `semiotic/realtime/react` | **1 KB** | Stream status and synced push hooks |
382
- | `semiotic/server` | **189 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
383
- | `semiotic/server/node` | **189 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
384
- | `semiotic/server/edge` | **188 KB** | renderChart, renderChartWithEvidence, renderToStaticSVG, renderDashboard |
385
- | `semiotic/utils` | **71 KB** | ThemeProvider, validators, serialization — no chart components |
386
- | `semiotic/utils/core` | **70 KB** | Theme helpers and serialization utilities |
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 |
387
385
  | `semiotic/utils/react` | **4 KB** | ThemeProvider, useTheme, useReducedMotion, useHighContrast, useStreamStatus |
388
386
  | `semiotic/recipes` | **53 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
389
387
  | `semiotic/recipes/core` | **52 KB** | Pure layout functions (waffle, marimekko, flextree, dagre, …) |
@@ -393,13 +391,14 @@ The numbers below are **first-party artifact cost**: the gzip size of Semiotic's
393
391
  | `semiotic/themes/react` | **4 KB** | ThemeProvider/useTheme and hooks |
394
392
  | `semiotic/data` | **3 KB** | bin, rollup, groupBy, pivot, fromVegaLite |
395
393
  | `semiotic/value` | **6 KB** | BigNumber — focal-value KPI / scorecard (SingleValueFrame POC) |
396
- | `semiotic/physics` | **98 KB** | GaltonBoardChart, EventDropChart, PhysicsPileChart, CollisionSwarmChart, PhysicalFlowChart, PhysicsCustomChart |
394
+ | `semiotic/physics` | **104 KB** | GaltonBoardChart, EventDropChart, PhysicsPileChart, CollisionSwarmChart, PhysicalFlowChart, PhysicsCustomChart |
397
395
  | `semiotic/physics/matter` | **1 KB** | Matter.js migration helpers + optional peer guard (no chart components) |
398
396
  | `semiotic/physics/rapier` | **1 KB** | Rapier peer guard + adapter decision metadata (no chart components) |
399
397
  | `semiotic/ai` | **394 KB** | All schema-backed charts + validation — optimized for LLM code generation |
400
- | `semiotic/ai/core` | **79 KB** | suggestCharts, validateProps, describeChart, repairChartConfig, tool adapters — no chart components |
401
- | `semiotic/controls` | **5 KB** | DirectManipulationControl, CircularBrush, MobileStandardControls, auditVisualizationControls — no frame renderer |
402
- | `semiotic` | **258 KB** | Everything below (full bundle) |
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 |
400
+ | `semiotic/rough` | **3 KB** | Optional deterministic Rough.js paint backend — exact Semiotic geometry remains authoritative |
401
+ | `semiotic` | **251 KB** | Everything below (full bundle) |
403
402
 
404
403
  <!-- semiotic-bundle-sizes:end -->
405
404
 
@@ -420,33 +419,34 @@ Method: fresh `npm pack --ignore-scripts` tarball → temporary consumer → min
420
419
 
421
420
  | Public named import | Runtime | gzip cold-consumer bundle |
422
421
  |---|---:|---:|
423
- | `import { LineChart } from "semiotic"` | browser | **290.2 KiB** |
424
- | `import { LineChart } from "semiotic/xy"` | browser | **138.9 KiB** |
425
- | `import { BarChart } from "semiotic/ordinal"` | browser | **114.3 KiB** |
426
- | `import { SankeyDiagram } from "semiotic/network"` | browser | **118.2 KiB** |
427
- | `import { RealtimeLineChart } from "semiotic/realtime"` | browser | **157.2 KiB** |
428
- | `import { RingBuffer } from "semiotic/realtime/core"` | browser | **157.2 KiB** |
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** |
429
428
  | `import { useStreamStatus } from "semiotic/realtime/react"` | browser | **0.6 KiB** |
430
- | `import { GaltonBoardChart } from "semiotic/physics"` | browser | **109.5 KiB** |
429
+ | `import { GaltonBoardChart } from "semiotic/physics"` | browser | **113.6 KiB** |
431
430
  | `import { MATTER_PHYSICS_CAPABILITIES } from "semiotic/physics/matter"` | browser | **0.2 KiB** |
432
431
  | `import { RAPIER_PHYSICS_CAPABILITIES } from "semiotic/physics/rapier"` | browser | **0.2 KiB** |
433
- | `import { renderChart } from "semiotic/server"` | node | **249.5 KiB** |
434
- | `import { generateFrameSVGs } from "semiotic/server/edge"` | node | **190.7 KiB** |
435
- | `import { renderToImage } from "semiotic/server/node"` | node | **249.9 KiB** |
436
- | `import { suggestCharts } from "semiotic/ai"` | browser | **414.4 KiB** |
437
- | `import { suggestCharts } from "semiotic/ai/core"` | browser | **44.0 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** |
438
437
  | `import { bin } from "semiotic/data"` | browser | **0.4 KiB** |
439
- | `import { ChoroplethMap } from "semiotic/geo"` | browser | **102.8 KiB** |
438
+ | `import { ChoroplethMap } from "semiotic/geo"` | browser | **104.1 KiB** |
439
+ | `import { createRoughRenderMode } from "semiotic/rough"` | browser | **3.3 KiB** |
440
440
  | `import { resolveThemePreset } from "semiotic/themes"` | browser | **3.4 KiB** |
441
441
  | `import { resolveThemePreset } from "semiotic/themes/core"` | browser | **3.4 KiB** |
442
442
  | `import { ThemeProvider } from "semiotic/themes/react"` | browser | **4.4 KiB** |
443
- | `import { validateProps } from "semiotic/utils"` | browser | **20.4 KiB** |
444
- | `import { smartTickFormat } from "semiotic/utils/core"` | browser | **18.9 KiB** |
443
+ | `import { validateProps } from "semiotic/utils"` | browser | **7.9 KiB** |
444
+ | `import { smartTickFormat } from "semiotic/utils/core"` | browser | **2.1 KiB** |
445
445
  | `import { useReducedMotion } from "semiotic/utils/react"` | browser | **1.8 KiB** |
446
446
  | `import { waffleLayout } from "semiotic/recipes"` | browser | **1.3 KiB** |
447
447
  | `import { waffleLayout } from "semiotic/recipes/core"` | browser | **1.3 KiB** |
448
448
  | `import { Glyph } from "semiotic/recipes/react"` | browser | **0.9 KiB** |
449
- | `import { BigNumber } from "semiotic/value"` | browser | **5.6 KiB** |
449
+ | `import { BigNumber } from "semiotic/value"` | browser | **5.9 KiB** |
450
450
  | `import { DirectManipulationControl } from "semiotic/controls"` | browser | **1.3 KiB** |
451
451
 
452
452
  <!-- semiotic-cold-consumer:end -->
@@ -4036,7 +4036,7 @@ var require_core = __commonJS({
4036
4036
  constructor(opts = {}) {
4037
4037
  this.schemas = {};
4038
4038
  this.refs = {};
4039
- this.formats = {};
4039
+ this.formats = /* @__PURE__ */ Object.create(null);
4040
4040
  this._compilations = /* @__PURE__ */ new Set();
4041
4041
  this._loading = {};
4042
4042
  this._cache = /* @__PURE__ */ new Map();
@@ -32383,6 +32383,59 @@ function resolveHTTPListenHost(args, env = process.env) {
32383
32383
  return getFlagValue(args, "--host")?.trim() || env.MCP_HOST?.trim() || DEFAULT_HTTP_HOST;
32384
32384
  }
32385
32385
 
32386
+ // ai/mcp-request-cancellation.ts
32387
+ function createMcpRequestCancellationSignal(req, res) {
32388
+ const controller = new AbortController();
32389
+ const abort = () => controller.abort();
32390
+ req.once("aborted", abort);
32391
+ req.once("close", () => {
32392
+ if (!req.complete) abort();
32393
+ });
32394
+ res.once("close", () => {
32395
+ if (!res.writableFinished) abort();
32396
+ });
32397
+ return controller.signal;
32398
+ }
32399
+
32400
+ // ai/mcp-build-info.ts
32401
+ function nonEmptyEnvValue(env, name) {
32402
+ const value = env[name]?.trim();
32403
+ return value || void 0;
32404
+ }
32405
+ function normalizeGitSha(value) {
32406
+ return value && /^[0-9a-f]{40,128}$/i.test(value) ? value.toLowerCase() : void 0;
32407
+ }
32408
+ function resolveDeploymentChannel(value) {
32409
+ return value?.toLowerCase() === "nightly" ? "nightly" : "stable";
32410
+ }
32411
+ function resolveSemioticBuildInfo(options) {
32412
+ const env = options.env ?? process.env;
32413
+ const commitSha = normalizeGitSha(nonEmptyEnvValue(env, "SEMIOTIC_GIT_SHA"));
32414
+ return {
32415
+ channel: resolveDeploymentChannel(
32416
+ nonEmptyEnvValue(env, "SEMIOTIC_DEPLOYMENT_CHANNEL")
32417
+ ),
32418
+ packageVersion: options.packageVersion,
32419
+ surfaceVersion: options.surfaceVersion,
32420
+ ...commitSha ? { commitSha, shortCommitSha: commitSha.slice(0, 7) } : {},
32421
+ ...nonEmptyEnvValue(env, "SEMIOTIC_BUILD_ID") ? { buildId: nonEmptyEnvValue(env, "SEMIOTIC_BUILD_ID") } : {},
32422
+ ...nonEmptyEnvValue(env, "SEMIOTIC_BUILD_TIME") ? { builtAt: nonEmptyEnvValue(env, "SEMIOTIC_BUILD_TIME") } : {},
32423
+ toolProfile: options.toolProfile,
32424
+ nodeVersion: options.nodeVersion ?? process.version
32425
+ };
32426
+ }
32427
+ function mcpServerInfoForBuild(buildInfo) {
32428
+ if (buildInfo.channel !== "nightly") {
32429
+ return { name: "semiotic", version: buildInfo.packageVersion };
32430
+ }
32431
+ const packageVersion = buildInfo.packageVersion.split("+", 1)[0];
32432
+ const nightlyVersion = packageVersion.includes("-nightly") ? packageVersion : `${packageVersion}-nightly`;
32433
+ return {
32434
+ name: "semiotic-nightly",
32435
+ version: `${nightlyVersion}+${buildInfo.shortCommitSha || "unknown"}`
32436
+ };
32437
+ }
32438
+
32386
32439
  // ai/mcp-logging.ts
32387
32440
  var DEFAULT_MCP_LOG_LEVEL = "info";
32388
32441
  var DEFAULT_MCP_LOG_RETENTION_DAYS = 30;
@@ -32422,7 +32475,6 @@ var SAFE_ROUTES = /* @__PURE__ */ new Set([
32422
32475
  "/",
32423
32476
  "/mcp",
32424
32477
  "/health",
32425
- "/healthz",
32426
32478
  "/.well-known/openai-apps-challenge"
32427
32479
  ]);
32428
32480
  function boundedPositiveInteger(value, fallback, min, max) {
@@ -33059,6 +33111,12 @@ var {
33059
33111
  } = import_behaviorContracts.default;
33060
33112
  var schemaPath = path.resolve(__dirname, "../schema.json");
33061
33113
  var schema = JSON.parse(fs.readFileSync(schemaPath, "utf-8"));
33114
+ var packageManifestPath = path.resolve(__dirname, "../../package.json");
33115
+ var packageManifest = JSON.parse(fs.readFileSync(packageManifestPath, "utf-8"));
33116
+ if (typeof packageManifest.version !== "string" || !packageManifest.version) {
33117
+ throw new Error("Semiotic package.json must provide a package version");
33118
+ }
33119
+ var PACKAGE_VERSION = packageManifest.version;
33062
33120
  var schemaByComponent = {};
33063
33121
  for (const tool of schema.tools) {
33064
33122
  schemaByComponent[tool.function.name] = tool.function;
@@ -33700,7 +33758,14 @@ function capInteractiveWidgetResult(result) {
33700
33758
  setting: "MCP_MAX_WIDGET_OUTPUT_BYTES"
33701
33759
  });
33702
33760
  }
33703
- var SURFACE_VERSION = `${schema.version || "3.0.0"}-ai`;
33761
+ var SURFACE_VERSION = `${PACKAGE_VERSION}-ai`;
33762
+ function buildInfoForProfile(profile) {
33763
+ return resolveSemioticBuildInfo({
33764
+ packageVersion: PACKAGE_VERSION,
33765
+ surfaceVersion: SURFACE_VERSION,
33766
+ toolProfile: profile
33767
+ });
33768
+ }
33704
33769
  function profileResult(result) {
33705
33770
  return { ...result, surfaceVersion: SURFACE_VERSION };
33706
33771
  }
@@ -34610,15 +34675,25 @@ var READ_ONLY_TOOL_ANNOTATIONS = {
34610
34675
  openWorldHint: false
34611
34676
  };
34612
34677
  function createServer2(profile = "developer", options = {}) {
34678
+ const buildInfo = buildInfoForProfile(profile);
34613
34679
  const serverRenderContext = {
34614
34680
  signal: options.signal,
34615
34681
  limits: options.limits ?? resolveMcpRenderExecutionLimits()
34616
34682
  };
34617
34683
  const srv = new McpServer({
34618
- name: "semiotic",
34619
- version: schema.version || "3.0.0",
34684
+ ...mcpServerInfoForBuild(buildInfo),
34620
34685
  description: "Deterministic Semiotic chart selection, validation, rendering, and non-visual chart grounding. Use suggestCharts, getSchema, diagnoseConfig, and renderChart in that order for static chart generation."
34621
34686
  });
34687
+ srv.registerResource(
34688
+ "semiotic-build-info",
34689
+ "semiotic://build-info",
34690
+ {
34691
+ title: "Semiotic Build Information",
34692
+ description: "Read-only deployment identity for this Semiotic MCP server.",
34693
+ mimeType: "application/json"
34694
+ },
34695
+ (uri) => textResource(uri, "application/json", JSON.stringify(buildInfo, null, 2))
34696
+ );
34622
34697
  srv.registerResource(
34623
34698
  "semiotic-schema",
34624
34699
  "semiotic://schema",
@@ -35223,19 +35298,26 @@ async function main() {
35223
35298
  reason: "request_stream_error"
35224
35299
  }));
35225
35300
  });
35301
+ const buildInfo = buildInfoForProfile(toolProfile);
35226
35302
  const healthBody = () => JSON.stringify({
35227
35303
  status: "ok",
35228
35304
  name: "semiotic-mcp",
35229
- version: schema.version || "3.0.0",
35305
+ version: buildInfo.packageVersion,
35230
35306
  transport: "streamable-http",
35231
- mode: "stateless"
35307
+ mode: "stateless",
35308
+ channel: buildInfo.channel,
35309
+ packageVersion: buildInfo.packageVersion,
35310
+ surfaceVersion: buildInfo.surfaceVersion,
35311
+ ...buildInfo.commitSha ? { commitSha: buildInfo.commitSha } : {},
35312
+ ...buildInfo.buildId ? { buildId: buildInfo.buildId } : {},
35313
+ ...buildInfo.builtAt ? { builtAt: buildInfo.builtAt } : {}
35232
35314
  });
35315
+ const writeHealthResponse = (res) => {
35316
+ res.writeHead(200, { "Content-Type": "application/json" });
35317
+ res.end(healthBody());
35318
+ };
35233
35319
  const httpServer = http.createServer(async (req, res) => {
35234
35320
  const requestStartedAt = Date.now();
35235
- const requestAbortController = new AbortController();
35236
- const abortRequest = () => requestAbortController.abort();
35237
- req.on("aborted", abortRequest);
35238
- req.on("close", abortRequest);
35239
35321
  const pathname = (() => {
35240
35322
  try {
35241
35323
  return new URL(req.url || "/", "http://localhost").pathname;
@@ -35288,9 +35370,8 @@ async function main() {
35288
35370
  return;
35289
35371
  }
35290
35372
  }
35291
- if (req.method === "GET" && (pathname === "/healthz" || pathname === "/health")) {
35292
- res.writeHead(200, { "Content-Type": "application/json" });
35293
- res.end(healthBody());
35373
+ if (req.method === "GET" && pathname === "/health") {
35374
+ writeHealthResponse(res);
35294
35375
  return;
35295
35376
  }
35296
35377
  if (req.method === "GET" && pathname === "/.well-known/openai-apps-challenge" && openaiAppsChallengeToken) {
@@ -35312,8 +35393,7 @@ async function main() {
35312
35393
  res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32e3, message: "Method not allowed (stateless server offers no SSE stream)" }, id: null }));
35313
35394
  return;
35314
35395
  }
35315
- res.writeHead(200, { "Content-Type": "application/json" });
35316
- res.end(healthBody());
35396
+ writeHealthResponse(res);
35317
35397
  return;
35318
35398
  }
35319
35399
  if (req.method !== "POST") {
@@ -35321,6 +35401,7 @@ async function main() {
35321
35401
  res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32e3, message: "Method not allowed" }, id: null }));
35322
35402
  return;
35323
35403
  }
35404
+ const requestAbortSignal = createMcpRequestCancellationSignal(req, res);
35324
35405
  if (!hasSupportedAccept(String(req.headers.accept || ""))) {
35325
35406
  mcpLogger.warn("request_rejected", {
35326
35407
  reason: "unsupported_accept",
@@ -35396,7 +35477,7 @@ async function main() {
35396
35477
  return;
35397
35478
  }
35398
35479
  const srv = createServer2(toolProfile, {
35399
- signal: requestAbortController.signal,
35480
+ signal: requestAbortSignal,
35400
35481
  limits: renderExecutionLimits
35401
35482
  });
35402
35483
  const transport = new StreamableHTTPServerTransport({
package/ai/schema.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "name": "semiotic",
4
- "version": "3.8.0",
4
+ "version": "3.8.1",
5
5
  "description": "React data visualization library for charts, networks, and beyond",
6
6
  "tools": [
7
7
  {
@@ -7,7 +7,7 @@
7
7
  "src/components/semiotic-ai.ts",
8
8
  "ai/mcp-server.ts"
9
9
  ],
10
- "version": "3.8.0",
10
+ "version": "3.8.1",
11
11
  "components": {
12
12
  "schema": 54,
13
13
  "aiChartExports": 51,
@@ -181,9 +181,10 @@
181
181
  ],
182
182
  "activation": "semiotic-mcp --profile public or MCP_TOOL_PROFILE=public"
183
183
  },
184
- "resourceCount": 7,
184
+ "resourceCount": 8,
185
185
  "resources": [
186
186
  "semiotic-behavior-contracts",
187
+ "semiotic-build-info",
187
188
  "semiotic-chatgpt-chart-widget",
188
189
  "semiotic-components",
189
190
  "semiotic-examples",
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- semiotic-bundle-sizes:start -->
4
4
  <!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
5
- **Use sub-path imports** — `semiotic/xy` (101KB gz), `semiotic/ordinal` (82KB gz), `semiotic/network` (85KB gz), `semiotic/geo` (62KB gz), `semiotic/realtime` (111KB gz), `semiotic/realtime/core` (110KB gz), `semiotic/realtime/react` (1KB gz), `semiotic/server` (189KB gz), `semiotic/server/node` (189KB gz), `semiotic/server/edge` (188KB gz), `semiotic/utils` (71KB gz), `semiotic/utils/core` (70KB 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` (98KB gz), `semiotic/physics/matter` (1KB gz), `semiotic/physics/rapier` (1KB gz), `semiotic/ai` (394KB gz), `semiotic/ai/core` (79KB gz), `semiotic/controls` (5KB gz). Full `semiotic` is 258KB gz.
5
+ **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.
6
6
  <!-- semiotic-bundle-sizes:end -->
7
7
 
8
8
  ## Flat Array Data (`data: object[]`)
@@ -89,12 +89,13 @@ For advanced streaming control, use Stream Frames (`StreamXYFrame`, `StreamOrdin
89
89
  `onClick={(datum, { x, y }) => ...}` — called when a data element is clicked. Receives the original datum and pixel coordinates. Works on lines, bars, areas, pie slices, nodes, and geo features.
90
90
 
91
91
  ### onObservation
92
- Callback receiving `ChartObservation`: `{ type: "hover"|"click"|"brush"|"selection", datum: <your data>, x, y, timestamp, chartType, chartId }`. The `datum` field is your original data object. Hover-end/click-end events omit `datum`.
92
+ Callback receiving `ChartObservation`. Pointer exploration emits `hover`/`click`; keyboard or structured traversal additionally emits semantic `focus`/`activate` with `inputType: "keyboard"|"pointer"|"touch"|"navigation-tree"`. Stable widget annotations emit `annotation-activate` with `annotationId`. Events also include `timestamp`, `chartType`, and optional `chartId`; datum events carry your original data object. Hover-end/click-end events omit `datum`.
93
93
 
94
94
  ### emphasis
95
95
  `emphasis="primary"` makes a chart span two columns inside a `ChartGrid`.
96
96
 
97
97
  ## Annotations (all chart families)
98
+ - Give interactive `widget` annotations an `id`, `stableId`, or `provenance.stableId`; activation identity never falls back to array index. Observe widget activation on Stream Frames with `onAnnotationActivate`, or on HOCs through `frameProps.onAnnotationActivate`.
98
99
  - `annotations={[{ type: "y-threshold", value: 200, label: "SLA limit", color: "#e45050", labelPosition: "right" }]}` — horizontal reference line (works on XY and vertical ordinal charts). `labelPosition`: "left"|"center"|"right"
99
100
  - `annotations={[{ type: "x-threshold", value: 50, label: "Cutoff", labelPosition: "top" }]}` — vertical reference line. `labelPosition`: "top"|"center"|"bottom"
100
101
  - `annotations={[{ type: "callout-circle", x: 5, y: 20, label: "Peak", radius: 12 }]}` — data-bound callout; use `callout-rect` with `width`/`height` for a rectangular subject
@@ -0,0 +1,20 @@
1
+ import type { Datum } from "../../components/charts/shared/datumTypes";
2
+ export interface JsonRpcResponse {
3
+ jsonrpc: "2.0";
4
+ id: string | number;
5
+ result: Datum;
6
+ error?: Datum;
7
+ }
8
+ export interface ListedMcpTool {
9
+ name: string;
10
+ _meta?: {
11
+ ui?: {
12
+ resourceUri: string;
13
+ };
14
+ "openai/outputTemplate"?: string;
15
+ };
16
+ annotations?: {
17
+ readOnlyHint?: boolean;
18
+ destructiveHint?: boolean;
19
+ };
20
+ }
@@ -1,5 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type NavTreeNode } from "./ai/navigationTree";
3
+ import { type OnObservationCallback } from "./store/ObservationStore";
4
+ import { type OnAnnotationActivateCallback } from "./charts/shared/annotationActivation";
3
5
  export interface AccessibleNavTreeProps {
4
6
  tree: NavTreeNode;
5
7
  /** Accessible name for the tree. */
@@ -22,5 +24,9 @@ export interface AccessibleNavTreeProps {
22
24
  * the conversation-arc store is enabled — zero-overhead otherwise.
23
25
  */
24
26
  chartId?: string;
27
+ /** Normalized focus/activation events produced by structured navigation. */
28
+ onObservation?: OnObservationCallback;
29
+ /** Observe activation of an annotation leaf in the navigation tree. */
30
+ onAnnotationActivate?: OnAnnotationActivateCallback;
25
31
  }
26
- export declare function AccessibleNavTree({ tree, label, visible, className, onActiveChange, activeId: controlledActiveId, chartId }: AccessibleNavTreeProps): React.JSX.Element;
32
+ export declare function AccessibleNavTree({ tree, label, visible, className, onActiveChange, activeId: controlledActiveId, chartId, onObservation, onAnnotationActivate }: AccessibleNavTreeProps): React.JSX.Element;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AUTO-GENERATED from chartSpecs.ts and chartDefinitionPilot.ts by
3
+ * scripts/regenerate-schema.ts.
4
+ * Do not edit by hand; run `npm run docs:chart-specs:schema`.
5
+ */
6
+ import type { ChartCategory } from "../charts/shared/chartSpecs";
7
+ interface ChartClinicMetadata {
8
+ readonly category: ChartCategory;
9
+ readonly recommendedImport: string;
10
+ readonly serverImport?: "semiotic/server";
11
+ readonly docsRoute?: string;
12
+ readonly pilot?: true;
13
+ }
14
+ export declare const CHART_CLINIC_METADATA: Readonly<Record<string, ChartClinicMetadata>>;
15
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { ChartObservation } from "../store/ObservationStore";
1
2
  import type { NavTreeNode } from "./navigationTree";
2
3
  import type { Datum } from "../charts/shared/datumTypes";
3
4
  /**
@@ -29,8 +30,12 @@ export interface UseNavigationSyncOptions {
29
30
  matchFields?: string[];
30
31
  /** Selection name shared with the chart's `selection={{ name }}`. Default "__semiotic-nav-sync". */
31
32
  selectionName?: string;
32
- /** Which canvas observations move the tree. Default ["hover", "click"]. */
33
- observe?: Array<"hover" | "click">;
33
+ /**
34
+ * Which chart observations move the tree. Defaults to pointer hover/click
35
+ * plus keyboard focus/activation so raw frames and HOC charts stay in sync
36
+ * for both pointer and keyboard readers.
37
+ */
38
+ observe?: Array<"hover" | "click" | "focus" | "activate">;
34
39
  /**
35
40
  * The chart's annotations. An annotation anchored to a datum carries that
36
41
  * datum's identifying fields (the same `matchFields` used for hover sync), so
@@ -49,6 +54,16 @@ export interface UseNavigationSyncResult {
49
54
  selection: {
50
55
  name: string;
51
56
  };
57
+ /**
58
+ * Feed a chart observation directly into the sync. This is useful for raw
59
+ * StreamFrames or custom interactions that call `onObservation` themselves
60
+ * instead of publishing through the chart HOCs. Matching pointer and
61
+ * keyboard observations move the tree; events later received from the global
62
+ * observation store are de-duplicated by object identity.
63
+ */
64
+ onObservation: (observation: ChartObservation) => void;
65
+ /** Alias of `onObservation` for composing an externally supplied handler. */
66
+ handleObservation: (observation: ChartObservation) => void;
52
67
  /** Nav-tree leaf ids that an annotation anchors to — mark these as "has a note". */
53
68
  annotatedIds: Set<string>;
54
69
  /**
@@ -0,0 +1,9 @@
1
+ import type { ReactElement } from "react";
2
+ import type { MobileStandardControlRequest, MobileStandardControlsProps } from "./MobileStandardControls";
3
+ import type { MobileInteractionProp } from "./charts/shared/types";
4
+ export declare function canReceiveChartProps(child: ReactElement): boolean;
5
+ export declare function isMobileStandardControlsProps(value: MobileStandardControlRequest | MobileStandardControlsProps | undefined): value is MobileStandardControlsProps;
6
+ export declare function standardControlsFromInteraction(mobileInteraction: MobileInteractionProp | undefined): MobileStandardControlRequest | undefined;
7
+ export declare function targetSizeFromInteraction(mobileInteraction: MobileInteractionProp | undefined): number | undefined;
8
+ export declare function hasStandardControlsRequest(request: MobileStandardControlRequest | undefined): request is MobileStandardControlRequest;
9
+ export declare function withStandardControls(source: MobileInteractionProp | undefined, controls: MobileStandardControlRequest | undefined): MobileInteractionProp | undefined;