Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Releases: nteract/semiotic

Semiotic v3.7.4

16 Jun 15:12
@github-actions github-actions
626cc08
This commit was created on GitHub.com and signed with GitHub’s verified signature.
GPG key ID: B5690EEEBB952194
Verified
Learn about vigilant mode.

Choose a tag to compare

Added

  • Lineage DAG recipe helpers. semiotic/recipes now exports lineage DAG helpers for
    data-flow and KStreams-style network layouts, with tests covering stable topology layout.
  • KStreams docs demo. The docs add a KStreams recipe page and example data,
    plus expanded custom network chart guidance for selection-aware layouts.

Fixed

  • Network custom layout selection metadata. Network custom layouts now preserve selection
    metadata through pipeline layout and render paths, with regression coverage for selection
    actions and NetworkCustomChart behavior.

Changed

  • Refreshed developer/dependency tooling, including Prettier, TypeScript ESLint, Rollup, and Sharp.
Assets 2
Loading

Semiotic v3.7.3

13 Jun 19:40
@github-actions github-actions
982b611
This commit was created on GitHub.com and signed with GitHub’s verified signature.
GPG key ID: B5690EEEBB952194
Verified
Learn about vigilant mode.

Choose a tag to compare

Added

  • OpenAI Apps domain verification for hosted MCP. HTTP mode now serves the raw
    OPENAI_APPS_CHALLENGE_TOKEN from /.well-known/openai-apps-challenge, allowing
    ChatGPT Apps domain verification against Cloud Run and other HTTPS-hosted MCP origins without
    committing the token.
  • Cloud Run verification playbook. deploy/cloud-run documents the Challenge Base URL shape,
    token environment variable, and curl check for ChatGPT Apps verification, and the wrapper now
    tracks the semiotic@^3.7.3 release line.

Tests

  • Added MCP HTTP regression coverage for the OpenAI Apps challenge route while confirming the
    unauthenticated OAuth protected-resource probe continues to return 404.
Loading

Semiotic v3.7.2

13 Jun 04:44
@github-actions github-actions

Choose a tag to compare

Added

  • Stateless MCP HTTP mode for hosted connectors. semiotic-mcp --http now creates an
    ephemeral MCP server + Streamable HTTP transport per request, returns JSON responses instead of
    holding long-lived SSE streams open, and exposes /mcp, /healthz, and /health endpoints. This
    makes the read-only MCP tool surface suitable for autoscaling serverless hosts such as Cloud Run.
  • Cloud Run deployment wrapper. deploy/cloud-run packages a minimal public MCP deployment that
    runs the published semiotic-mcp binary, documents unauthenticated read-only deployment, health
    endpoints, host allowlisting, and ChatGPT/Claude connector setup, and includes hosted-app privacy
    and terms pages for app review.

