Graflume · Alpha

Documentation

Build your first chart with the exact verified snapshot. Learn the data, ChartSpec, Scene, and lifecycle contracts.

Quick start

Graflume.create()

Build your first chart with the exact verified snapshot.

  1. 1

    Browser snapshot

    exact commit · SRI · CDN

  2. 2

    Row data

    row[] / TypedArray columns

  3. 3

    ChartSpec 0.1

    create() · resize() · destroy()

<script defer
  src="https://cdn.jsdelivr.net/gh/statground/graflume@4affa24255ec2145ef9983a7f0aea586d5189926/cdn/graflume.global.js"
  integrity="sha384-5RM5TBHV62iDnvZKAHQFcMiZsT2ASkHua9qBVG6rwNuPIa3qABTKT3us0S26nITS"
  crossorigin="anonymous"></script>
<div id="chart" style="height: 360px"></div>
<script>
  const rows = [
    { month: 'Jan', sales: 42 },
    { month: 'Feb', sales: 51 },
    { month: 'Mar', sales: 49 }
  ];

  const chart = Graflume.line('#chart', rows, {
    x: { field: 'month', type: 'ordinal' },
    y: { field: 'sales', type: 'quantitative' },
    theme: 'graflume-light',
    mark: { point: true }
  });
</script>

npm · Not published · UNLICENSED

Manual

Graflume · Manual

Learn the data, ChartSpec, Scene, and lifecycle contracts.

01row / structured data
02ChartSpec / SpatialSpec 0.1
03validate · normalize · compile
04Canvas 2D / WebGL
  1. 1

    Choose a chart type and theme, then render again to see the same row data expressed by another specification.

  2. 2

    Select a chart mark and inspect the status area to see which row its safe data event identifies.

  3. 3

    Compare the table with the generated ChartSpec, export a PNG, and destroy the instance when leaving the page.

ChartSpec 0.1

Portable schema

Function-free ChartSpec 0.1 keeps charts portable and serializable.

urn:graflume:schema:0.1 · function-free JSON
DataTable

Row data

Row data and zero-copy TypedArray columns share one data contract.

row objects · zero-copy TypedArray columns
standard · large · ultra

Performance

Standard, large, and ultra profiles bound rendering work.

bounded line · point · bar rendering · responsive resize
validate()

Security defaults

Functions, unsafe keys, raw HTML, and runtime evaluation are rejected.

functions · unsafe keys · raw HTML · runtime evaluation

ChartSpec · current runtime

Core concepts

Current executable foundations are ordered by the embedded Graflume catalog. Every statement below describes an enforced schema or runtime boundary.

transform-dataflow supported

Transform dataflow & lineage

Ordered function-free transforms, top-level and layer pipelines, deterministic row lineage, parameters, seeded operations, aggregation counts, named sources, reusable branches and a shared transform DAG are supported.

  • transform[]
  • compile().dataLineage
  • Scene.metadata.dataLineage

Current boundary: The portable transform registry is closed and function-free: arbitrary executable transforms, host side effects and opaque callbacks are rejected.

encoding-scale-registry supported

Encoding & scale registry

A closed portable encoding map, conditional mark channels, geographic and trading channels, 17 positional/categorical/probability/temporal scale types, four color scale types, and shared or independent multi-view domains, axes, legends and colorbars are supported.

  • encoding
  • createPositionScale()
  • createColorScale()
  • Scale.map()
  • Scale.invert()
  • Scale.ticks()

Current boundary: Channels and scales use a closed registered vocabulary; arbitrary executable accessors and unregistered mark/channel contracts fail validation.

analytic-interaction supported

Analytic selection & domain navigation

A closed immutable v1 store, union/intersection semantics, point/interval/rectangle/axis/lasso state, Canvas pointer/touch and keyboard-authored geometry, continuous and categorical pixel/domain navigation, linked multi-view state, and lineage-preserving selection-driven filtering are supported.

  • interaction.selection
  • interaction.domainNavigation
  • getAnalyticSelection()
  • applyAnalyticSelection()
  • domainToPixel()
  • pixelToDomain()
  • zoomDomainBy()
  • panDomainBy()

