semiotic 3.4.2 → 3.5.0

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 (160) hide show
  1. package/CLAUDE.md +114 -9
  2. package/README.md +45 -4
  3. package/ai/behaviorContracts.cjs +311 -0
  4. package/ai/chartSuggestions.cjs +291 -0
  5. package/ai/cli.js +255 -30
  6. package/ai/componentMetadata.cjs +107 -0
  7. package/ai/dist/mcp-server.js +907 -227
  8. package/ai/schema.json +3954 -2537
  9. package/ai/system-prompt.md +23 -4
  10. package/dist/components/LinkedCharts.d.ts +5 -1
  11. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  12. package/dist/components/charts/custom/NetworkCustomChart.d.ts +64 -0
  13. package/dist/components/charts/custom/OrdinalCustomChart.d.ts +71 -0
  14. package/dist/components/charts/custom/XYCustomChart.d.ts +59 -0
  15. package/dist/components/charts/geo/ChoroplethMap.d.ts +93 -2
  16. package/dist/components/charts/geo/DistanceCartogram.d.ts +51 -4
  17. package/dist/components/charts/geo/FlowMap.d.ts +55 -0
  18. package/dist/components/charts/geo/ProportionalSymbolMap.d.ts +53 -0
  19. package/dist/components/charts/index.d.ts +6 -0
  20. package/dist/components/charts/network/ChordDiagram.d.ts +34 -2
  21. package/dist/components/charts/network/CirclePack.d.ts +36 -1
  22. package/dist/components/charts/network/ForceDirectedGraph.d.ts +130 -2
  23. package/dist/components/charts/network/OrbitDiagram.d.ts +37 -0
  24. package/dist/components/charts/network/SankeyDiagram.d.ts +51 -2
  25. package/dist/components/charts/network/TreeDiagram.d.ts +37 -2
  26. package/dist/components/charts/network/Treemap.d.ts +36 -2
  27. package/dist/components/charts/ordinal/BarChart.d.ts +111 -1
  28. package/dist/components/charts/ordinal/BoxPlot.d.ts +31 -0
  29. package/dist/components/charts/ordinal/DonutChart.d.ts +36 -0
  30. package/dist/components/charts/ordinal/DotPlot.d.ts +31 -0
  31. package/dist/components/charts/ordinal/FunnelChart.d.ts +40 -0
  32. package/dist/components/charts/ordinal/GaugeChart.d.ts +45 -0
  33. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +38 -0
  34. package/dist/components/charts/ordinal/Histogram.d.ts +95 -0
  35. package/dist/components/charts/ordinal/LikertChart.d.ts +42 -0
  36. package/dist/components/charts/ordinal/PieChart.d.ts +90 -1
  37. package/dist/components/charts/ordinal/RidgelinePlot.d.ts +27 -0
  38. package/dist/components/charts/ordinal/StackedBarChart.d.ts +38 -0
  39. package/dist/components/charts/ordinal/SwarmPlot.d.ts +36 -0
  40. package/dist/components/charts/ordinal/SwimlaneChart.d.ts +60 -0
  41. package/dist/components/charts/ordinal/ViolinPlot.d.ts +32 -0
  42. package/dist/components/charts/realtime/RealtimeHeatmap.d.ts +22 -4
  43. package/dist/components/charts/realtime/RealtimeHistogram.d.ts +5 -2
  44. package/dist/components/charts/realtime/RealtimeLineChart.d.ts +24 -3
  45. package/dist/components/charts/realtime/RealtimeSwarmChart.d.ts +12 -0
  46. package/dist/components/charts/realtime/RealtimeWaterfallChart.d.ts +14 -0
  47. package/dist/components/charts/realtime/defaultRealtimeTooltip.d.ts +43 -0
  48. package/dist/components/charts/realtime/resolveWindowSize.d.ts +26 -0
  49. package/dist/components/charts/shared/chartSpecs.d.ts +91 -0
  50. package/dist/components/charts/shared/colorPalettes.d.ts +62 -0
  51. package/dist/components/charts/shared/colorUtils.d.ts +9 -10
  52. package/dist/components/charts/shared/numberFormat.d.ts +58 -0
  53. package/dist/components/charts/shared/sparseArray.d.ts +27 -0
  54. package/dist/components/charts/shared/streamPropsHelpers.d.ts +113 -0
  55. package/dist/components/charts/shared/timeFormat.d.ts +60 -0
  56. package/dist/components/charts/shared/useChartSetup.d.ts +8 -0
  57. package/dist/components/charts/shared/useCustomChartSetup.d.ts +84 -0
  58. package/dist/components/charts/shared/useFrameImperativeHandle.d.ts +28 -0
  59. package/dist/components/charts/shared/useOrdinalStreaming.d.ts +6 -19
  60. package/dist/components/charts/shared/useStreamingLegend.d.ts +27 -11
  61. package/dist/components/charts/shared/validateProps.d.ts +2 -2
  62. package/dist/components/charts/shared/validationMap.d.ts +2 -1
  63. package/dist/components/charts/shared/withChartWrapper.d.ts +13 -4
  64. package/dist/components/charts/xy/AreaChart.d.ts +30 -1
  65. package/dist/components/charts/xy/CandlestickChart.d.ts +33 -6
  66. package/dist/components/charts/xy/ConnectedScatterplot.d.ts +24 -0
  67. package/dist/components/charts/xy/MinimapChart.d.ts +51 -0
  68. package/dist/components/charts/xy/MultiAxisLineChart.d.ts +27 -0
  69. package/dist/components/charts/xy/QuadrantChart.d.ts +21 -0
  70. package/dist/components/charts/xy/Scatterplot.d.ts +34 -2
  71. package/dist/components/charts/xy/ScatterplotMatrix.d.ts +16 -0
  72. package/dist/components/charts/xy/StackedAreaChart.d.ts +49 -1
  73. package/dist/components/realtime/types.d.ts +2 -4
  74. package/dist/components/recipes/bullet.d.ts +86 -0
  75. package/dist/components/recipes/calendar.d.ts +43 -0
  76. package/dist/components/recipes/dagre.d.ts +56 -0
  77. package/dist/components/recipes/flextree.d.ts +55 -0
  78. package/dist/components/recipes/marimekko.d.ts +55 -0
  79. package/dist/components/recipes/parallelCoordinates.d.ts +97 -0
  80. package/dist/components/recipes/recipeUtils.d.ts +27 -0
  81. package/dist/components/recipes/waffle.d.ts +46 -0
  82. package/dist/components/semiotic-ai.d.ts +4 -0
  83. package/dist/components/semiotic-network.d.ts +3 -0
  84. package/dist/components/semiotic-ordinal.d.ts +3 -0
  85. package/dist/components/semiotic-recipes.d.ts +24 -0
  86. package/dist/components/semiotic-xy.d.ts +3 -0
  87. package/dist/components/semiotic.d.ts +2 -2
  88. package/dist/components/server/renderToStaticSVG.d.ts +8 -2
  89. package/dist/components/server/serverChartConfigs.d.ts +47 -1
  90. package/dist/components/server/staticAnnotations.d.ts +6 -0
  91. package/dist/components/store/ObservationStore.d.ts +1 -3
  92. package/dist/components/store/SelectionStore.d.ts +1 -3
  93. package/dist/components/store/ThemeStore.d.ts +4 -4
  94. package/dist/components/store/TooltipStore.d.ts +1 -3
  95. package/dist/components/store/createStore.d.ts +4 -2
  96. package/dist/components/stream/CanvasHitTester.d.ts +10 -8
  97. package/dist/components/stream/DataSourceAdapter.d.ts +9 -0
  98. package/dist/components/stream/GeoPipelineStore.d.ts +9 -0
  99. package/dist/components/stream/GeoTileRenderer.d.ts +14 -0
  100. package/dist/components/stream/NetworkPipelineStore.d.ts +25 -0
  101. package/dist/components/stream/OrdinalPipelineStore.d.ts +12 -0
  102. package/dist/components/stream/PipelineStore.d.ts +51 -0
  103. package/dist/components/stream/SVGOverlay.d.ts +12 -0
  104. package/dist/components/stream/SceneGraph.d.ts +15 -1
  105. package/dist/components/stream/SceneToSVG.d.ts +1 -1
  106. package/dist/components/stream/categoryDomain.d.ts +4 -0
  107. package/dist/components/stream/composeOverlays.d.ts +15 -0
  108. package/dist/components/stream/customLayout.d.ts +76 -0
  109. package/dist/components/stream/customLayoutPalette.d.ts +29 -0
  110. package/dist/components/stream/geoTypes.d.ts +13 -0
  111. package/dist/components/stream/hoverUtils.d.ts +4 -10
  112. package/dist/components/stream/networkCustomLayout.d.ts +67 -0
  113. package/dist/components/stream/networkTypes.d.ts +45 -0
  114. package/dist/components/stream/ordinalCustomLayout.d.ts +84 -0
  115. package/dist/components/stream/ordinalTypes.d.ts +35 -1
  116. package/dist/components/stream/renderers/barFunnelCanvasRenderer.d.ts +9 -1
  117. package/dist/components/stream/renderers/canvasRenderHelpers.d.ts +92 -0
  118. package/dist/components/stream/sampleCurvePath.d.ts +9 -0
  119. package/dist/components/stream/types.d.ts +44 -1
  120. package/dist/components/stream/useHydration.d.ts +89 -0
  121. package/dist/components/stream/useStableShallow.d.ts +1 -0
  122. package/dist/components/stream/xySceneBuilders/types.d.ts +4 -0
  123. package/dist/geo.min.js +2 -1
  124. package/dist/geo.module.min.js +2 -1
  125. package/dist/network.min.js +2 -1
  126. package/dist/network.module.min.js +2 -1
  127. package/dist/ordinal.min.js +2 -1
  128. package/dist/ordinal.module.min.js +2 -1
  129. package/dist/realtime.min.js +2 -1
  130. package/dist/realtime.module.min.js +2 -1
  131. package/dist/semiotic-ai.d.ts +69 -65
  132. package/dist/semiotic-ai.min.js +2 -1
  133. package/dist/semiotic-ai.module.min.js +2 -1
  134. package/dist/semiotic-data.d.ts +4 -4
  135. package/dist/semiotic-geo.d.ts +15 -15
  136. package/dist/semiotic-network.d.ts +19 -16
  137. package/dist/semiotic-ordinal.d.ts +31 -28
  138. package/dist/semiotic-realtime.d.ts +17 -17
  139. package/dist/semiotic-recipes.d.ts +24 -0
  140. package/dist/semiotic-recipes.min.js +1 -0
  141. package/dist/semiotic-recipes.module.min.js +1 -0
  142. package/dist/semiotic-server.d.ts +6 -6
  143. package/dist/semiotic-statisticalOverlays-C3DsOgr_.js +1 -0
  144. package/dist/semiotic-themes.d.ts +3 -3
  145. package/dist/semiotic-themes.min.js +2 -1
  146. package/dist/semiotic-themes.module.min.js +2 -1
  147. package/dist/semiotic-utils.d.ts +23 -23
  148. package/dist/semiotic-utils.min.js +2 -1
  149. package/dist/semiotic-utils.module.min.js +2 -1
  150. package/dist/semiotic-xy.d.ts +27 -24
  151. package/dist/semiotic.d.ts +63 -63
  152. package/dist/semiotic.min.js +2 -1
  153. package/dist/semiotic.module.min.js +2 -1
  154. package/dist/server.min.js +1 -1
  155. package/dist/server.module.min.js +1 -1
  156. package/dist/test-utils/canvasMock.d.ts +34 -5
  157. package/dist/xy.min.js +2 -1
  158. package/dist/xy.module.min.js +2 -1
  159. package/package.json +38 -17
  160. package/dist/semiotic-statisticalOverlays-Ckd_jM8z.js +0 -1
