semiotic 3.1.1 → 3.2.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 (83) hide show
  1. package/CLAUDE.md +134 -216
  2. package/LICENSE +197 -10
  3. package/README.md +1 -0
  4. package/ai/dist/componentRegistry.js +6 -0
  5. package/ai/dist/mcp-server.js +232 -65
  6. package/ai/dist/renderHOCToSVG.js +5 -3
  7. package/ai/examples.md +93 -0
  8. package/ai/schema.json +3916 -878
  9. package/ai/system-prompt.md +27 -0
  10. package/dist/components/ThemeProvider.d.ts +5 -3
  11. package/dist/components/charts/geo/ChoroplethMap.d.ts +1 -1
  12. package/dist/components/charts/index.d.ts +8 -1
  13. package/dist/components/charts/ordinal/BarChart.d.ts +1 -0
  14. package/dist/components/charts/ordinal/BoxPlot.d.ts +1 -0
  15. package/dist/components/charts/ordinal/DonutChart.d.ts +1 -0
  16. package/dist/components/charts/ordinal/DotPlot.d.ts +1 -0
  17. package/dist/components/charts/ordinal/FunnelChart.d.ts +55 -0
  18. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +1 -0
  19. package/dist/components/charts/ordinal/Histogram.d.ts +1 -0
  20. package/dist/components/charts/ordinal/PieChart.d.ts +1 -0
  21. package/dist/components/charts/ordinal/RidgelinePlot.d.ts +1 -0
  22. package/dist/components/charts/ordinal/StackedBarChart.d.ts +1 -0
  23. package/dist/components/charts/ordinal/SwarmPlot.d.ts +1 -0
  24. package/dist/components/charts/ordinal/ViolinPlot.d.ts +1 -0
  25. package/dist/components/charts/shared/colorManipulation.d.ts +15 -0
  26. package/dist/components/charts/shared/formatUtils.d.ts +28 -0
  27. package/dist/components/charts/shared/hatchPattern.d.ts +35 -0
  28. package/dist/components/charts/shared/hooks.d.ts +16 -1
  29. package/dist/components/charts/shared/legendUtils.d.ts +2 -1
  30. package/dist/components/charts/shared/selectionUtils.d.ts +11 -0
  31. package/dist/components/charts/shared/statisticalOverlays.d.ts +49 -5
  32. package/dist/components/charts/shared/types.d.ts +4 -1
  33. package/dist/components/charts/xy/Heatmap.d.ts +1 -1
  34. package/dist/components/charts/xy/MultiAxisLineChart.d.ts +71 -0
  35. package/dist/components/realtime/types.d.ts +2 -0
  36. package/dist/components/semiotic-ai.d.ts +3 -0
  37. package/dist/components/semiotic-ordinal.d.ts +3 -0
  38. package/dist/components/semiotic-themes.d.ts +64 -0
  39. package/dist/components/semiotic-xy.d.ts +1 -0
  40. package/dist/components/semiotic.d.ts +11 -5
  41. package/dist/components/store/ThemeStore.d.ts +22 -2
  42. package/dist/components/stream/OrdinalSVGOverlay.d.ts +1 -0
  43. package/dist/components/stream/PipelineStore.d.ts +2 -0
  44. package/dist/components/stream/SVGOverlay.d.ts +5 -3
  45. package/dist/components/stream/accessorUtils.d.ts +14 -0
  46. package/dist/components/stream/networkTypes.d.ts +2 -0
  47. package/dist/components/stream/ordinalSceneBuilders/barFunnelScene.d.ts +27 -0
  48. package/dist/components/stream/ordinalSceneBuilders/funnelScene.d.ts +26 -0
  49. package/dist/components/stream/ordinalTypes.d.ts +16 -2
  50. package/dist/components/stream/renderers/barFunnelCanvasRenderer.d.ts +12 -0
  51. package/dist/components/stream/renderers/trapezoidCanvasRenderer.d.ts +15 -0
  52. package/dist/components/stream/sceneUtils.d.ts +10 -0
  53. package/dist/components/stream/types.d.ts +10 -3
  54. package/dist/geo.min.js +1 -1
  55. package/dist/geo.module.min.js +1 -1
  56. package/dist/network.min.js +1 -1
  57. package/dist/network.module.min.js +1 -1
  58. package/dist/ordinal.min.js +1 -1
  59. package/dist/ordinal.module.min.js +1 -1
  60. package/dist/realtime.min.js +1 -1
  61. package/dist/realtime.module.min.js +1 -1
  62. package/dist/semiotic-ai-statisticalOverlays-C2PPlmXv.js +1 -0
  63. package/dist/semiotic-ai.d.ts +3 -0
  64. package/dist/semiotic-ai.min.js +1 -1
  65. package/dist/semiotic-ai.module.min.js +1 -1
  66. package/dist/semiotic-ordinal.d.ts +3 -0
  67. package/dist/semiotic-statisticalOverlays-D8LhSbQt.js +1 -0
  68. package/dist/semiotic-themes.d.ts +64 -0
  69. package/dist/semiotic-themes.min.js +1 -0
  70. package/dist/semiotic-themes.module.min.js +1 -0
  71. package/dist/semiotic-xy.d.ts +1 -0
  72. package/dist/semiotic.d.ts +11 -5
  73. package/dist/semiotic.min.js +1 -1
  74. package/dist/semiotic.module.min.js +1 -1
  75. package/dist/server.min.js +1 -1
  76. package/dist/server.module.min.js +1 -1
  77. package/dist/xy-statisticalOverlays-C2PPlmXv.js +1 -0
  78. package/dist/xy.min.js +1 -1
  79. package/dist/xy.module.min.js +1 -1
  80. package/package.json +24 -5
  81. package/dist/semiotic-ai-statisticalOverlays-C1f7TYyD.js +0 -1
  82. package/dist/semiotic-statisticalOverlays-C1f7TYyD.js +0 -1
  83. package/dist/xy-statisticalOverlays-C1f7TYyD.js +0 -1
