Saltar al contenido
SuperScheduler

Empieza aquíSe aplica aSuperScheduler Lite

Inicio rápido con Lite

Ejecuta npm install super-scheduler-lite, importa SuperSchedulerComponent y super-scheduler-lite/styles.css, y pasa startDate, days, resources y events. Lite pinta una línea de tiempo virtualizada y de solo lectura con una celda por día, comunica los clics mediante onEventClick y onTimeRangeClick, y lanza un error ante cualquier opción que no implemente.

Verificado con v0.1.0 · revisado el 7 de octubre de 2026.md

SuperScheduler Lite es la edición pública y de solo lectura: una fila por recurso, una columna por día, los eventos como barras y los clics comunicados a tu código. Es la forma más rápida de poner un gráfico de ocupación o de disponibilidad en una aplicación React. Esta guía te lleva de un proyecto vacío a una línea de tiempo funcionando y después repasa todas las opciones, los callbacks, la API imperativa y lo que Lite rechaza a propósito.

Si necesitas arrastrar, redimensionar, horas y minutos, zoom o árboles de recursos, eso es cosa de Pro: consulta Instalar SuperScheduler Pro y Migrar de Lite a Pro.

Requisitos

  • React 18.2 o posterior, o React 19. React es una peer dependency, así que Lite usa la copia de tu aplicación.
  • Un bundler o framework que entienda módulos ES o CommonJS (Vite, Next.js, webpack, Parcel y similares). El paquete incluye ambos formatos con sus declaraciones de TypeScript.
  • Un entorno de navegador para pintar. El paquete se puede importar durante el renderizado en servidor; la línea de tiempo en sí se construye en el navegador cuando el componente se monta.

Instalar el paquete

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

react-dom aparece porque es lo que usas para renderizar, no porque Lite lo importe.

Pintar una primera línea de tiempo

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} />
  )
}

Deberías ver una cuadrícula de 400 píxeles de alto con una cabecera de etiquetas de día (1 Oct, 2 Oct, …), tres filas de habitaciones y tres barras. La reserva 1042 ocupa el 2, el 3 y el 4 de octubre: la fecha de fin es exclusiva, así que una estancia que termina el 2026-10-05 desaparece a medianoche del día 5. La reserva 1043 se solapa con ella, así que Room 101 pasa a tener dos líneas y apila las dos barras. La reserva 1051 empieza a las 14:00 del día 6 y termina a las 11:00 del día 9: Lite coloca las barras en su hora exacta dentro de las celdas de día.

Haz scroll en cualquier dirección. Solo las filas, los días y los eventos visibles existen en el DOM, y el scroll nunca provoca un render de React, sea cual sea el tamaño de tus datos.

Importar los estilos

Importa super-scheduler-lite/styles.css una sola vez, normalmente en tu archivo de entrada o en el layout raíz. Las reglas viven en una capa de cascada CSS llamada super-scheduler, así que cualquier regla sin capa de tu propia hoja de estilos las sobrescribe sin !important.

El elemento raíz tiene la clase super-scheduler-lite y seis propiedades personalizadas. Sobrescríbelas en esa clase (no en un ancestro lejano, porque la raíz declara sus propios valores):

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 define su propia fuente (system UI de 13 px) y ocupa todo el ancho de su contenedor. Los colores de cada evento salen de los datos (backColor, fontColor) o de una cssClass a la que das estilo tú.

Opciones y valores por defecto

Todas las opciones que acepta Lite están en esta tabla. Cualquier otra lanza un error (consulta Lo que Lite rechaza).

OpciónTipoPor defectoNotas
startDatecadena ISO o SuperScheduler.DateHoyEl primer día; la hora se ignora
daysentero positivo31Número de columnas de día
scale'Day''Day'El único valor aceptado
cellWidthnúmero (px)64Ancho de un día
heightnúmero (px)400Alto total de la caja con scroll, cabecera incluida
rowHeaderWidthnúmero (px)160Ancho de la columna con el nombre del recurso
rowMinHeightnúmero (px)40Las filas crecen cuando se apilan eventos solapados
eventHeightnúmero (px)26Alto de una línea de eventos
resourcesResourceData[][]{ id, name }, plana
eventsEventData[][]Consulta Campos de eventos
localecadena'en-us'Etiquetas de día en la cabecera, como es-es o de-de
ariaLabelcadena'Resource schedule'Nombre accesible de la cuadrícula, que también se muestra en la esquina superior izquierda
emptyStatecadena'No resources'Texto que se muestra cuando resources está vacío
onEventClickfunciónningunoConsulta Responder a los clics
onTimeRangeClickfunciónningunoConsulta Responder a los clics

