Zum Inhalt springen
SuperScheduler

EinstiegGilt fürSuperScheduler Lite

Schnellstart mit Lite

Führen Sie npm install super-scheduler-lite aus, importieren Sie SuperSchedulerComponent und super-scheduler-lite/styles.css und übergeben Sie startDate, days, resources und events. Lite rendert eine schreibgeschützte, virtualisierte Zeitleiste mit einer Zelle pro Tag, meldet Klicks über onEventClick und onTimeRangeClick und wirft bei jeder Option, die es nicht implementiert, einen Fehler.

Geprüft mit v0.1.0 · überarbeitet am 7. Oktober 2026.md

SuperScheduler Lite ist die öffentliche, schreibgeschützte Edition: eine Zeile pro Ressource, eine Spalte pro Tag, Ereignisse als Balken, Klicks werden an Ihren Code gemeldet. So kommt eine Belegungs- oder Verfügbarkeitsübersicht am schnellsten in eine React-Anwendung. Dieser Leitfaden führt Sie von einem leeren Projekt zu einer funktionierenden Zeitleiste und behandelt dann alle Optionen, die Callbacks, die imperative API und das, was Lite bewusst ablehnt.

Wenn Sie Ziehen, Dauer ändern, Stunden und Minuten, Zoom oder Ressourcenbäume brauchen, gehört das zu Pro: siehe SuperScheduler Pro installieren und Von Lite zu Pro migrieren.

Voraussetzungen

  • React 18.2 oder neuer oder React 19. React ist eine Peer-Abhängigkeit, Lite verwendet also die Kopie Ihrer Anwendung.
  • Ein Bundler oder Framework, das ES-Module oder CommonJS versteht (Vite, Next.js, webpack, Parcel und ähnliche). Beide Formate samt TypeScript-Deklarationen sind im Paket enthalten.
  • Eine Browserumgebung zum Rendern. Das Paket lässt sich beim Server-Rendering importieren; die Zeitleiste selbst wird im Browser aufgebaut, wenn die Komponente gemountet wird.

Das Paket installieren

shsh
npm install super-scheduler-lite react react-dom

react-dom steht in der Liste, weil Sie damit rendern, nicht weil Lite es importiert.

Eine erste Zeitleiste rendern

src/Planning.tsxtsx
import { SuperSchedulerComponent } from 'super-scheduler-lite'
import type { SuperScheduler } from 'super-scheduler-lite'
import 'super-scheduler-lite/styles.css'

// Module-level arrays keep the same identity on every render, so React never re-applies them.
const ROOMS: SuperScheduler.ResourceData[] = [
  { id: 'r101', name: 'Room 101' },
  { id: 'r102', name: 'Room 102' },
  { id: 'r103', name: 'Room 103' },
]

const BOOKINGS: SuperScheduler.EventData[] = [
  // Date-only values: the bar covers 2, 3 and 4 October (the end is exclusive).
  { id: 1, resource: 'r101', start: '2026-10-02', end: '2026-10-05', text: 'Booking 1042' },
  // Overlaps the first booking on the same row: Lite stacks it on a second line.
  {
    id: 2,
    resource: 'r101',
    start: '2026-10-04',
    end: '2026-10-07',
    text: 'Booking 1043',
    backColor: '#dbeafe',
  },
  // Times are kept: the bar starts at 14:00 and ends at 11:00, inside the day cells.
  {
    id: 3,
    resource: 'r103',
    start: '2026-10-06T14:00:00',
    end: '2026-10-09T11:00:00',
    text: 'Booking 1051',
  },
]

export function Planning() {
  return (
    <SuperSchedulerComponent startDate="2026-10-01" days={31} resources={ROOMS} events={BOOKINGS} />
  )
}

Sie sollten ein 400 Pixel hohes Raster mit einem Kopf aus Tagesbeschriftungen (1 Oct, 2 Oct, …), drei Zimmerzeilen und drei Balken sehen. Buchung 1042 umfasst den 2., 3. und 4. Oktober: Das Enddatum ist exklusiv, ein Aufenthalt, der am 2026-10-05 endet, ist also um Mitternacht des 5. vorbei. Buchung 1043 überlappt sich mit ihr, daher wächst Room 101 auf zwei Zeilen und stapelt beide Balken. Buchung 1051 beginnt am 6. um 14:00 Uhr und endet am 9. um 11:00 Uhr: Lite platziert Balken zu ihren exakten Zeiten innerhalb der Tageszellen.

