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.
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
npm install super-scheduler-lite react react-domreact-dom aparece porque es lo que usas para renderizar, no porque Lite lo importe.
Pintar una primera línea de tiempo
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):
.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ón | Tipo | Por defecto | Notas |
|---|---|---|---|
startDate | cadena ISO o SuperScheduler.Date | Hoy | El primer día; la hora se ignora |
days | entero positivo | 31 | Número de columnas de día |
scale | 'Day' | 'Day' | El único valor aceptado |
cellWidth | número (px) | 64 | Ancho de un día |
height | número (px) | 400 | Alto total de la caja con scroll, cabecera incluida |
rowHeaderWidth | número (px) | 160 | Ancho de la columna con el nombre del recurso |
rowMinHeight | número (px) | 40 | Las filas crecen cuando se apilan eventos solapados |
eventHeight | número (px) | 26 | Alto de una línea de eventos |
resources | ResourceData[] | [] | { id, name }, plana |
events | EventData[] | [] | Consulta Campos de eventos |
locale | cadena | 'en-us' | Etiquetas de día en la cabecera, como es-es o de-de |
ariaLabel | cadena | 'Resource schedule' | Nombre accesible de la cuadrícula, que también se muestra en la esquina superior izquierda |
emptyState | cadena | 'No resources' | Texto que se muestra cuando resources está vacío |
onEventClick | función | ninguno | Consulta Responder a los clics |
onTimeRangeClick | función | ninguno | Consulta 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:
| Campo | Obligatorio | Significado |
|---|---|---|
id | sí | Cadena o número finito, único entre los eventos |
resource | sí | El id de la fila a la que pertenece, con el mismo tipo |
start, end | sí | Cadenas ISO (2026-10-02 o 2026-10-02T14:00:00, segundos incluidos) o SuperScheduler.Date; end es exclusivo |
text | sí | La etiqueta, que se pinta como texto (nunca como HTML) |
backColor, fontColor | no | Cualquier color CSS |
cssClass | no | Nombres de clase adicionales en el botón del evento |
toolTip | no | Tooltip nativo; por defecto, text |
tags | no | Cualquier 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.
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).
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:
| Miembro | Qué 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:
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
allowEventOverlapozoomLevels, aunque se pasen desde JavaScript plano:SuperScheduler Lite: unsupported option "zoomLevels". - Un
scaledistinto de'Day'. - Un recurso con
children,frozen,splitocolumns(resource children requires Pro). - Ids de recurso duplicados, ids que no son cadenas ni números finitos, y eventos cuyo
endes anterior a sustart. - Tamaños no positivos o no finitos, y un
daysfraccionario.
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
- Entiende las reglas de datos comunes a ambas ediciones: Recursos, eventos e intervalos.
- Integra el componente correctamente en una aplicación React más grande: Integración con React.
- Mira cómo es una planificación editable en los ejemplos, todos construidos con Pro.
- Cuando necesites edición: Migrar de Lite a Pro.