@@ -92,6 +92,33 @@ export interface StackedAreaChartProps<TDatum extends Datum = Datum> extends Bas
92
92
  * @default false
93
93
  */
94
94
  normalize?: boolean;
95
+ /**
96
+ * Stacked baseline mode — controls where the stack origin sits.
97
+ * - `"zero"` (default): standard stacked area, baseline at y=0.
98
+ * - `"wiggle"`: streamgraph offset (Byron–Wattenberg). Minimizes visual
99
+ * wiggle across series — best for high-cardinality series where
100
+ * relative shape matters more than absolute values.
101
+ * - `"silhouette"`: center the stack symmetrically around y=0.
102
+ *
103
+ * Mutually exclusive with `normalize` — when `normalize` is true,
104
+ * baseline is forced to `"zero"`.
105
+ *
106
+ * @default "zero"
107
+ */
108
+ baseline?: "zero" | "wiggle" | "silhouette";
109
+ /**
110
+ * Stack order — controls which series sits at the top, middle, or
111
+ * bottom of the stack. Pair with `baseline: "wiggle"` or
112
+ * `"silhouette"` for the canonical streamgraph look:
113
+ *
114
+ * - `"key"` (default): alphabetical by series key. Stable under
115
+ * streaming (no re-shuffling on data eviction).
116
+ * - `"insideOut"`: largest-total series in the middle, smaller series
117
+ * wrapping outward. The classic d3 streamgraph aesthetic — gives
118
+ * you a "central anchor" layer with everything else built off of it.
119
+ * - `"asc"` / `"desc"`: by total ascending / descending.
120
+ */
121
+ stackOrder?: "key" | "insideOut" | "asc" | "desc";
95
122
  /**
96
123
  * Enable hover annotations
97
124
  * @default true
@@ -119,7 +146,13 @@ export interface StackedAreaChartProps<TDatum extends Datum = Datum> extends Bas
119
146
  */