Scrollen Sie das Raster in jede Richtung. Nur die sichtbaren Zeilen, Tage und Ereignisse existieren im DOM, und Scrollen löst nie ein React-Rendering aus, egal wie groß Ihre Daten sind.

Die Styles importieren

Importieren Sie super-scheduler-lite/styles.css einmal, typischerweise in Ihrer Einstiegsdatei oder im Root-Layout. Die Regeln liegen in einem CSS-Cascade-Layer namens super-scheduler, sodass jede Regel Ihres eigenen Stylesheets außerhalb eines Layers sie ohne !important überschreibt.

Das Wurzelelement hat die Klasse super-scheduler-lite und sechs Custom Properties. Überschreiben Sie sie auf dieser Klasse (nicht auf einem entfernten Vorfahren, denn die Wurzel deklariert eigene Werte):

csscss
.super-scheduler-lite {
  --super-scheduler-background: #ffffff;
  --super-scheduler-text: #18212f;
  --super-scheduler-border: #dce3ed;
  --super-scheduler-header: #f4f7fb;
  --super-scheduler-event: #d7e8fa;
  --super-scheduler-focus: #005cbf;
}

/* A dark theme driven by your own class on <html>. */
.dark .super-scheduler-lite {
  --super-scheduler-background: #121518;
  --super-scheduler-text: #f4f4f5;
  --super-scheduler-border: #2b3139;
  --super-scheduler-header: #1b1f24;
  --super-scheduler-event: #1f3a5c;
}

Lite setzt seine eigene Schrift (13 px System-UI) und füllt die Breite seines Elternelements. Farben pro Ereignis kommen aus den Daten (backColor, fontColor) oder aus einer cssClass, die Sie selbst gestalten.

Optionen und Standardwerte

Jede Option, die Lite akzeptiert, steht in dieser Tabelle. Alles andere wirft einen Fehler (siehe Was Lite ablehnt).

OptionTypStandardHinweise
startDateISO-String oder SuperScheduler.DateHeuteDer erste Tag; eine Uhrzeit wird ignoriert
dayspositive Ganzzahl31Anzahl der Tagesspalten
scale'Day''Day'Der einzige zulässige Wert
cellWidthZahl (px)64Breite eines Tages
heightZahl (px)400Gesamthöhe des Scrollbereichs, Kopf eingeschlossen
rowHeaderWidthZahl (px)160Breite der Spalte mit den Ressourcennamen
rowMinHeightZahl (px)40Zeilen wachsen, wenn sich überlappende Ereignisse stapeln
eventHeightZahl (px)26Höhe einer Ereigniszeile
resourcesResourceData[][]{ id, name }, flach
eventsEventData[][]Siehe Felder von Ereignissen
localeString'en-us'Tagesbeschriftungen im Kopf, etwa es-es oder de-de
ariaLabelString'Resource schedule'Barrierefreier Name des Rasters, auch in der linken oberen Ecke angezeigt
emptyStateString'No resources'Text, der erscheint, wenn resources leer ist
onEventClickFunktionkeinerSiehe Auf Klicks reagieren
onTimeRangeClickFunktionkeinerSiehe Auf Klicks reagieren

Numerische Optionen müssen positiv und endlich sein, und days muss eine Ganzzahl sein.

Felder von Ereignissen und Ressourcen

Eine Ressource ist { id, name }. Ein Ereignis hat fünf Pflichtfelder und fünf optionale:

FeldPflichtBedeutung
idjaString oder endliche Zahl, eindeutig unter den Ereignissen
resourcejaDie id der Zeile, zu der es gehört, mit demselben Typ
start, endjaISO-Strings (2026-10-02 oder 2026-10-02T14:00:00, einschließlich Sekunden) oder SuperScheduler.Date; end ist exklusiv
textjaDie Beschriftung, als Text gerendert (nie als HTML)
backColor, fontColorneinBeliebige CSS-Farbe
cssClassneinZusätzliche Klassennamen auf dem Ereignis-Button
toolTipneinNativer Tooltip; standardmäßig text
tagsneinEin beliebiger Wert, den Sie in onEventClick zurückerhalten

