Atomic Angular — Doc interne

Aggregation Timeline

A time series with a drag-to-select range brush, on Chart.js — no d3, no date adapter, gap-filled buckets.

A date aggregation's buckets, plotted as a stepped line with an optional drag-to-select brush — replacing an ~800-line d3 timeline with Chart.js alone, plus a category axis and a small brush plugin.

Optional peer dependency

Ships from @sinequa/atomic-angular/charts, same as <AggregationChart> — see that page for the chart.js install note and the shared <ChartCanvas> lifecycle rules.

Minimal example

Documents by modification date
sample.component.ts
import { Component, signal } from "@angular/core";
import { AggregationTimelineComponent } from "@sinequa/atomic-angular/charts";
import type { TimelineRange } from "@sinequa/atomic-angular/charts";
import type { TimelineSeriesInput } from "@sinequa/atomic-angular/charts";

@Component({
  selector: "sample-component",
  imports: [AggregationTimelineComponent],
  template: `
    <div class="h-64">
      <AggregationTimeline [series]="series()" (rangeSelected)="onRange($event)" />
    </div>
  `,
})
export class SampleComponent {
  readonly series = signal<TimelineSeriesInput[]>([]);

  protected onRange(range: TimelineRange) {
    console.log(`Zoom into ${range.from} .. ${range.to}`);
  }
}

How it works

A category axis, never "time" — this library ships no Chart.js date adapter, and setting scales.x.type = "time" without one compiles perfectly and throws at runtime. Bucket labels are resolved by buildTimeline() (a pure function, unit-testable without a chart), which also fills gaps: an empty bucket is drawn flat at zero rather than skipped, so the shape of the series is never silently misrepresented.

on release series input buildTimeline(series, options) labels + gap-filled values per series ChartConfiguration (category axis, stepped line) createTimelineBrushPlugin() drag-to-select rangeSelected

(rangeSelected) only reports a range — it does not zoom anything on its own. If nothing in the host reacts to it, dragging paints a selection rectangle that then disappears and nothing else happens; the component is working as designed. Keep a stack of ranges in the host: a drag pushes one (zoom in), a control pops it (zoom out).

Recipes

Comparing two periods

dashSecondary renders every second series dashed, the "previous period" convention, and pairs it with the same color as the series it compares against rather than doubling the palette.

This period vs. the previous one
period-comparison.component.ts
import { Component, signal } from "@angular/core";
import { AggregationTimelineComponent } from "@sinequa/atomic-angular/charts";
import type { TimelineSeriesInput } from "@sinequa/atomic-angular/charts";

@Component({
  selector: "period-comparison",
  imports: [AggregationTimelineComponent],
  template: `
    <div class="h-64">
      <AggregationTimeline [series]="series()" [dashSecondary]="true" mask="YYYY-MM-DD" />
    </div>
  `,
})
export class PeriodComparisonComponent {
  // This-period and previous-period series, interleaved: [current, previous, current, previous, ...].
  readonly series = signal<TimelineSeriesInput[]>([]);
}

Options

Prop

Type

Pitfalls

What's next

On this page