Kit API reference
The parts every safety.viz chart is built from, exported for a second chart library on the same page. Generated from src/kit.js — npm run docs:api fails on an undocumented member.
- Members
- 36from 8 shared modules and Chart.js
- Reached as
SafetyViz.kitor thekitexport of the ES module bundle- Draws with
- Chart.js 4.5.1the copy every chart in the bundle uses
- Public surface
- from v1.9.0a change to a member is a breaking change
Overview
The shared parts every safety.viz chart is built from, exported so a second chart library on the same page builds from them instead of copying them. Each member is the same function the charts themselves call. The object is flat and frozen.
Loading it beside another library
The kit is part of the safety.viz bundle, so there is nothing else to load. Put safety.viz first, then the library that builds on it:
<script src="dist/safety.viz-1.9.1/safety.viz.js"></script>
<script src="your-library.js"></script>
<script>
const { renderShell, renderFilterControl, Chart } = SafetyViz.kit;
</script>
Or, from the ES module bundle:
import { kit } from './dist/safety.viz-1.9.1/safety.viz.esm.js';
const { renderShell, renderFilterControl, Chart } = kit;
- One file is needed:
dist/safety.viz-1.9.1/safety.viz.jsfor a script tag, orsafety.viz.esm.jsfrom the same folder for an import. The.mapfile beside each is its source map and is optional. - Use one bundle on a page, not both. The script-tag bundle and the ES module bundle are separate copies, each with its own Chart.js.
- Take everything from that one copy. A library that brings its own Chart.js, or its own copy of these functions, draws charts and controls that drift from safety.viz's.
kit.Chartis Chart.js 4.5.1 with what the charts registered on it: thebar,line,scattercontrollers, thebar,line,pointelements, thecategory,linear,logarithmicscales, and thelegend,title,tooltipplugins. A chart of one of those types needs nothing more; anything else is registered on the same constructor withkit.Chart.register().- A working page built this way is the fixture the browser tests drive, tests/e2e/fixtures/kit.html: a sidebar, a filter, a bar chart, a record listing and the participant rail, from the kit alone.
What is promised
- The kit is public surface from v1.9.0: a change to any member, whether its name, its signature, what it returns or the elements and class names it produces, is a breaking change, and the release notes say so.
- Every member is the function the charts in the bundle call, not a copy or a wrapper, so a page built from the kit behaves as the charts do. Unit tests hold each member to its module's export, and browser tests build a page from the committed bundle and the kit alone.
- The kit is flat and frozen: members sit directly on it under the names below, and a library on the page cannot replace, add or remove one.
- Adding a member is not a breaking change.
kmEstimatefollows the Time-to-Event Explorer's Experimental status, which holds until an external clinical review confirms its Kaplan–Meier implementation (obot.roadmap#182): its estimates, intervals and at-risk counts may change after that review without counting as a breaking change. Its name and its arguments are kept.- The other 35 members are public surface in full.
Members
36 members, grouped by where they come from. Each signature is read from the function itself.
Chart.js
From Chart.js 4.5.1. The constructor the bundle contains, so a second library draws with the same copy.
| Member | What it does |
|---|---|
new Chart(item, userConfig) | The Chart.js constructor this bundle contains: the one every safety.viz chart draws with, carrying the controllers, elements, scales and plugins the charts registered on it. Draw with it instead of loading a second Chart.js. |
Shell and controls
From src/shell.js. The collapsible control sidebar, the slots a chart draws into, and the control builders.
| Member | What it does |
|---|---|
createElement(tag, className, text) | Create a detached element with an optional class and text content. |
option(select, value, label, selected) | Append an option to a select. |
multiSelect({ values, selected, onChange }) | Build the multiselect control: a collapsible checkbox list with an All row and a live summary. The selection is null for everything, or an array of the chosen values. |
applyShellStyles() | Inject the shared sv- stylesheet once per document. renderShell calls it, so a page that builds a shell need not. |
renderShell(element, { moduleClass = '', onToggle } = {}) | Empty a container and build the shared layout into it: the collapsible control sidebar, the main column of notes, chart canvas, footnote, small multiples and listing, and the participant rail. Returns those slots by name. |
controlBuilders(controls) | The control builders bound to a shell's controls container: addSection, addRow, addControl and addReset. |
renderViewSelector(addSection, { options, active, onChange, title = 'View' }) | Render a view selector into its own sidebar section: one button per view, the active one marked. |
Filters
From src/filters.js. The filter contract: what a filter spec means, its opening state, its control and its test.
| Member | What it does |
|---|---|
ALL_VALUE = "__all__" | The option value that stands for no restriction in a single-value filter. |
normalizeFilterSpec(value, fallbackLabel) | Normalize a column name or a filter spec to the filter contract: value_col, label, start, all and multiple. |
initFilterState(specs) | The opening filter state for a list of normalized specs: each spec's start value, or null for no restriction. |
reconcileFilters(state, specs, valuesOf) | Reconcile a filter state with the filters about to be drawn, so the selection each control shows is the selection the chart filters by: a filter with no control leaves no restriction behind, a new filter opens on its spec's start, a selection the data lacks falls back to All with a console warning, and with all: false the first value is selected. Returns the spec, values and selection for each control to draw. It is on the kit because every chart now calls it as it builds its filter controls: it joined the filter contract in the v1.8.0 review (safety.viz #166 and #171), after the kit's member list was first written. |
filterMatches(rowValue, selection) | Whether one row's value passes one filter's selection: null passes everything, an array is membership, anything else is equality. |
renderFilterControl({ spec, values, selected, onChange }) | Build one filter control from its spec: a select with an optional All option, or the multiselect when the spec says multiple. |
Axis limits
From src/axis-limits.js. The Lower and Upper inputs that show the limit in force and keep only what was edited.
| Member | What it does |
|---|---|
limitDigits(domain) | Decimal places for a displayed axis limit: three significant figures of the axis range. |
formatLimit(value, digits) | Format a limit for its number input, dropping trailing zeros; blank when the value is not finite. |
syncAxisLimits(state, domain, inputs = {}) | Record the domain a render resolved on state.axisDomain and write it into the Lower and Upper inputs. |
seedLimitInput(state, key) | The value a limit input carries when the controls are rebuilt: the user's override, or else the domain last in force. |
applyLimitEdit(state, key, raw) | Apply an edited limit to state.lower or state.upper: an empty entry returns that side to automatic, and a pair that crosses is swapped. |
clearAxisLimits(state) | Drop both overrides and the recorded domain, so the next render derives the limits from the data. |
Record listing
From src/histogram/listing.js. The linked listing, with its search, sort, paging and CSV functions.
| Member | What it does |
|---|---|
renderListing(instance) | Draw the record listing into instance.listingWrap, with its search box, paging buttons, sortable headers and CSV export. It reads the columns from instance.settings.details, the page size from settings.page_size, and the rows and view state from instance.currentTableData, listingSearch, listingSort and page. When instance.onListingRowClick is a function the rows are clickable and keyboard-focusable, and rows whose settings.id_col value equals instance.listingSelectedId are marked. |
searchRows(rows, cols, query) | The rows in which any listed column contains the query, ignoring case. |
sortRows(rows, sort) | A sorted copy of the rows by one column, ascending or descending: numeric when both values are numbers, otherwise as text. |
paginate(rows, page, pageSize) | One page of rows, with the number of pages and the page number held within it. |
buildCsv(rows, cols) | The listing as CSV text: a header of column labels, then one line of quoted values per row. |
exportCsv(rows, cols) | Download the listing as a CSV file. The file is named safety-histogram-listing.csv. |
Participant rail
From src/profile-host.js. What a host chart calls to open the participant profile beside itself.
| Member | What it does |
|---|---|
buildProfileRows(rawData, mapping) | Build the rows the participant rail reads, from a host's raw lab records and its column mapping, once per data load. Rows with no positive upper limit of normal are dropped. |
mountProfileRail(host, settingsFn, { target = null } = {}) | Mount the participant rail into host.railWrap and subscribe it to the participantsSelected event on host.root, or on options.target. The event's detail.data is the list of participant ids, and an empty list clears the rail. It does nothing unless host.settings.profile is set, and reads the rows from host.profileRows. |
unmountProfileRail(host) | Unsubscribe the rail, destroy its charts and empty its slot. |
syncProfileRail(host, settingsFn) | Reconcile the rail with the host's current settings: mount or unmount it when profile changes, otherwise hand it the current rows and settings. |
resetProfileRail(host) | Empty the rail when the host resets its own selection. |
Box drawing
From src/box-whisker.js. Box-and-whisker marks on a Chart.js canvas, and the plugin that draws them.
| Member | What it does |
|---|---|
drawBoxWhisker(ctx, { scales, chartArea }, specs) | Draw box-and-whisker marks on a canvas through a chart's x and y scales: for each spec a box from the first to the third quartile, whiskers to the 5th and 95th percentiles, a median line and a mean marker. |
boxWhiskerPlugin(idPrefix, getSpecs) | A Chart.js plugin that draws the box-and-whisker marks for whatever specs its getter returns at draw time. |
Measure list
From src/measure-list.js. Which measures a Measure control offers, and in what order.
| Member | What it does |
|---|---|
resolveMeasureList(present, configured, { warn = true } = {}) | The labels a Measure control offers: the configured measures in their order, or every measure in the data, sorted, when none is configured or none is found. |
presentMeasures(rows, settings, label) | The distinct measures in cleaned rows, in first-seen order, as the label and raw name that resolveMeasureList takes. |
Kaplan–Meier estimator
From src/time-to-event/km.js. The estimator behind the Time-to-Event Explorer.
| Member | What it does |
|---|---|
kmEstimate(observations) | The Kaplan–Meier estimate for one group, from one observation per participant of a time, whether it ends in the event, and an id: the steps with their at-risk and event counts, standard errors and pointwise 95% intervals, the censoring times, and a reader for the at-risk table. Follows the Time-to-Event Explorer's Experimental status: see what is promised. |
Not in the kit
- The chart factories.
SafetyViz.histogram()and the rest are the library's own public surface, documented on each chart's API reference; the kit is what they are built from. prototypeBannerandexperimentalBanner, whichsrc/shell.jsalso exports: their wording is safety.viz's own release status.hexToRgba, whichsrc/box-whisker.jsalso exports: a colour helper private to the box drawing.- Everything else under
src/: each chart's data preparation, scales and plugins stay internal and can change without notice.