120
147
  legendPosition?: LegendPosition;
121
148
  /**
122
- * Tooltip configuration
149
+ * Tooltip configuration.
150
+ *
151
+ * Pass `"multi"` to enable hover-anywhere mode: hovering at any x along the
152
+ * chart surfaces a single tooltip listing every stacked series at that x,
153
+ * with values interpolated between rendered path samples. Stacked series
154
+ * report band height rather than the cumulative stack top. Without `"multi"`,
155
+ * the tooltip only appears within `hoverRadius` of an explicit data point.
123
156
  */
124
157
  tooltip?: TooltipProp;
125
158
  /**
@@ -143,6 +176,7 @@ export interface StackedAreaChartProps<TDatum extends Datum = Datum> extends Bas
143
176
  *
144
177
  * @example
145
178
  * ```tsx
179
+ * // Stacked series — each category contributes a band of height
146
180
  * <StackedAreaChart
147
181
  * data={[
148
182
  * {x: 1, y: 10, category: 'A'},
@@ -156,6 +190,20 @@ export interface StackedAreaChartProps<TDatum extends Datum = Datum> extends Bas
156
190
  * yLabel="Value"
157
191
  * />
158
192
  * ```
193
+ *
194
+ * @example
195
+ * ```tsx
196
+ * // 100% normalized stack — y axis becomes share of total
197
+ * <StackedAreaChart
198
+ * data={data}
199
+ * xAccessor="t"
200
+ * yAccessor="value"
201
+ * areaBy="category"
202
+ * colorBy="category"
203
+ * normalize
204
+ * yFormat={(v) => `${(v * 100).toFixed(0)}%`}
205
+ * />
206
+ * ```
159
207
  */