Current boundary: Spatial analytic selection remains a separate renderer boundary; selection state and filtering stay inside the closed portable interaction contract.

composition-resolve supported

Composition & resolve

Legacy flat layers and the closed layer/facet/repeat/hconcat/vconcat/concat/inset Canvas composition grammar are supported with deterministic bounded layout, scoped semantic and lineage identities, named axes, shared or independent multi-view domains/axes/legends/colorbars, linked view state, per-layer transforms, z-order and clipping.

  • layer
  • facet
  • repeat
  • hconcat
  • vconcat
  • concat
  • inset
  • resolve

Current boundary: Facet virtualization, renderer mixing and Spatial composition remain separate boundaries; composition stays deterministic and bounded.

semantic-index-accessibility supported

Semantic accessibility mirror

All Canvas families compile a bounded lineage-aware semantic index and expose a virtualized native explorer with full roving traversal, focus-ring, tooltip and selection synchronization. Spatial GPU views expose projected roving traversal and active-descendant synchronization, while a bounded stable-key focus store links Canvas and Spatial views through a portable authored contract.

  • getSemanticIndex()
  • toAccessibleRows()
  • getAccessibilityState()
  • accessibility.table
  • accessibility.navigation

Current boundary: Accessibility explorers and focus stores are bounded, authored semantic projections rather than an unbounded DOM mirror of every rendered primitive.

label-layout-authoring supported

Mark-label layout & annotation authoring

All 41 Canvas families support function-free reusable markLabels with stable-key portable positions, deterministic automatic collision placement, connectors, editing handles, pointer drag, keyboard selection and nudging, grid/mark/plot snapping, bounded undo/redo, runtime import/export events and accessible instructions/live status. Annotation adds a closed data-coordinate point/rule/band/label/callout registry with drag, resize and history.

  • markLabels
  • getMarkLabelState()
  • getMarkLabelPositions()
  • setMarkLabelPositions()
  • undoMarkLabelEdit()
  • redoMarkLabelEdit()
  • marklabelchange
  • getAnnotations()
  • setAnnotations()
  • addAnnotation()
  • removeAnnotation()
  • annotationchange

Current boundary: Authoring uses closed markLabels and data-coordinate annotation primitives; raw HTML, arbitrary event code, freehand drawing and image authoring are excluded.

incremental-worker-binary supported

Incremental streaming & worker adapter

Stable-key append/upsert/replaceLast uses bounded ring storage, explicit reject/drop-oldest/coalesce queues, count/event-time retention and replay. Row-local transforms recompute changed keys with exact global fallback; the frame runtime adds RAF coalescing, cancellation, pause/follow-live and lazy bounded history. Automatic module Workers accept row, typed-column and Arrow-compatible binary envelopes, injected JavaScript/WASM adapters and worker-owned renderers with bounded work and cancellation.

  • streaming
  • appendData()
  • updateData()
  • upsertData()
  • replaceLastData()
  • getStreamingState()
  • exportStreamingReplay()
  • replayData()
  • createIncrementalDataStore()
  • createTransformWorkerAdapter()
  • installTransformWorker()

Current boundary: Queues, histories and worker work remain explicitly bounded; JavaScript/WASM adapters must be installed by the host and cannot introduce opaque unbounded execution.

ChartSpec · axes

Axis system

Configure axis placement, value formatting, label direction, typography, ticks, grids, and spacing with a function-free ChartSpec.

format.type · dateStyle · timeStyle · timeZone

Value format and locale

number · compact · currency · percent · date · time · datetime

labels.orientation · font

Label direction and typography

auto · horizontal · vertical-up · vertical-down · angle · maxLength

ticks · grid · offset

Ticks and spacing

count · values · spacing · padding · dash · opacity

x · y · x2 · y2 · axisId

This example binds differently scaled layers to the primary y axis on the left and an independent y2 axis on the right.