@@ -76,6 +76,33 @@ Callback receiving `ChartObservation`: `{ type: "hover"|"click"|"brush"|"selecti
76
76
  ### emphasis
77
77
  `emphasis="primary"` makes a chart span two columns inside a `ChartGrid`.
78
78
 
79
+ ## Annotations (XY charts)
80
+ - `annotations={[{ type: "y-threshold", value: 200, label: "SLA limit", color: "#e45050" }]}` — horizontal reference line
81
+ - `annotations={[{ type: "x-threshold", value: 50, label: "Cutoff" }]}` — vertical reference line
82
+ - `annotations={[{ type: "widget", time: 42, latency: 850, dy: -10, content: <span>Alert</span> }]}` — place React element at data coordinates
83
+ - `annotations={[{ type: "enclose", coordinates: [datum1, datum2], label: "Cluster" }]}` — circle enclosing data points
84
+
85
+ ## Theming & Brand Styling
86
+ All charts respond to CSS custom properties on any ancestor:
87
+ ```css
88
+ .my-theme {
89
+ --semiotic-bg: #1a1a2e; /* chart background */
90
+ --semiotic-text: #ededed; /* primary text */
91
+ --semiotic-text-secondary: #aaa; /* tick labels */
92
+ --semiotic-grid: #333; /* grid lines */
93
+ --semiotic-border: #555; /* axis lines */
94
+ --semiotic-font-family: Georgia, serif;
95
+ --semiotic-tooltip-bg: #1a1a2e;
96
+ --semiotic-tooltip-text: #ededed;
97
+ --semiotic-tooltip-radius: 8px;
98
+ }
99
+ ```
100
+ Or use ThemeProvider with 15 named presets: `<ThemeProvider theme="tufte">`, `"tufte-dark"`, `"pastels"`, `"bi-tool"`, `"italian"`, `"journalist"`, `"playful"` (each with `-dark` variant), `"dark"`, `"high-contrast"`.
101
+
102
+ `semiotic/themes` entry point: `themeToCSS(theme, selector)` generates CSS string, `themeToTokens(theme)` generates DTCG design tokens, `resolveThemePreset("tufte")` returns theme object by name. Theme objects: `TUFTE_LIGHT`, `TUFTE_DARK`, `PASTELS_LIGHT`, `BI_TOOL_LIGHT`, `ITALIAN_LIGHT`, `JOURNALIST_LIGHT`, `PLAYFUL_LIGHT`, etc.
103
+
104
+ `COLOR_BLIND_SAFE_CATEGORICAL` — 8-color accessible palette (Wong 2011). Import from `semiotic`.
105
+
79
106
  ## Key Patterns
80
107
  - **Percentile band + main line**: Layer `<AreaChart yAccessor="p95" y0Accessor="p5" showLine={false} />` + `<LineChart yAccessor="p50" />`. AreaChart's `showLine` only draws the top edge, NOT a separate main line.
81
108
  - **SSR**: `renderToStaticSVG("ordinal", props)` or `renderOrdinalToStaticSVG(props)` from `semiotic/server`. Frame type is `"xy"` | `"ordinal"` | `"network"` (NOT component name).
@@ -1,12 +1,14 @@
1
1
  import * as React from "react";
2
- import { LIGHT_THEME, DARK_THEME } from "./store/ThemeStore";
2
+ import { LIGHT_THEME, DARK_THEME, HIGH_CONTRAST_THEME } from "./store/ThemeStore";
3
3
  import type { SemioticTheme } from "./store/ThemeStore";
4
+ import type { ThemePresetName } from "./semiotic-themes";
4
5
  interface ThemeProviderProps {
5
- theme?: "light" | "dark" | Partial<SemioticTheme>;
6
+ /** Theme preset name (e.g. "tufte", "pastels-dark", "bi-tool") or a partial SemioticTheme object. */
7
+ theme?: ThemePresetName | Partial<SemioticTheme>;
6
8
  children: React.ReactNode;
7
9
  }
8
10
  declare function ThemeProviderWrapper({ theme, children }: ThemeProviderProps): React.JSX.Element;
9
11
  declare function useTheme(): SemioticTheme;
10
12
  export { ThemeProviderWrapper as ThemeProvider, useTheme };
11
- export { LIGHT_THEME, DARK_THEME };
13
+ export { LIGHT_THEME, DARK_THEME, HIGH_CONTRAST_THEME };
12
14
  export type { SemioticTheme };
@@ -47,7 +47,7 @@ export interface ChoroplethMapProps<TDatum extends Record<string, any> = Record<
47
47
  /** Passthrough to StreamGeoFrame */
48
48
  frameProps?: Partial<Omit<StreamGeoFrameProps, "areas" | "projection">>;
49
49
  }
50
- export declare function ChoroplethMap<TDatum extends Record<string, any> = Record<string, any>>(props: ChoroplethMapProps<TDatum>): React.JSX.Element | null;
50
+ export declare function ChoroplethMap<TDatum extends Record<string, any> = Record<string, any>>(props: ChoroplethMapProps<TDatum>): React.JSX.Element;
51
51
  export declare namespace ChoroplethMap {
52
52
  var displayName: string;
53
53
  }
@@ -26,6 +26,8 @@ export { MinimapChart } from "./xy/MinimapChart";
26
26
  export type { MinimapChartProps, MinimapConfig } from "./xy/MinimapChart";
27
27
  export { QuadrantChart } from "./xy/QuadrantChart";
28
28
  export type { QuadrantChartProps, QuadrantsConfig, QuadrantConfig, CenterlineStyle } from "./xy/QuadrantChart";
29
+ export { MultiAxisLineChart } from "./xy/MultiAxisLineChart";
30
+ export type { MultiAxisLineChartProps, MultiAxisSeriesConfig } from "./xy/MultiAxisLineChart";
29
31
  export { BarChart } from "./ordinal/BarChart";
30
32
  export type { BarChartProps } from "./ordinal/BarChart";
31
33
  export { StackedBarChart } from "./ordinal/StackedBarChart";
@@ -40,6 +42,8 @@ export { ViolinPlot } from "./ordinal/ViolinPlot";
40
42
  export type { ViolinPlotProps } from "./ordinal/ViolinPlot";
41
43
  export { RidgelinePlot } from "./ordinal/RidgelinePlot";
42
44
  export type { RidgelinePlotProps } from "./ordinal/RidgelinePlot";
45
+ export { FunnelChart } from "./ordinal/FunnelChart";
46
+ export type { FunnelChartProps } from "./ordinal/FunnelChart";
43
47
  export { DotPlot } from "./ordinal/DotPlot";
44
48
  export type { DotPlotProps } from "./ordinal/DotPlot";
45
49
  export { PieChart } from "./ordinal/PieChart";
@@ -75,6 +79,9 @@ export type { RealtimeHeatmapProps } from "./realtime/RealtimeHeatmap";
75
79
  export type { BaseChartProps, AxisConfig, Accessor, ChartAccessor, ChartMode } from "./shared/types";
76
80
  export { useColorScale, useSortedData, DEFAULT_COLOR } from "./shared/hooks";
77
81
  export { COLOR_SCHEMES, DEFAULT_COLORS, getColor, createColorScale, getSize } from "./shared/colorUtils";
78
- export { formatNumber, formatDate, formatAxis, createTooltip, formatLargeNumber, truncateText } from "./shared/formatUtils";
82
+ export { formatNumber, formatDate, formatAxis, createTooltip, formatLargeNumber, truncateText, adaptiveTimeTicks } from "./shared/formatUtils";
83
+ export { darkenColor, lightenColor } from "./shared/colorManipulation";
79
84
  export { Tooltip, MultiLineTooltip, normalizeTooltip } from "../Tooltip/Tooltip";
80
85
  export type { TooltipProp, TooltipConfig, TooltipField, MultiLineTooltipConfig } from "../Tooltip/Tooltip";
86
+ export { createHatchPattern } from "./shared/hatchPattern";
87
+ export type { HatchPatternOptions } from "./shared/hatchPattern";
@@ -21,6 +21,7 @@ export interface BarChartProps<TDatum extends Record<string, any> = Record<strin
21
21
  barPadding?: number;
22
22
  enableHover?: boolean;
23
23
  showGrid?: boolean;
24
+ showCategoryTicks?: boolean;
24
25
  showLegend?: boolean;
25
26
  legendInteraction?: LegendInteractionMode;
26
27
  legendPosition?: "right" | "left" | "top" | "bottom";
@@ -19,6 +19,7 @@ export interface BoxPlotProps<TDatum extends Record<string, any> = Record<string
19
19
  categoryPadding?: number;
20
20
  enableHover?: boolean;
21
21
  showGrid?: boolean;
22
+ showCategoryTicks?: boolean;
22
23
  showLegend?: boolean;
23
24
  legendInteraction?: LegendInteractionMode;
24
25
  legendPosition?: LegendPosition;
@@ -15,6 +15,7 @@ export interface DonutChartProps<TDatum extends Record<string, any> = Record<str
15
15
  startAngle?: number;
16
16
  slicePadding?: number;
17
17
  enableHover?: boolean;
18
+ showCategoryTicks?: boolean;
18
19
  showLegend?: boolean;
19
20
  legendInteraction?: LegendInteractionMode;
20
21
  legendPosition?: LegendPosition;
@@ -19,6 +19,7 @@ export interface DotPlotProps<TDatum extends Record<string, any> = Record<string
19
19
  categoryPadding?: number;
20
20
  enableHover?: boolean;
21
21
  showGrid?: boolean;
22
+ showCategoryTicks?: boolean;
22
23
  showLegend?: boolean;
23
24
  legendInteraction?: LegendInteractionMode;
24
25
  legendPosition?: LegendPosition;
@@ -0,0 +1,55 @@
1
+ import * as React from "react";
2
+ import type { StreamOrdinalFrameProps } from "../../stream/ordinalTypes";
3
+ import type { LegendInteractionMode } from "../shared/hooks";
4
+ import type { BaseChartProps, ChartAccessor } from "../shared/types";
5
+ import { type TooltipProp } from "../../Tooltip/Tooltip";
6
+ import type { RealtimeFrameHandle } from "../../realtime/types";
7
+ /**
8
+ * FunnelChart component props
9
+ */
10
+ export interface FunnelChartProps<TDatum extends Record<string, any> = Record<string, any>> extends BaseChartProps {
11
+ data?: TDatum[];
12
+ /** Accessor for funnel step names (e.g., "Awareness", "Interest", "Purchase") */
13
+ stepAccessor?: ChartAccessor<TDatum, string>;
14
+ /** Accessor for the numeric value at each step */
15
+ valueAccessor?: ChartAccessor<TDatum, number>;
16
+ /** Accessor for splitting into mirrored categories (e.g., "control" vs "treatment") */
17
+ categoryAccessor?: ChartAccessor<TDatum, string>;
18
+ colorBy?: ChartAccessor<TDatum, string>;
19
+ colorScheme?: string | string[];
20
+ /**
21
+ * Funnel orientation.
22
+ *
23
+ * - `"horizontal"` (default): steps run top-to-bottom with centered bars and
24
+ * trapezoid connectors between steps.
25
+ * - `"vertical"`: steps on the x-axis as vertical bars. Each bar is stacked:
26
+ * solid = retained value, hatched = dropoff from the previous step.
27
+ * Multi-category data renders grouped bars within each step.
28
+ */
29
+ orientation?: "horizontal" | "vertical";
30
+ /** Opacity of the trapezoid connectors between steps (0–1, default 0.3). Horizontal only. */
31
+ connectorOpacity?: number;
32
+ /** Show step name + value labels on bars (default true) */
33
+ showLabels?: boolean;
34
+ enableHover?: boolean;
35
+ showLegend?: boolean;
36
+ legendInteraction?: LegendInteractionMode;
37
+ legendPosition?: "right" | "left" | "top" | "bottom";
38
+ tooltip?: TooltipProp;
39
+ annotations?: Record<string, any>[];
40
+ frameProps?: Partial<Omit<StreamOrdinalFrameProps, "data" | "size">>;
41
+ }
42
+ /**
43
+ * FunnelChart — Visualize sequential conversion steps.
44
+ *
45
+ * **Horizontal** (default): centered bars narrowing top-to-bottom with
46
+ * trapezoid connectors. Multi-category mirrors around center axis.
47
+ *
48
+ * **Vertical** (`orientation="vertical"`): vertical bars with hatched
49
+ * dropoff stacking. Each bar shows retained (solid) + dropoff from
50
+ * previous step (hatched). Multi-category renders grouped bars.
51
+ */
52
+ export declare const FunnelChart: {
53
+ <TDatum extends Record<string, any> = Record<string, any>>(props: FunnelChartProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
54
+ displayName?: string;
55
+ };
@@ -18,6 +18,7 @@ export interface GroupedBarChartProps<TDatum extends Record<string, any> = Recor
18
18
  barPadding?: number;
19
19
  enableHover?: boolean;
20
20
  showGrid?: boolean;
21
+ showCategoryTicks?: boolean;
21
22
  showLegend?: boolean;
22
23
  legendInteraction?: LegendInteractionMode;
23
24
  legendPosition?: "right" | "left" | "top" | "bottom";
@@ -18,6 +18,7 @@ export interface HistogramProps<TDatum extends Record<string, any> = Record<stri
18
18
  categoryPadding?: number;
19
19
  enableHover?: boolean;
20
20
  showGrid?: boolean;
21
+ showCategoryTicks?: boolean;
21
22
  showLegend?: boolean;
22
23
  legendPosition?: LegendPosition;
23
24
  tooltip?: TooltipProp;
@@ -13,6 +13,7 @@ export interface PieChartProps<TDatum extends Record<string, any> = Record<strin
13
13
  startAngle?: number;
14
14
  slicePadding?: number;
15
15
  enableHover?: boolean;
16
+ showCategoryTicks?: boolean;
16
17
  showLegend?: boolean;
17
18
  legendInteraction?: LegendInteractionMode;
18
19
  legendPosition?: LegendPosition;
@@ -19,6 +19,7 @@ export interface RidgelinePlotProps<TDatum extends Record<string, any> = Record<
19
19
  categoryPadding?: number;
20
20
  enableHover?: boolean;
21
21
  showGrid?: boolean;
22
+ showCategoryTicks?: boolean;
22
23
  showLegend?: boolean;
23
24
  legendPosition?: LegendPosition;
24
25
  tooltip?: TooltipProp;
@@ -19,6 +19,7 @@ export interface StackedBarChartProps<TDatum extends Record<string, any> = Recor
19
19
  barPadding?: number;
20
20
  enableHover?: boolean;
21
21
  showGrid?: boolean;
22
+ showCategoryTicks?: boolean;
22
23
  showLegend?: boolean;
23
24
  legendInteraction?: LegendInteractionMode;
24
25
  legendPosition?: "right" | "left" | "top" | "bottom";
@@ -21,6 +21,7 @@ export interface SwarmPlotProps<TDatum extends Record<string, any> = Record<stri
21
21
  categoryPadding?: number;
22
22
  enableHover?: boolean;
23
23
  showGrid?: boolean;
24
+ showCategoryTicks?: boolean;
24
25
  showLegend?: boolean;
25
26
  legendInteraction?: LegendInteractionMode;
26
27
  legendPosition?: LegendPosition;
@@ -20,6 +20,7 @@ export interface ViolinPlotProps<TDatum extends Record<string, any> = Record<str
20
20
  categoryPadding?: number;
21
21
  enableHover?: boolean;
22
22
  showGrid?: boolean;
23
+ showCategoryTicks?: boolean;
23
24
  showLegend?: boolean;
24
25
  legendPosition?: LegendPosition;
25
26
  tooltip?: TooltipProp;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Lightweight color manipulation helpers.
3
+ * Extracted from statisticalOverlays to avoid pulling the heavy module
4
+ * into the main barrel import graph.
5
+ */
6
+ /**
7
+ * Darken a CSS hex color by a factor (0–1). factor=0.5 darkens by 50%.
8
+ * Returns the original string unchanged if it's not a valid hex color.
9
+ */
10
+ export declare function darkenColor(hex: string, factor?: number): string;
11
+ /**
12
+ * Lighten a CSS hex color by a factor (0–1). factor=0.5 lightens by 50%.
13
+ * Returns the original string unchanged if it's not a valid hex color.
14
+ */
15
+ export declare function lightenColor(hex: string, factor?: number): string;
@@ -84,6 +84,33 @@ export declare function formatLargeNumber(value: number, decimals?: number): str
84
84
  * Used as the default axis tickFormat when no explicit format is provided.
85
85
  */
86
86
  export declare function smartTickFormat(value: any): string;
87
+ type TimeGranularity = "seconds" | "minutes" | "hours" | "days" | "months" | "years";
88
+ /**
89
+ * Creates a hierarchical time axis formatter.
90
+ *
91
+ * The first tick is fully qualified (e.g., "Mar 24, 2026 14:33:52").
92
+ * Subsequent ticks show only the significant unit change (e.g., ":53").
93
+ * When a time boundary is crossed (new minute, hour, day, etc.), the
94
+ * label re-qualifies up to that boundary (e.g., "14:34:00").
95
+ *
96
+ * Designed to be passed as `xFormat` on any Semiotic XY chart.
97
+ * Uses the extended `(value, index, allTicks)` signature.
98
+ *
99
+ * @param granularity - Optional explicit granularity. If omitted,
100
+ * auto-detected from the tick spacing on first call.
101
+ *
102
+ * @example
103
+ * ```tsx
104
+ * import { adaptiveTimeTicks } from "semiotic"
105
+ *
106
+ * // Auto-detect granularity from the data
107
+ * <LineChart data={ts} xFormat={adaptiveTimeTicks()} />
108
+ *
109
+ * // Explicit granularity
110
+ * <LineChart data={ts} xFormat={adaptiveTimeTicks("minutes")} />
111
+ * ```
112
+ */
113
+ export declare function adaptiveTimeTicks(granularity?: TimeGranularity): (value: any, index?: number, allTicks?: number[]) => string;
87
114
  /**
88
115
  * Truncates text to specified length with ellipsis
89
116
  *
@@ -92,3 +119,4 @@ export declare function smartTickFormat(value: any): string;
92
119
  * @returns Truncated text
93
120
  */
94
121
  export declare function truncateText(text: string, maxLength?: number): string;
122
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Create a diagonal-line hatch CanvasPattern for use as a fill style.
3
+ *
4
+ * Returns a CanvasPattern that can be passed as `fill` in any pieceStyle,
5
+ * nodeStyle, or edgeStyle function. Works with all canvas-rendered charts.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const hatch = createHatchPattern({ background: "#4e79a7", stroke: "#fff" })
10
+ * <BarChart
11
+ * pieceStyle={(d) => ({ fill: d.projected ? hatch : "#4e79a7" })}
12
+ * />
13
+ * ```
14
+ */
15
+ export interface HatchPatternOptions {
16
+ /** Background color of the pattern tile */
17
+ background?: string;
18
+ /** Color of the diagonal lines */
19
+ stroke?: string;
20
+ /** Width of the diagonal lines in pixels @default 1.5 */
21
+ lineWidth?: number;
22
+ /** Spacing between lines in pixels @default 6 */
23
+ spacing?: number;
24
+ /** Angle of the lines in degrees (0 = horizontal, 45 = diagonal) @default 45 */
25
+ angle?: number;
26
+ }
27
+ /**
28
+ * Create a repeating diagonal-line hatch pattern for canvas fills.
29
+ *
30
+ * Must be called in a browser environment (needs canvas). Returns null
31
+ * in server/test environments where canvas is unavailable.
32
+ */
33
+ export declare function createHatchPattern(options?: HatchPatternOptions,
34
+ /** Optional target canvas to create the pattern on (for correct DPR scaling) */
35
+ targetCtx?: CanvasRenderingContext2D): CanvasPattern | null;
@@ -8,6 +8,17 @@ import type { TransitionConfig } from "../../stream/types";
8
8
  * Default fill color used when no colorBy is specified
