Skip to content
SuperScheduler

ProductionApplies toLite and Pro

Migrating from Lite to Pro

Install the Pro tarball as `super-scheduler`, change the imports and the stylesheet from `super-scheduler-lite` to `super-scheduler`, and write out Lite's defaults, because Pro's defaults differ (one day of hourly cells, editing on, keyboard off). The component name, ISO date strings, resource and event fields and the basic options carry over. Replace Lite's `onTimeRangeClick` with `onTimeRangeSelected`, then enable Pro features one at a time.

Verified against v0.1.0 · reviewed October 7, 2026.md

Lite and Pro share their component name, their civil date model and their basic data shapes, so a Lite view moves to Pro with a handful of edits. The differences that matter are the defaults, a few callbacks and the styling tokens. This guide converts a Lite view to an equivalent read-only Pro view first, then adds Pro features one by one, so each step can be tested on its own.

What stays the same

AreaShared by Lite and Pro
ComponentSuperSchedulerComponent, with ref.current.control and controlRef
DatesCivil ISO strings with seconds, half-open intervals, SuperScheduler.Date and SchedulerDate with the same methods
Resources{ id, name }, ids compared strictly (1 and '1' differ)
Eventsid, resource, start, end, text, backColor, fontColor, cssClass, toolTip, tags
OptionsstartDate, days, scale: 'Day', cellWidth, height, rowHeaderWidth, rowMinHeight, eventHeight, locale, emptyState
Controlupdate(), scrollTo(), scrollToResource(), visibleStart(), visibleEnd(), dispose(), disposed()
CallbackonEventClick({ e }) with e.data

Everything Lite accepts has a Pro counterpart except ariaLabel (see below). Pro options such as treeEnabled or zoomLevels, which Lite rejects with "unsupported option", work once you switch.

Switch the package

Pro is installed from a versioned HTTPS tarball under the package name super-scheduler. Remove Lite unless another part of your app still uses it:

shsh
npm uninstall super-scheduler-lite
npm install https://npm.superscheduler.org/pro/YOUR_DOWNLOAD_KEY/0.1.0.tgz

package.json then lists the URL and your lockfile records its integrity. The key in that URL is a download secret: it appears in package.json and the lockfile, so treat both accordingly. Install SuperScheduler Pro covers keys, CI and upgrades. Pro lists React and React DOM (18.2 or later, or 19) as peer dependencies.

Update imports, styles and defaults

Here is a Lite view:

src/Availability.tsx (Lite)tsx
import { useState } from 'react'
import { SuperSchedulerComponent } from 'super-scheduler-lite'
import type { SuperScheduler } from 'super-scheduler-lite'
import 'super-scheduler-lite/styles.css'

const ROOMS: SuperScheduler.ResourceData[] = [
  { id: 'r101', name: 'Room 101' },
  { id: 'r102', name: 'Room 102' },
]
const EVENTS: SuperScheduler.EventData[] = [
  {
    id: 'b-1042',
    resource: 'r101',
    start: '2026-10-02T14:00:00',
    end: '2026-10-05T11:00:00',
    text: 'Ana Ruiz',
    backColor: '#dbeafe',
  },
  {
    id: 'b-1043',
    resource: 'r102',
    start: '2026-10-03T14:00:00',
    end: '2026-10-08T11:00:00',
    text: 'Tom Berg',
    backColor: '#dcfce7',
  },
]

/** Before: the read-only Lite view. */
export function Availability() {
  const [picked, setPicked] = useState('')
  return (
    <>
      <p aria-live="polite">{picked}</p>
      <SuperSchedulerComponent
        startDate="2026-10-01"
        resources={ROOMS}
        events={EVENTS}
        ariaLabel="Room availability"
        onEventClick={({ e }) => setPicked(`Booking ${String(e.data.id)}`)}
        onTimeRangeClick={({ start, resource }) =>
          setPicked(`Free: ${String(resource)} on ${start.toString('d MMM')}`)
        }
      />
    </>
  )
}

And the same view on Pro:

src/Availability.tsx (Pro)tsx
import { useCallback, useState } from 'react'
import { SuperSchedulerComponent } from 'super-scheduler'
import type {
  SchedulerEventClickArgs,
  SchedulerTimeRangeSelectedArgs,
  SuperScheduler,
} from 'super-scheduler'
import 'super-scheduler/styles.css'