axes: {
  x: {
    position: 'bottom',
    format: { type: 'datetime', dateStyle: 'medium', timeStyle: 'short', timeZone: 'Asia/Seoul' },
    labels: {
      orientation: 'vertical-up', padding: 10,
      font: { family: 'Inter', size: 11, weight: 'semibold' }
    },
    ticks: { count: 6, spacing: 48 }
  },
  y: { grid: { visible: true, dash: [4, 4], opacity: 0.7 } }
}

ChartSpec · SpatialSpec · storytelling

Legend and emphasis

Identify series, emphasize a datum or range, place a custom callout, and let readers select marks.

legend
Explain the series and scale represented by each color, line, or symbol inside the chart.
highlights[]
Emphasize a datum, value set, axis interval, or plot region without changing source values.
annotations[] · placement: 'auto' · style.maxWidth
Attach user-authored safe text to a datum, axis range, or normalized plot position. Auto placement compares perimeter candidates and avoids the plot, legend, and other callouts when possible. Explicit placement is preserved with only necessary safety correction. Callout text wraps safely inside the bubble. Long unbroken tokens are visually shortened within the line budget, while the complete source text remains available to assistive technology.
interaction.playback.transition
Playback smoothly interpolates matching stable keys for 600 ms with ease-in-out. Entering or exiting marks fade, incompatible shapes crossfade, and reduced-motion jumps directly to the final state.
interaction.selection
Click a mark to select it, press Escape to clear it, and consume selection state and events in the host application.
legend: { mode: 'categories', field: 'series', position: 'bottom' },
highlights: [
  { id: 'focus', target: { type: 'datum', field: 'city', value: 'Seoul' } },
  { id: 'quarter', target: { type: 'range', x: { from: 'Apr', to: 'Jun' } } }
],
annotations: [{
  id: 'note',
  target: { type: 'datum', rowIndex: 3 },
  text: 'Campaign started', detail: 'User-authored plain text',
  placement: 'auto', style: { maxWidth: 220 }
}],
interaction: {
  controls: { annotations: true },
  playback: {
    field: 'period', key: 'period', mode: 'cumulative',
    transition: { duration: 600, easing: 'ease-in-out' }
  },
  selection: {
    mode: 'multiple', toggle: true,
    clearOnBackground: true, clearOnEscape: true
  }
}

Canvas target types: datum · layer · range · normalized plot. Spatial target types: picked datum · layer · world point · world box. Spatial category and continuous legends are display-only; layer legends can toggle a layer.

Auto placement compares perimeter candidates and avoids the plot, legend, and other callouts when possible. Explicit placement is preserved with only necessary safety correction. Callout text wraps safely inside the bubble. Long unbroken tokens are visually shortened within the line budget, while the complete source text remains available to assistive technology. Playback smoothly interpolates matching stable keys for 600 ms with ease-in-out. Entering or exiting marks fade, incompatible shapes crossfade, and reduced-motion jumps directly to the final state.

Spatial callouts that follow the camera are DOM overlays and are not included in the current PNG framebuffer export.

Browser API

Graflume.create()

Choose a chart type and theme, then render again to see the same row data expressed by another specification.

const chart = Graflume.create('#chart', {
  specVersion: '0.1', data,
  mark: { type: 'line', point: true },
  x: { field: 'period', type: 'ordinal' },
  y: { field: 'actual', type: 'quantitative' },
  interaction: { hover: true, click: true }
});

chart.on('click', ({ hit }) => console.log(hit?.datum));
chart.setData(nextRows);
chart.appendData(nextBatch); // bounded streaming applies when spec.streaming is configured
chart.resize();
chart.toDataURL('image/png');
chart.destroy();
Graflume.compile(spec)

DOM-free validation · normalize · Scene

bar() · line() · combo()

Chart family · Quick API

setSpec(spec)

Choose a chart type and theme, then render again to see the same row data expressed by another specification.

setData(rows)

Row data

appendData(rows) · upsertData(rows) · replaceLastData(rows)

legacy append · explicit streaming retention / replay

resize()

Responsive

on('click')

Select a chart mark and inspect the status area to see which row its safe data event identifies.

toDataURL()

Compare the table with the generated ChartSpec, export a PNG, and destroy the instance when leaving the page.

destroy()

Integration checklist

Browser API

Core concepts