9
9
  */
10
10
  export declare const DEFAULT_COLOR = "#007bff";
11
+ /**
12
+ * Returns the theme's categorical palette, or undefined if no ThemeProvider or
13
+ * the palette is empty. Safe to call outside a ThemeProvider (returns undefined).
14
+ */
15
+ export declare function useThemeCategorical(): string[] | undefined;
16
+ /**
17
+ * Resolve the effective color for a data element when no colorBy is specified.
18
+ * Priority: color prop > theme categorical > colorScheme > DEFAULT_COLOR.
19
+ * When a palette is available, cycles through colors by category name.
20
+ */
21
+ export declare function resolveDefaultFill(color: string | undefined, themeCategorical: string[] | undefined, colorScheme: string | string[] | undefined, category: string | undefined, categoryIndexMap: Map<string, number>): string;
11
22
  /**
12
23
  * Resolve an accessor (string key or function) into a function.
13
24
  * Used across chart components to normalize `valueAccessor`, `categoryAccessor`, etc.
@@ -50,7 +61,7 @@ export declare function useChartSelection({ selection, linkedHover, fallbackFiel
50
61
  * expansion pattern that every chart with color encoding repeats.
51
62
  */
52
63
  export type LegendPosition = "right" | "left" | "top" | "bottom";
