Source

81 chart lines · 2 files · 2.3 kBBenchmark harness excluded · shared/mount.ts

U.S. industry unemployment1,708 records · CSV · 53.9 kB
@charts-poc/demo-data/industries

Selection: Complete published snapshot

date
Date
industry
string
unemployed
number

U.S. Bureau of Labor Statistics@observablehq/sample-datasets@1.0.1 · revision 732c0148de74 · industries.csv · ISC distribution; upstream source credited · SHA-256 4cfc13b6ebe0Pinned snapshot

cases/02-multi-line-end-labels/tanstack.ts58 lines · entry
cases/02-multi-line-end-labels/tanstack.ts
import { defineChart, lineY, text } from '@tanstack/charts'
import { group } from 'd3-array'
import { scaleLinear, scaleUtc } from 'd3-scale'
import { industries } from '@charts-poc/demo-data/industries'
import type { ConformanceInput, ConformanceMount } from '../../types'
import { tanstackMount } from '../../shared/mount'
import { selectMultiLineData } from './selection'
import type { MultiLineDatum } from './selection'

const colors = ['#2563eb', '#ea580c', '#059669']

const definition = (input: ConformanceInput) => {
  const rows = selectMultiLineData(industries, input.revision)
  const endpoints = lastBySeries(rows)

  return defineChart({
    marks: [
      lineY(rows, {
        x: 'date',
        y: 'unemployed',
        color: 'industry',
        strokeWidth: 2.25,
      }),
      text(endpoints, {
        x: 'date',
        y: 'unemployed',
        text: 'industry',
        color: 'industry',
        anchor: 'start',
        dx: 5,
        fontWeight: 600,
      }),
    ],
    x: { scale: scaleUtc, axis: { label: 'Week' } },
    y: {
      scale: scaleLinear,
      grid: true,
      axis: { label: 'Unemployed (thousands)' },
    },
    color: {
      range: colors,
    },
    margin: { right: 112 },
  })
}

export const mount: ConformanceMount = tanstackMount(
  definition,
  'Unemployment by industry with direct end labels',
)

function lastBySeries(
  rows: readonly MultiLineDatum[],
): readonly MultiLineDatum[] {
  return Array.from(group(rows, (row) => row.industry).values(), (groupRows) =>
    groupRows.at(-1),
  ).filter((row): row is MultiLineDatum => row !== undefined)
}
cases/02-multi-line-end-labels/selection.ts23 lines · support
cases/02-multi-line-end-labels/selection.ts
import type { IndustriesRow } from '@charts-poc/demo-data/industries'

export const industryNames = ['Manufacturing', 'Construction', 'Finance']
export type IndustryName = (typeof industryNames)[number]
export type MultiLineDatum = IndustriesRow & {
  readonly industry: IndustryName
}

export function selectMultiLineData(
  rows: readonly IndustriesRow[],
  revision = 0,
): readonly MultiLineDatum[] {
  const offset = Math.abs(revision) % 2
  const start = Date.UTC(2000, offset)
  const end = Date.UTC(2003, offset)

  return rows.filter(
    (row): row is MultiLineDatum =>
      row.date.getTime() >= start &&
      row.date.getTime() < end &&
      industryNames.some((industry) => industry === row.industry),
  )
}