Skip to content

Commit 3909fea

Browse files
authored
Merge pull request #789 from nteract/integration-2
3.2.0 pre-release fixes
2 parents 3b7da79 + abb67d3 commit 3909fea

85 files changed

Lines changed: 2361 additions & 296 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clinerules

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ Frame callbacks (`nodeStyle`, `edgeStyle`, `nodeSize` as fn) receive `RealtimeNo
117117
```
118118
Same applies to `frameProps` style functions on HOCs. `customHoverBehavior`/`customClickBehavior` receive `{ type, data, x, y } | null`. `tooltipContent` receives `{ type, data }`.
119119

120+
## Hover Indicator
121+
The hover dot automatically matches the hovered element's color (line stroke, point fill, etc.). Override via `frameProps`:
122+
```jsx
123+
<LineChart frameProps={{ hoverAnnotation: { pointColor: "#ff0000" } }} />
124+
```
125+
Fallback chain: `pointColor` → element color → `--semiotic-primary` CSS var → `#007bff`.
126+
120127
## Coordinated Views
121128

122129
**LinkedCharts** — `selections` (resolution: "union"|"intersect"|"crossfilter"), `showLegend`, `legendPosition`, `legendInteraction`, `legendSelectionName`, `legendField`
@@ -205,6 +212,10 @@ Color-blind palette: `import { COLOR_BLIND_SAFE_CATEGORICAL } from "semiotic"` (
205212

206213
Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas charts read vars via `getComputedStyle`. `exportChart` inlines computed styles.
207214

215+
**Dark/light mode merge rules:** String preset (e.g. `"dark"`) → full replacement with that preset's theme. Object with `mode` (e.g. `{ mode: "dark", colors: { categorical: [...] } }`) → merges onto the matching base theme (`DARK_THEME` or `LIGHT_THEME`), so background/text/grid adapt while your overrides are preserved. Object without `mode` → shallow-merges onto the current theme (partial override). ThemeProvider is reactive — changing the `theme` prop re-applies immediately.
216+
217+
**CSS interop:** Host app `--semiotic-*` vars on `:root` are overridden by ThemeProvider's closer wrapper div. To let app tokens flow through, either skip ThemeProvider and set `--semiotic-*` vars in CSS, or use the hybrid approach (ThemeProvider for palette only, CSS vars for chrome).
218+
208219
## Server-Side Rendering
209220
- HOC charts and Frames render SVG automatically in server environments
210221
- `renderXYToStaticSVG(props)`, `renderOrdinalToStaticSVG(props)`, `renderNetworkToStaticSVG(props)`, `renderGeoToStaticSVG(props)` from `semiotic/server`
@@ -229,6 +240,7 @@ Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas c
229240

230241
- **Tooltip datum shape**: HOC tooltip functions get raw data. Frame `tooltipContent` gets wrapped data — use `d.data`.
231242
- **Legend positioning**: "bottom" auto-expands margin ~80px. For narrow charts (<400px), prefer "bottom" or "top".
243+
- **MultiAxisLineChart legend**: Always use `legendPosition="bottom"` (or `"top"`) — the right-hand axis occupies the space where a right-side legend would go.
232244
- **Log scale**: Clamps domain min to 1e-6 (log(0) undefined).
233245
- **barPadding**: Pixel value, defaults 40/60. Reduce for small charts.
234246
- **Horizontal bars**: Need wider left margin with long labels: `margin={{ left: 120 }}`.

.cursorrules

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ Frame callbacks (`nodeStyle`, `edgeStyle`, `nodeSize` as fn) receive `RealtimeNo
117117
```
118118
Same applies to `frameProps` style functions on HOCs. `customHoverBehavior`/`customClickBehavior` receive `{ type, data, x, y } | null`. `tooltipContent` receives `{ type, data }`.
119119

120+
## Hover Indicator
121+
The hover dot automatically matches the hovered element's color (line stroke, point fill, etc.). Override via `frameProps`:
122+
```jsx
123+
<LineChart frameProps={{ hoverAnnotation: { pointColor: "#ff0000" } }} />
124+
```
125+
Fallback chain: `pointColor` → element color → `--semiotic-primary` CSS var → `#007bff`.
126+
120127
## Coordinated Views
121128

122129
**LinkedCharts** — `selections` (resolution: "union"|"intersect"|"crossfilter"), `showLegend`, `legendPosition`, `legendInteraction`, `legendSelectionName`, `legendField`
@@ -205,6 +212,10 @@ Color-blind palette: `import { COLOR_BLIND_SAFE_CATEGORICAL } from "semiotic"` (
205212

206213
Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas charts read vars via `getComputedStyle`. `exportChart` inlines computed styles.
207214

215+
**Dark/light mode merge rules:** String preset (e.g. `"dark"`) → full replacement with that preset's theme. Object with `mode` (e.g. `{ mode: "dark", colors: { categorical: [...] } }`) → merges onto the matching base theme (`DARK_THEME` or `LIGHT_THEME`), so background/text/grid adapt while your overrides are preserved. Object without `mode` → shallow-merges onto the current theme (partial override). ThemeProvider is reactive — changing the `theme` prop re-applies immediately.
216+
217+
**CSS interop:** Host app `--semiotic-*` vars on `:root` are overridden by ThemeProvider's closer wrapper div. To let app tokens flow through, either skip ThemeProvider and set `--semiotic-*` vars in CSS, or use the hybrid approach (ThemeProvider for palette only, CSS vars for chrome).
218+
208219
## Server-Side Rendering
209220
- HOC charts and Frames render SVG automatically in server environments
210221
- `renderXYToStaticSVG(props)`, `renderOrdinalToStaticSVG(props)`, `renderNetworkToStaticSVG(props)`, `renderGeoToStaticSVG(props)` from `semiotic/server`
@@ -229,6 +240,7 @@ Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas c
229240

230241
- **Tooltip datum shape**: HOC tooltip functions get raw data. Frame `tooltipContent` gets wrapped data — use `d.data`.
231242
- **Legend positioning**: "bottom" auto-expands margin ~80px. For narrow charts (<400px), prefer "bottom" or "top".
243+
- **MultiAxisLineChart legend**: Always use `legendPosition="bottom"` (or `"top"`) — the right-hand axis occupies the space where a right-side legend would go.
232244
- **Log scale**: Clamps domain min to 1e-6 (log(0) undefined).
233245
- **barPadding**: Pixel value, defaults 40/60. Reduce for small charts.
234246
- **Horizontal bars**: Need wider left margin with long labels: `margin={{ left: 120 }}`.

.github/copilot-instructions.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ Frame callbacks (`nodeStyle`, `edgeStyle`, `nodeSize` as fn) receive `RealtimeNo
117117
```
118118
Same applies to `frameProps` style functions on HOCs. `customHoverBehavior`/`customClickBehavior` receive `{ type, data, x, y } | null`. `tooltipContent` receives `{ type, data }`.
119119

120+
## Hover Indicator
121+
The hover dot automatically matches the hovered element's color (line stroke, point fill, etc.). Override via `frameProps`:
122+
```jsx
123+
<LineChart frameProps={{ hoverAnnotation: { pointColor: "#ff0000" } }} />
124+
```
125+
Fallback chain: `pointColor` → element color → `--semiotic-primary` CSS var → `#007bff`.
126+
120127
## Coordinated Views
121128

122129
**LinkedCharts**`selections` (resolution: "union"|"intersect"|"crossfilter"), `showLegend`, `legendPosition`, `legendInteraction`, `legendSelectionName`, `legendField`
@@ -205,6 +212,10 @@ Color-blind palette: `import { COLOR_BLIND_SAFE_CATEGORICAL } from "semiotic"` (
205212

206213
Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas charts read vars via `getComputedStyle`. `exportChart` inlines computed styles.
207214

215+
**Dark/light mode merge rules:** String preset (e.g. `"dark"`) → full replacement with that preset's theme. Object with `mode` (e.g. `{ mode: "dark", colors: { categorical: [...] } }`) → merges onto the matching base theme (`DARK_THEME` or `LIGHT_THEME`), so background/text/grid adapt while your overrides are preserved. Object without `mode` → shallow-merges onto the current theme (partial override). ThemeProvider is reactive — changing the `theme` prop re-applies immediately.
216+
217+
**CSS interop:** Host app `--semiotic-*` vars on `:root` are overridden by ThemeProvider's closer wrapper div. To let app tokens flow through, either skip ThemeProvider and set `--semiotic-*` vars in CSS, or use the hybrid approach (ThemeProvider for palette only, CSS vars for chrome).
218+
208219
## Server-Side Rendering
209220
- HOC charts and Frames render SVG automatically in server environments
210221
- `renderXYToStaticSVG(props)`, `renderOrdinalToStaticSVG(props)`, `renderNetworkToStaticSVG(props)`, `renderGeoToStaticSVG(props)` from `semiotic/server`
@@ -229,6 +240,7 @@ Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas c
229240

230241
- **Tooltip datum shape**: HOC tooltip functions get raw data. Frame `tooltipContent` gets wrapped data — use `d.data`.
231242
- **Legend positioning**: "bottom" auto-expands margin ~80px. For narrow charts (<400px), prefer "bottom" or "top".
243+
- **MultiAxisLineChart legend**: Always use `legendPosition="bottom"` (or `"top"`) — the right-hand axis occupies the space where a right-side legend would go.
232244
- **Log scale**: Clamps domain min to 1e-6 (log(0) undefined).
233245
- **barPadding**: Pixel value, defaults 40/60. Reduce for small charts.
234246
- **Horizontal bars**: Need wider left margin with long labels: `margin={{ left: 120 }}`.

.windsurfrules

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ Frame callbacks (`nodeStyle`, `edgeStyle`, `nodeSize` as fn) receive `RealtimeNo
117117
```
118118
Same applies to `frameProps` style functions on HOCs. `customHoverBehavior`/`customClickBehavior` receive `{ type, data, x, y } | null`. `tooltipContent` receives `{ type, data }`.
119119

120+
## Hover Indicator
121+
The hover dot automatically matches the hovered element's color (line stroke, point fill, etc.). Override via `frameProps`:
122+
```jsx
123+
<LineChart frameProps={{ hoverAnnotation: { pointColor: "#ff0000" } }} />
124+
```
125+
Fallback chain: `pointColor` → element color → `--semiotic-primary` CSS var → `#007bff`.
126+
120127
## Coordinated Views
121128

122129
**LinkedCharts** — `selections` (resolution: "union"|"intersect"|"crossfilter"), `showLegend`, `legendPosition`, `legendInteraction`, `legendSelectionName`, `legendField`
@@ -205,6 +212,10 @@ Color-blind palette: `import { COLOR_BLIND_SAFE_CATEGORICAL } from "semiotic"` (
205212

206213
Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas charts read vars via `getComputedStyle`. `exportChart` inlines computed styles.
207214

215+
**Dark/light mode merge rules:** String preset (e.g. `"dark"`) → full replacement with that preset's theme. Object with `mode` (e.g. `{ mode: "dark", colors: { categorical: [...] } }`) → merges onto the matching base theme (`DARK_THEME` or `LIGHT_THEME`), so background/text/grid adapt while your overrides are preserved. Object without `mode` → shallow-merges onto the current theme (partial override). ThemeProvider is reactive — changing the `theme` prop re-applies immediately.
216+
217+
**CSS interop:** Host app `--semiotic-*` vars on `:root` are overridden by ThemeProvider's closer wrapper div. To let app tokens flow through, either skip ThemeProvider and set `--semiotic-*` vars in CSS, or use the hybrid approach (ThemeProvider for palette only, CSS vars for chrome).
218+
208219
## Server-Side Rendering
209220
- HOC charts and Frames render SVG automatically in server environments
210221
- `renderXYToStaticSVG(props)`, `renderOrdinalToStaticSVG(props)`, `renderNetworkToStaticSVG(props)`, `renderGeoToStaticSVG(props)` from `semiotic/server`
@@ -229,6 +240,7 @@ Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas c
229240

230241
- **Tooltip datum shape**: HOC tooltip functions get raw data. Frame `tooltipContent` gets wrapped data — use `d.data`.
231242
- **Legend positioning**: "bottom" auto-expands margin ~80px. For narrow charts (<400px), prefer "bottom" or "top".
243+
- **MultiAxisLineChart legend**: Always use `legendPosition="bottom"` (or `"top"`) — the right-hand axis occupies the space where a right-side legend would go.
232244
- **Log scale**: Clamps domain min to 1e-6 (log(0) undefined).
233245
- **barPadding**: Pixel value, defaults 40/60. Reduce for small charts.
234246
- **Horizontal bars**: Need wider left margin with long labels: `margin={{ left: 120 }}`.

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.2.0] - 2026-03-25
9+
10+
### Added
11+
12+
- **Hover dot color matching** — The hover indicator dot now automatically matches the hovered element's color (line stroke, area stroke, point fill) instead of hardcoded blue. Override with `frameProps={{ hoverAnnotation: { pointColor: "#custom" } }}`. Fallback chain: explicit `pointColor` → element color → `--semiotic-primary` CSS var → `#007bff`. Affects all XY and Geo charts.
13+
- **`pointColor` option on `HoverAnnotationConfig`** — New opt-in override for hover dot color on Stream Frames.
14+
- **Adaptive time tick formatting** — New `adaptiveTimeTicks(granularity?)` export from `semiotic`. Produces hierarchical axis labels: first tick is fully qualified, subsequent ticks only show what changed (e.g. seconds when the minute is the same, full timestamp when the hour rolls over). Tick labels auto-space based on label width to prevent overlap.
15+
- **Forecast: training line styling**`trainStroke` ("darken" or CSS color), `trainLinecap` ("round"), `trainUnderline` (true | "lighten"), `trainOpacity`, `forecastOpacity` on `ForecastConfig`. Enables dashed training lines with solid underlines for visual distinction.
16+
- **Forecast: per-datum anomaly styling**`anomalyColor`, `anomalyRadius`, and `anomalyStyle` on `ForecastConfig` now accept functions `(datum) => value` for data-driven anomaly rendering (e.g. sizing dots by anomaly count).
17+
- **Forecast: multi-metric boundary duplication**`_groupBy` internal field on `ForecastConfig`. When `lineBy` and `forecast` are both active, boundary points are duplicated within each metric group (not across groups), preventing stray cross-metric connecting lines in interleaved data.
18+
- **`training-base` segment type** — New segment for solid underlines beneath dashed training lines. PipelineStore renders training-base first (insertion order) so the solid line appears beneath the dashed one.
19+
- **`resolveNodeColor` shared utility** — Extracted to `sceneUtils.ts`, used by both StreamXYFrame and StreamGeoFrame for consistent hover color resolution. Handles `CanvasPattern` fills correctly.
20+
- **128 new unit tests** — Multi-metric boundary duplication (3 tests), ThemeStore dark mode merging (5 tests), PipelineStore reproduction (9 tests), LineChart integration (8 tests), plus expanded statisticalOverlays coverage.
21+
22+
### Fixed
23+
24+
- **SVGOverlay left axis label missing in dual-axis mode**`MultiAxisLineChart` passes left axis label via `axes` config, but SVGOverlay only read the `yLabel` prop (which is suppressed in dual-axis mode). Now reads `leftAxis?.label || yLabel`.
25+
- **ThemeStore `mode: "dark"` merged onto wrong base**`{ mode: "dark", colors: { categorical: [...] } }` was merging onto `LIGHT_THEME`, so dark-mode text/background/grid colors were lost. Now correctly merges onto `DARK_THEME`.
26+
- **Tick label overlap on time axes** — X-axis tick spacing now accounts for actual label width (estimated at 6.5px/char) instead of using a fixed 55px minimum, preventing label collision on dense time axes.
27+
- **`tickFormat` signature expanded**`AxisConfig.tickFormat` and `xFormat` now receive `(value, index, allTickValues)` so formatters can produce hierarchical labels (e.g. show full date only on first tick or at boundary crossings).
28+
- **Function accessors with forecast/anomaly** — When `xAccessor` or `yAccessor` is a function, resolved values are now baked into data under `__resolvedX`/`__resolvedY` fields so the statistical overlay pipeline and annotation renderer can access them by string key.
29+
- **Geo hover ring color** — Geo frame point hover ring now uses `resolveNodeColor` (shared utility) instead of inline logic, and correctly handles `CanvasPattern` fills.
30+
- **Tick color dark mode fallback** — SVGOverlay tick color CSS var chain is now `--semiotic-text-secondary``--semiotic-text``#666`, improving visibility when only `--semiotic-text` is set.
31+
- **Annotation accessor fallback** — SVGOverlay annotation renderer receives `"__resolvedX"`/`"__resolvedY"` when accessors are functions, preventing annotations from rendering at wrong positions.
32+
33+
### Changed
34+
35+
- **`SegmentType` union expanded** — Added `"training-base"` to the exported type.
36+
- **`ForecastConfig` interface expanded** — Added `trainStroke`, `trainLinecap`, `trainUnderline`, `trainOpacity`, `forecastOpacity`, `anomalyStyle`, `_groupBy`. `anomalyColor` and `anomalyRadius` now accept functions.
37+
- **HOC early return guard** — LineChart (and other HOCs with statistical overlays) no longer returns early before loading/empty state, ensuring all hooks are called unconditionally (React rules of hooks compliance).
38+
839
## [3.1.2] - 2026-03-21
940

1041
> **Note:** v3.1.1 was yanked from npm due to broken MCP tool schemas. Upgrade directly from 3.1.0 to 3.1.2.

CLAUDE.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ Frame callbacks (`nodeStyle`, `edgeStyle`, `nodeSize` as fn) receive `RealtimeNo
117117
```
118118
Same applies to `frameProps` style functions on HOCs. `customHoverBehavior`/`customClickBehavior` receive `{ type, data, x, y } | null`. `tooltipContent` receives `{ type, data }`.
119119

120+
## Hover Indicator
121+
The hover dot automatically matches the hovered element's color (line stroke, point fill, etc.). Override via `frameProps`:
122+
```jsx
123+
<LineChart frameProps={{ hoverAnnotation: { pointColor: "#ff0000" } }} />
124+
```
125+
Fallback chain: `pointColor` → element color → `--semiotic-primary` CSS var → `#007bff`.
126+
120127
## Coordinated Views
121128

122129
**LinkedCharts**`selections` (resolution: "union"|"intersect"|"crossfilter"), `showLegend`, `legendPosition`, `legendInteraction`, `legendSelectionName`, `legendField`
@@ -205,6 +212,10 @@ Color-blind palette: `import { COLOR_BLIND_SAFE_CATEGORICAL } from "semiotic"` (
205212

206213
Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas charts read vars via `getComputedStyle`. `exportChart` inlines computed styles.
207214

215+
**Dark/light mode merge rules:** String preset (e.g. `"dark"`) → full replacement with that preset's theme. Object with `mode` (e.g. `{ mode: "dark", colors: { categorical: [...] } }`) → merges onto the matching base theme (`DARK_THEME` or `LIGHT_THEME`), so background/text/grid adapt while your overrides are preserved. Object without `mode` → shallow-merges onto the current theme (partial override). ThemeProvider is reactive — changing the `theme` prop re-applies immediately.
216+
217+
**CSS interop:** Host app `--semiotic-*` vars on `:root` are overridden by ThemeProvider's closer wrapper div. To let app tokens flow through, either skip ThemeProvider and set `--semiotic-*` vars in CSS, or use the hybrid approach (ThemeProvider for palette only, CSS vars for chrome).
218+
208219
## Server-Side Rendering
209220
- HOC charts and Frames render SVG automatically in server environments
210221
- `renderXYToStaticSVG(props)`, `renderOrdinalToStaticSVG(props)`, `renderNetworkToStaticSVG(props)`, `renderGeoToStaticSVG(props)` from `semiotic/server`
@@ -229,6 +240,7 @@ Key: `ThemeProvider` sets CSS vars on a wrapper div (no React context). Canvas c
229240

230241
- **Tooltip datum shape**: HOC tooltip functions get raw data. Frame `tooltipContent` gets wrapped data — use `d.data`.
231242
- **Legend positioning**: "bottom" auto-expands margin ~80px. For narrow charts (<400px), prefer "bottom" or "top".
243+
- **MultiAxisLineChart legend**: Always use `legendPosition="bottom"` (or `"top"`) — the right-hand axis occupies the space where a right-side legend would go.
232244
- **Log scale**: Clamps domain min to 1e-6 (log(0) undefined).
233245
- **barPadding**: Pixel value, defaults 40/60. Reduce for small charts.
234246
- **Horizontal bars**: Need wider left margin with long labels: `margin={{ left: 120 }}`.

0 commit comments

Comments
 (0)