Las opciones numéricas deben ser positivas y finitas, y days debe ser un entero.

Campos de eventos y recursos

Un recurso es { id, name }. Un evento tiene cinco campos obligatorios y cinco opcionales:

CampoObligatorioSignificado
idsíCadena o número finito, único entre los eventos
resourcesíEl id de la fila a la que pertenece, con el mismo tipo
start, endsíCadenas ISO (2026-10-02 o 2026-10-02T14:00:00, segundos incluidos) o SuperScheduler.Date; end es exclusivo
textsíLa etiqueta, que se pinta como texto (nunca como HTML)
backColor, fontColornoCualquier color CSS
cssClassnoNombres de clase adicionales en el botón del evento
toolTipnoTooltip nativo; por defecto, text
tagsnoCualquier valor que quieras recuperar en onEventClick

Los ids se comparan de forma estricta: 1 y '1' son ids distintos, así que un evento con resource: '101' no aparece en una fila con id: 101. Las fechas son valores civiles de reloj sin zona horaria; la guía del modelo de datos explica las reglas, que son las mismas en ambas ediciones.

Responder a los clics

Lite comunica dos interacciones. onEventClick recibe { control, e, originalEvent }, donde e.data es tu objeto de evento. onTimeRangeClick recibe { control, start, end, resource, originalEvent } cuando se pulsa una celda de día vacía; start es ese día a medianoche y end la medianoche siguiente, ambos como 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}
      />
    </>
  )
}

Deberías ver cómo cambia el párrafo al pulsar una reserva o una celda libre. Los mismos callbacks funcionan con el teclado: Tab pone el foco en la cuadrícula, las flechas mueven la celda activa e Intro o Espacio sobre ella llaman a onTimeRangeClick; los eventos son botones, así que Intro sobre un evento con foco llama a onEventClick. originalEvent es el evento DOM que hay detrás de la llamada: el KeyboardEvent cuando Intro o Espacio activaron una celda, y un evento de clic en los demás casos.

Controlar la línea de tiempo desde código

El componente React crea un control al montarse y lo libera al desmontarse. Accede a él mediante ref.current.control en el componente o con la prop controlRef (un objeto ref o un callback; Lite lo pone a null al desmontar).

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}
      />
    </>
  )
}

El control de Lite tiene ocho miembros:

MiembroQué hace
update(options)Combina options con las opciones actuales y vuelve a dibujar. Un undefined explícito restaura el valor por defecto
scrollTo(date)Hace scroll para que date quede en el borde izquierdo
scrollToResource(id)Hace scroll para que esa fila quede arriba
visibleStart(), visibleEnd()Las fechas en los bordes izquierdo y derecho de la vista desplazada
disposed()Si dispose() ya se ha ejecutado
dispose()Elimina el DOM, los listeners y los observers, y libera los datos
init()Construye el DOM; el componente React lo llama por ti

Sin React, crea el control sobre un elemento que sea tuyo:

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()
}

Actualizar los datos

El componente solo envía a control.update() las props que han cambiado, comparándolas por identidad. Para cambiar los datos, pasa un array nuevo: setEvents([...events, next]) funciona, mientras que events.push(next) sobre el mismo array no llega a la línea de tiempo hasta que llamas tú a control.update(). Las actualizaciones que solo cambian onEventClick u onTimeRangeClick sustituyen los callbacks sin volver a dibujar.

Lo que Lite rechaza

Lite valida su entrada y lanza un error en lugar de ignorar lo que no sabe hacer, así que un error de configuración aparece durante el desarrollo y no como una pantalla que funciona a medias:

  • Una opción que no está en la tabla anterior, incluidas opciones de Pro como allowEventOverlap o zoomLevels, aunque se pasen desde JavaScript plano: SuperScheduler Lite: unsupported option "zoomLevels".
  • Un scale distinto de 'Day'.
  • Un recurso con children, frozen, split o columns (resource children requires Pro).
  • Ids de recurso duplicados, ids que no son cadenas ni números finitos, y eventos cuyo end es anterior a su start.
  • Tamaños no positivos o no finitos, y un days fraccionario.

Cuando update() lanza un error, la configuración anterior sigue en pantalla y utilizable. En React, el error se lanza mientras el componente aplica las props nuevas, así que un error boundary por encima lo captura.

Siguientes pasos