160
208
  export declare const StackedAreaChart: {
161
209
  <TDatum extends Datum = Datum>(props: StackedAreaChartProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
@@ -72,10 +72,8 @@ export interface HoverData {
72
72
  x: number;
73
73
  /** Pixel Y coordinate of the hovered element */
74
74
  y: number;
75
- /** Pixel X coordinate, aliased as "time" for backwards compatibility with realtime charts */
76
- time: number;
77
- /** Pixel Y coordinate, aliased as "value" for backwards compatibility with realtime charts */
78
- value: number;
75
+ /** @internal Explicit marker used to distinguish Semiotic hover wrappers from raw user data. */
76
+ __semioticHoverData?: true;
79
77
  /** All series values at hovered X (multi-point tooltip mode) */
80
78
  allSeries?: Array<{
81
79
  group: string;
@@ -0,0 +1,86 @@
1
+ import type { OrdinalCustomLayout } from "../stream/ordinalCustomLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface BulletConfig {
4
+ /** Field (or function) yielding the row label per datum. Each row is one bullet. */
5
+ categoryAccessor: string | ((d: Datum) => string);
6
+ /** Field (or function) yielding the actual measured value (the dark bar). */
7
+ valueAccessor: string | ((d: Datum) => number);
8
+ /** Field (or function) yielding the target marker value (the perpendicular tick). */
9
+ targetAccessor: string | ((d: Datum) => number);
10
+ /**
11
+ * Field (or function) yielding the qualitative range thresholds — an
12
+ * ascending array of cutoffs ([poor, satisfactory, good]) per datum.
13
+ * The ranges paint as background bars in successively darker shades.
14
+ */
15
+ rangesAccessor: string | ((d: Datum) => number[]);
16
+ /** Pixel height of each row's bullet. @default 28 */
17
+ rowHeight?: number;
18
+ /** Pixel gap between rows. @default 12 */
19
+ rowGap?: number;
20
+ /** Color for the actual-value bar. Defaults to theme primary. */
21
+ actualColor?: string;
22
+ /** Color for the target tick. Defaults to theme text. */
23
+ targetColor?: string;
24
+ /**
25
+ * Render the metric name to the left of each row. Reserves
26
+ * `labelWidth` from the bullet area. @default true
27
+ */
28
+ showLabels?: boolean;
29
+ /**
30
+ * Pixel width reserved on the left for row labels. Only used when
31
+ * `showLabels` is true. @default 120
32
+ */
33
+ labelWidth?: number;
34
+ /**
35
+ * Render value-axis tick marks below each bullet (since each row is
36
+ * independently scaled, ticks are per-row). @default true
37
+ */
38
+ showTicks?: boolean;
39
+ /**
40
+ * Format function for the per-row tick labels rendered below each
41
+ * bullet. @default v => v.toLocaleString()
42
+ */
43
+ tickFormat?: (v: number) => string;
44
+ }
45
+ /**
46
+ * Bullet chart (Stephen Few, 2005) — a compact replacement for KPI gauges.
47
+ * Each row stacks three layers along the value axis:
48
+ *
49
+ * 1. Three background bars in successively darker shades (poor →
50
+ * satisfactory → good zones) sized by `rangesAccessor` values.
51
+ * 2. The actual measured value as a thinner dark bar.
52
+ * 3. A perpendicular tick at the target.
53
+ *
54
+ * Reads from low to high left-to-right. Far better than a half-circle
55
+ * gauge for dashboards — same information, ~5× the data density, no
56
+ * pie-shaped overhead.
57
+ *
58
+ * All inputs (`actual`, `target`, range thresholds) are treated as
59
+ * non-negative — values < 0 or non-finite are clamped to 0. Range
60
+ * thresholds are also sorted ascending so band order is always
61
+ * deterministic regardless of input order.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * import { OrdinalCustomChart } from "semiotic/ordinal"
66
+ * import { bulletLayout } from "semiotic/recipes"
67
+ *
68
+ * <OrdinalCustomChart
69
+ * data={[
70
+ * { metric: "Revenue", actual: 270, target: 250, ranges: [150, 225, 300] },
71
+ * { metric: "Profit", actual: 23, target: 27, ranges: [ 20, 25, 30] },
72
+ * { metric: "Order Size", actual: 102, target: 120, ranges: [ 80, 110, 140] },
73
+ * ]}
74
+ * layout={bulletLayout}
75
+ * layoutConfig={{
76
+ * categoryAccessor: "metric",
77
+ * valueAccessor: "actual",
78
+ * targetAccessor: "target",
79
+ * rangesAccessor: "ranges",
80
+ * }}
81
+ * width={500}
82
+ * height={180}
83
+ * />
84
+ * ```
85
+ */
86
+ export declare const bulletLayout: OrdinalCustomLayout<BulletConfig>;
@@ -0,0 +1,43 @@
1
+ import type { CustomLayout } from "../stream/customLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface CalendarConfig {
4
+ /** Field name (or function) yielding a Date or epoch ms per datum. */
5
+ dateAccessor: string | ((d: Datum) => Date | number);
6
+ /** Field name (or function) yielding the value used to color each day. */
7
+ valueAccessor: string | ((d: Datum) => number);
8
+ /**
9
+ * Two-stop color ramp: [low, high]. By default, this uses the active
10
+ * theme's semantic colors from `surface` to `primary` — pass explicit
11
+ * colors here for non-default ramps.
12
+ */
13
+ colorRamp?: [string, string];
14
+ /**
15
+ * Calendar year to render. If omitted, infers the year from the first datum.
16
+ * For multi-year series, render one XYCustomChart per year.
17
+ */
18
+ year?: number;
19
+ /** Pixel gap between cells. @default 2 */
20
+ gutter?: number;
21
+ /** Inset on the left to leave room for weekday labels. @default 0 */
22
+ labelInset?: number;
23
+ }
24
+ /**
25
+ * GitHub-style calendar heatmap — 53 columns (ISO weeks) × 7 rows (days of
26
+ * week), color-encoded by daily value. One year per layout.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * <XYCustomChart
31
+ * data={dailyEvents}
32
+ * layout={calendarLayout}
33
+ * layoutConfig={{
34
+ * dateAccessor: "date",
35
+ * valueAccessor: "count",
36
+ * year: 2025,
37
+ * }}
38
+ * width={900}
39
+ * height={140}
40
+ * />
41
+ * ```
42
+ */
43
+ export declare const calendarLayout: CustomLayout<CalendarConfig>;
@@ -0,0 +1,56 @@
1
+ import type { NetworkCustomLayout } from "../stream/networkCustomLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface DagreConfig {
4
+ /** Default node width when nodes don't carry a `width` field. @default 100 */
5
+ nodeWidth?: number;
6
+ /** Default node height when nodes don't carry a `height` field. @default 36 */
7
+ nodeHeight?: number;
8
+ /** Edge style — straight polyline through waypoints, or smoothed bezier. @default "polyline" */
9
+ edgeStyle?: "polyline" | "smooth";
10
+ /** Render text labels at node centers. @default true */
11
+ showLabels?: boolean;
12
+ /** Field name (or function) yielding the label string per node. @default "label" */
13
+ labelAccessor?: string | ((d: Datum) => string);
14
+ /** Per-node fill style override. */
15
+ nodeFill?: string;
16
+ /** Stroke for edges. */
17
+ edgeStroke?: string;
18
+ }
19
+ /**
20
+ * Dagre layout recipe — renders a pre-positioned directed acyclic graph
21
+ * (e.g. output of `dagre`).
22
+ *
23
+ * The user runs `dagre.layout(g)` themselves and flattens the result into
24
+ * `nodes` (each with `x`, `y`, `width`, `height`, `label`) and `edges`
25
+ * (each with `source`, `target`, optional `points` waypoint array). The
26
+ * recipe handles scene emission only.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import dagre from "dagre"
31
+ * import { dagreLayout } from "semiotic/recipes"
32
+ *
33
+ * const g = new dagre.graphlib.Graph()
34
+ * g.setGraph({ rankdir: "TB" })
35
+ * g.setDefaultEdgeLabel(() => ({}))
36
+ * for (const n of myNodes) g.setNode(n.id, { width: 120, height: 40, label: n.label })
37
+ * for (const e of myEdges) g.setEdge(e.source, e.target)
38
+ * dagre.layout(g)
39
+ *
40
+ * const nodes = g.nodes().map((id) => {
41
+ * const n = g.node(id)
42
+ * return { id, x: n.x, y: n.y, width: n.width, height: n.height, label: n.label }
43
+ * })
44
+ * const edges = g.edges().map((e) => {
45
+ * const ed = g.edge(e)
46
+ * return { source: e.v, target: e.w, points: ed.points }
47
+ * })
48
+ *
49
+ * <StreamNetworkFrame
50
+ * chartType="force"
51
+ * nodes={nodes} edges={edges}
52
+ * customNetworkLayout={dagreLayout}
53
+ * />
54
+ * ```
55
+ */
56
+ export declare const dagreLayout: NetworkCustomLayout<DagreConfig>;
@@ -0,0 +1,55 @@
1
+ import type { NetworkCustomLayout } from "../stream/networkCustomLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface FlextreeConfig {
4
+ /** Default node width when nodes don't carry a `width` field. @default 80 */
5
+ nodeWidth?: number;
6
+ /** Default node height when nodes don't carry a `height` field. @default 30 */
7
+ nodeHeight?: number;
8
+ /** Edge style — curved (cubic-bezier path) or straight lines. @default "curved" */
9
+ edgeCurve?: "line" | "curved";
10
+ /** Tree orientation. Affects bezier control-point placement. @default "vertical" */
11
+ orientation?: "vertical" | "horizontal";
12
+ /** Render text labels at node centers. @default true */
13
+ showLabels?: boolean;
14
+ /** Field name (or function) yielding the label string per node. @default "id" */
15
+ labelAccessor?: string | ((d: Datum) => string);
16
+ /** Per-node fill style override. */
17
+ nodeFill?: string;
18
+ }
19
+ /**
20
+ * Flextree layout recipe — renders a pre-positioned variable-width tree
21
+ * (e.g. output of `d3-flextree`).
22
+ *
23
+ * The user runs `d3-flextree` themselves and passes the laid-out nodes
24
+ * as data. Each node should carry `x`, `y`, optional `width`/`height`.
25
+ * Edges should be parent → child links (no waypoints needed).
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import flextree from "d3-flextree"
30
+ * import { flextreeLayout } from "semiotic/recipes"
31
+ *
32
+ * const layout = flextree({ nodeSize: (n) => [n.data.size, 40] })
33
+ * const tree = layout.hierarchy(rootData)
34
+ * layout(tree)
35
+ *
36
+ * const nodes = tree.descendants().map((n) => ({
37
+ * id: n.data.id,
38
+ * x: n.x, y: n.y,
39
+ * width: n.size[0], height: n.size[1],
40
+ * label: n.data.name,
41
+ * }))
42
+ * const edges = tree.links().map((l) => ({
43
+ * source: l.source.data.id,
44
+ * target: l.target.data.id,
45
+ * }))
46
+ *
47
+ * <StreamNetworkFrame
48
+ * chartType="force"
49
+ * nodes={nodes} edges={edges}
50
+ * customNetworkLayout={flextreeLayout}
51
+ * layoutConfig={{ orientation: "vertical" }}
52
+ * />
53
+ * ```
54
+ */
55
+ export declare const flextreeLayout: NetworkCustomLayout<FlextreeConfig>;
@@ -0,0 +1,55 @@
1
+ import type { OrdinalCustomLayout } from "../stream/ordinalCustomLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface MarimekkoConfig {
4
+ /** Field (or function) yielding the category for each datum. Categories become x-axis bars. */
5
+ categoryAccessor: string | ((d: Datum) => string);
6
+ /** Field (or function) yielding the value (segment height contribution). */
7
+ valueAccessor: string | ((d: Datum) => number);
8
+ /** Field (or function) yielding the stack key — segments inside each bar. */
9
+ stackBy: string | ((d: Datum) => string);
10
+ /** Pixel gap between adjacent category bars. @default 2 */
11
+ gutter?: number;
12
+ /** Optional explicit category order. If omitted, uses data insertion order. */
13
+ categoryOrder?: string[];
14
+ /** Optional explicit stack order. If omitted, uses insertion order. */
15
+ stackOrder?: string[];
16
+ /**
17
+ * Render category labels under each bar via SVG overlays. The default
18
+ * ordinal axis can't position labels under variable-width bars (it
19
+ * assumes a uniform band scale), so the recipe handles label
20
+ * placement itself. @default true
21
+ */
22
+ showCategoryLabels?: boolean;
23
+ /**
24
+ * Pixel-padding reserved beneath the bars for labels. Subtracted from
25
+ * the plot height when laying out the bars. @default 22 when labels
26
+ * are shown, 0 otherwise.
27
+ */
28
+ labelPadding?: number;
29
+ }
30
+ /**
31
+ * Marimekko (mosaic) chart — variable-width stacked bars where each bar's
32
+ * width encodes its category's contribution to the grand total, and the
33
+ * inner stacked segments encode the within-category breakdown by
34
+ * `stackBy`. Both dimensions are proportional, making it the natural pick
35
+ * for cohort revenue analysis, market share by segment × product, etc.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * import { OrdinalCustomChart } from "semiotic/ordinal"
40
+ * import { marimekkoLayout } from "semiotic/recipes"
41
+ *
42
+ * <OrdinalCustomChart
43
+ * data={salesByRegionAndProduct}
44
+ * layout={marimekkoLayout}
45
+ * layoutConfig={{
46
+ * categoryAccessor: "region",
47
+ * stackBy: "product",
48
+ * valueAccessor: "revenue",
49
+ * }}
50
+ * width={700}
51
+ * height={400}
52
+ * />
53
+ * ```
54
+ */
55
+ export declare const marimekkoLayout: OrdinalCustomLayout<MarimekkoConfig>;
@@ -0,0 +1,97 @@
1
+ import type { OrdinalCustomLayout } from "../stream/ordinalCustomLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface ParallelCoordinatesConfig {
4
+ /**
5
+ * Field names (in order) defining the axes. Each field must yield a
6
+ * numeric value per datum. The leftmost field is axis 0.
7
+ */
8
+ fields: string[];
9
+ /**
10
+ * Field (or function) yielding a category per datum used for line
11
+ * coloring. If omitted, all lines render in the theme primary color.
12
+ */
13
+ colorBy?: string | ((d: Datum) => string);
14
+ /**
15
+ * Optional per-field [min, max] domains. If omitted, computed from
16
+ * data per field. Useful for locking axes when streaming.
17
+ */
18
+ domains?: Record<string, [number, number]>;
19
+ /** Line opacity. Lower for many overlapping rows. @default 0.45 */
20
+ opacity?: number;
21
+ /** Line stroke width in px. @default 1.25 */
22
+ strokeWidth?: number;
23
+ /**
24
+ * Render small dots at each row's value on each axis. @default false
25
+ * (recommended for low-cardinality data only — gets noisy with 100+ rows).
26
+ */
27
+ showPoints?: boolean;
28
+ /**
29
+ * Render axis chrome — vertical axis lines, top labels (the field
30
+ * name), and 5 tick marks per axis showing the domain range. Each
31
+ * axis is independently scaled, so each gets its own ticks. @default
32
+ * true
33
+ */
34
+ showAxes?: boolean;
35
+ /**
36
+ * Pixel padding reserved at the **top** of the plot for axis field-name
37
+ * labels. Used only when `showAxes` is `true`. Subtracted from the line
38
+ * drawing area along with bottom padding. @default 24
39
+ *
40
+ * The recipe also reserves bottom padding for tick numbers — 18px when
41
+ * `showAxes` is true, 8px when it's false. That bottom value is fixed;
42
+ * use a smaller chart `margin.bottom` if you need tighter packing.
43
+ * Top padding when `showAxes` is false is also a fixed 8px (so polyline
44
+ * endpoints don't hug the chart edge).
45
+ */
46
+ axisLabelPadding?: number;
47
+ /**
48
+ * Optional per-field tick formatter map. Falls back to
49
+ * `v.toLocaleString()` for fields without explicit formatters.
50
+ */
51
+ tickFormat?: Record<string, (v: number) => string>;
52
+ /**
53
+ * Predicate that decides which rows render at full opacity. Rows where
54
+ * `highlightFn(d) === false` render at `dimmedOpacity` instead, with
55
+ * the matching rows z-ordered on top so they don't get covered by
56
+ * neighbors. Recipes are pure functions so they can't own brush state
57
+ * themselves — wire this from a parent component that manages the
58
+ * selection (hover, brush, search query, etc.). Leave undefined for
59
+ * uniform opacity.
60
+ *
61
+ * Roadmap: a future `<ParallelCoordinatesBrushes>` overlay component
62
+ * will manage drag-to-brush state and feed this hook automatically;
63
+ * `useBrushSelection` will carry per-field range constraints across
64
+ * linked charts. This prop is the integration point both will use.
65
+ */
66
+ highlightFn?: (d: Datum) => boolean;
67
+ /** Stroke opacity for non-matching rows when `highlightFn` is set. @default 0.08 */
68
+ dimmedOpacity?: number;
69
+ }
70
+ /**
71
+ * Parallel coordinates — one polyline per row, traced across N parallel
72
+ * vertical axes. Each axis represents a numeric field with its own
73
+ * independent linear scale, so columns in different units can sit
74
+ * side-by-side without normalizing.
75
+ *
76
+ * Useful for high-dimensional pattern hunting: clusters of similar rows,
77
+ * outliers that "swing wildly" between axes, and inverse correlations
78
+ * (lines crossing).
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * import { OrdinalCustomChart } from "semiotic/ordinal"
83
+ * import { parallelCoordinatesLayout } from "semiotic/recipes"
84
+ *
85
+ * <OrdinalCustomChart
86
+ * data={cars}
87
+ * layout={parallelCoordinatesLayout}
88
+ * layoutConfig={{
89
+ * fields: ["mpg", "displacement", "horsepower", "weight", "acceleration"],
90
+ * colorBy: "origin",
91
+ * }}
92
+ * width={800}
93
+ * height={400}
94
+ * />
95
+ * ```
96
+ */
97
+ export declare const parallelCoordinatesLayout: OrdinalCustomLayout<ParallelCoordinatesConfig>;
@@ -0,0 +1,27 @@
1
+ import type { Datum } from "../charts/shared/datumTypes";
2
+ /**
3
+ * Normalize a string-or-function accessor into a function. Recipes
4
+ * consistently accept either form, so this collapses the type-check at
5
+ * the boundary and lets the layout body call a single function.
6
+ */
7
+ export declare function resolveAccessor<T = unknown>(a: string | ((d: Datum) => T)): (d: Datum) => T;
8
+ /**
9
+ * Build a datum object whose own-properties are safe to set from
10
+ * user-supplied accessor names. `Object.create(null)` produces a
11
+ * prototype-less object so adversarial keys like `__proto__`,
12
+ * `constructor`, or `prototype` become normal own-properties instead of
13
+ * invoking the prototype setter on a normal object literal (which
14
+ * silently drops the assignment).
15
+ *
16
+ * The builder takes a callback that receives a `set(key, value)` writer
17
+ * bound to the null-prototype object. This API forces every assignment
18
+ * through the safe target — passing a plain `Record<string, unknown>`
19
+ * instead would be unsafe, since constructing that intermediate via an
20
+ * object literal lets `__proto__` hit the setter before we ever reach
21
+ * the helper.
22
+ *
23
+ * Recipes funnel every datum-emit through this helper so the
24
+ * prototype-pollution invariant is enforced in one place rather than
25
+ * scattered across each recipe's inner loops.
26
+ */
27
+ export declare function createSafeDatum(populate: (set: (key: string, value: unknown) => void) => void): Datum;
@@ -0,0 +1,46 @@
1
+ import type { CustomLayout } from "../stream/customLayout";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ export interface WaffleConfig {
4
+ /** Number of rows in the grid. @default 10 */
5
+ rows?: number;
6
+ /** Number of columns in the grid. @default 10 */
7
+ columns?: number;
8
+ /** Pixel gap between cells. @default 2 */
9
+ gutter?: number;
10
+ /** Field name (or function) yielding the category for each datum. */
11
+ categoryAccessor?: string | ((d: Datum) => string);
12
+ /** Field name (or function) yielding the cell count per datum. If omitted, each datum counts as 1. */
13
+ valueAccessor?: string | ((d: Datum) => number);
14
+ /**
15
+ * Optional ordering hint. Categories listed here render first, in the
16
+ * order given (duplicates removed). Categories present in the data but
17
+ * not in this list follow in insertion order. Categories listed here
18
+ * but absent from the data are silently skipped.
19
+ */
20
+ categoryOrder?: string[];
21
+ }
22
+ /**
23
+ * Waffle chart — a grid of cells where each cell represents one share of the
24
+ * total. Categories are filled in row-major order, scaled so the count of
25
+ * cells per category is proportional to its value (rounded to nearest cell).
26
+ *
27
+ * Layouts that don't drive scales (waffle, calendar) ignore them — the grid
28
+ * is sized to the plot rect directly.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * import { XYCustomChart } from "semiotic/xy"
33
+ * import { waffleLayout } from "semiotic/recipes"
34
+ *
35
+ * <XYCustomChart
36
+ * data={[
37
+ * { region: "AMER", value: 42 },
38
+ * { region: "EMEA", value: 33 },
39
+ * { region: "APAC", value: 25 },
40
+ * ]}
41
+ * layout={waffleLayout}
42
+ * layoutConfig={{ rows: 10, columns: 10, categoryAccessor: "region", valueAccessor: "value" }}
43
+ * />
44
+ * ```
45
+ */
46
+ export declare const waffleLayout: CustomLayout<WaffleConfig>;
@@ -6,8 +6,10 @@ export { ConnectedScatterplot } from "./charts/xy/ConnectedScatterplot";
6
6
  export { BubbleChart } from "./charts/xy/BubbleChart";
