Temporeum Timelinev1.0.2

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
  1. 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:

  2. 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 vite
  3. Open 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):

MappingPluginFrom
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 event x is an onX prop (frameworks).
  • No date library. Times are a Date or 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 unless packMode: "overlap".
  • Read-only until told. react-calendar-timeline moves, resizes and changes groups unless told otherwise; Temporeum does none of it until editing.enabled (and crossLane to change lanes). Each edit is one reversible command, and the library never saves (editing).
  • The timeline owns its view. Instead of controlled visibleTimeStart and visibleTimeEnd, set the view with zoomTo and hear about it with viewportChanged.
  • Markers are decorations. TodayMarker and CustomMarker are decorations; 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.

Setup
react-calendar-timelineTemporeumStatusNotes
<Timeline groups items defaultTimeStart defaultTimeEnd />createTimeline(container, { items, lanes, domain })RenamedIn 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 dependencyDate or epoch millisecondsDifferentNo date library. A moment or a dayjs converts with .valueOf().
groups: [{ id, title }]lanes: [{ id, label }]RenamedIds are strings.
items: [{ id, group, title, start_time, end_time }]{ id, laneId, label, start, end }DifferentIds are strings; group is laneId; times are a Date or epoch milliseconds.
keys: { itemIdKey, itemTitleKey, ... }map the fields onceDifferentThere is one shape for items and lanes; convert other field names when the data comes in.
resizeDetectoralways onSameThe timeline follows its container's size; below breakpoint it turns vertical when orientation is "auto".
classNamethe container's own classDifferentThe container is the host's element; style it, and the theme's custom properties.
View
react-calendar-timelineTemporeumStatusNotes
defaultTimeStart, defaultTimeEnddomain: [start, end]RenamedWithout a domain the view fits the items, with a margin.
visibleTimeStart, visibleTimeEnd, onTimeChange (controlled)timeline.zoomTo([start, end]), on("viewportChanged")DifferentThe timeline owns its view: set it with zoomTo, hear about it with viewportChanged. In React, take the instance with timelineRef.
minZoom, maxZoomlimits: { minSpanMs, maxSpanMs }RenamedThe shortest and longest visible span, in milliseconds, as in react-calendar-timeline.
bufferautomaticDifferentNothing to set: once touched, the view draws a viewport ahead on each side while it rests.
traditionalZoomctrl + wheel, pinch, + and -DifferentA plain wheel scrolls or pans; ctrl + wheel and a pinch zoom; + and - zoom from the keyboard. interactions.zoom: false turns zooming off.
sidebarWidth, sidebarContentlaneHeaders: trueDifferentThe lane labels head their rows; with laneHeaders they stay in view while the view pans.
lineHeight, itemHeightRatiodensityDifferentRow height follows the density; auto picks one at which every row fits.
group.heightlane.minCrossSizeRenamedThe least size across, in CSS pixels; a lane grows with its rows.
stackItems, group.stackItemspackMode: "pack" | "overlap", lane.packModeDifferentreact-calendar-timeline overlaps items unless told to stack; Temporeum packs them into rows unless told otherwise. packMode: "overlap" is react-calendar-timeline's default.
selectedselectedIds, timeline.select(ids)Renamed
itemRenderertemplate (HTML) or hooks.renderItem (scene nodes)DifferentA template is sanitised HTML in place of the label; hooks.renderItem returns scene nodes, and also renders on the server.
item.itemProps.classNameitem.classNameRenamed
<DateHeader labelFormat />formatTick(tick, timeZone)DifferentOne function for every axis label; tick.granularity says what it stands for.
<TodayMarker />decorations: [{ kind: "now", time: Date.now() }]DifferentThe 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 timeBarsRenamedA marker is drawn; a time bar (timeBars) can also be dragged, and says so with timeBarMoved.
rightSidebarWidth, rightSidebarContent, group.rightTitle—Not yetOne column of lane labels.
groupRenderer—Not yetLane labels are text.
timeSteps—Not yetTicks are chosen for the zoom level; formatTick writes them.
verticalLineClassNamesForTime—Not yetdecorations: [{ kind: "banding" }] alternates the tick bands; a class per time is not supported.
horizontalLineClassNamesForGroup—Not yetGroups take a className (groups); plain lanes do not.
item.itemProps.style—Not yetUse className and a stylesheet.
<CursorMarker />—Not yet
<TimelineHeaders>, <SidebarHeader>, <CustomHeader>—Not yetThe axis is one band, drawn by the library; formatTick writes its labels.
scrollRef—Not yetThe view moves with zoomTo and scrollTo, not a scroll element.
Editing
react-calendar-timelineTemporeumStatusNotes
canMove, canResize, canChangeGroupediting: { enabled: true, crossLane: true }Differentreact-calendar-timeline is editable until told otherwise; Temporeum is read-only until editing.enabled. Moving between lanes is crossLane.
item.canMove, item.canResizeitem.movable, item.resizableRenamed
dragSnapediting.snapMsRenamedIn 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.
minResizeWidthediting.minDurationMsDifferentA least duration in time, not a least width in pixels.
moveResizeValidatorediting.canMove(item, next)DifferentReturn false to refuse the move or the resize; snapping is snapMs.
onCanvasDoubleClick(groupId, time)editing: { add: true }, on("itemsAdded")DifferentA double tap on empty lane space, or n, adds an item; createItem says what it is.
useResizeHandle—Not yetAn item is resized at its edges, or with Shift and an arrow.
Events
react-calendar-timelineTemporeumStatusNotes
onItemClick(itemId, e, time)on("itemClick")RenamedAlso fires for Enter on the focused item.
onItemDoubleClick(itemId, e, time)on("itemDblClick")Renamed
onItemSelect, onItemDeselecton("selectionChanged")RenamedOne event with the ids now selected and before.
onItemMove(itemId, dragTime, newGroupOrder)on("itemMoved")DifferentCarries 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, onBoundsChangeon("viewportChanged")RenamedWith its reason: zoom, pan, resize, api.
onCanvasClick(groupId, time)rangeSelect: true, on("rangeSelected")DifferentA drag on empty time selects a range; a click on it selects nothing.
onItemDrag—Not yetA move is reported once, when it ends (itemMoved); getSnapshot().editing says one is under way.
onItemContextMenu, onCanvasContextMenu—Not yetListen 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.