IDs werden strikt verglichen: 1 und '1' sind verschiedene IDs, ein Ereignis mit resource: '101' erscheint also nicht in einer Zeile mit id: 101. Datumsangaben sind bürgerliche Zeitwerte (lokale Datum-Uhrzeit) ohne Zeitzone; der Leitfaden zum Datenmodell erklärt die Regeln, die in beiden Editionen gleich sind.

Auf Klicks reagieren

Lite meldet zwei Interaktionen. onEventClick erhält { control, e, originalEvent }, wobei e.data Ihr Ereignisobjekt ist. onTimeRangeClick erhält { control, start, end, resource, originalEvent } bei einem Klick auf eine leere Tageszelle; start ist dieser Tag um Mitternacht und end die nächste Mitternacht, beide als SuperScheduler.Date.

src/PlanningWithDetails.tsxtsx
import { useCallback, useState } from 'react'
import { SuperSchedulerComponent } from 'super-scheduler-lite'
import type {
  SchedulerEventClickArgs,
  SchedulerTimeRangeClickArgs,
  SuperScheduler,
} from 'super-scheduler-lite'

interface PlanningProps {
  readonly rooms: SuperScheduler.ResourceData[]
  readonly bookings: SuperScheduler.EventData[]
}

export function PlanningWithDetails({ rooms, bookings }: PlanningProps) {
  const [detail, setDetail] = useState('Select a booking or a free day.')

  // Stable callbacks: a new function per render would be sent to the control on every render.
  const onEventClick = useCallback((args: SchedulerEventClickArgs) => {
    // Lite hands you the event's own data object, including `tags`.
    setDetail(`${args.e.data.text} (id ${String(args.e.data.id)})`)
  }, [])

  const onTimeRangeClick = useCallback((args: SchedulerTimeRangeClickArgs) => {
    // One day cell: `end` is the next midnight. Enter and Space on the active cell also land here.
    setDetail(`Free cell: ${String(args.resource)} on ${args.start.toString('d MMMM yyyy')}`)
  }, [])

  return (
    <>
      <p aria-live="polite">{detail}</p>
      <SuperSchedulerComponent
        startDate="2026-10-01"
        days={31}
        resources={rooms}
        events={bookings}
        onEventClick={onEventClick}
        onTimeRangeClick={onTimeRangeClick}
      />
    </>
  )
}

Der Absatz sollte sich ändern, wenn Sie auf eine Buchung oder eine freie Zelle klicken. Dieselben Callbacks laufen auch über die Tastatur: Tab fokussiert das Raster, die Pfeiltasten bewegen die aktive Zelle, und Eingabetaste oder Leertaste auf dieser Zelle ruft onTimeRangeClick auf; Ereignisse sind Buttons, die Eingabetaste auf einem fokussierten Ereignis ruft also onEventClick auf. originalEvent ist das DOM-Event hinter dem Aufruf: das KeyboardEvent, wenn Eingabe oder Leertaste eine Zelle aktiviert hat, sonst ein Klick-Event.

Die Zeitleiste aus Code steuern

Die React-Komponente erzeugt beim Mounten ein Control und gibt es beim Unmounten frei. Sie erreichen es über ref.current.control auf der Komponente oder mit der Prop controlRef (ein Ref-Objekt oder ein Callback; Lite setzt sie beim Unmounten auf null).

src/NavigablePlanning.tsxtsx
import { useRef } from 'react'
import { SuperScheduler, SuperSchedulerComponent } from 'super-scheduler-lite'

interface PlanningProps {
  readonly rooms: SuperScheduler.ResourceData[]
  readonly bookings: SuperScheduler.EventData[]
}