7
7
  export { Heatmap } from "./charts/xy/Heatmap";
8
8
  export { ScatterplotMatrix } from "./charts/xy/ScatterplotMatrix";
9
+ export { MinimapChart } from "./charts/xy/MinimapChart";
9
10
  export { QuadrantChart } from "./charts/xy/QuadrantChart";
10
11
  export { MultiAxisLineChart } from "./charts/xy/MultiAxisLineChart";
12
+ export { CandlestickChart } from "./charts/xy/CandlestickChart";
11
13
  export { LinkedCharts } from "./LinkedCharts";
12
14
  export { useSelection, useLinkedHover, useBrushSelection, useFilteredData } from "./LinkedCharts";
13
15
  export { BarChart } from "./charts/ordinal/BarChart";
@@ -21,8 +23,10 @@ export { DotPlot } from "./charts/ordinal/DotPlot";
21
23
  export { RidgelinePlot } from "./charts/ordinal/RidgelinePlot";
22
24
  export { PieChart } from "./charts/ordinal/PieChart";
23
25
  export { DonutChart } from "./charts/ordinal/DonutChart";
26
+ export { GaugeChart } from "./charts/ordinal/GaugeChart";
24
27
  export { FunnelChart } from "./charts/ordinal/FunnelChart";
25
28
  export { LikertChart } from "./charts/ordinal/LikertChart";