const ROOMS: SuperScheduler.ResourceData[] = [
  { id: 'r101', name: 'Room 101' },
  { id: 'r102', name: 'Room 102' },
]
const EVENTS: SuperScheduler.EventData[] = [
  {
    id: 'b-1042',
    resource: 'r101',
    start: '2026-10-02T14:00:00',
    end: '2026-10-05T11:00:00',
    text: 'Ana Ruiz',
    backColor: '#dbeafe',
  },
  {
    id: 'b-1043',
    resource: 'r102',
    start: '2026-10-03T14:00:00',
    end: '2026-10-08T11:00:00',
    text: 'Tom Berg',
    backColor: '#dcfce7',
  },
]
// Lite draws one header row with "d MMM" per day.
const TIME_HEADERS: SuperScheduler.TimeHeaderData[] = [{ groupBy: 'Day', format: 'd MMM' }]

/** After: the same view on Pro, still read-only. */
export function Availability() {
  const [picked, setPicked] = useState('')
  // Pro splices the events array it receives: give it its own copy.
  const [events] = useState(() => EVENTS.slice())

  const onEventClick = useCallback((args: SchedulerEventClickArgs) => {
    setPicked(`Booking ${String(args.e.id())}`)
  }, [])

  // Lite's onTimeRangeClick fires for any empty cell. In Pro, clicking an empty cell selects it;
  // Pro's own onTimeRangeClick fires only for a click on a range that is already selected.
  const onTimeRangeSelected = useCallback((args: SchedulerTimeRangeSelectedArgs) => {
    args.control.clearSelection()
    if (args.origin !== 'click' && args.origin !== 'keyboard') return
    setPicked(`Free: ${String(args.resource)} on ${args.start.toString('d MMM')}`)
  }, [])

  return (
    // Pro has no ariaLabel option: name the region around it.
    <section aria-label="Room availability">
      <p aria-live="polite">{picked}</p>
      <SuperSchedulerComponent
        // Lite's defaults, written out: Pro's defaults differ.
        startDate="2026-10-01"
        days={31}
        scale="Day"
        cellWidth={64}
        heightSpec="Fixed"
        height={400}
        rowHeaderWidth={160}
        rowHeaderWidthAutoFit={false}
        rowMinHeight={40}
        eventHeight={26}
        timeHeaders={TIME_HEADERS}
        emptyState="No resources"
        // Read-only, as in Lite: Pro enables dragging, resizing and zoom gestures by default.
        eventMoveHandling="Disabled"
        eventResizeHandling="Disabled"
        zoomGesture={false}
        // Keyboard navigation is built into Lite and opt-in in Pro.
        keyboardEnabled
        keyboardTarget="component"
        keyboardMode="Full"
        resources={ROOMS}
        events={events}
        onEventClick={onEventClick}
        onTimeRangeSelected={onTimeRangeSelected}
      />
    </section>
  )
}

You should see the same rooms, bookings and colors, the same messages on click, and no dragging. The grid uses your page's font instead of Lite's 13 px system font, and Pro's theme colors.

The edits, in order:

  1. Imports: super-scheduler-lite becomes super-scheduler, and super-scheduler-lite/styles.css becomes super-scheduler/styles.css.
  2. Defaults: write out every Lite default you relied on (table below).
  3. Behavior: disable what Pro turns on by default, enable keyboard support.
  4. Callbacks: move cell clicks to onTimeRangeSelected.
  5. Data: give the control its own copy of the events array, because Pro splices the array it receives when events change. Lite treats its arrays as read-only.
OptionLite defaultPro default
days311
scale'Day' (the only value)'CellDuration' with cellDuration: 60, hourly cells
cellWidth6440
height400, fixed600, a maximum (heightSpec: 'Max'): the grid shrinks to its rows
rowHeaderWidth16080, and rowHeaderWidthAutoFit: true grows it to the names
rowMinHeight400
eventHeight2635
emptyState'No resources'none
ariaLabel'Resource schedule'not available
Time headerone row, d MMM[{ groupBy: 'Default' }, { groupBy: 'Cell' }]

Pro has no ariaLabel option: its grid has a built-in accessible name. Put the label on the region that contains it, as the example does with <section aria-label>.

Styles and selectors

Class names and tokens change prefix. Lite's root is .super-scheduler-lite with parts such as .super-scheduler-lite__event; Pro's root is .super-scheduler with .super-scheduler__event, plus [data-super-scheduler-part] markers. Map Lite's six tokens as a starting point:

