# Schnellstart mit Lite

> super-scheduler-lite von npm installieren und eine schreibgeschützte Tageszeitleiste für Ressourcen in React rendern: Optionen, Klick-Callbacks, Control und Grenzen.

Source: https://superscheduler.org/de/docs/quick-start-lite/
Reviewed: 2026-10-07

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.

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](https://superscheduler.org/de/docs/install-pro/) und [Von Lite zu Pro migrieren](https://superscheduler.org/de/docs/migrate-lite-to-pro/).

## 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
```sh
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
```tsx
// src/Planning.tsx
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.

> **Tip:**
> Halten Sie `resources` und `events` zwischen Renderings stabil: Modulkonstanten, State oder `useMemo`. Die Komponente vergleicht Props per Identität und gibt nur geänderte an das Control weiter; ein neues Array-Literal bei jedem Rendering baut die Zeitleiste also jedes Mal neu auf.

## 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):

```css
.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](#rejects)).

| Option | Typ | Standard | Hinweise |
|---|---|---|---|
| `startDate` | ISO-String oder `SuperScheduler.Date` | Heute | Der erste Tag; eine Uhrzeit wird ignoriert |
| `days` | positive Ganzzahl | `31` | Anzahl der Tagesspalten |
| `scale` | `'Day'` | `'Day'` | Der einzige zulässige Wert |
| `cellWidth` | Zahl (px) | `64` | Breite eines Tages |
| `height` | Zahl (px) | `400` | Gesamthöhe des Scrollbereichs, Kopf eingeschlossen |
| `rowHeaderWidth` | Zahl (px) | `160` | Breite der Spalte mit den Ressourcennamen |
| `rowMinHeight` | Zahl (px) | `40` | Zeilen wachsen, wenn sich überlappende Ereignisse stapeln |
| `eventHeight` | Zahl (px) | `26` | Höhe einer Ereigniszeile |
| `resources` | `ResourceData[]` | `[]` | `{ id, name }`, flach |
| `events` | `EventData[]` | `[]` | Siehe [Felder von Ereignissen](#event-fields) |
| `locale` | String | `'en-us'` | Tagesbeschriftungen im Kopf, etwa `es-es` oder `de-de` |
| `ariaLabel` | String | `'Resource schedule'` | Barrierefreier Name des Rasters, auch in der linken oberen Ecke angezeigt |
| `emptyState` | String | `'No resources'` | Text, der erscheint, wenn `resources` leer ist |
| `onEventClick` | Funktion | keiner | Siehe [Auf Klicks reagieren](#clicks) |
| `onTimeRangeClick` | Funktion | keiner | Siehe [Auf Klicks reagieren](#clicks) |

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:

| Feld | Pflicht | Bedeutung |
|---|---|---|
| `id` | ja | String oder endliche Zahl, eindeutig unter den Ereignissen |
| `resource` | ja | Die `id` der Zeile, zu der es gehört, mit demselben Typ |
| `start`, `end` | ja | ISO-Strings (`2026-10-02` oder `2026-10-02T14:00:00`, einschließlich Sekunden) oder `SuperScheduler.Date`; `end` ist exklusiv |
| `text` | ja | Die Beschriftung, als Text gerendert (nie als HTML) |
| `backColor`, `fontColor` | nein | Beliebige CSS-Farbe |
| `cssClass` | nein | Zusätzliche Klassennamen auf dem Ereignis-Button |
| `toolTip` | nein | Nativer Tooltip; standardmäßig `text` |
| `tags` | nein | Ein 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](https://superscheduler.org/de/docs/resources-events-intervals/) 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`.

```tsx
// src/PlanningWithDetails.tsx
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.

> **Behavior:**
> Die Callback-Argumente von Lite sind schlanker als die von Pro: `e` stellt nur `data` bereit. In Pro ist `args.e` ein `SuperScheduler.Event`-Wrapper mit Methoden wie `id()` und `start()`. Stützen Sie die Logik Ihrer Handler auf Felder von `e.data`, wenn Sie eine Migration planen.

## 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`).

```tsx
// src/NavigablePlanning.tsx
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:

| Member | Was 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:

```ts
// src/mount-planning.ts
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.

> **Limitation:**
> Lite hat keine Bearbeitung, keine Stunden- oder Minutenzellen, keinen Zoom, kein unendliches Scrollen, keine Ressourcenbäume, keine fixierten oder geteilten Zeilen, keine Verknüpfungen, keine Auswahl, keine Konfliktmarkierung, keine Minimap, keine Bereiche, keinen Verlauf, keine gespeicherten Ansichten, kein bereichsweises Laden und keine React-Render-Slots. Der Code dafür ist nicht im Paket enthalten. Zusätzliche Felder in Ihren Ereignisobjekten bleiben erhalten, schalten aber nichts frei.

## Nächste Schritte
- Die Datenregeln verstehen, die für beide Editionen gelten: [Ressourcen, Ereignisse und Intervalle](https://superscheduler.org/de/docs/resources-events-intervals/).
- Die Komponente korrekt in eine größere React-App einbetten: [React-Integration](https://superscheduler.org/de/docs/react-integration/).
- In den [Beispielen](https://superscheduler.org/de/examples/), alle mit Pro gebaut, sehen Sie, wie eine bearbeitbare Planung aussieht.
- Wenn Sie Bearbeitung brauchen: [Von Lite zu Pro migrieren](https://superscheduler.org/de/docs/migrate-lite-to-pro/).