53
- export declare function useChartLegendAndMargin({ data, colorBy, colorScale, showLegend, legendPosition, userMargin, defaults, }: {
64
+ export declare function useChartLegendAndMargin({ data, colorBy, colorScale, showLegend, legendPosition, userMargin, defaults, categories, }: {
54
65
  data: Array<Record<string, any>>;
55
66
  colorBy: Accessor<string> | undefined;
56
67
  colorScale: ((v: string) => string) | undefined;
@@ -63,6 +74,7 @@ export declare function useChartLegendAndMargin({ data, colorBy, colorScale, sho
63
74
  left: number;
64
75
  right: number;
65
76
  };
77
+ categories?: string[];
66
78
  }): {
67
79
  legend: ReturnType<typeof createLegend> | undefined;
68
80
  margin: {
@@ -102,6 +114,9 @@ interface ChartModeInput {
102
114
  enableHover?: boolean;
103
115
  showLegend?: boolean;
104
116
  showLabels?: boolean;
117
+ showCategoryTicks?: boolean;
118
+ /** "vertical" | "horizontal" — used to shrink the category-axis margin when showCategoryTicks is false */
119
+ orientation?: string;
105
120
  title?: string;
106
121
  xLabel?: string;
107
122
  yLabel?: string;
@@ -11,13 +11,14 @@ import type { LegendItem } from "../../types/legendTypes";
11
11
  * @param strokeWidth - Optional stroke width for legend items
12
12
  * @returns Legend configuration object for Semiotic frames
13
13
  */
14
- export declare function createLegend({ data, colorBy, colorScale, getColor, strokeColor, strokeWidth }: {
14
+ export declare function createLegend({ data, colorBy, colorScale, getColor, strokeColor, strokeWidth, categories }: {
15
15
  data: Array<Record<string, any>>;
16
16
  colorBy: Accessor<string>;
17
17
  colorScale?: ((v: string) => string);
18
18
  getColor: (d: Record<string, any>, accessor: Accessor<string>, scale?: ((v: string) => string)) => string;
19
19
  strokeColor?: string;
20
20
  strokeWidth?: number;
21
+ categories?: string[];
21
22
  }): {
22
23
  legendGroups: {
23
24
  styleFn: (d: LegendItem) => Record<string, string | number>;
@@ -44,8 +44,19 @@ export interface SelectionStyleConfig {
44
44
  unselectedStyle?: Record<string, any>;
45
45
  selectedStyle?: Record<string, any>;
46
46
  }
47
+ /** Default opacity for unselected (dimmed) elements */
48
+ export declare const DEFAULT_SELECTION_OPACITY = 0.2;
49
+ /**
50
+ * Read the --semiotic-selection-opacity CSS variable from a container element.
51
+ * Returns the numeric value or the default if not set or not parseable.
52
+ */
53
+ export declare function readSelectionOpacityFromCSS(container: Element | null): number;
47
54
  /**
48
55
  * Wrap a base style function with selection awareness.
49
56
  * When a selection is active, non-matching datums get dimmed.
57
+ *
58
+ * Dimming opacity is resolved in this order:
59
+ * 1. `config.unselectedOpacity` (explicit prop)
60
+ * 2. `DEFAULT_SELECTION_OPACITY` (0.2)
50
61
  */
51
62
  export declare function wrapStyleWithSelection(baseStyleFn: (d: Record<string, any>) => Record<string, any>, selectionHook: SelectionHookResult | null, config?: SelectionStyleConfig): (d: Record<string, any>) => Record<string, any>;
@@ -56,20 +56,64 @@ export interface ForecastConfig {
56
56
  trainDasharray?: string;
57
57
  /** Dash pattern for forecast line segment. Default: "4,4" */
58
58
  forecastDasharray?: string;
59
- /** Outlier dot color (pre-computed mode). Default: "#ef4444" */
60
- anomalyColor?: string;
61
- /** Outlier dot radius (pre-computed mode). Default: 6 */
62
- anomalyRadius?: number;
59
+ /** Stroke opacity for the training line segment (0–1). Default: 1 */
60
+ trainOpacity?: number;
61
+ /** Stroke opacity for the forecast line segment (0–1). Default: 1 */
62
+ forecastOpacity?: number;
63
+ /**
64
+ * Training line stroke color.
65
+ * - `"darken"`: auto-darken the line's own color by 50% (hex colors only —
66
+ * non-hex values like `rgb()` or CSS variables pass through unchanged).
67
+ * - Any CSS color string: use that color explicitly.
68
+ * - Omit to inherit the line's color unchanged.
69
+ */
70
+ trainStroke?: string;
71
+ /** Training line linecap (e.g. "round"). Default: inherits from base style */
72
+ trainLinecap?: string;
73
+ /**
74
+ * Render a solid underline beneath the dashed training line.
75
+ * - `true`: solid line in the base (or lightened) color beneath the dashed training line
76
+ * - `"lighten"`: solid line in a 40% lightened version of the line's color
77
+ * - Omit or `false`: no underline (default)
78
+ */
79
+ trainUnderline?: boolean | "lighten";
80
+ /**
81
+ * Outlier dot color.
82
+ * - `string`: fixed color (default: "#ef4444")
83
+ * - `(datum) => string`: per-datum color function
84
+ */
85
+ anomalyColor?: string | ((datum: Record<string, any>) => string);
86
+ /**
87
+ * Outlier dot radius.
88
+ * - `number`: fixed radius (default: 6)
89
+ * - `(datum) => number`: per-datum radius function (e.g. for count-based sizing)
90
+ */
91
+ anomalyRadius?: number | ((datum: Record<string, any>) => number);
92
+ /**
93
+ * Full style override for anomaly dots.
94
+ * When provided as a function, receives the datum and should return a CSS style object.
95
+ * Overrides `anomalyColor` when provided.
96
+ */
97
+ anomalyStyle?: Record<string, any> | ((datum: Record<string, any>) => Record<string, any>);
98
+ /**
99
+ * Internal: field name used to group data into separate lines (e.g. "metricLabel").
100
+ * When set, boundary point duplication only bridges within the same group,
101
+ * preventing cross-metric stray lines. Set automatically by LineChart when
102
+ * both lineBy and forecast are active.
103
+ * @internal
104
+ */
105
+ _groupBy?: string;
63
106
  /** Label for the forecast/envelope region */
64
107
  label?: string;
65
108
  }
66
109
  /** Internal segment marker added to each datum */
67
110
  export declare const SEGMENT_FIELD: "__forecastSegment";
68
- export type SegmentType = "training" | "observed" | "forecast";
111
+ export type SegmentType = "training" | "training-base" | "observed" | "forecast";
69
112
  export declare function buildAnomalyAnnotations(config: AnomalyConfig): Record<string, any>[];
70
113
  export interface ForecastResult {
71
114
  processedData: Record<string, any>[];
72
115
  annotations: Record<string, any>[];
73
116
  }
74
117
  export declare function buildForecast(data: Record<string, any>[], xAccessor: string, yAccessor: string, forecastConfig: ForecastConfig, anomalyConfig?: AnomalyConfig): ForecastResult;
118
+ export { darkenColor, lightenColor } from "./colorManipulation";
75
119
  export declare function createSegmentLineStyle(baseStyle: (d: Record<string, any>) => Record<string, any>, forecastConfig: ForecastConfig): (d: Record<string, any>) => Record<string, any>;
@@ -73,6 +73,9 @@ export interface BaseChartProps {
73
73
  loading?: boolean;
74
74
  /** Custom content to render when data is empty. Set to `false` to disable empty state. */
75
75
  emptyContent?: React.ReactNode | false;
76
+ /** Uniform fill color for all data marks. Overrides colorScheme and theme categorical.
77
+ * For per-category coloring, use `colorBy` + `colorScheme` instead. */
78
+ color?: string;
76
79
  /** Visual emphasis level for dashboard hierarchy. "primary" spans two columns in ChartGrid. */
77
80
  emphasis?: "primary" | "secondary";
78
81
  /** Enable declarative bounded animation (enter/exit/update transitions).
@@ -91,7 +94,7 @@ export interface AxisConfig {
91
94
  /** Label for the y-axis */
92
95
  yLabel?: string;
93
96
  /** Format function for x-axis tick labels */
94
- xFormat?: (d: any) => string;
97
+ xFormat?: (d: any, index?: number, allTicks?: number[]) => string;
95
98
  /** Format function for y-axis tick labels */
96
99
  yFormat?: (d: any) => string;
97
100
  }
@@ -42,7 +42,7 @@ export interface HeatmapProps<TDatum extends Record<string, any> = Record<string
42
42
  /**
43
43
  * Format function for x-axis tick labels
44
44
  */
45
- xFormat?: (d: any) => string;
45
+ xFormat?: (d: any, index?: number, allTicks?: number[]) => string;
46
46
  /**
47
47
  * Format function for y-axis tick labels
48
48
  */
@@ -0,0 +1,71 @@
1
+ import * as React from "react";
2
+ import type { StreamXYFrameProps, CurveType } from "../../stream/types";
3
+ import type { RealtimeFrameHandle } from "../../realtime/types";
4
+ import type { BaseChartProps, AxisConfig, ChartAccessor } from "../shared/types";
5
+ import { type TooltipProp } from "../../Tooltip/Tooltip";
6
+ import type { LegendInteractionMode, LegendPosition } from "../shared/hooks";
7
+ /**
8
+ * Configuration for a single series in a MultiAxisLineChart.
9
+ */
10
+ export interface MultiAxisSeriesConfig<TDatum = Record<string, any>> {
11
+ /** Field name or function to access y values for this series */
12
+ yAccessor: ChartAccessor<TDatum, number>;
13
+ /** Axis label for this series */
14
+ label?: string;
15
+ /** Override color for this series (defaults to theme palette) */
16
+ color?: string;
17
+ /** Tick format function for this series' axis */
18
+ format?: (d: number) => string;
19
+ /** Fixed extent [min, max] for this series. Required for push API streaming.
20
+ * If omitted, computed from data. */
21
+ extent?: [number, number];
22
+ }
23
+ /**
24
+ * MultiAxisLineChart component props
25
+ */
26
+ export interface MultiAxisLineChartProps<TDatum extends Record<string, any> = Record<string, any>> extends BaseChartProps, AxisConfig {
27
+ /** Array of data points shared by both series */
28
+ data?: TDatum[];
29
+ /** Field name or function to access x values @default "x" */
30
+ xAccessor?: ChartAccessor<TDatum, number>;
31
+ /** Series configuration — exactly 2 for dual-axis mode.
32
+ * If not exactly 2, renders as a normal line chart with a console warning. */
33
+ series: MultiAxisSeriesConfig<TDatum>[];
34
+ /** Color scheme or custom colors array @default "category10" */
35
+ colorScheme?: string | string[];
36
+ /** Enable hover annotations @default true */
37
+ enableHover?: boolean;
38
+ /** Curve interpolation @default "monotoneX" */
39
+ curve?: CurveType;
40
+ /** Line width in pixels @default 2 */
41
+ lineWidth?: number;
42
+ /** Show legend @default true */
43
+ showLegend?: boolean;
44
+ /** Show grid lines @default false */
45
+ showGrid?: boolean;
46
+ /** Tooltip configuration */
47
+ tooltip?: TooltipProp;
48
+ /** Legend interaction mode */
49
+ legendInteraction?: LegendInteractionMode;
50
+ /** Legend position */
51
+ legendPosition?: LegendPosition;
52
+ /** Annotations */
53
+ annotations?: Record<string, any>[];
54
+ /** Additional StreamXYFrame props */
55
+ frameProps?: Partial<Omit<StreamXYFrameProps, "chartType" | "data" | "size">>;
56
+ }
57
+ /**
58
+ * MultiAxisLineChart — Dual Y-axis line chart for comparing two series
59
+ * with different scales on the same time/x axis.
60
+ *
61
+ * Data is unitized (normalized to [0,1]) internally so both series share
62
+ * a common visual scale. The left axis shows series[0] values and the
63
+ * right axis shows series[1] values in their original units.
64
+ *
65
+ * If `series` does not contain exactly 2 entries, renders as a standard
66
+ * multi-line chart with a dev-mode console warning.
67
+ */
68
+ export declare const MultiAxisLineChart: {
69
+ <TDatum extends Record<string, any> = Record<string, any>>(props: MultiAxisLineChartProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
70
+ displayName?: string;
71
+ };
@@ -56,6 +56,8 @@ export interface CrosshairStyle {
56
56
  export interface HoverAnnotationConfig {
57
57
  crosshair?: boolean | CrosshairStyle;
58
58
  snapToPoint?: boolean;
59
+ /** Color of the hover indicator dot. Defaults to the hovered element's color (stroke for lines, fill for points). Set a CSS color string to override. */
60
+ pointColor?: string;
59
61
  }
60
62
  export interface HoverData {
61
63
  data: Record<string, any>;
@@ -6,6 +6,8 @@ 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 { QuadrantChart } from "./charts/xy/QuadrantChart";
10
+ export { MultiAxisLineChart } from "./charts/xy/MultiAxisLineChart";
9
11
  export { LinkedCharts } from "./LinkedCharts";
10
12
  export { useSelection, useLinkedHover, useBrushSelection, useFilteredData } from "./LinkedCharts";
11
13
  export { BarChart } from "./charts/ordinal/BarChart";
@@ -19,6 +21,7 @@ export { DotPlot } from "./charts/ordinal/DotPlot";
19
21
  export { RidgelinePlot } from "./charts/ordinal/RidgelinePlot";
20
22
  export { PieChart } from "./charts/ordinal/PieChart";
21
23
  export { DonutChart } from "./charts/ordinal/DonutChart";
24
+ export { FunnelChart } from "./charts/ordinal/FunnelChart";
22
25
  export { ForceDirectedGraph } from "./charts/network/ForceDirectedGraph";
23
26
  export { ChordDiagram } from "./charts/network/ChordDiagram";
24
27
  export { SankeyDiagram } from "./charts/network/SankeyDiagram";
@@ -15,4 +15,7 @@ export { DotPlot } from "./charts/ordinal/DotPlot";
15
15
  export { PieChart } from "./charts/ordinal/PieChart";
16
16
  export { DonutChart } from "./charts/ordinal/DonutChart";
17
17
  export { RidgelinePlot } from "./charts/ordinal/RidgelinePlot";
18
+ export { FunnelChart } from "./charts/ordinal/FunnelChart";
19
+ export { createHatchPattern } from "./charts/shared/hatchPattern";
20
+ export type { HatchPatternOptions } from "./charts/shared/hatchPattern";
18
21
  export type { StreamOrdinalFrameProps, StreamOrdinalFrameHandle, OrdinalChartType, OrdinalScales, OrdinalSceneNode } from "./stream/ordinalTypes";