Changed

  • MCP HTTP hardening. HTTP mode normalizes the Host header for optional
    MCP_ALLOWED_HOSTS DNS-rebinding protection, returns clean 404s for non-MCP paths including
    .well-known/* probes, makes request teardown idempotent, and closes each per-request transport
    promptly to avoid serverless keep-alive leaks.
  • Docs dark-mode polish. The visible AccessibleNavTree selected row now resolves through
    --semiotic-surface, --semiotic-grid, and --semiotic-bg, with --semiotic-text applied to
    visible rows. The Accessibility / Structured Navigation bidirectional BarChart now mirrors the
    docs theme by switching between carbon and carbon-dark.
  • Annotation blog demo reliability. The "Annotations That Get Contested, and Heard" chart now
    uses numeric XY coordinates with month tick formatting, so editorial-status callouts render on the
    visible line while the prose and navigation tree keep human-readable month labels.
  • Cloud Run wrapper release line. The Cloud Run package now depends on semiotic@^3.7.2 so the
    hosted wrapper resolves the 3.7.2 MCP server after the npm package is published.

Fixed

  • Fixed a light selected-row fallback in the accessible navigation tree when the docs site was in
    dark mode but no --semiotic-surface token was present.
  • Fixed the bidirectional sync demo's BarChart rendering as a light Carbon island inside dark docs.
  • Fixed missing visual annotations in the contested-annotations blog demo caused by string month
    values being used as XY coordinates.
Loading

Semiotic v3.7.1

12 Jun 01:35
@github-actions github-actions
fe4ab1d
This commit was created on GitHub.com and signed with GitHub’s verified signature.
GPG key ID: B5690EEEBB952194
Verified
Learn about vigilant mode.

Choose a tag to compare

Added

  • Render evidence. renderChartWithEvidence() (semiotic/server) returns the SVG plus a
    machine-readable RenderEvidence object computed from the rendered scene graph — mark counts by
    scene type, resolved axis domains, an empty flag, category/node/edge counts, annotation count,
    and the accessible name — so agent repair loops and CI assertions can verify a chart actually drew
    data marks without pixel inspection. The MCP renderChart tool now returns the same evidence block
    alongside its SVG/PNG output.
  • Misleading-design diagnostics. diagnoseConfig() gains a deception-check pack: inverted
    extents (INVERTED_AXIS), unlabeled dual-axis series (DUAL_AXIS_UNLABELED), trend windows
    cropped to a favorable slice (CHERRY_PICKED_WINDOW), negative values in part-to-whole encodings
    (PART_TO_WHOLE_NEGATIVE — an error for pie/donut/funnel), non-interpolating curve="basis"
    smoothing (NON_PASSING_CURVE), slope-distorting aspect ratios (EXTREME_ASPECT_RATIO), and
    over-sliced pies (PIE_TOO_MANY_SLICES). These patterns mislead human readers and — per the
    chart-deception literature — vision-language models the same way.
  • Theme contrast conformance gate. Every shipped theme preset is now tested against WCAG-derived
    floors (4.5:1 for text/tooltip/annotation roles, 3:1 for the focus indicator), with sub-3:1 mark
    colors pinned in an exact-match known-exceptions ledger so palette regressions fail and
    improvements must shrink the ledger. The axe integration scan re-enables the color-contrast
    rule on the strength of the gate.
  • Scorecard top-1 agreement. The capability quality scorecard now reports strict
    top1AgreementRate beside the lenient top-3 rate (current canonical set: 93% top-1 / 100% top-3),
    ranks the top-3 over distinct components rather than variants of one chart, and gains fixtures
    for the previously unexercised Heatmap, GaugeChart, FlowMap, and DistanceCartogram descriptors.
  • ChatGPT Apps widget (experimental). The MCP server gains renderInteractiveChart, which
    renders a static-data chart through the same server render path as renderChart and returns a
    text/html;profile=mcp-app widget (ui://semiotic/chart-widget.html) with fit/zoom, data,
    hover, and render-evidence controls for ChatGPT developer-mode connectors over
    semiotic-mcp --http. A deployment playbook lives in the repo as CHATGPT_APPS_DEPLOYMENT.md,
    and an MCP protocol test suite covers the tool and widget resource end to end.
  • Docs prerender route artifacts. The docs build now emits one prerendered HTML file per
    route with sanitized, route-specific machine-readable content in each page's <noscript>
    fallback, plus a docs/build/llms-routes.json route index for agent readers; the docs route
    check verifies the output.

Changed

  • Theme legibility fixes (WCAG AA). pastels textSecondary/focus/annotation, bi-tool
    textSecondary, and the tufte-dark/journalist/playful annotation colors were deepened to
    clear the contrast floors; the empty-state / BigNumber-empty / data-table-caption fallback color
    moved from #999 (2.8:1) to #666, matching the default theme's textSecondary.
  • Capability descriptor judgment fixes. DifferenceChart no longer takes full compare-series
    marks when it would silently drop series beyond its native two; flat BarChart yields on crossed
    two-categorical matrices (Grouped/Stacked/Heatmap show the matrix) and on raw-observation data;
    ChoroplethMap requires at least two area features (a one-region choropleth has nothing to
    compare).
  • contrastRatio() now parses 3-digit hex shorthand (#333), making the default themes measurable.

Tests

  • Colocated tests for the NetworkCustomChart and OrdinalCustomChart escape hatches (the
    XY variant was already covered).
Loading

Semiotic v3.7.0

08 Jun 03:26
@github-actions github-actions

Choose a tag to compare

Added

  • Accessibility audit, descriptions, and structured reader navigation. auditAccessibility() /
    formatAccessibilityAudit() grade chart configs against Chartability-style heuristics, while
    describeChart(), buildNavigationTree(), AccessibleNavTree, and useNavigationSync() provide
    layered chart descriptions, WAI-ARIA tree navigation, bidirectional tree/canvas focus sync, and
    annotation-anchor focus for non-visual readers.
  • IDID reader-grounding and receivability primitives. describeChart() can emit an optional L4
    communicative-act sentence from a chart capability, buildReaderGrounding() combines description,
    intent, and structure into one agent-readable payload, AudienceProfile.receptionModality lets
    suggestCharts() penalize charts a non-visual audience cannot receive, and
    accessibilityCaveats() feeds audit warnings into recommendation caveats.
  • Conversation-arc telemetry. enableConversationArc(), disableConversationArc(),
    getConversationArcStore(), useConversationArc(), and summarizeArc() expose a bounded,
    opt-in event stream for suggestion, interrogation, navigation, export, and annotation-status
    events, with zero overhead while disabled. registerConversationArcSink(),
    createLocalStorageConversationArcSink(), createIndexedDBConversationArcSink(),
    createWebhookConversationArcSink(), loadConversationArc(), and replayConversationArc() add
    opt-in durable capture and replay hydration without duplicating sink or analytics events.
  • Variant-discovery API and MCP tool. proposeVariant() emits registered variants,
    conservative heuristic transforms, and same-intent cross-family alternatives;
    evaluateVariantProposal() scores fit, novelty, risk, rubric deltas, and audience bias; and
    MCP now exposes proposeChartVariants for agent-driven variant exploration.
  • Chart repair workflow primitive. repairChartConfig() and the MCP repairChartConfig tool
    use capability fit and chart suggestions to critique a proposed chart choice and return safer
    alternatives for agent retry loops.
  • semiotic/value and BigNumber. A focal-value KPI component now ships as a lightweight value
    entry point, with formatting, threshold, comparison/target, staleness, push-buffer, and slot APIs
    for embedding trend or chart context.
  • First-class annotation design assistance for 3.7.0. autoPlaceAnnotations now composes collision-aware placement, curved connector routing, density budgets, progressive disclosure, responsive shedding, redundant association cues, cohesion modes, audience-aware amount, and defensive annotations. Per-annotation emphasis establishes hierarchy, while provenance confidence supplies a default reading order when hierarchy is not explicit.
  • Annotation provenance and editorial lifecycle. AnnotationProvenance and AnnotationLifecycle carry actor, evidence, confidence, stable identity, freshness, editorial status, and supersession metadata. applyAnnotationLifecycle, applyAnnotationStatus, and filterAnnotationsByStatus keep visual treatment, descriptions, and structured navigation aligned on the current annotation set.
  • Stable semantic annotation anchors. anchor: "semantic" / lifecycle.anchor: "semantic" now re-resolves annotations through provenance.stableId after data refresh, using point scene nodes or matching data rows before falling back to the recorded coordinate when the target is gone.
  • Annotation reception surfaces. describeChart leads with author-marked features, buildNavigationTree adds an Annotations branch, and the accessibility audit checks color-only note-to-target association.
  • Annotation connector diagnostics. diagnoseConfig() now warns about far notes without a
    connector and very long connectors, keeping placement guidance aligned with the annotation design
    assistant.
  • Annotation design guidance docs. The first-class Annotations docs section now includes Overview, Design Guidance, Advanced Annotations, and Provenance & Lifecycle pages with live examples.
  • Linked-hover series mode. linkedHover={{ mode: "series" }} now resolves each chart's
    series-identity field automatically, with seriesField available as an override for cross-chart
    series highlighting.
  • Capability-driven visual baseline gate. check:visual-baseline-capabilities derives SSR and
    linked-hover visual coverage requirements from chartSpecs.ts, verifies the current Playwright
    evidence, and keeps the remaining SSR/CSR parity and linked-hover interaction snapshots in
    one-way burn-down maps. It is wired into CI, release:check, and prepublishOnly.
  • Shareable, restorable docs playgrounds. Every /playground/* page now
    serializes its knob + dataset state into the URL (?sc=...&ds=...) and restores it
    on load, with "Copy link" and "Copy config (JSON)" affordances. The round-trip
    dogfoods the library's own toConfig / toURL / fromURL / fromConfig /
    copyConfig so a playground configuration becomes a portable, inspectable
    ChartConfig artifact; non-serializable composite playgrounds degrade
    gracefully (no toolbar, no URL writes).
  • Faithful "Copy" in docs live examples. The code a docs LiveExample copies to the clipboard
    now serializes the real props the chart rendered with, instead of the trimmed/elided display stub —
    so copied example code reproduces the example rather than referencing undefined or shortened values.
    Display stays readable; copy is runnable. The pure code-generation moved to a React-free
    codegen module.
  • Generated, complete llms.txt. docs:llms (scripts/generate-llms-txt.mjs) regenerates the
    root llms.txt retrieval index with the full chart catalog derived from chartSpecs (grouped by
    family, every charted component), each entry tagged with its communicative act
    (resolveCommunicativeAct) so an agent reader gets what a chart is for, not just what it shows.
    Replaces the previously hand-maintained (and stale) index; kept fresh by the check:llms gate in CI
    and release:check, and regenerated during website:build.
  • Docs: per-chart "At a glance" grounding panel. A reusable ChartGrounding component renders,
    live for each chart, the communicative act it performs (buildReaderGrounding), a layered L1–L3
    description (describeChart), the chart type's reader caveats, and an accessibility badge
    (auditAccessibility — hovering the badge lists the specific findings; clicking opens the full
    audit) — the reader/agent grounding for the chart, computed from the shipped intelligence APIs so it
    can't drift. Now on all 39 static chart pages (props centralized in a reviewed fixtures map;
    realtime/push-only charts are exempt), and enforced by check:docs-coverage.
  • Docs: "Reshape to unlock" generative suggestions. The /choose picker now goes beyond charts the
    data already fits: from a flat table's field profile it proposes the transform that unlocks
    Semiotic's distinctive charts — pivot two columns into a Sankey, stamp an event log with time for
    a ProcessSankey, nest categories into a Treemap, etc. — each with the reshape and why that
    chart is worth it. Surfaces the flow/temporal/hierarchy/geo charts that a fit-only recommender can
    never reach. Driven by a pure suggestReshapes(profile) heuristic.
  • Docs: "Choose a Chart" front door. A new top-level /choose page profiles a dataset and ranks
    the catalog by fit and communicative act (live suggestCharts), showing each recommendation's score,
    reasons, and caveats with links to the chart pages. An audience selector demonstrates how the ranking
    shifts per reader — with the biasing familiarity/targets and their rationale shown — and surfaces
    governed stretch picks. Users can arrive with data and intent instead of a component name.
  • Docs: a11y hooks & theming serialization. The Accessibility docs now cover the preference hooks
    useReducedMotion / useHighContrast and the useNavigationSync tree↔canvas sync hook; the Theming
    docs now cover resolveThemePreset, themeToCSS, themeToTokens, and building custom theme objects.
    Custom Charts cross-links the related Cookbook recipes.
  • Docs: AI authoring & tooling pages. The Intelligence docs section gains four pages closing the
    previously-undocumented AI surface: CLI & MCP (every npx semiotic-ai flag and every
    npx semiotic-mcp tool, with agent setup), Variant Discovery & Repair (proposeVariant,
    evaluateVariantProposal, registerVariantDiscovery, repairChartConfig), Capability Authoring
    (the ChartCapability descriptor, registerChartCapability, registerIntent, and the intent
    taxonomy), and Audience Profiles (the AudienceProfile shape, suggestion bias, stretch picks,
    reception modality, and governance).
  • Playground control-drift gate. check:docs-playground-controls checks each playground's
    select knobs against chartSpecs.ts: a knob bound to an enum-typed prop can no longer offer an
    option the chart doesn't accept. It only gates enum-typed props (and treats mapProps-transformed
    pages as informational), so an enum member renamed in the API now fails the build instead of
    leaving a dead knob. Wired into CI, release:check, and prepublishOnly.
  • Prop-table drift gate. check:docs-prop-tables resolves each chart's prop surface from
    chartSpecs.ts (ownProps over resolved PROP_BAGS) and AST-checks every chart page's
    documented prop names against it, failing if a statically-required prop is undocumented. It keeps
    the hand-authored tables (and their curation) verifiable against the canonical registry rather than
    replacing them; --verbose reports props documented but absent from chartSpecs as a follow-up
    backlog. Wired into CI, release:check, and prepublishOnly.
  • Docs coverage gate + per-page quality bar. `check:docs-...
Read more
Loading

Semiotic v3.6.0

26 May 22:25
@github-actions github-actions

Choose a tag to compare

Added

  • semiotic/ai subpath — the AI-facing API surface as a first-class entry point. 211 KB gzip; the heuristic engine works without any LLM call, but every primitive returns LLM-friendly structured context so a model can ride on top. The entry covers four families of capability:
    • Recommendation. suggestCharts(data, options?) returns ranked chart suggestions for a profiled dataset and optional intent; each suggestion carries a runnable props object, an intent-score breakdown, the chart's rubric (familiarity / accuracy / precision), human-readable reasons[], and caveats[]. suggestDashboard returns a multi-panel composite covering distinct analytical intents (with intentsMissing for honesty about what the data can't show). suggestStretchCharts returns the literacy-growth surface — charts the audience is unfamiliar with but the data actually supports. scoreChart and explainCapabilityFit give single-chart introspection. useChartSuggestions is the React hook wrapping the same engine for live UI.
    • Profiling. profileData(data) returns a ChartDataProfile with candidate fields per role (x / y / size / category / series / time), distinct counts, monotonicity, structure detection (hierarchy / network / geo). diffProfile reports schema changes between two profiles. inferIntent is a zero-dependency regex classifier that maps natural-language phrases ("why is X different?", "compare these", "trend over time") to one of 13 built-in intents.
    • Audience calibration. AudienceProfile is a serializable per-organization config — familiarity (chart → 1-5 number map) and targets (chart → {direction: "increase" | "decrease", weight, reason}) — that biases recommendations toward what a specific audience already knows AND toward charts the organization is trying to grow into. Three built-in personas (executivePersona, analystPersona, dataScientistPersona) ship as starting points; bias is meaningful (target weight 2 = ±2.0 on a 5-point composite score) and visible (the audience's verbatim rationale string lands on reasons[] so the policy is auditable in the UI).
    • Capability descriptors per chart. Every chart now ships a <ChartName>.capability.ts next to its TSX, declaring family, rubric, fits(profile) → reason | null, intentScores, optional variants, caveats, and buildProps. The registry is runtime-extensible via registerChartCapability / unregisterChartCapability so consumers can add their own charts to the recommendation pool without forking the engine.
    • 13 built-in intents in intents.ts: trend, compare-series, compare-categories, rank, part-to-whole, distribution, correlation, flow, hierarchy, geo, outlier-detection, composition-over-time, change-detection. Each carries a descriptor with synonyms, alias phrases, and a default scorer; registerIntent extends the taxonomy at runtime.
  • useChartInterrogation and useChartFocus hooks (semiotic/ai) — the headless conversational primitives. useChartInterrogation gives consumers a { ask, history, summary, annotations, loading, error, reset } surface; the consumer brings their own LLM via onQuery, and the hook supplies it with the profiled summary, the suggestion list, and the current focus datum as structured context. Returned annotations route directly to the chart's standard annotations prop so the AI's response can render as callouts, threshold lines, and bands, not just text. useChartFocus subscribes to the chart's observation store and returns the current point-of-focus ({ datum, x, y, source }), with configurable event-type filtering for sticky-focus UIs.
  • semiotic-mcp server — Model Context Protocol server (npx semiotic-mcp) exposing renderChart, interrogateChart, suggestCharts, and diagnoseConfig as MCP tools so agents inside Claude Code, Cursor, Windsurf, and other MCP-aware environments can drive Semiotic directly. The interrogation tool returns the same statistical summary and AI-facing instructions the hook produces; the suggestion tool returns ranked structured content with runnable props.
  • semiotic-ai CLI extensions--doctor validates a {component, props, data} JSON spec against validateProps + diagnoseConfig; --schema emits the chart-schema JSON; --compact and --examples produce LLM-prompt-sized context. Pair with the MCP server for agent workflows that need both schema and validation in one place.
  • Three case-study blog posts/blog/charts-that-know-what-theyre-for (the recommendation engine and audience layer), /blog/anchored-conversations (point-anchored AI conversation via useChartFocus + useChartInterrogation), and /blog/live-conversational-dashboard (the streaming + interrogation + annotation composition). The three together describe the product surface 3.6.0 makes possible.

Changed

  • AreaChart is now a single-series chart. Multi-series area overlays are an occlusion nightmare; the capability rejects the multi-series intent scores it previously claimed and buildProps subselects to the leading series (largest cumulative y) when the input has 2+ groups, surfacing a caveats[] line so the reader knows they're looking at one slice. Gradient (gradientFill: true, areaOpacity: 0.55) is the baseline default. trend score is 5 for clean single-series and 3 when subselected. LineChart.trend yields to AreaChart on single-series (4 vs AreaChart's 5) but still wins on multi-series (5 vs AreaChart's 3) because LineChart shows the whole dataset.
  • DifferenceChart accepts 2+ series via top-2 subselection. Previously rejected anything other than seriesCount === 2; now picks the two series with the highest cumulative y from the input and emits a caveats[] line when subselecting from 3+ series. Same ordered-x guard the other time-series capabilities apply (xProvenance === "scatter" && !monotonicX is rejected) so the chart no longer shows up for scatter-shaped data with two categorical groups.
  • Scatterplot and ConnectedScatterplot prefer the canonical 2-numeric form when a sequence axis is present. With a strong-x (time or named) AND 2+ other numerics in the dataset, both charts plot the two numerics against each other (revenue ×ばつ profit) instead of recapitulating a line chart on the sequence axis. ConnectedScatterplot threads the sequence as orderAccessor so the path encodes temporal progression. ConnectedScatterplot's correlation intent scores 5 when canonical (vs 4 otherwise), and Scatterplot's correlation steps back to 4 when canonical is available so ConnectedScatterplot wins the tiebreak — both charts fit, but the one with the temporal annotation is strictly more informative.
  • X_FIELD_HINT recognizes calendar-segment field names. The profiler's x-axis name regex now matches quarter, qtr, fiscal, and week in addition to the existing year / month / day / date / time / timestamp. Without this, data shaped as {quarter, revenue, region} fell into scatter-fallback provenance and series detection never fired — lineBy / areaBy were silently dropped and multi-series time-series charts zigzagged across regions.
Loading

Semiotic v3.5.4

22 May 04:38
@github-actions github-actions
c9561da
This commit was created on GitHub.com and signed with GitHub’s verified signature.
GPG key ID: B5690EEEBB952194
Verified
Learn about vigilant mode.

Choose a tag to compare

Added

  • band prop on LineChart and AreaChart (and StreamXYFrame) — asymmetric min/max envelope drawn under the lines/areas, driven by independent y0Accessor / y1Accessor. Distinct from the existing boundsAccessor (symmetric ±offset) and from AreaChart.y0Accessor (which replaces the area baseline). Pass a single BandConfig or an array of them for percentile fans (e.g. p25/p75 stacked on top of p10/p90). Per-series by default — one ribbon per lineBy / colorBy group, colored from the parent line at 0.2 fillOpacity. Pass perSeries: false for an aggregate min/max envelope across all series. Non-interactive by default (hovers pass through to the line on top); set interactive: true if the band should participate in hit testing. Band y0/y1 values feed yExtent auto-derivation so a tall envelope can never clip, with explicit yExtent still winning.
    • Tooltip enrichment now covers every interaction surface: the hovered datum carries band: { y0, y1 } (first band) and bands: [...] (all bands) on the pointer hover path, each allSeries[i].datum in multi-mode, and the keyboard-navigation datum — one shared enrichDatumWithBand helper drives all three. Bounds-sourced ribbons stay decorative and are excluded from the contract.
    • Default tooltip surfaces band values automatically: configure band without supplying a custom tooltip function and the default tooltip gains one row pair per band (low + high). String accessors become labels; function accessors fall back to low / high. Custom tooltips still read datum.band / datum.bands directly. Live demo at /charts/line-chart#band.
  • tickAnchor: "edges" on frameProps.axes[i] — flips the leftmost tick's text-anchor to start and the rightmost to end on horizontal axes (and dominant-baseline to hanging / auto on vertical axes) so edge tick labels can't overflow the plot area. Default "middle" keeps existing behavior. Pairs naturally with axisExtent: "exact": exact pins the domain to the literal data min/max, edges keeps the labels readable at those bounds. Edge detection is pixel-based, not array-index-based, so inverted y scales (the default [height, 0]) and reversed x scales (streaming arrowOfTime: "left") anchor the right edges. Closes a common wrapper-library workaround that previously routed through xFormat returning ReactNodes with translateX math.
  • --semiotic-tick-font-size and --semiotic-axis-label-font-size CSS variables — emitted from the canonical theme typography fields (tickSize, labelSize) alongside the existing --semiotic-tick-font-family and --semiotic-title-font-size. Both themeToCSS (raw string serialization) and ThemeProvider (inline style) write them; themeToTokens exports them as DTCG dimension tokens. SVG axes consume the variables via style={{ fontSize: "var(--semiotic-tick-font-size, 10px)" }} so a CSS-var override on any ancestor (<div style={{ "--semiotic-tick-font-size": "14px" }}>) flows down without consumers needing !important. Landmark ticks bump by calc(... + 1px) so the +1 size stays relative to the var.
  • data-orient attributes and per-axis class names on axis groups — each axis now renders as its own <g class="semiotic-axis semiotic-axis-{bottom|left|right|top}" data-orient="..."> inside the .stream-axes wrapper. Consumers can target one axis at a time from external CSS without affecting the others: [data-orient='left'] text { font-size: 14px } works. Tick text carries class="semiotic-axis-tick", axis labels class="semiotic-axis-label", and chart titles class="semiotic-chart-title" for class-based targeting too.
  • loadingContent prop on all HOCs — sibling to emptyContent. When loading is true and loadingContent is set, it renders in place of the default shimmer-bar skeleton (wrapped in the same sized container so the chart slot stays reserved). Pass false to suppress the loading UI entirely (the early-return becomes null and a consumer's outer loading state takes over). Threaded through useChartSetup, useNetworkChartSetup, and useCustomChartSetup; all 47 HOCs accept it via BaseChartProps.

Fixed

  • website:build parcel resolution for the Atom feed linkdocs/public/index.html previously declared <link rel="alternate" href="/blog/feed.xml"> with an absolute path so prerendered nested routes (e.g. /charts/line-chart/) wouldn't resolve it as /charts/line-chart/blog/feed.xml. Parcel's HTML packager couldn't resolve the absolute path during build, so the website build failed. Moved the link injection into scripts/prerender.mjs alongside the existing /llms.txt alternate injection — same strip-and-inject pattern, same absolute-URL semantics, and Parcel no longer sees the unresolvable reference in source HTML.

Changed

  • boundsAccessor and band now share one rendering primitive. Both public envelope APIs normalize to a single resolvedRibbons: ResolvedRibbon[] array at the PipelineStore layer, then flow through xySceneBuilders/ribbonScene.ts — one scene builder, one y-extent expansion pass, one style cascade. boundsScene.ts and bandScene.ts are deleted; the public prop surfaces stay distinct (asymmetric pairs read better as band than as a boundsAccessor union return type) but the implementation is no longer duplicated. The bounds ribbon also now correctly skips datums with null/NaN y (previously the coerced +null === 0 could silently render a ribbon around the implicit-zero "value" of a missing row). The kind: "bounds" | "band" discriminator on each ribbon lets the hover handler restrict datum.band / datum.bands enrichment to band-sourced envelopes — bounds stays decorative-only, matching its prior contract.
Loading

Semiotic v3.5.3

19 May 03:50
@github-actions github-actions

Choose a tag to compare

Added

  • DifferenceChart (XY) — two-series A/B comparison chart that fills the area between two series with a color that switches at each crossover (seriesAColor where A > B, seriesBColor where B > A). Crossover x-values are linearly interpolated so adjacent segments meet at zero-width vertices (no jagged seams). Both series can be drawn as overlay lines on top of the fill via showLines (default true). Renders through chartType: "mixed" with the segment groups in areaGroups — single frame, single set of scales, perfect geometric alignment between fill and overlay. Push API supported (HOC owns internal raw-data state; push triggers segment recomputation). Classic uses: temperature anomaly, forecast vs. actual, budget variance, any A/B comparison where the direction of the difference is the message. Live demos + Quick Start streaming toggle at /charts/difference-chart. New SSR config + validation map entry + chartSpecs entry → schema regenerated.
  • axisExtent prop on all XY and ordinal HOCs"nice" (default, current behavior) uses d3-scale's rounded tick generator; "exact" pins the first and last tick to the literal data min/max with equidistant intermediate ticks. Applies to XY x/y axes and the ordinal value (r) axis only; no-op on network/geo/hierarchy. In exact mode the pipeline ALSO skips extentPadding so the domain reflects the literal data bounds, not a padded version — explicit tickValues, xExtent/yExtent/rExtent still win over both modes. Three demos at /features/axes#axis-extent (temporal LineChart, Scatterplot, SwarmPlot). Centralized equidistantTicks + ticksForMode helpers in src/components/charts/shared/axisExtent.ts.
  • roundedTop on SwimlaneChart — pixel radius rounds the outermost ends of each lane (left+right for horizontal, top+bottom for vertical). Middle segments stay square so adjacent pieces butt against each other; single-segment lanes round all four corners. Implemented via a new cornerRadii?: { tl, tr, br, bl } field on RectSceneNode and shared shape utilities in src/components/stream/renderers/cornerRadii.ts (canvas and SVG renderers share the geometry; each owns its drawing language). Live demo at /charts/swimlane-chart#rounded-corners.
  • buildHistogramTooltip helper — histogram-specific default tooltip for RealtimeHistogram, sibling to buildWaterfallTooltip / buildHeatmapTooltip. Surfaces range: <binStart>–<binEnd>, count: <total>, and category: <category> instead of the canonical x:/y: shape, which produced empty strings on aggregated bin datums. Falls back to the canonical shape when a non-binned datum sneaks through.
  • tickValues on XY axes (frameProps.axes[i].tickValues) — explicit per-axis tick positions, mirroring the ordinal frame's rTickValues. Previously the field appeared in the docs and the docs LiveExample but was silently ignored by SVGOverlay's tick computation; now it bypasses both d3's "nice" generator and axisExtent: "exact" and wins over includeMax. Pixel-distance filtering still drops overlapping labels. Accepts Array<number | Date>. Pinning regression test in SVGOverlay.tickValues.test.tsx.
  • ProcessSankey systemInTimeAccessor / systemOutTimeAccessor and showLabels — optional per-edge lifecycle timestamps let a source band show mass waiting before the edge departs and a target band show mass retained after the edge arrives. The band outline now extends to those lifecycle bounds and paints per-edge gradient stubs; showLabels={false} suppresses dense band labels without dropping the legend. The docs page adds a helpdesk-ticket example plus the Process Sankey vs. classic Sankey recipe.
  • Docs blog/blog now has article and index routes, a distinct no-sidebar shell, Atom feed generation, social-card generation, route prerender metadata, and seven launch entries covering release notes, chart explainers, and case studies.

Fixed

  • Area canvas renderer respects CSS-variable fillsareaCanvasRenderer.ts now resolves style.fill through the existing resolveCanvasFill helper (same primitive bars use), so var(--...) references resolve from the canvas DOM ancestor. Previously the fill path skipped this resolution while the stroke path included it — passing a CSS variable as the area fill produced no visible color (canvas silently rejects unresolved CSS vars) and the gradient path fell back to the sentinel blue regardless of the requested color. Affects any chart that emits area-type scene nodes with var(--...) fills.
  • DifferenceChart accessor coercionxAccessor / seriesAAccessor / seriesBAccessor outputs now flow through a toNumber coercer that handles Date (→ getTime() ms) and numeric strings ("5"5) before the Number.isFinite filter. Previously, time-series data (Date objects in xAccessor) and CSV-style numeric strings were silently dropped at the segment-algorithm guard, producing an empty chart.
  • DifferenceChart crossover detection across non-finite rows — the segment algorithm now tracks the last VALID point (not sorted[i - 1]) for crossover comparison, so a NaN gap between two valid rows no longer suppresses the segment break that should sit between them.
  • DifferenceChart remove() / update() synchronous return values — both methods compute results from a useRef-backed live buffer and return them synchronously at call time. The earlier pattern built results inside the setState updater, which could return empty arrays under React 18+ concurrent batching if the updater was deferred or replayed.
  • DifferenceChart bounded push buffer — new top-level windowSize prop caps the raw-row buffer with FIFO eviction. Long-running streams no longer accumulate unbounded rows that the segment algorithm has to re-sort and re-segment on every render. The previous frameProps.windowSize recommendation in the docs had no effect (the underlying frame receives static data from this chart, not streaming inputs), so the docs streaming example and Quick Start were updated to use the new prop.
  • ProcessSankey hover and tooltip regressions — decorative gradient stubs opt out of hit testing, filled bezier-body hits now return finite pointer coordinates for ProcessSankey's custom datum shape, and the default tooltip no longer turns short numeric domains (day/month indices) into 1970 dates.
  • ProcessSankey SSR parity for lifecycle stubsrenderChart("ProcessSankey", ...) now threads systemInTimeAccessor and systemOutTimeAccessor into the shared scene builder, so static SVG output uses the same lifecycle band bounds as the client HOC.
  • Blog metadata correctness — blog entry dates are formatted at UTC midnight so US timezones do not display the previous day, and the Atom feed link is absolute so prerendered nested routes do not point at /charts/blog/feed.xml.

Changed

  • extentPadding skipped in axisExtent="exact" mode — both PipelineStore and OrdinalPipelineStore now treat extentPadding as 0 when config.axisExtent === "exact", so the scale domain pins to the literal data min/max and the first/last ticks read as the actual bounds. Trade-off documented: glyphs at the extremes can sit at the plot edge in exact mode. Default "nice" keeps the existing padded domain.
  • Per-corner radius geometry centralizedhasAnyCornerRadius and corner-clamping logic extracted from barCanvasRenderer.ts and SceneToSVG.tsx to a shared cornerRadii.ts module. Each renderer keeps its own path-tracing primitives (arcTo vs SVG A); the geometry agrees by construction.
  • Capability matrix regenerated and release-gatedai/capabilities.json and docs/capabilities.md now index all 45 chart schemas, including DifferenceChart; QuadrantChart is marked supportsSSR: true to match its renderChart registration; check:capabilities is wired into CI, release:check, and prepublishOnly.
  • Blog registry drift is release-gated — new check:blog-entries keeps docs/src/blog/entries.js and entries-meta.js in sync, and runs during website:build, CI, release:check, and prepublishOnly.
  • Server-rendered QuadrantChart officially supported — the SSR config emits quadrant fills, centerlines, and labels via svgPreRenderers, which also powers the QuadrantChart blog OG card.
Loading

Semiotic v3.5.2

12 May 22:38
@github-actions github-actions

Choose a tag to compare

Added

  • useSeriesFeatures hookforecast + anomaly props are now first-class on AreaChart, Scatterplot, and ConnectedScatterplot (previously LineChart-only). Each consumer collapses from ~85 LOC of synthetic-key + lazy-load + state-management boilerplate to ~10 lines via the shared hook. series-features, forecast, and anomaly capability tags surface through chartSpecs.ts / ai/capabilities.json for agent discovery.
  • useEncodingDomain hook — generic [min, max] tracker over bounded data + push-mode values, extracted from BubbleChart's sizeBy logic. Scatterplot's sizeBy now picks up correctly-scaled radii in push mode (previously a latent bug that returned the raw sizeBy value as the pixel radius). String-field accessors hitting numeric-string values ("5", "12") coerce cleanly instead of leaking strings into downstream math.
  • useStreamStatus hook — user-facing observer for push-API charts. Wraps a ref, intercepts push/pushMany, and exposes a reactive status enum ("idle" | "active" | "stale") plus lastPushTime. Surfaced via semiotic/utils and semiotic/realtime. Wrap-once symbol guard prevents StrictMode double-wrap.
  • useXYLineStyle hook (Phase 2 step 5 of the HOC/Frame audit) — the line-side analogue of useXYPointStyle. LineChart, MultiAxisLineChart, and MinimapChart (both main + overview lines) all collapse to a single hook call covering the five-step recipe: base stroke width → color resolution → optional group-aware fill → mergeShapeStyle primitives overlay → wrapStyleWithSelection. A resolveStroke(d, group?) override absorbs MultiAxisLineChart's per-series colorMap; unset selection-hook / primitives args keep MinimapChart's main + overview paths intact (no-ops on the wraps preserve referential identity). LineChart's forecast/anomaly segment-aware wrap stays HOC-side as a post-pass over the hook's output — the lazy-load + state-management contract has no counterpart in the other two consumers. Net ~65 LOC removed across the three HOCs. 15 unit tests pin the recipe.
  • Bundle-size truth sourcescripts/sync-bundle-sizes.mjs reads package.json#exports, gzips each *.module.min.js, and upserts marker-block sections in README.md, CLAUDE.md, and ai/system-prompt.md (the synced .cursorrules / .windsurfrules / .github/copilot-instructions.md / .clinerules / docs/public/llms-full.txt follow from CLAUDE.md). check:bundle-sizes is wired into release:check, prepublishOnly, and the CI workflow alongside the other doc-correctness gates, so dependency bumps that nudge a bundle past its rounded KB boundary now fail CI when the docs haven't been regenerated. Drops the stale // 200 KB gzip hero comment in the README — the autogenerated table is the only source of truth.
  • radialGeometry helperssweepToAngles, valueToAngle, computeArcBoundingBox extracted from GaugeChart into a shared module, exposed via semiotic/utils. Custom radial-chart authors (XYCustomChart, bespoke layouts) no longer have to re-derive the gauge sweep math.
  • ProcessSankey temporal validatorsvalidateProcessSankey and formatProcessSankeyIssue exported from semiotic and semiotic/network. External code (data pipelines, AI agents, server-side validators) can pre-check graphs against the same value-conservation + endpoint-resolution rules the chart enforces.
  • regression prop on Scatterplot, BubbleChart, ConnectedScatterplot, BarChart, DotPlot — sugar over the trend annotation. Accepts true | method string ("linear" | "polynomial" | "loess") | full RegressionConfig. Ordinal charts treat categories as integer indices and project the regression line through the band scale (with linear interpolation between band centers for LOESS fractional indices).
  • FlowMap push API — joined the realtime-capable HOC family. The frame gained a geo-lines variant on useFrameImperativeHandle plus pushLine / pushManyLines / removeLine / getLines / lineIdAccessor on GeoPipelineStore. supportsPush: true in capabilities; docs streaming demo flipped from setState(flows) to ref.current.push(flow).
  • Capability matrix at ai/capabilities.json — 44 charts indexed across 5 categories with renderModes / supportsPush / supportsSSR / supportsLegend / supportsSelection / supportsLinkedHover / colorModel / layoutMode / specialFeatures fields. Generated alongside docs/capabilities.md by npm run docs:capabilities; locked against chartSpecs.ts by check:capabilities. suggestCharts({ capabilities }) accepts push/linkedHover/ssr/selection/legend constraints and surfaces a filteredOut list with reasons. New /features/capabilities website page renders an interactive filterable matrix.

Changed

  • ProcessSankey particles unified with SankeyDiagram — particles now ride the canvas + ParticlePool path. The HOC writes pre-computed cubic bezier control points onto each ribbon spec; NetworkPipelineStore's particle-pool gate broadened from chartType === "sankey" to also accept customNetworkLayout. SVG particle overlay deleted (~80 LOC, including the <circle>-per-particle allocation per frame). Prop surface aligned: showParticles + particleStyle (same ParticleStyle shape as SankeyDiagram). Individual particleRadius / particleDuration / particleDensity / particleMaxPerEdge props removed. Particles inherit source-band colors via nodeColorMap binding through invisible color-binding scene nodes.
  • Ribbon geometry unified — new src/components/geometry/ribbonGeometry.ts is the single source of truth for the M-C-L-C-Z ribbon path emission. SankeyDiagram passes cp1X = xi(curvature), cp2X = xi(1-curvature) (d3-sankey S-curve); ProcessSankey passes cp1X = cp2X = cx (lane-aware single-point bend). Both buildScenes.ts (SSR) and the HOCs (CSR) call the same helper.
  • algorithm.jsalgorithm.ts — last JS file in the chart source tree migrated to TypeScript with all types inlined as the canonical source (algorithm.d.ts deleted). 7 import sites updated to drop the .js extension; test file converted with type-annotated fixtures.
  • getSize clamps to sizeRange — normalized position is now clamped to [0, 1] before mapping into the size range, so a pushed point whose sizeBy value falls outside the running domain (most common in push-mode initial state) renders at the boundary radius instead of producing an arbitrarily large pixel value.
  • Push-mode bezier carry-throughNetworkPipelineStore.ingestBounded now copies pre-computed bezier from raw edges onto internal RealtimeEdge records, validated against the BezierCache shape (object + circular: boolean + 4-point or non-empty-segments + finite halfWidth). Malformed shapes are silently dropped instead of crashing the particle pipeline.
  • Edge value preservation — bounded ingestion now uses Number.isFinite(numValue) ? numValue : 1 instead of Number(v) || 1, so a legitimate value: 0 edge survives end-to-end (e.g. suppressed-flow markers in particle pipelines).
  • Particle CSS variable resolutionnetworkParticleRenderer runs all colors through resolveCSSColor so particleStyle.color="var(--semiotic-primary)" and theme-token-returning edgeColorFn results paint correctly (canvas's fillStyle silently rejects CSS custom properties otherwise).
  • Particle color resolution moved out of the renderer — functional particleStyle.color is now invoked in getParticleColor with a resolveEdgeEndpoint-resolved RealtimeNode. Custom-layout charts (ProcessSankey) where edge.source is a string id now correctly invoke the user's color function instead of falling back to a hardcoded default.
  • Keyboard nav skips invisible scene nodesextractNetworkNavPoints skips r <= 0 circles and w <= 0 || h <= 0 rects (matching the canvas renderer's own skip gates). Keyboard focus on ProcessSankey now lands on a real band/ribbon instead of an off-canvas color-binding placeholder.
  • Bundle countssemiotic/ai covers 40 HOCs (XY + ordinal + network + realtime); semiotic/recipes added to the table; full schema covers 44 charts.
  • Documentation refreshed — README, CLAUDE.md, ai/system-prompt.md, and the synced .cursorrules / .windsurfrules / .github/copilot-instructions.md / .clinerules / docs/public/llms-full.txt all carry current bundle sizes, chart counts, and entry-point inventory.
  • Bundle-size docs corrected — earlier in this release cycle the README/CLAUDE.md/ai/system-prompt.md bundle table briefly carried inflated numbers because npm run dist (no --production) writes non-minified output to dist/*.module.min.js. The published artifacts come from npm run dist:prod, which terser-minifies. Both scripts/sync-bundle-sizes.mjs and size-limit read dist/*.module.min.js directly, so a local dist build silently substituted unminified bytes into the docs. The corrected numbers (xy 81 KB gz, ordinal 66 KB, network 62 KB, etc.) now reflect actual published artifacts. The bundle-size check tolerates ±3 KB build-machine variance so local↔CI minor differences don't fail without real growth.

Fixed

  • Fixed ProcessSankey particles not flowing when showParticles was toggled on (root cause: customNetworkLayout charts skipped finalizeLayout, so pre-computed bezier never reached store.edges).
  • Fixed ProcessSankey particles rendering as light grey instead of inheriting source-node category color.
  • Fixed Number.isFinite coercion in useEncodingDomain so the running domain is always numeric.
Loading

Semiotic v3.5.1

06 May 16:26
@github-actions github-actions

Choose a tag to compare

Added

  • Added explicit extent examples and tests covering chart-level xExtent/yExtent pass-through.

Fixed

  • Fixed yExtent handling so explicit user bounds continue to control the rendered domain instead of being overridden by envelope-derived extents.
  • Fixed realtime heatmap tooltip metadata so bin-center values are available and agg="sum" tooltips report summed values.
Loading
Previous 1 3 4 5 13 14
Previous

AltStyle によって変換されたページ (->オリジナル) /