semiotic 3.8.5 → 3.8.6

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 (176) hide show
  1. package/CLAUDE.md +5 -4
  2. package/README.md +42 -42
  3. package/ai/behaviorContracts.cjs +2 -2
  4. package/ai/componentMetadata.cjs +1 -1
  5. package/ai/dist/mcp-server.js +2 -0
  6. package/ai/examples.md +44 -2
  7. package/ai/schema.json +385 -14
  8. package/ai/surface-manifest.json +6 -4
  9. package/ai/system-prompt.md +1 -1
  10. package/dist/{chunk-chartContainerDataAudit-74TLKIP6.module.min.js → chunk-chartContainerDataAudit-FEOD5GTQ.module.min.js} +1 -1
  11. package/dist/chunk-chunk-2CHN2TA3.module.min.js +1 -0
  12. package/dist/chunk-chunk-2JGJ5GUG.module.min.js +1 -0
  13. package/dist/chunk-chunk-3NGIKFD6.module.min.js +1 -0
  14. package/dist/chunk-chunk-3SHB24AG.module.min.js +1 -0
  15. package/dist/chunk-chunk-4MMOOYTX.module.min.js +2 -0
  16. package/dist/{chunk-chunk-KT2VAZMZ.module.min.js → chunk-chunk-75OTQSXS.module.min.js} +1 -1
  17. package/dist/chunk-chunk-A5GRQUOF.module.min.js +1 -0
  18. package/dist/chunk-chunk-AAF5LZAU.module.min.js +2 -0
  19. package/dist/{chunk-chunk-4AANPFOX.module.min.js → chunk-chunk-ARZGA4LJ.module.min.js} +1 -1
  20. package/dist/chunk-chunk-CAFLML4L.module.min.js +2 -0
  21. package/dist/chunk-chunk-FHBN7OEB.module.min.js +2 -0
  22. package/dist/{chunk-chunk-TMWIZL3K.module.min.js → chunk-chunk-GFTVACTO.module.min.js} +1 -1
  23. package/dist/chunk-chunk-IP2UE74X.module.min.js +1 -0
  24. package/dist/chunk-chunk-ITDWLZXV.module.min.js +2 -0
  25. package/dist/chunk-chunk-LPSPATPC.module.min.js +1 -0
  26. package/dist/chunk-chunk-OM6NWS4H.module.min.js +2 -0
  27. package/dist/chunk-chunk-PX5YQGDP.module.min.js +2 -0
  28. package/dist/chunk-chunk-Q2BS46W2.module.min.js +2 -0
  29. package/dist/{chunk-chunk-LJLS6DY7.module.min.js → chunk-chunk-RA7JCG7D.module.min.js} +1 -1
  30. package/dist/chunk-chunk-RNUHEXZA.module.min.js +2 -0
  31. package/dist/chunk-chunk-ROZWKEUG.module.min.js +1 -0
  32. package/dist/chunk-chunk-SMVD3EQJ.module.min.js +2 -0
  33. package/dist/chunk-chunk-T2FKJD4O.module.min.js +2 -0
  34. package/dist/{chunk-chunk-K3DMEW22.module.min.js → chunk-chunk-UDREYOLV.module.min.js} +1 -1
  35. package/dist/chunk-chunk-VOWE3SAP.module.min.js +2 -0
  36. package/dist/chunk-chunk-VQPNBUSW.module.min.js +2 -0
  37. package/dist/{chunk-chunk-N5DDKCCF.module.min.js → chunk-chunk-WAWCIHFJ.module.min.js} +1 -1
  38. package/dist/{chunk-chunk-XXWSHGPL.module.min.js → chunk-chunk-WYARAXHR.module.min.js} +1 -1
  39. package/dist/{chunk-chunk-I36PJ4OC.module.min.js → chunk-chunk-XP3OHHFX.module.min.js} +1 -1
  40. package/dist/chunk-chunk-XV3KGYTR.module.min.js +2 -0
  41. package/dist/chunk-chunk-YC2IVEPX.module.min.js +1 -0
  42. package/dist/components/ai/chartCapabilities.d.ts +2 -1
  43. package/dist/components/charts/custom/XYCustomChart.d.ts +3 -0
  44. package/dist/components/charts/geo/DistanceCartogram.d.ts +1 -1
  45. package/dist/components/charts/index.d.ts +3 -0
  46. package/dist/components/charts/ordinal/BarChart.d.ts +7 -14
  47. package/dist/components/charts/ordinal/GaugeChart.d.ts +3 -0
  48. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +3 -0
  49. package/dist/components/charts/ordinal/StackedBarChart.d.ts +3 -0
  50. package/dist/components/charts/ordinal/SwimlaneChart.d.ts +4 -14
  51. package/dist/components/charts/shared/chartSpecCore.d.ts +2 -4
  52. package/dist/components/charts/shared/gaugeGradient.d.ts +4 -8
  53. package/dist/components/charts/shared/gradient.d.ts +35 -0
  54. package/dist/components/charts/shared/hatchFill.d.ts +3 -10
  55. package/dist/components/charts/shared/hooks.d.ts +2 -50
  56. package/dist/components/charts/shared/knownChartComponents.d.ts +1 -1
  57. package/dist/components/charts/shared/streamPropsHelpers.d.ts +1 -2
  58. package/dist/components/charts/shared/useChartLegend.d.ts +58 -0
  59. package/dist/components/charts/shared/useChartSetup.d.ts +5 -0
  60. package/dist/components/charts/shared/useCustomChartSetup.d.ts +6 -1
  61. package/dist/components/charts/shared/useNetworkChartSetup.d.ts +1 -0
  62. package/dist/components/charts/shared/useStreamingLegend.d.ts +1 -1
  63. package/dist/components/charts/xy/AreaChart.d.ts +25 -42
  64. package/dist/components/charts/xy/BumpChart.capability.d.ts +11 -0
  65. package/dist/components/charts/xy/BumpChart.d.ts +161 -0
  66. package/dist/components/charts/xy/DifferenceChart.d.ts +3 -10
  67. package/dist/components/charts/xy/Heatmap.d.ts +3 -0
  68. package/dist/components/charts/xy/LineChart.d.ts +6 -8
  69. package/dist/components/geometry/bumpRibbonGeometry.d.ts +36 -0
  70. package/dist/components/legendLayout.d.ts +19 -1
  71. package/dist/components/semiotic-ai.d.ts +2 -1
  72. package/dist/components/semiotic-geo.d.ts +1 -0
  73. package/dist/components/semiotic-network.d.ts +1 -0
  74. package/dist/components/semiotic-ordinal.d.ts +2 -0
  75. package/dist/components/semiotic-physics.d.ts +1 -0
  76. package/dist/components/semiotic-realtime-core.d.ts +1 -0
  77. package/dist/components/semiotic-server-edge.d.ts +1 -1
  78. package/dist/components/semiotic-server.d.ts +1 -1
  79. package/dist/components/semiotic-xy.d.ts +4 -0
  80. package/dist/components/semiotic.d.ts +4 -4
  81. package/dist/components/server/serverChartConfigs.d.ts +1 -0
  82. package/dist/components/server/serverChartConfigsXY.d.ts +1 -0
  83. package/dist/components/server/staticLegend.d.ts +4 -2
  84. package/dist/components/server/staticSVGChrome.d.ts +4 -4
  85. package/dist/components/stream/GeoSVGOverlay.d.ts +4 -10
  86. package/dist/components/stream/NetworkSVGOverlay.d.ts +2 -6
  87. package/dist/components/stream/OrdinalSVGOverlay.d.ts +2 -6
  88. package/dist/components/stream/SVGOverlay.d.ts +2 -6
  89. package/dist/components/stream/StalenessBadge.d.ts +2 -6
  90. package/dist/components/stream/geoTypes.d.ts +3 -6
  91. package/dist/components/stream/legendRenderer.d.ts +2 -6
  92. package/dist/components/stream/ordinalTypes.d.ts +7 -31
  93. package/dist/components/stream/physics/PhysicsKernel.d.ts +1 -0
  94. package/dist/components/stream/physics/PhysicsSVGOverlay.d.ts +2 -6
  95. package/dist/components/stream/physics/StreamPhysicsTypes.d.ts +2 -6
  96. package/dist/components/stream/pipelineConfig.d.ts +7 -15
  97. package/dist/components/stream/renderers/canvasRenderHelpers.d.ts +9 -69
  98. package/dist/components/stream/renderers/cornerRadii.d.ts +2 -9
  99. package/dist/components/stream/renderers/thresholdLineSegments.d.ts +12 -0
  100. package/dist/components/stream/sceneToSVGShared.d.ts +3 -5
  101. package/dist/components/stream/types.d.ts +32 -56
  102. package/dist/components/stream/xySceneBuilders/areaGradient.d.ts +4 -20
  103. package/dist/components/stream/xySceneBuilders/types.d.ts +6 -6
  104. package/dist/components/types/legendTypes.d.ts +15 -6
  105. package/dist/geo.min.js +1 -1
  106. package/dist/geo.module.min.js +1 -1
  107. package/dist/network.min.js +1 -1
  108. package/dist/network.module.min.js +1 -1
  109. package/dist/ordinal.min.js +1 -1
  110. package/dist/ordinal.module.min.js +1 -1
  111. package/dist/physics.min.js +1 -1
  112. package/dist/physics.module.min.js +1 -1
  113. package/dist/physicsWorker.js +1 -1
  114. package/dist/realtime.min.js +1 -1
  115. package/dist/realtime.module.min.js +1 -1
  116. package/dist/semiotic-ai-core.min.js +1 -1
  117. package/dist/semiotic-ai-core.module.min.js +1 -1
  118. package/dist/semiotic-ai.d.ts +2 -1
  119. package/dist/semiotic-ai.min.js +1 -1
  120. package/dist/semiotic-ai.module.min.js +1 -1
  121. package/dist/semiotic-experimental.min.js +1 -1
  122. package/dist/semiotic-experimental.module.min.js +1 -1
  123. package/dist/semiotic-geo.d.ts +1 -0
  124. package/dist/semiotic-network.d.ts +1 -0
  125. package/dist/semiotic-ordinal.d.ts +2 -0
  126. package/dist/semiotic-physics.d.ts +1 -0
  127. package/dist/semiotic-realtime-core.d.ts +1 -0
  128. package/dist/semiotic-realtime-core.min.js +1 -1
  129. package/dist/semiotic-realtime-core.module.min.js +1 -1
  130. package/dist/semiotic-recipes-core.module.min.js +1 -1
  131. package/dist/semiotic-recipes.module.min.js +1 -1
  132. package/dist/semiotic-server-edge.d.ts +1 -1
  133. package/dist/semiotic-server-edge.min.js +1 -1
  134. package/dist/semiotic-server-edge.module.min.js +1 -1
  135. package/dist/semiotic-server-node.min.js +1 -1
  136. package/dist/semiotic-server-node.module.min.js +1 -1
  137. package/dist/semiotic-server.d.ts +1 -1
  138. package/dist/semiotic-utils-core.min.js +1 -1
  139. package/dist/semiotic-utils-core.module.min.js +1 -1
  140. package/dist/semiotic-utils.min.js +1 -1
  141. package/dist/semiotic-utils.module.min.js +1 -1
  142. package/dist/semiotic-xy.d.ts +4 -0
  143. package/dist/semiotic.d.ts +4 -4
  144. package/dist/semiotic.min.js +1 -1
  145. package/dist/semiotic.module.min.js +1 -1
  146. package/dist/server.min.js +1 -1
  147. package/dist/server.module.min.js +1 -1
  148. package/dist/xy.min.js +1 -1
  149. package/dist/xy.module.min.js +1 -1
  150. package/package.json +1 -1
  151. package/dist/chunk-chunk-5I3UZV4Q.module.min.js +0 -2
  152. package/dist/chunk-chunk-74CCPVXB.module.min.js +0 -1
  153. package/dist/chunk-chunk-ANYDWOZF.module.min.js +0 -1
  154. package/dist/chunk-chunk-AVBI6GDT.module.min.js +0 -1
  155. package/dist/chunk-chunk-BANTPINB.module.min.js +0 -2
  156. package/dist/chunk-chunk-C57LR3YG.module.min.js +0 -1
  157. package/dist/chunk-chunk-CKMD5NV3.module.min.js +0 -2
  158. package/dist/chunk-chunk-CWQ5YIHX.module.min.js +0 -2
  159. package/dist/chunk-chunk-E6TXX6MI.module.min.js +0 -1
  160. package/dist/chunk-chunk-L6EA5V3G.module.min.js +0 -2
  161. package/dist/chunk-chunk-LJPCLYSC.module.min.js +0 -2
  162. package/dist/chunk-chunk-LRIFN2HK.module.min.js +0 -1
  163. package/dist/chunk-chunk-NEVE562N.module.min.js +0 -1
  164. package/dist/chunk-chunk-NLO44TOS.module.min.js +0 -2
  165. package/dist/chunk-chunk-PZJ2SBLL.module.min.js +0 -2
  166. package/dist/chunk-chunk-QUJ6TTLY.module.min.js +0 -1
  167. package/dist/chunk-chunk-RBIDBUT4.module.min.js +0 -2
  168. package/dist/chunk-chunk-RFLAG356.module.min.js +0 -1
  169. package/dist/chunk-chunk-RPU4IZAV.module.min.js +0 -2
  170. package/dist/chunk-chunk-SKMBCFIL.module.min.js +0 -2
  171. package/dist/chunk-chunk-TAE7W424.module.min.js +0 -2
  172. package/dist/chunk-chunk-TUBMTZMU.module.min.js +0 -2
  173. package/dist/chunk-chunk-UFFEXJQY.module.min.js +0 -1
  174. package/dist/chunk-chunk-XSCHTS4D.module.min.js +0 -2
  175. package/dist/chunk-statisticalOverlays-QGDLRUHX.module.min.js +0 -1
  176. package/dist/chunk-statisticalOverlays-T77OKLDY.module.min.js +0 -1
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` (138KB gz), `semiotic/ordinal` (117KB gz), `semiotic/network` (124KB gz), `semiotic/geo` (98KB gz), `semiotic/realtime` (151KB gz), `semiotic/realtime/core` (145KB gz), `semiotic/realtime/react` (1KB gz), `semiotic/server` (205KB gz), `semiotic/server/node` (205KB gz), `semiotic/server/edge` (224KB gz), `semiotic/utils` (83KB gz), `semiotic/utils/core` (81KB gz), `semiotic/utils/react` (6KB gz), `semiotic/recipes` (84KB gz), `semiotic/recipes/core` (83KB 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` (153KB gz), `semiotic/physics/matter` (1KB gz), `semiotic/physics/rapier` (1KB gz), `semiotic/ai` (462KB gz), `semiotic/ai/core` (77KB gz), `semiotic/controls` (12KB gz), `semiotic/rough` (4KB gz). Full `semiotic` is 376KB gz.
7
+ - **Use sub-path imports** — `semiotic/xy` (143KB gz), `semiotic/ordinal` (119KB gz), `semiotic/network` (125KB gz), `semiotic/geo` (98KB gz), `semiotic/realtime` (152KB gz), `semiotic/realtime/core` (146KB gz), `semiotic/realtime/react` (1KB gz), `semiotic/server` (207KB gz), `semiotic/server/node` (207KB gz), `semiotic/server/edge` (226KB gz), `semiotic/utils` (83KB gz), `semiotic/utils/core` (81KB gz), `semiotic/utils/react` (6KB gz), `semiotic/recipes` (84KB gz), `semiotic/recipes/core` (83KB 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` (154KB gz), `semiotic/physics/matter` (1KB gz), `semiotic/physics/rapier` (1KB gz), `semiotic/ai` (468KB gz), `semiotic/ai/core` (78KB gz), `semiotic/controls` (12KB gz), `semiotic/rough` (4KB gz). Full `semiotic` is 382KB 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
 
@@ -21,8 +21,9 @@ HOC Charts (simple, default) → Stream Frames (full control). Use HOCs unless y
21
21
  ## XY Charts (`semiotic/xy`)
22
22
 
23
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
- **AreaChart** — LineChart props + `areaBy`, `y0Accessor`, `gradientFill`, `areaOpacity` (0.7), `showLine` (true), `band`, `tooltip="multi"`
24
+ **AreaChart** — LineChart props + `areaBy`, `y0Accessor`, `gradientFill`, `semanticGradient` (`{stops: [{offset: 0–1, color?, opacity?}]}`; offset follows the resolved y-domain), `semanticLine` (true with semanticGradient; false keeps the normal stroke/lineGradient), `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
+ **BumpChart** — Ranking-over-x. Each x-column ranks series by `yAccessor`; rank is vertical position. `data`, `xAccessor` ("x"), `yAccessor` ("y"), `lineBy` ("series"), `rankDirection` ("descending"|"ascending"), `ribbon` (false — encode magnitude as true perpendicular-offset ribbon width instead of fixed-width lines; line↔ribbon share centerline geometry so `animate` tweens width only), `curve` ("smooth"|"linear"), `ribbonSizeRange` ([4,28]), `samplesPerSegment` (12), `lineWidth` (3), `highlightTop` (color only the N best series by mean rank; the rest share `neutralColor`), `neutralColor`, `styleRules` (per-series; resolve against each series' first observation), `showPoints`, `showLabels` (true|"start"|"end"|"both"), `hoverHighlight`, `annotations` (x may use original x values incl. `Date`). Wraps XYCustomChart.
26
27
  **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
28
  **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
29
  **BubbleChart** — Scatterplot + `sizeBy` (required), `sizeRange` ([5,40]), `regression`
@@ -36,7 +37,7 @@ HOC Charts (simple, default) → Stream Frames (full control). Use HOCs unless y
36
37
 
37
38
  ## Ordinal Charts (`semiotic/ordinal`)
38
39
 
39
- **BarChart** — `categoryAccessor`, `valueAccessor`, `orientation`, `colorBy`, `sort`, `barPadding` (40), `roundedTop`, `gradientFill` (true | {topOpacity, bottomOpacity} | {colorStops}; tip→base), `styleRules`, `regression`
40
+ **BarChart** — `categoryAccessor`, `valueAccessor`, `orientation`, `colorBy`, `sort`, `barPadding` (40), `roundedTop`, `gradientFill` (`{stops: [{offset: 0–1, color?, opacity?}]}`; tip→base), `styleRules`, `regression`
40
41
  **StackedBarChart** — + `stackBy` (required), `normalize`, `sort` (false default — insertion order), `styleRules`
41
42
  **GroupedBarChart** — + `groupBy` (required), `barPadding` (60), `sort` (false default), `styleRules`
42
43
  **SwarmPlot** — `colorBy`, `sizeBy`, `symbolBy` (categorical field → glyph shape, like Scatterplot), `symbolMap`, `pointRadius`, `pointOpacity`
@@ -58,7 +59,7 @@ All ordinal: `colorBy`, `colorScheme`, `categoryFormat` (string|ReactNode), `sho
58
59
 
59
60
  ## Network Charts (`semiotic/network`)
60
61
 
61
- **ForceDirectedGraph** — `nodes`, `edges`, `nodeIDAccessor`, `sourceAccessor`, `targetAccessor`, `colorBy`, `nodeSize`, `nodeSizeRange`, `nodeStroke`/`nodeStrokeWidth` (node-only outline), `edgeWidth`, `edgeColor`/`edgeOpacity` (edge-only stroke), `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). **Node vs edge stroking**: the generic `stroke`/`strokeWidth`/`opacity` style *all* marks uniformly; to stroke nodes and edges separately use node-only `nodeStroke`/`nodeStrokeWidth` (e.g. `nodeStroke="none"` drops the node ring) and edge-only `edgeColor`/`edgeWidth`/`edgeOpacity`. Precedence per property: specific > generic > built-in default (so an explicit `edgeColor` is no longer clobbered by a generic `stroke`).
62
+ **ForceDirectedGraph** — `nodes`, `edges`, `nodeIDAccessor`, `sourceAccessor`, `targetAccessor`, `colorBy`, `nodeSize`, `nodeSizeRange`, `nodeStroke`/`nodeStrokeWidth` (node-only outline), `edgeWidth`, `edgeColor`/`edgeOpacity` (edge-only stroke), `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). **Node vs edge stroking**: the generic `stroke`/`strokeWidth`/`opacity` style *all* marks uniformly; to stroke nodes and edges separately use node-only `nodeStroke`/`nodeStrokeWidth` (e.g. `nodeStroke="none"` drops the node ring) and edge-only `edgeColor`/`edgeWidth`/`edgeOpacity`. Precedence per property: specific > generic > built-in default.
62
63
  **SankeyDiagram** — `edges`, `nodes`, `valueAccessor`, `nodeIdAccessor`, `colorBy`, `edgeColorBy`, `orientation`, `nodeAlign`, `nodeWidth`, `nodePaddingRatio`, `showLabels`
63
64
  **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.
64
65
  **ChordDiagram** — `edges`, `nodes`, `valueAccessor`, `edgeColorBy`, `padAngle`, `showLabels`
package/README.md CHANGED
@@ -16,21 +16,21 @@ 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.5
20
-
21
- 3.8.5 adds a new physics chart and two network/word-cloud recipes, then closes another round of
22
- server/browser render gaps:
23
-
24
- - New `CrucibleChart` (`semiotic/physics`): bounded peer components undergo authored phases and
25
- events, form declared products, and settle into reason-labelled outlets with full source lineage.
26
- - New `wordTrailsLayout` and `netEnsembleLayout` recipes (`semiotic/recipes`) for quantitatively
27
- anchored word clouds and small-multiple layouts of disconnected graph ensembles, plus a
28
- Langren-style strip layout for `DistanceCartogram` and separate node/edge stroke controls on
29
- `ForceDirectedGraph`.
30
- - `renderChart` now runs a chart's custom `svgAnnotationRules` server-side, honors `frameProps`
31
- axis/legend/label overrides, and renders ordinal `x-threshold` annotations—closing SSR gaps that
32
- used to silently drop custom overlays and chrome toggles. `renderChartWithEvidence` also exposes
33
- the resolved margin and plot rectangle.
19
+ ## What's New in 3.8.6
20
+
21
+ 3.8.6 adds a ranking chart and semantic-line area bands, then refines legend layout across the
22
+ client and server renderers:
23
+
24
+ - New `BumpChart` (`semiotic/xy`): ranks every series within each x-column and connects each
25
+ series' rank across columns. Set `ribbon` to encode the original magnitude as true
26
+ perpendicular-offset ribbon width instead of a fixed-width line — both modes share one
27
+ centerline, so the toggle animates as a pure width change.
28
+ - `AreaChart` gains `semanticLine` (default on) for hard, value-banded color segments along the
29
+ area's top stroke, and `gradientFill`/`lineGradient`/`semanticGradient` now share one
30
+ `{ stops }` config (with `GradientConfig` and friends exported).
31
+ - Legend layout gains `legendLayout.sideGutter` (space between a side legend and axis chrome) and
32
+ a `legendDistance` control, with content-measured side-legend widths and tightened defaults,
33
+ aligned across the client and SSR renderers.
34
34
 
35
35
  ```jsx
36
36
  import { LineChart } from "semiotic/xy"
@@ -379,16 +379,16 @@ The numbers below are **first-party artifact cost**: the gzip size of Semiotic's
379
379
 
380
380
  | Entry Point | gzip | What's inside |
381
381
  |---|---|---|
382
- | `semiotic/xy` | **138 KB** | LineChart, AreaChart, Scatterplot, Heatmap, + 8 more XY charts |
383
- | `semiotic/ordinal` | **117 KB** | BarChart, PieChart, BoxPlot, Histogram, + 11 more categorical charts |
384
- | `semiotic/network` | **124 KB** | ForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more |
382
+ | `semiotic/xy` | **143 KB** | LineChart, AreaChart, Scatterplot, Heatmap, + 8 more XY charts |
383
+ | `semiotic/ordinal` | **119 KB** | BarChart, PieChart, BoxPlot, Histogram, + 11 more categorical charts |
384
+ | `semiotic/network` | **125 KB** | ForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more |
385
385
  | `semiotic/geo` | **98 KB** | ChoroplethMap, FlowMap, DistanceCartogram, ProportionalSymbolMap |
386
- | `semiotic/realtime` | **151 KB** | RealtimeLineChart, RealtimeHistogram, + 4 streaming charts |
387
- | `semiotic/realtime/core` | **145 KB** | Streaming chart types, HOCs, and buffer helpers |
386
+ | `semiotic/realtime` | **152 KB** | RealtimeLineChart, RealtimeHistogram, + 4 streaming charts |
387
+ | `semiotic/realtime/core` | **146 KB** | Streaming chart types, HOCs, and buffer helpers |
388
388
  | `semiotic/realtime/react` | **1 KB** | Stream status and synced push hooks |
389
- | `semiotic/server` | **205 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
390
- | `semiotic/server/node` | **205 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
391
- | `semiotic/server/edge` | **224 KB** | renderChart, renderChartWithEvidence, renderToStaticSVG, renderDashboard |
389
+ | `semiotic/server` | **207 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
390
+ | `semiotic/server/node` | **207 KB** | renderChart, renderDashboard, renderToImage, renderToAnimatedGif |
391
+ | `semiotic/server/edge` | **226 KB** | renderChart, renderChartWithEvidence, renderToStaticSVG, renderDashboard |
392
392
  | `semiotic/utils` | **83 KB** | ThemeProvider, numeric/accessibility audits, serialization — no chart components |
393
393
  | `semiotic/utils/core` | **81 KB** | Pure theme helpers, numeric/accessibility audits, and serialization |
394
394
  | `semiotic/utils/react` | **6 KB** | ThemeProvider, useTheme, useReducedMotion, useHighContrast, useStreamStatus |
@@ -400,14 +400,14 @@ The numbers below are **first-party artifact cost**: the gzip size of Semiotic's
400
400
  | `semiotic/themes/react` | **6 KB** | ThemeProvider/useTheme and hooks |
401
401
  | `semiotic/data` | **4 KB** | bin, rollup, groupBy, pivot, fromVegaLite |
402
402
  | `semiotic/value` | **8 KB** | BigNumber — focal-value KPI / scorecard (SingleValueFrame POC) |
403
- | `semiotic/physics` | **153 KB** | GaltonBoardChart, EventDropChart, PhysicsPileChart, CollisionSwarmChart, PhysicalFlowChart, PhysicsCustomChart |
403
+ | `semiotic/physics` | **154 KB** | GaltonBoardChart, EventDropChart, PhysicsPileChart, CollisionSwarmChart, PhysicalFlowChart, PhysicsCustomChart |
404
404
  | `semiotic/physics/matter` | **1 KB** | Matter.js migration helpers + optional peer guard (no chart components) |
405
405
  | `semiotic/physics/rapier` | **1 KB** | Rapier peer guard + adapter decision metadata (no chart components) |
406
- | `semiotic/ai` | **462 KB** | All schema-backed charts + validation — optimized for LLM code generation |
407
- | `semiotic/ai/core` | **77 KB** | suggestCharts, auditData, describeChart, repairChartConfig, tool adapters — no chart components |
406
+ | `semiotic/ai` | **468 KB** | All schema-backed charts + validation — optimized for LLM code generation |
407
+ | `semiotic/ai/core` | **78 KB** | suggestCharts, auditData, describeChart, repairChartConfig, tool adapters — no chart components |
408
408
  | `semiotic/controls` | **12 KB** | DirectManipulationControl, CircularBrush, MobileStandardControls, auditVisualizationControls — no frame renderer |
409
409
  | `semiotic/rough` | **4 KB** | Optional deterministic Rough.js paint backend — exact Semiotic geometry remains authoritative |
410
- | `semiotic` | **376 KB** | Everything below (full bundle) |
410
+ | `semiotic` | **382 KB** | Everything below (full bundle) |
411
411
 
412
412
  <!-- semiotic-bundle-sizes:end -->
413
413
 
@@ -428,23 +428,23 @@ Method: fresh `npm pack --ignore-scripts` tarball → temporary consumer → min
428
428
 
429
429
  | Public named import | Runtime | gzip cold-consumer bundle |
430
430
  |---|---:|---:|
431
- | `import { LineChart } from "semiotic"` | browser | **148.0 KiB** |
432
- | `import { LineChart } from "semiotic/xy"` | browser | **148.0 KiB** |
433
- | `import { BarChart } from "semiotic/ordinal"` | browser | **122.1 KiB** |
434
- | `import { SankeyDiagram } from "semiotic/network"` | browser | **127.3 KiB** |
435
- | `import { RealtimeLineChart } from "semiotic/realtime"` | browser | **121.3 KiB** |
436
- | `import { RingBuffer } from "semiotic/realtime/core"` | browser | **169.7 KiB** |
431
+ | `import { LineChart } from "semiotic"` | browser | **152.8 KiB** |
432
+ | `import { LineChart } from "semiotic/xy"` | browser | **152.8 KiB** |
433
+ | `import { BarChart } from "semiotic/ordinal"` | browser | **122.9 KiB** |
434
+ | `import { SankeyDiagram } from "semiotic/network"` | browser | **127.8 KiB** |
435
+ | `import { RealtimeLineChart } from "semiotic/realtime"` | browser | **122.5 KiB** |
436
+ | `import { RingBuffer } from "semiotic/realtime/core"` | browser | **170.9 KiB** |
437
437
  | `import { useStreamStatus } from "semiotic/realtime/react"` | browser | **0.6 KiB** |
438
- | `import { GaltonBoardChart } from "semiotic/physics"` | browser | **137.1 KiB** |
438
+ | `import { GaltonBoardChart } from "semiotic/physics"` | browser | **138.0 KiB** |
439
439
  | `import { MATTER_PHYSICS_CAPABILITIES } from "semiotic/physics/matter"` | browser | **0.2 KiB** |
440
440
  | `import { RAPIER_PHYSICS_CAPABILITIES } from "semiotic/physics/rapier"` | browser | **0.2 KiB** |
441
- | `import { renderChart } from "semiotic/server"` | node | **263.8 KiB** |
442
- | `import { generateFrameSVGs } from "semiotic/server/edge"` | node | **165.7 KiB** |
443
- | `import { renderToImage } from "semiotic/server/node"` | node | **264.3 KiB** |
444
- | `import { suggestCharts } from "semiotic/ai"` | browser | **214.3 KiB** |
445
- | `import { suggestCharts } from "semiotic/ai/core"` | browser | **34.1 KiB** |
441
+ | `import { renderChart } from "semiotic/server"` | node | **266.6 KiB** |
442
+ | `import { generateFrameSVGs } from "semiotic/server/edge"` | node | **165.0 KiB** |
443
+ | `import { renderToImage } from "semiotic/server/node"` | node | **267.0 KiB** |
444
+ | `import { suggestCharts } from "semiotic/ai"` | browser | **219.7 KiB** |
445
+ | `import { suggestCharts } from "semiotic/ai/core"` | browser | **34.7 KiB** |
446
446
  | `import { bin } from "semiotic/data"` | browser | **0.4 KiB** |
447
- | `import { ChoroplethMap } from "semiotic/geo"` | browser | **107.3 KiB** |
447
+ | `import { ChoroplethMap } from "semiotic/geo"` | browser | **108.2 KiB** |
448
448
  | `import { createRoughRenderMode } from "semiotic/rough"` | browser | **3.4 KiB** |
449
449
  | `import { resolveThemePreset } from "semiotic/themes"` | browser | **3.4 KiB** |
450
450
  | `import { resolveThemePreset } from "semiotic/themes/core"` | browser | **3.4 KiB** |
@@ -470,7 +470,7 @@ import { ChoroplethMap } from "semiotic/geo"
470
470
 
471
471
  **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.
472
472
 
473
- **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.
473
+ **When to use `"semiotic"`**: Fine when you want one import for mixed families. Shared chunks prevent duplicated runtime code across family subpaths; the cold-consumer table above is the better guide for a single named import.
474
474
 
475
475
  ## TypeScript
476
476
 
@@ -557,7 +557,7 @@ host-header allowlisting. For ChatGPT Apps domain verification, set
557
557
  | **`renderChart`** | Render a Semiotic chart to static SVG. Supports the components returned by `getSchema` that are marked `[renderable]`. Pass `{ component: "LineChart", props: { data: [...], xAccessor: "x", yAccessor: "y" } }`. Returns SVG string plus a "Render evidence" JSON block (mark counts by scene type, resolved axis domains, empty flag, annotation count, accessible name) so agents can verify the chart drew data marks, or validation errors with fix suggestions. |
558
558
  | **`renderInteractiveChart`** | Render a static-data chart as a ChatGPT Apps widget. Uses the same Semiotic server render path as `renderChart`, then hydrates an iframe UI with fit, zoom, data, hover, and render-evidence controls. |
559
559
  | **`getSchema`** | Return the prop schema for a specific component. Pass `{ component: "LineChart" }` to get its props, or omit `component` to list the complete schema-backed catalog. Components marked `[renderable]` are available through `renderChart`; realtime charts require a browser/live environment. |
560
- | **`suggestChart`** | Legacy sample-row recommender. Pass `{ data: [{...}, ...] }` with 1–5 sample objects plus optional broad intent/capability filters. |
560
+ | **`suggestChart`** | Sample-row recommender. Pass `{ data: [{...}, ...] }` with 1–5 sample objects plus optional broad intent/capability filters. |
561
561
  | **`suggestCharts`** | Capability-based recommender for bounded row data. Returns ranked chart suggestions with scores, reasons, caveats, import paths, and ready-to-use props. |
562
562
  | **`suggestStreamCharts`** | Recommend realtime charts from a stream schema, throughput, and retention hints. |
563
563
  | **`suggestDashboard`** | Build a multi-panel dashboard suggestion that covers distinct analytical intents. |
@@ -27,8 +27,8 @@ const DOC_MARKER_END = "<!-- semiotic-behavior-contracts:end -->"
27
27
  // diagnoseConfig as "OK" in static mode. Keying off the presence of a `data`
28
28
  // property catches them (and still includes the charts that DO list `data`).
29
29
  //
30
- // `STATIC_DATA_COMPONENTS` stays exported as a Set for test/legacy callers
31
- // that probe the surface, and is rebuilt from disk at module load time.
30
+ // `STATIC_DATA_COMPONENTS` is exported as a Set and rebuilt from disk at
31
+ // module load time.
32
32
  function loadStaticDataComponentsFromSchema() {
33
33
  // Source layout has this file at `<repo>/ai/behaviorContracts.cjs` and the
34
34
  // schema at `<repo>/ai/schema.json` — `__dirname` works directly.
@@ -4,7 +4,7 @@ const CATEGORY_ORDER = ["xy", "ordinal", "network", "geo", "realtime", "physics"
4
4
 
5
5
  const COMPONENTS_BY_CATEGORY = {
6
6
  xy: [
7
- "LineChart", "AreaChart", "DifferenceChart", "StackedAreaChart", "Scatterplot", "QuadrantChart",
7
+ "LineChart", "BumpChart", "AreaChart", "DifferenceChart", "StackedAreaChart", "Scatterplot", "QuadrantChart",
8
8
  "MultiAxisLineChart", "CandlestickChart", "BubbleChart", "Heatmap",
9
9
  "ConnectedScatterplot", "ScatterplotMatrix", "MinimapChart",
10
10
  ],
@@ -6898,6 +6898,7 @@ var require_componentMetadata = __commonJS({
6898
6898
  var COMPONENTS_BY_CATEGORY = {
6899
6899
  xy: [
6900
6900
  "LineChart",
6901
+ "BumpChart",
6901
6902
  "AreaChart",
6902
6903
  "DifferenceChart",
6903
6904
  "StackedAreaChart",
@@ -33016,6 +33017,7 @@ var import_geo = require("semiotic/geo");
33016
33017
  var COMPONENT_REGISTRY = {
33017
33018
  LineChart: { component: import_ai.LineChart, category: "xy" },
33018
33019
  AreaChart: { component: import_ai.AreaChart, category: "xy" },
33020
+ BumpChart: { component: import_ai.BumpChart, category: "xy" },
33019
33021
  DifferenceChart: { component: import_ai.DifferenceChart, category: "xy" },
33020
33022
  StackedAreaChart: { component: import_ai.StackedAreaChart, category: "xy" },
33021
33023
  Scatterplot: { component: import_ai.Scatterplot, category: "xy" },
package/ai/examples.md CHANGED
@@ -147,7 +147,12 @@ const data = [
147
147
  data={data}
148
148
  xAccessor="month"
149
149
  yAccessor="revenue"
150
- gradientFill
150
+ gradientFill={{
151
+ stops: [
152
+ { offset: 0, opacity: 0.8 },
153
+ { offset: 1, opacity: 0.05 }
154
+ ]
155
+ }}
151
156
  xLabel="Month"
152
157
  yLabel="Revenue ($)"
153
158
  />
@@ -180,7 +185,12 @@ const data = [
180
185
  y0Accessor="p5"
181
186
  showLine={false}
182
187
  areaOpacity={0.3}
183
- gradientFill
188
+ gradientFill={{
189
+ stops: [
190
+ { offset: 0, opacity: 0.8 },
191
+ { offset: 1, opacity: 0.05 }
192
+ ]
193
+ }}
184
194
  width={600}
185
195
  height={400}
186
196
  />
@@ -235,6 +245,38 @@ Fills the region between two series with a color that switches based on which se
235
245
 
236
246
  Key props: `seriesALabel` / `seriesBLabel` (legend + tooltip), `seriesAColor` / `seriesBColor` (defaults to `var(--semiotic-danger)` / `var(--semiotic-info)`), `showLines` (default `true` — draws both series on top of the fill), `areaOpacity` (0.6), `gradientFill` (same shape as AreaChart), `windowSize` (max raw rows in push buffer; FIFO eviction). Push API: `ref.current.push({ x, a, b })` — accessor outputs coerce through a `toNumber` helper so `Date` (time series) and numeric strings (CSV/JSON) work transparently.
237
247
 
248
+ ### BumpChart
249
+
250
+ ```jsx
251
+ import { BumpChart } from "semiotic/ai"
252
+
253
+ const data = [
254
+ { quarter: "Q1", team: "North", sales: 420 },
255
+ { quarter: "Q1", team: "South", sales: 380 },
256
+ { quarter: "Q1", team: "East", sales: 510 },
257
+ { quarter: "Q1", team: "West", sales: 290 },
258
+ { quarter: "Q2", team: "North", sales: 460 },
259
+ { quarter: "Q2", team: "South", sales: 500 },
260
+ { quarter: "Q2", team: "East", sales: 480 },
261
+ { quarter: "Q2", team: "West", sales: 350 },
262
+ { quarter: "Q3", team: "North", sales: 610 },
263
+ { quarter: "Q3", team: "South", sales: 470 },
264
+ { quarter: "Q3", team: "East", sales: 520 },
265
+ { quarter: "Q3", team: "West", sales: 540 }
266
+ ]
267
+
268
+ <BumpChart
269
+ data={data}
270
+ xAccessor="quarter"
271
+ yAccessor="sales"
272
+ lineBy="team"
273
+ highlightTop={2}
274
+ xLabel="Quarter"
275
+ />
276
+ ```
277
+
278
+ Ranks every series within each x-column and connects each series' rank across columns — the classic "who's leading over time" chart. `yAccessor` is the magnitude used to rank (highest value = rank 1 by default; use `rankDirection="ascending"` when lower is better). `highlightTop` colors only the N best series by mean rank and greys the rest via `neutralColor`. Set `ribbon={true}` to encode the raw magnitude as true perpendicular-offset ribbon width instead of fixed-width lines — line and ribbon share the same centerline geometry, so `animate` tweens only the width. Endpoint labels show by default (`showLabels`).
279
+
238
280
  ### StackedAreaChart
239
281
 
240
282
  ```jsx