Portable specification fields and browser methods are shown together so that declarative and runtime contracts remain distinguishable.

transform-dataflow supported

Transform dataflow & lineage

Ordered function-free transforms, top-level and layer pipelines, deterministic row lineage, parameters, seeded operations, aggregation counts, named sources, reusable branches and a shared transform DAG are supported.

  • transform[]
  • compile().dataLineage
  • Scene.metadata.dataLineage

Current boundary: The portable transform registry is closed and function-free: arbitrary executable transforms, host side effects and opaque callbacks are rejected.

encoding-scale-registry supported

Encoding & scale registry

A closed portable encoding map, conditional mark channels, geographic and trading channels, 17 positional/categorical/probability/temporal scale types, four color scale types, and shared or independent multi-view domains, axes, legends and colorbars are supported.

  • encoding
  • createPositionScale()
  • createColorScale()
  • Scale.map()
  • Scale.invert()
  • Scale.ticks()

Current boundary: Channels and scales use a closed registered vocabulary; arbitrary executable accessors and unregistered mark/channel contracts fail validation.

analytic-interaction supported

Analytic selection & domain navigation

A closed immutable v1 store, union/intersection semantics, point/interval/rectangle/axis/lasso state, Canvas pointer/touch and keyboard-authored geometry, continuous and categorical pixel/domain navigation, linked multi-view state, and lineage-preserving selection-driven filtering are supported.

  • interaction.selection
  • interaction.domainNavigation
  • getAnalyticSelection()
  • applyAnalyticSelection()
  • domainToPixel()
  • pixelToDomain()
  • zoomDomainBy()
  • panDomainBy()

Current boundary: Spatial analytic selection remains a separate renderer boundary; selection state and filtering stay inside the closed portable interaction contract.

composition-resolve supported

Composition & resolve

Legacy flat layers and the closed layer/facet/repeat/hconcat/vconcat/concat/inset Canvas composition grammar are supported with deterministic bounded layout, scoped semantic and lineage identities, named axes, shared or independent multi-view domains/axes/legends/colorbars, linked view state, per-layer transforms, z-order and clipping.

  • layer
  • facet
  • repeat
  • hconcat
  • vconcat
  • concat
  • inset
  • resolve

Current boundary: Facet virtualization, renderer mixing and Spatial composition remain separate boundaries; composition stays deterministic and bounded.

semantic-index-accessibility supported

Semantic accessibility mirror

All Canvas families compile a bounded lineage-aware semantic index and expose a virtualized native explorer with full roving traversal, focus-ring, tooltip and selection synchronization. Spatial GPU views expose projected roving traversal and active-descendant synchronization, while a bounded stable-key focus store links Canvas and Spatial views through a portable authored contract.

  • getSemanticIndex()
  • toAccessibleRows()
  • getAccessibilityState()
  • accessibility.table
  • accessibility.navigation

Current boundary: Accessibility explorers and focus stores are bounded, authored semantic projections rather than an unbounded DOM mirror of every rendered primitive.

label-layout-authoring supported

Mark-label layout & annotation authoring

All 41 Canvas families support function-free reusable markLabels with stable-key portable positions, deterministic automatic collision placement, connectors, editing handles, pointer drag, keyboard selection and nudging, grid/mark/plot snapping, bounded undo/redo, runtime import/export events and accessible instructions/live status. Annotation adds a closed data-coordinate point/rule/band/label/callout registry with drag, resize and history.

  • markLabels
  • getMarkLabelState()
  • getMarkLabelPositions()
  • setMarkLabelPositions()
  • undoMarkLabelEdit()
  • redoMarkLabelEdit()
  • marklabelchange
  • getAnnotations()
  • setAnnotations()
  • addAnnotation()
  • removeAnnotation()
  • annotationchange

Current boundary: Authoring uses closed markLabels and data-coordinate annotation primitives; raw HTML, arbitrary event code, freehand drawing and image authoring are excluded.

incremental-worker-binary supported

Incremental streaming & worker adapter