29
+ export { SwimlaneChart } from "./charts/ordinal/SwimlaneChart";
26
30
  export { ForceDirectedGraph } from "./charts/network/ForceDirectedGraph";
27
31
  export { ChordDiagram } from "./charts/network/ChordDiagram";
28
32
  export { SankeyDiagram } from "./charts/network/SankeyDiagram";
@@ -11,6 +11,7 @@ export { TreeDiagram } from "./charts/network/TreeDiagram";
11
11
  export { Treemap } from "./charts/network/Treemap";
12
12
  export { CirclePack } from "./charts/network/CirclePack";
13
13
  export { OrbitDiagram } from "./charts/network/OrbitDiagram";
14
+ export { NetworkCustomChart } from "./charts/custom/NetworkCustomChart";
14
15
  export type { StreamNetworkFrameProps, StreamNetworkFrameHandle, NetworkChartType, NetworkSceneNode, NetworkSceneEdge, NetworkLabel, ThresholdAlertConfig } from "./stream/networkTypes";
15
16
  export type { ForceDirectedGraphProps } from "./charts/network/ForceDirectedGraph";
16
17
  export type { SankeyDiagramProps } from "./charts/network/SankeyDiagram";
@@ -19,3 +20,5 @@ export type { TreeDiagramProps } from "./charts/network/TreeDiagram";
19
20
  export type { TreemapProps } from "./charts/network/Treemap";