export function NavigablePlanning({ rooms, bookings }: PlanningProps) {
  // Lite sets `current` after mount and clears it on unmount.
  const controlRef = useRef<SuperScheduler.Scheduler | null>(null)

  const goToToday = () => controlRef.current?.scrollTo(SuperScheduler.Date.today())
  const findRoom = (id: SuperScheduler.ResourceData['id']) =>
    controlRef.current?.scrollToResource(id)
  const logRange = () => {
    const control = controlRef.current
    if (control !== null)
      console.info(`${control.visibleStart().value} to ${control.visibleEnd().value}`)
  }

  return (
    <>
      <div role="toolbar" aria-label="Planning navigation">
        <button type="button" onClick={goToToday}>
          Today
        </button>
        <button type="button" onClick={() => findRoom('r310')}>
          Room 310
        </button>
        <button type="button" onClick={logRange}>
          Visible range
        </button>
      </div>
      <SuperSchedulerComponent
        controlRef={controlRef}
        startDate="2026-10-01"
        days={92}
        height={520}
        resources={rooms}
        events={bookings}
      />
    </>
  )
}

Das Lite-Control hat acht Member:

MemberWas es tut
update(options)Führt options mit den aktuellen zusammen und zeichnet neu. Ein explizites undefined stellt einen Standardwert wieder her
scrollTo(date)Scrollt so, dass date am linken Rand steht
scrollToResource(id)Scrollt so, dass diese Zeile oben steht
visibleStart(), visibleEnd()Die Datumsangaben am linken und rechten Rand der gescrollten Ansicht
disposed()Ob dispose() gelaufen ist
dispose()Entfernt DOM, Listener und Observer und gibt die Daten frei
init()Baut das DOM auf; die React-Komponente ruft es für Sie auf

Ohne React erzeugen Sie das Control auf einem Element, das Ihnen gehört:

src/mount-planning.tsts
import { SuperScheduler } from 'super-scheduler-lite'
import 'super-scheduler-lite/styles.css'

/** Mounts a read-only planning into `host` without React and returns its teardown. */
export function mountPlanning(host: HTMLElement): () => void {
  const control = new SuperScheduler.Scheduler(host, {
    startDate: '2026-10-01',
    days: 31,
    resources: [
      { id: 'r101', name: 'Room 101' },
      { id: 'r102', name: 'Room 102' },
    ],
    events: [
      { id: 1, resource: 'r101', start: '2026-10-02', end: '2026-10-05', text: 'Booking 1042' },
    ],
    onEventClick: ({ e }) => console.info('booking', e.data.id),
  })
  control.init()

  // update() merges with the current options; an explicit undefined restores a default.
  control.update({ days: 62, cellWidth: 48 })
  control.scrollTo('2026-10-15')

  return () => control.dispose()
}

Die Daten aktualisieren

Die Komponente gibt nur geänderte Props an control.update() weiter und vergleicht sie per Identität. Um die Daten zu ändern, übergeben Sie ein neues Array: setEvents([...events, next]) funktioniert, während events.push(next) auf demselben Array die Zeitleiste erst erreicht, wenn Sie control.update() selbst aufrufen. Updates, die nur onEventClick oder onTimeRangeClick ändern, tauschen die Callbacks aus, ohne neu zu zeichnen.

Was Lite ablehnt

Lite validiert seine Eingaben und wirft einen Fehler, statt zu ignorieren, was es nicht kann. Eine Fehlkonfiguration zeigt sich so schon in der Entwicklung statt als halb funktionierender Bildschirm:

  • Eine Option, die nicht in der Tabelle oben steht, einschließlich Pro-Optionen wie allowEventOverlap oder zoomLevels, auch wenn sie aus reinem JavaScript übergeben wird: SuperScheduler Lite: unsupported option "zoomLevels".
  • Ein anderer scale-Wert als 'Day'.
  • Eine Ressource mit children, frozen, split oder columns (resource children requires Pro).
  • Doppelte Ressourcen-IDs, IDs, die weder Strings noch endliche Zahlen sind, und Ereignisse, deren end vor ihrem start liegt.
  • Nicht positive oder nicht endliche Größen und ein gebrochener Wert für days.

Wenn update() einen Fehler wirft, bleibt die vorherige Konfiguration sichtbar und benutzbar. In React wird der Fehler geworfen, während die Komponente die neuen Props übernimmt, sodass eine Error Boundary darüber ihn abfängt.

Nächste Schritte