Lite tokenPro token
--super-scheduler-background--super-scheduler-surface
--super-scheduler-text--super-scheduler-text
--super-scheduler-border--super-scheduler-border
--super-scheduler-headerno single equivalent; style the timeHeader slot or .super-scheduler__header
--super-scheduler-event--super-scheduler-event-bg (or backColor per event)
--super-scheduler-focus--super-scheduler-focus-color and --super-scheduler-focus-ring

Pro has a richer token set, dark mode and density presets; see Theming.

Behavior that Pro turns on

Lite is read-only by construction. Pro is an editor, so out of the box it:

  • moves and resizes events by dragging (eventMoveHandling and eventResizeHandling default to 'Update');
  • selects time ranges on click and drag (timeRangeSelectedHandling: 'Enabled'), leaving the selection shadow until the next selection, a click elsewhere or clearSelection();
  • zooms with Ctrl or Cmd plus the wheel and with pinch gestures (zoomGesture: true);
  • leaves keyboard support off (keyboardEnabled: false), while Lite always has arrow-key navigation. With keyboardEnabled Pro listens on the whole document unless keyboardTarget is 'component'.

The Pro example above pins all of these to Lite's behavior. Remove those lines one at a time as you adopt features.

Callbacks with richer arguments

LitePro
onEventClick({ control, e: { data }, originalEvent })onEventClick({ e, div, control, originalEvent, ctrl, shift, meta, preventDefault }), where e is a SuperScheduler.Event with data, id(), start(), end(), text(), resource() and duration(); then onEventClicked
onTimeRangeClick({ control, start, end, resource, originalEvent }) on any empty cellonTimeRangeSelected({ start, end, resource, control, origin, multirange }), with origin 'click', 'drag', 'keyboard' or 'api'

Other differences to check in your handlers:

  • In Pro, handlers run with this set to the control, and most arguments include control.
  • In Lite, originalEvent is a KeyboardEvent when a cell or event is activated from the keyboard. In Pro, Enter on an event dispatches a click, so onEventClick always receives a MouseEvent, and Enter on a cell is a selection with origin: 'keyboard'.
  • controlRef callbacks are called with null on unmount in Lite; Pro calls them only with the control and clears ref objects on unmount.
  • scrollTo(date) takes optional animated and position arguments in Pro.

When both packages are installed

Some products keep Lite on public pages and use Pro in the back office. That works, with two rules:

  • Exchange ISO strings, not date objects. Each edition has its own date class, and Pro rejects a Lite date object.
  • Keep their CSS apart. Each package has its own stylesheet. Some token names exist in both (--super-scheduler-text, --super-scheduler-border), so scope Lite overrides to .super-scheduler-lite instead of :root.
src/dates.tsts
import { type SuperScheduler as Lite } from 'super-scheduler-lite'
import { SuperScheduler as Pro } from 'super-scheduler'

// Each edition has its own date class. Passing a Lite date object to Pro throws
// ("expected a Date, a SchedulerDate, a number of ticks or an ISO 8601 string").
export function toProDate(date: Lite.Date): Pro.Date {
  return new Pro.Date(date.value)
}

// Shared state, URLs and storage hold civil ISO strings, which both editions accept.
export const selectedDay: string = Pro.Date.today().value

Import the two components under different local names when one module needs both, for example import { SuperSchedulerComponent as LiteScheduler } from 'super-scheduler-lite'.

Adopt Pro features step by step

Once the read-only view matches, add one capability at a time and test it:

  1. Keyboard and accessibility. Keep keyboardEnabled and keyboardMode="Full"; see Keyboard, accessibility and touch.
  2. Editing. Remove eventMoveHandling="Disabled" and eventResizeHandling="Disabled", add rules with onEventMoving and onEventMove, and persist changes from onEventsChange; see Drag and resize rules and Controlled state.
  3. Creating bookings. Use onTimeRangeSelected with origin === 'drag' to open a form.
  4. Hours and zoom. Add zoomLevels, remove zoomGesture={false}; see Time scales and zoom.
  5. Rows. Trees, frozen rows, split rows and row header columns; see Trees, columns and selection.
  6. Modules. Undo and redo, Minimap, Links, Panes and saved views and Range loading.
  7. React content. Switch the import to super-scheduler/react-render when you need React inside events or headers; see React render slots.

Hotel room planningA shower leaks in Room 104. Rehouse the next guest, block the room for the plumber and find the nights that are already full. For commercial questions about Pro, see the pricing page.