Date range selector
Choose calendar presets or an inclusive date range. UTC is the default; an explicit IANA timezone can govern calendar arithmetic and date inputs. This feature belongs to @revolist/charts and can be used without Pivot or a grid.
Try it live
Section titled “Try it live”Try 1M, 3M, YTD, 1Y or All, or enter custom start/end dates. Presets anchor to the latest available full-domain date, not today’s date. This sample contains January–December 2026.
Months/years use UTC calendar arithmetic with month-end clamping. YTD starts at UTC midnight on January 1. Custom dates include the final day’s last millisecond, clipped to available bounds.
Loading chart…
Inspect live chart state
The chart uses the native Charts renderer. Buttons outside the plot are example application controls calling the public API.
Complete chart setup with sample data
Install Charts using the installation guide, then run this setup after the host mounts. The data is illustrative. Additional actions for this tool are explained below.
<div id="chart" style="width:100%;height:500px"></div>import { createChartFactory } from '@revolist/charts/core';import { lineChart } from '@revolist/charts/line';import { groupedColumnChart } from '@revolist/charts/grouped-column';import { columnLineChart } from '@revolist/charts/column-line';
const rows = [ { "date": 1767225600000, "month": "Jan", "revenue": 65, "costs": 45 }, { "date": 1769904000000, "month": "Feb", "revenue": 82, "costs": 50 }, { "date": 1772323200000, "month": "Mar", "revenue": 76, "costs": 48 }, { "date": 1775001600000, "month": "Apr", "revenue": 95, "costs": 65 }, { "date": 1777593600000, "month": "May", "revenue": 110, "costs": 72 }, { "date": 1780272000000, "month": "Jun", "revenue": 102, "costs": 68 }, { "date": 1782864000000, "month": "Jul", "revenue": 121, "costs": 80 }, { "date": 1785542400000, "month": "Aug", "revenue": 115, "costs": 76 }, { "date": 1788220800000, "month": "Sep", "revenue": 135, "costs": 89 }, { "date": 1790812800000, "month": "Oct", "revenue": 128, "costs": 85 }, { "date": 1793491200000, "month": "Nov", "revenue": 145, "costs": 92 }, { "date": 1796083200000, "month": "Dec", "revenue": 155, "costs": 100 }];const mapping = { "category": { "field": "date", "label": "month" }, "series": [ { "field": "revenue", "label": "Revenue" }, { "field": "costs", "label": "Costs" } ]};const createChart = createChartFactory([lineChart, groupedColumnChart, columnLineChart]);const container = document.getElementById('chart')!;const chart = await createChart({ container, data: rows, mapping, "chartType": "line", "axes": { "x": { "scale": "time" } }, "presentation": { "title": "Monthly performance", "subtitle": "Illustrative data · 2026", "legendPosition": "bottom" }, "interaction": { "mode": "select", "selectionMode": "multiple" }, "navigation": { "enabled": true, "rangeSelector": {} }});
// When the host unmounts:// chart.destroy();API and configuration
Section titled “API and configuration”await chart.update({ axes: { ...chart.model.axes, x: { scale: 'time' } }, navigation: { enabled: true, rangeSelector: { presets: ['1M', { id: 'fortnight', label: 'Two weeks', unit: 'week', count: 2 }, 'YTD', 'all'], custom: true, } },});Support and behavior
Section titled “Support and behavior”Preset definitions
Section titled “Preset definitions”rangeSelector.presets accepts a dense array of up to 32 built-in strings
or ChartCalendarPresetDefinition objects. Omission uses all five defaults;
[] removes preset choices while retaining custom inputs unless disabled.
Entries display in authored order. Each built-in can appear only once.
| Definition field | Required contract |
|---|---|
id | Unique nonempty trimmed string, at most 128 characters. Built-in IDs (1M, 3M, YTD, 1Y, all) and __proto__, constructor, prototype are reserved. The ID controls selection/focus and is independent of its caption. |
label | Nonblank string of at most 256 characters. Displayed as text, never HTML; applications supply localized captions. Leading/trailing spaces are preserved when the caption has nonwhitespace content. |
unit | 'day', 'week', 'month' or 'year'. |
count | Integer from 1 to 10000. |
Objects accept exactly those fields and must have ordinary/null prototypes.
Duplicate IDs, sparse arrays, unsupported fields, invalid counts/units and
malformed definitions reject before a model update commits. Parsed arrays and
definitions are owned snapshots; later caller mutation cannot change saved or
queued settings. ChartCalendarPreset is the union of built-ins and definitions.
Pivot exports PivotChartCalendarPreset and PivotChartCalendarPresetDefinition
from its root and charts entry points.
Calendar semantics
Section titled “Calendar semantics”Every preset anchors to the latest available full-domain instant. Synchronized
or host-provided full-domain bounds take precedence over a loaded page’s data;
wall-clock time never supplies the anchor. All windows are intersected with the
available domain. Built-in all has priority when the viewport matches the full
domain; otherwise the first authored matching preset is selected. Different
presets may resolve to the same range on a short domain.
With the timezone omitted, days and weeks select an exact trailing UTC duration while preserving the anchor time of day; a week is seven UTC days. A seven-day duration anchored at midnight includes both endpoint instants, so it can contain eight daily observations. It is distinct from selecting seven inclusive calendar dates. Months and years use UTC calendar shifts with month-end clamping, including leap days and years below 100. A year is twelve calendar months. For example, one year before February 29, 2024 resolves to February 28, 2023 at the same UTC time.
A window that cannot produce finite, increasing Date-representable bounds is disabled and does not commit a viewport. This includes shifts beyond the supported Date range. Custom date inputs retain their existing inclusive behavior: the end date includes its final millisecond, clipped to the available domain. Named zones are opt-in as described below. Explicit exchange-session calendars and ordinal financial navigation use the separate financial session policy.
Named timezone policy
Section titled “Named timezone policy”Set navigation.rangeSelector.timeZone to an Intl-supported IANA name such as
'America/New_York'. Omission uses UTC and retains the previous UTC preset/input
semantics. The option applies to all built-in and named presets and both date
inputs on navigation.xAxis (primary when omitted). Standalone and Pivot use the
same policy, independent of the machine timezone.
await chart.update({ navigation: { ...chart.model.navigation, rangeSelector: { ...chart.model.navigation?.rangeSelector, timeZone: 'America/New_York', presets: ['1M', { id: 'day', label: 'Civil day', unit: 'day', count: 1 }, 'YTD', 'all'], custom: true, }, },});Names must be nonempty trimmed strings of at most 128 characters recognized by
the host’s Intl timezone data. UTC and supported IANA aliases are accepted;
invalid names, offset-only strings, null and other types reject before an update
or restore commits. Persisted names are retained verbatim. Server/browser hosts
must support the authored zone; timezone rules follow their installed timezone
data. No silent machine-timezone fallback occurs.
Days/weeks subtract civil dates (seven days per week), so one day can span 23 or
25 elapsed hours. Months/years preserve civil clock fields and clamp month ends
and leap days. YTD starts at the zone’s January 1 boundary. All presets still
anchor to the full domain’s maximum instant, never the current viewport,
loaded page or current date. all returns that domain unchanged. A trailing
civil-day window includes both endpoint instants, distinct from inclusive date
input selection.
When a target clock time repeats in a fold, the earlier instant wins. Missing
clock times advance to the first valid civil minute, resetting seconds and
milliseconds to zero. A skipped target date advances similarly for presets.
Otherwise seconds and milliseconds are preserved. Custom date inputs include the
first valid civil minute of the start date through one millisecond before the next
civil day after the end date. Midnight folds choose the earlier instant;
midnight gaps advance to the first valid civil minute. A skipped authored start/end
date is invalid and does not commit; a skipped day immediately following a valid
end date is advanced over when resolving the exclusive boundary. For example,
New York March 10, 2024 selects 2024-03-10T05:00:00Z through
2024-03-11T03:59:59.999Z.
The selector displays dates in this zone and shows the authored zone name beside the presets. Axis tick labels and tooltips retain their existing formatting policy; setting the selector zone does not change them. Instants remain the projection, event, export and viewport identity. Custom inputs support civil years 0001–9999; outside that range fields are empty and presets remain available where representable. Invalid/nonfinite or unrepresentable shifts are unavailable, including Date-limit overflow; bounds are never wrapped or saturated into fabricated instants.
Saved models retain the policy and exact viewport instants; restore does not reinterpret them as wall times. Rejected asynchronous updates restore accepted policy and instants together. Named-X controls preserve independent primary windows. Enabling Pivot’s date-range control retains an already-authored configuration. Disabling it removes the range-selector configuration, including the zone and preset definitions; supply them again when re-enabling. Exchange sessions, holidays and ordinal trading time are outside this policy.
State and cleanup
Section titled “State and cleanup”Preset selection commits a time viewport with reason 'calendar'; named time
axes update their own viewport without replacing primary state. The viewport
participates in existing navigation, synchronization and async data requests.
Repaint derives the selected ID from committed bounds. Failed async commits
restore the previous selection and report the existing localized range error.
Controls retain their existing hidden/disabled UI policy and preview behavior.
Saved models retain definitions and committed viewport bounds. Pending custom
input edits are not saved. Normal chart exports exclude the interactive controls.
Pivot’s date-range opt-in preserves authored preset definitions; applications
configure the same navigation.rangeSelector object through creation, update or
saved models. Enabling the inspector option retains an existing configuration; disabling it removes
the selector configuration. Settings are whole-object replacements: spread values you want to keep
and await updates before reading state. Destroy the chart on host unmount.