20
21
  export type { CirclePackProps } from "./charts/network/CirclePack";
21
22
  export type { OrbitDiagramProps } from "./charts/network/OrbitDiagram";
23
+ export type { NetworkCustomChartProps } from "./charts/custom/NetworkCustomChart";
24
+ export type { NetworkCustomLayout, NetworkLayoutContext, NetworkLayoutResult, } from "./stream/networkCustomLayout";
@@ -20,6 +20,7 @@ export type { GaugeChartProps, GaugeThreshold } from "./charts/ordinal/GaugeChar
20
20
  export { RidgelinePlot } from "./charts/ordinal/RidgelinePlot";
21
21
  export { FunnelChart } from "./charts/ordinal/FunnelChart";
22
22
  export { LikertChart } from "./charts/ordinal/LikertChart";
23
+ export { OrdinalCustomChart } from "./charts/custom/OrdinalCustomChart";
23
24
  export { createHatchPattern } from "./charts/shared/hatchPattern";
24
25
  export type { HatchPatternOptions } from "./charts/shared/hatchPattern";
25
26
  export type { StreamOrdinalFrameProps, StreamOrdinalFrameHandle, OrdinalChartType, OrdinalScales, OrdinalSceneNode } from "./stream/ordinalTypes";
@@ -31,3 +32,5 @@ export type { PieChartProps } from "./charts/ordinal/PieChart";
31
32
  export type { DonutChartProps } from "./charts/ordinal/DonutChart";
