Source
135 chart lines · 2 files · 3.5 kBBenchmark harness excluded · shared/mount.ts
Flare package hierarchy252 records · CSV · 8.0 kB
@charts-poc/demo-data/flareSelection: Complete published snapshot
- name
- string
- size
- number | null
Flare visualization toolkit@observablehq/sample-datasets@1.0.1 · revision 732c0148de74 · flare.csv · ISC distribution; upstream source credited · SHA-256 704349b51b70Pinned snapshot
cases/96-nested-donut/tanstack.ts64 lines · entry
cases/96-nested-donut/tanstack.ts
import { flare } from '@charts-poc/demo-data/flare'
import { defineChart } from '@tanstack/charts'
import { polar, radialArc } from '@tanstack/charts/polar'
import { pie } from 'd3-shape'
import { nestedFlareDonut } from './transform'
import { tanstackMount } from '../../shared/mount'
import type { FlareDonutSlice } from './transform'
import type { ConformanceInput } from '../../types'
const innerLayout = pie<FlareDonutSlice>()
.sort(null)
.value(({ size }) => size)
const outerLayout = pie<FlareDonutSlice>()
.sort(null)
.value(({ size }) => size)
const names = [
'flare.animate',
'flare.data',
'flare.animate.core',
'flare.animate.interpolate',
'flare.data.core',
'flare.data.converters',
]
const colors = [
'#38bdf8',
'#8b5cf6',
'#0284c7',
'#0ea5e9',
'#7c3aed',
'#a855f7',
]
const definition = (input: ConformanceInput) => {
const sourceRows =
input.revision % 2 === 0
? flare
: flare.filter((row) => row.size === null || row.size >= 1_000)
const data = nestedFlareDonut(sourceRows)
const innerArcs = innerLayout([...data.inner])
const outerArcs = outerLayout([...data.outer])
return defineChart({
marks: [
polar({
radiusRatio: 0.8,
marks: [
radialArc(innerArcs, {
innerRadius: ({ radius }) => radius * 0.12,
outerRadius: ({ radius }) => radius * 0.46,
color: ({ data }) => data.name,
}),
radialArc(outerArcs, {
innerRadius: ({ radius }) => radius * 0.56,
color: ({ data }) => data.name,
}),
],
}),
],
color: { domain: names, range: colors },
margin: 0,
})
}
export const mount = tanstackMount(definition, 'Nested Flare package sizes')cases/96-nested-donut/transform.ts71 lines · support
cases/96-nested-donut/transform.ts
import type { FlareRow } from '@charts-poc/demo-data/flare'
export interface FlareDonutSlice {
name: string
size: number
}
export interface FlareDonutDetail extends FlareDonutSlice {
family: string
}
export interface FlareDonutData {
inner: readonly FlareDonutSlice[]
outer: readonly FlareDonutDetail[]
}
interface DetailGroup {
name: string
family: string
includes: (name: string) => boolean
}
const detailGroups: readonly DetailGroup[] = [
{
name: 'flare.animate.core',
family: 'flare.animate',
includes: (name) =>
name.startsWith('flare.animate.') &&
!name.startsWith('flare.animate.interpolate.'),
},
{
name: 'flare.animate.interpolate',
family: 'flare.animate',
includes: (name) => name.startsWith('flare.animate.interpolate.'),
},
{
name: 'flare.data.core',
family: 'flare.data',
includes: (name) =>
name.startsWith('flare.data.') &&
!name.startsWith('flare.data.converters.'),
},
{
name: 'flare.data.converters',
family: 'flare.data',
includes: (name) => name.startsWith('flare.data.converters.'),
},
]
export function nestedFlareDonut(rows: readonly FlareRow[]): FlareDonutData {
const leaves = rows.filter(
(row): row is FlareRow & { readonly size: number } => row.size !== null,
)
const outer = detailGroups.map((group) => ({
name: group.name,
family: group.family,
size: leaves.reduce(
(total, row) => total + (group.includes(row.name) ? row.size : 0),
0,
),
}))
const inner = ['flare.animate', 'flare.data'].map((family) => ({
name: family,
size: outer.reduce(
(total, detail) => total + (detail.family === family ? detail.size : 0),
0,
),
}))
return { inner, outer }
}