Migrating from react-calendar-timeline
A react-calendar-timeline setup moves over by renaming a handful of fields — title to label, group to laneId, start_time to start — and a handful of props. This page maps every react-calendar-timeline prop, item and group field, marker and header that has an equivalent, and lists, honestly, the ones that don't have one yet. Each mapping in the tables below is a running example in the test suite, and each "Not yet" row is checked against the configuration's types. A row that maps to something that doesn't exist fails the build.
Live example: react-calendar-timeline data, converted
Loading…
Run “react-calendar-timeline data, converted” on your own machine
Make an empty folder and put this example’s two files in it:
index.html— the page the code runs in, its markup and styles:<div id="timeline" style="height: 240px"></div> <p class="log" id="log" aria-live="polite">Drag an item to another person, or press Alt and an arrow on the focused one.</p>main.js— the code, as it is in the editor now, your edits included:In a terminal in that folder, install the library and Vite (it lets the browser follow the
imports), then start it:npm init -y npm install @temporeum/timeline-element npm install --save-dev vite npx viteOpen the address it prints,
http://localhost:5173/.
The plugins
Groups, items and the view as this example has them need nothing more. Some mappings below land on a plugin — a part on an entry point of its own, registered once with registerPlugin from @temporeum/timeline-element, before the first timeline (in a React app, in its entry module):
| Mapping | Plugin | From |
|---|---|---|
laneHeaders (the sidebar), timeBars (a marker the reader drags), rangeSelect (a click on the canvas) | toolsPlugin | @temporeum/timeline-element/tools |
template (an item renderer), editing.add (a double click on the canvas) | itemsPlugin | @temporeum/timeline-element/items |
Without its plugin, a configuration with one of these throws a TypeError where the timeline is created, naming the import that is missing. hooks.renderItem and decorations (TodayMarker, CustomMarker) need no plugin.
What changes
- The same keys in React and outside it. The examples on this page use
createTimeline; in React, the configuration is the props of<Timeline>from@temporeum/timeline-react, and each eventxis anonXprop (frameworks). - No date library. Times are a
Dateor epoch milliseconds; a moment or a dayjs converts with.valueOf(). Ids are strings. - Items pack into rows. react-calendar-timeline overlaps items in a group unless
stackItems; Temporeum packs them unlesspackMode: "overlap". - Read-only until told. react-calendar-timeline moves, resizes and changes groups unless told otherwise; Temporeum does none of it until
editing.enabled(andcrossLaneto change lanes). Each edit is one reversible command, and the library never saves (editing). - The timeline owns its view. Instead of controlled
visibleTimeStartandvisibleTimeEnd, set the view withzoomToand hear about it withviewportChanged. - Markers are decorations.
TodayMarkerandCustomMarkeraredecorations; a marker the reader can drag is a time bar (time tools). - The keyboard works by default. Every gesture has a key, and screen readers see the timeline as a listbox (accessibility).
The mapping
The timeline in each row's example has five items in two lanes; the row's code is the only difference.
| react-calendar-timeline | Temporeum | Status | Notes |
|---|---|---|---|
<Timeline groups items defaultTimeStart defaultTimeEnd /> | createTimeline(container, { items, lanes, domain }) | Renamed | In React the same configuration is <Timeline items={items} lanes={lanes} defaultDomain={domain} /> from @temporeum/timeline-react; every key on this page is the same prop, except that domain and selectedIds are defaultDomain and defaultSelectedIds there — where the view starts, as defaultTimeStart is — and each event x is an onX prop. |
moment or dayjs as a peer dependency | Date or epoch milliseconds | Different | No date library. A moment or a dayjs converts with .valueOf(). |
groups: [{ id, title }] | lanes: [{ id, label }] | Renamed | Ids are strings. |
items: [{ id, group, title, start_time, end_time }] | { id, laneId, label, start, end } | Different | Ids are strings; group is laneId; times are a Date or epoch milliseconds. |
keys: { itemIdKey, itemTitleKey, ... } | map the fields once | Different | There is one shape for items and lanes; convert other field names when the data comes in. |
resizeDetector | always on | Same | The timeline follows its container's size; below breakpoint it turns vertical when orientation is "auto". |
className | the container's own class | Different | The container is the host's element; style it, and the theme's custom properties. |
| react-calendar-timeline | Temporeum | Status | Notes |
|---|---|---|---|
defaultTimeStart, defaultTimeEnd | domain: [start, end] | Renamed | Without a domain the view fits the items, with a margin. |
visibleTimeStart, visibleTimeEnd, onTimeChange (controlled) | timeline.zoomTo([start, end]), on("viewportChanged") | Different | The timeline owns its view: set it with zoomTo, hear about it with viewportChanged. In React, take the instance with timelineRef. |
minZoom, maxZoom | limits: { minSpanMs, maxSpanMs } | Renamed | The shortest and longest visible span, in milliseconds, as in react-calendar-timeline. |
buffer | automatic | Different | Nothing to set: once touched, the view draws a viewport ahead on each side while it rests. |
traditionalZoom | ctrl + wheel, pinch, + and - | Different | A plain wheel scrolls or pans; ctrl + wheel and a pinch zoom; + and - zoom from the keyboard. interactions.zoom: false turns zooming off. |
sidebarWidth, sidebarContent | laneHeaders: true | Different | The lane labels head their rows; with laneHeaders they stay in view while the view pans. |
lineHeight, itemHeightRatio | density | Different | Row height follows the density; auto picks one at which every row fits. |
group.height | lane.minCrossSize | Renamed | The least size across, in CSS pixels; a lane grows with its rows. |
stackItems, group.stackItems | packMode: "pack" | "overlap", lane.packMode | Different | react-calendar-timeline overlaps items unless told to stack; Temporeum packs them into rows unless told otherwise. packMode: "overlap" is react-calendar-timeline's default. |
selected | selectedIds, timeline.select(ids) | Renamed | |
itemRenderer | template (HTML) or hooks.renderItem (scene nodes) | Different | A template is sanitised HTML in place of the label; hooks.renderItem returns scene nodes, and also renders on the server. |
item.itemProps.className | item.className | Renamed | |
<DateHeader labelFormat /> | formatTick(tick, timeZone) | Different | One function for every axis label; tick.granularity says what it stands for. |
<TodayMarker /> | decorations: [{ kind: "now", time: Date.now() }] | Different | The library never reads the clock; the host passes the time, and updates it if it should move. |
<CustomMarker date /> | decorations: [{ kind: "marker", id, time }], or timeBars | Renamed | A marker is drawn; a time bar (timeBars) can also be dragged, and says so with timeBarMoved. |
rightSidebarWidth, rightSidebarContent, group.rightTitle | — | Not yet | One column of lane labels. |
groupRenderer | — | Not yet | Lane labels are text. |
timeSteps | — | Not yet | Ticks are chosen for the zoom level; formatTick writes them. |
verticalLineClassNamesForTime | — | Not yet | decorations: [{ kind: "banding" }] alternates the tick bands; a class per time is not supported. |
horizontalLineClassNamesForGroup | — | Not yet | Groups take a className (groups); plain lanes do not. |
item.itemProps.style | — | Not yet | Use className and a stylesheet. |
<CursorMarker /> | — | Not yet | |
<TimelineHeaders>, <SidebarHeader>, <CustomHeader> | — | Not yet | The axis is one band, drawn by the library; formatTick writes its labels. |
scrollRef | — | Not yet | The view moves with zoomTo and scrollTo, not a scroll element. |
| react-calendar-timeline | Temporeum | Status | Notes |
|---|---|---|---|
canMove, canResize, canChangeGroup | editing: { enabled: true, crossLane: true } | Different | react-calendar-timeline is editable until told otherwise; Temporeum is read-only until editing.enabled. Moving between lanes is crossLane. |
item.canMove, item.canResize | item.movable, item.resizable | Renamed | |
dragSnap | editing.snapMs | Renamed | In milliseconds, as in react-calendar-timeline, from the epoch or snapOrigin. A grid of whole days lies on the timeline's timeZone midnights, all year. |
minResizeWidth | editing.minDurationMs | Different | A least duration in time, not a least width in pixels. |
moveResizeValidator | editing.canMove(item, next) | Different | Return false to refuse the move or the resize; snapping is snapMs. |
onCanvasDoubleClick(groupId, time) | editing: { add: true }, on("itemsAdded") | Different | A double tap on empty lane space, or n, adds an item; createItem says what it is. |
useResizeHandle | — | Not yet | An item is resized at its edges, or with Shift and an arrow. |
| react-calendar-timeline | Temporeum | Status | Notes |
|---|---|---|---|
onItemClick(itemId, e, time) | on("itemClick") | Renamed | Also fires for Enter on the focused item. |
onItemDoubleClick(itemId, e, time) | on("itemDblClick") | Renamed | |
onItemSelect, onItemDeselect | on("selectionChanged") | Renamed | One event with the ids now selected and before. |
onItemMove(itemId, dragTime, newGroupOrder) | on("itemMoved") | Different | Carries the item, where it was and where it is (to.start, to.laneId), and the reversible command. The library never saves. |
onItemResize(itemId, time, edge) | on("itemResized") | Renamed | |
onZoom, onBoundsChange | on("viewportChanged") | Renamed | With its reason: zoom, pan, resize, api. |
onCanvasClick(groupId, time) | rangeSelect: true, on("rangeSelected") | Different | A drag on empty time selects a range; a click on it selects nothing. |
onItemDrag | — | Not yet | A move is reported once, when it ends (itemMoved); getSnapshot().editing says one is under way. |
onItemContextMenu, onCanvasContextMenu | — | Not yet | Listen for contextmenu on the container. |
What is not here yet
The "Not yet" rows above, in short: an event per frame of a drag, context-menu events, a resize handle, a right sidebar, custom group and header renderers, custom time steps, classes per time or per lane, inline item styles, a cursor marker and a scroll element of the host's. If your app depends on one of them, say so in an issue: the order is decided by what users need.