32
33
  export type { FunnelChartProps } from "./charts/ordinal/FunnelChart";
33
34
  export type { LikertChartProps } from "./charts/ordinal/LikertChart";
35
+ export type { OrdinalCustomChartProps } from "./charts/custom/OrdinalCustomChart";
36
+ export type { OrdinalCustomLayout, OrdinalLayoutContext, OrdinalLayoutResult, } from "./stream/ordinalCustomLayout";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Recipes entry point — curated layout functions for use with `XYCustomChart`.
3
+ *
4
+ * Import from "semiotic/recipes" instead of the full bundle. Recipes are
5
+ * pure CustomLayout functions that emit standard SceneNodes; they get hit
6
+ * testing, transitions, decay, theme cascade, and SSR for free.
7
+ */
8
+ export { waffleLayout } from "./recipes/waffle";
9
+ export type { WaffleConfig } from "./recipes/waffle";
10
+ export { calendarLayout } from "./recipes/calendar";
11
+ export type { CalendarConfig } from "./recipes/calendar";
12
+ export { flextreeLayout } from "./recipes/flextree";
13
+ export type { FlextreeConfig } from "./recipes/flextree";
14
+ export { dagreLayout } from "./recipes/dagre";
15
+ export type { DagreConfig } from "./recipes/dagre";
16
+ export { marimekkoLayout } from "./recipes/marimekko";
17
+ export type { MarimekkoConfig } from "./recipes/marimekko";
18
+ export { bulletLayout } from "./recipes/bullet";
19
+ export type { BulletConfig } from "./recipes/bullet";
20
+ export { parallelCoordinatesLayout } from "./recipes/parallelCoordinates";
21
+ export type { ParallelCoordinatesConfig } from "./recipes/parallelCoordinates";
22
+ export type { CustomLayout, LayoutContext, LayoutResult, } from "./stream/customLayout";
23
+ export type { NetworkCustomLayout, NetworkLayoutContext, NetworkLayoutResult, } from "./stream/networkCustomLayout";
24
+ export type { OrdinalCustomLayout, OrdinalLayoutContext, OrdinalLayoutResult, } from "./stream/ordinalCustomLayout";
@@ -16,7 +16,9 @@ export { MinimapChart } from "./charts/xy/MinimapChart";
16
16
  export { QuadrantChart } from "./charts/xy/QuadrantChart";
17
17
  export { MultiAxisLineChart } from "./charts/xy/MultiAxisLineChart";
18
18
  export { CandlestickChart } from "./charts/xy/CandlestickChart";
19
+ export { XYCustomChart } from "./charts/custom/XYCustomChart";
19
20
  export type { StreamXYFrameProps, StreamXYFrameHandle } from "./stream/types";
21
+ export type { CustomLayout, LayoutContext, LayoutResult } from "./stream/customLayout";
20
22
  export type { LineChartProps } from "./charts/xy/LineChart";
21
23
  export type { AreaChartProps } from "./charts/xy/AreaChart";
22
24
  export type { StackedAreaChartProps } from "./charts/xy/StackedAreaChart";
@@ -27,3 +29,4 @@ export type { HeatmapProps } from "./charts/xy/Heatmap";
27
29
  export type { QuadrantChartProps } from "./charts/xy/QuadrantChart";
28
30
  export type { MultiAxisLineChartProps } from "./charts/xy/MultiAxisLineChart";
29
31
  export type { CandlestickChartProps } from "./charts/xy/CandlestickChart";
32
+ export type { XYCustomChartProps } from "./charts/custom/XYCustomChart";