Stable-key append/upsert/replaceLast uses bounded ring storage, explicit reject/drop-oldest/coalesce queues, count/event-time retention and replay. Row-local transforms recompute changed keys with exact global fallback; the frame runtime adds RAF coalescing, cancellation, pause/follow-live and lazy bounded history. Automatic module Workers accept row, typed-column and Arrow-compatible binary envelopes, injected JavaScript/WASM adapters and worker-owned renderers with bounded work and cancellation.

  • streaming
  • appendData()
  • updateData()
  • upsertData()
  • replaceLastData()
  • getStreamingState()
  • exportStreamingReplay()
  • replayData()
  • createIncrementalDataStore()
  • createTransformWorkerAdapter()
  • installTransformWorker()

Current boundary: Queues, histories and worker work remain explicitly bounded; JavaScript/WASM adapters must be installed by the host and cannot introduce opaque unbounded execution.

ChartSpec · AxisSpec

Axis system

Configure axis placement, value formatting, label direction, typography, ticks, grids, and spacing with a function-free ChartSpec.

axes.x / axes.y
This example uses external Cartesian x/y axes, and the options below are applied to the live chart.
axes.x2 / axes.y2
This example binds differently scaled layers to the primary y axis on the left and an independent y2 axis on the right.
AxisSpec | false
position · offset · line · ticks · labels · grid · title · format
legacy aliases
tickCount · format: string · labelAngle · grid: boolean · title: string
axes: {
  y: {
    position: 'left',
    format: { type: 'currency', currency: 'KRW', notation: 'compact' }
  },
  y2: {
    position: 'right', offset: 8, grid: false,
    format: { type: 'percent', fractionDigits: 1 }
  }
},
layers: [
  { mark: { type: 'bar' }, x: { field: 'period', axisId: 'x' }, y: { field: 'revenue', axisId: 'y' } },
  { mark: { type: 'line', point: true }, x: { field: 'period', axisId: 'x' }, y: { field: 'marginRate', axisId: 'y2' } }
]

Runtime · legend · annotation · selection

Legend and emphasis

Identify series, emphasize a datum or range, place a custom callout, and let readers select marks.

getLegendState() · setLegendItemVisible() · resetLegend()
Explain the series and scale represented by each color, line, or symbol inside the chart.
getAnnotations() · setAnnotations() · addAnnotation() · updateAnnotation() · removeAnnotation()
Attach user-authored safe text to a datum, axis range, or normalized plot position.
getAnnotationsVisible() · setAnnotationsVisible() · toggleAnnotations()
Auto placement compares perimeter candidates and avoids the plot, legend, and other callouts when possible. Explicit placement is preserved with only necessary safety correction. Callout text wraps safely inside the bubble. Long unbroken tokens are visually shortened within the line budget, while the complete source text remains available to assistive technology.
interaction.playback.key · transition
Playback smoothly interpolates matching stable keys for 600 ms with ease-in-out. Entering or exiting marks fade, incompatible shapes crossfade, and reduced-motion jumps directly to the final state.
getSelection() · setSelection() · clearSelection()
Click a mark to select it, press Escape to clear it, and consume selection state and events in the host application.
getAnalyticSelection() · applyAnalyticSelection() · clearAnalyticSelection()
Serializable point, interval, rectangle, axis and lasso selection state.
domainToPixel() · pixelToDomain() · zoomDomainBy() · panDomainBy() · resetDomainView()
Resolved-scale round-trip and continuous Cartesian domain navigation.
getSemanticIndex() · toAccessibleRows() · getAccessibilityState()
Bounded semantic sidecar, native table rows and accessibility mirror state.
legendchange · annotationchange · annotationvisibilitychange · selectionchange · analyticselectionchange · domainviewchange
Safe events
chart.on('selectionchange', ({ state }) => {
  console.log(state.items);
});

const noteId = chart.addAnnotation({
  target: { type: 'datum', rowIndex: 3 },
  text: 'Reviewed by the analyst',
  placement: 'auto'
});
chart.updateAnnotation(noteId, { placement: 'auto' });
chart.toggleAnnotations();

const legendItem = chart.getLegendState().items.find(item => item.toggleable);
if (legendItem) chart.setLegendItemVisible(legendItem.id, false);
chart.clearSelection();