@reservi/preact 1.3.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +137 -4
- package/dist/index.js +984 -565
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/render/slots.ts","../src/components/Toolbar.tsx","../src/render/nav.ts","../src/interaction/keyboard.ts","../src/interaction/daygrid-drag.ts","../src/views/daygrid/DayGridView.tsx","../src/interaction/drag.ts","../src/views/timegrid/TimeGridView.tsx","../src/views/list/ListView.tsx","../src/views/multimonth/MultiMonthView.tsx","../src/views/timeline/TimelineView.tsx","../src/views/resource/ResourceTimelineView.tsx","../src/views/resource/ResourceTimeGridView.tsx","../src/views/resource/ResourceDayGridView.tsx","../src/components/Calendar.tsx","../src/mount.ts","../src/ical.ts"],"sourcesContent":["import type { ComponentChildren } from \"preact\";\nimport type { SlotResult } from \"../types.js\";\n\n/**\n * Resuelve un slot de contenido: si el usuario aportó una función, usa su\n * resultado; si no, usa el contenido por defecto. Unifica el contrato de los\n * render hooks para todos los frameworks (en wrappers se adapta a su idioma).\n */\nexport function renderSlot<Arg>(\n slot: ((arg: Arg) => SlotResult) | undefined,\n arg: Arg,\n fallback: ComponentChildren,\n): ComponentChildren {\n if (!slot) return fallback;\n return slot(arg) as ComponentChildren;\n}\n\n/** Une clases base con las del usuario (filtra vacíos). */\nexport function cx(...classes: (string | undefined | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import { dl, getLocaleText, type CalendarApi } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport { useEffect, useRef, useState } from \"preact/hooks\";\nimport type { ReserviCalendarOptions } from \"../types.js\";\nimport { cx } from \"../render/slots.js\";\n\nconst NAV_SYMBOLS = { prev: \"‹\", next: \"›\" } as const;\n/** Tokens que NO son vistas (no aparecen como pestañas). */\nconst NON_VIEW_TOKENS = new Set([\"\", \"title\", \"today\", \"prev\", \"next\"]);\n/** Vistas cuyo datepicker elige MES (resto: elige DÍA). */\nconst MONTH_VIEW_RE = /month|year/i;\n\nconst pad2 = (n: number): string => String(n).padStart(2, \"0\");\n\n/** Icono de calendario junto al título. */\nfunction CalendarIcon(): VNode {\n return (\n <svg\n data-rsv=\"title-icon\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"1\" y=\"2.5\" width=\"12\" height=\"10.5\" rx=\"1.5\" />\n <line x1=\"1\" y1=\"5.5\" x2=\"13\" y2=\"5.5\" />\n <line x1=\"4.5\" y1=\"1\" x2=\"4.5\" y2=\"3.5\" />\n <line x1=\"9.5\" y1=\"1\" x2=\"9.5\" y2=\"3.5\" />\n </svg>\n );\n}\n\ninterface ToolbarProps {\n api: CalendarApi;\n title: string;\n activeView: string;\n options: ReserviCalendarOptions;\n}\n\n/** Vistas para la fila de pestañas: prop `views` o, en su defecto, tokens de `headerToolbar`. */\nfunction resolveViews(options: ReserviCalendarOptions): string[] {\n if (options.views?.length) return options.views;\n const tb = options.headerToolbar;\n if (!tb) return [];\n return [tb.start, tb.center, tb.end]\n .filter((s): s is string => Boolean(s))\n .flatMap((s) => s.split(/\\s+/))\n .flatMap((g) => g.split(\",\"))\n .filter((t) => !NON_VIEW_TOKENS.has(t));\n}\n\n/**\n * Toolbar de dos filas:\n * - Fila 1: slot de inicio (Filtrar/Personal del anfitrión) · navegación\n * (hoy ‹ título ›) · slot de fin + botón \"Añadir\" (opcional, vía props).\n * - Fila 2: pestañas de vista.\n *\n * El título abre un datepicker para saltar de fecha. En vistas de mes/año la\n * rejilla elige MES; en el resto (semana/día/lista) elige DÍA. Se abre también\n * con Ctrl+M y se cierra con Esc o clic fuera.\n */\nexport function Toolbar({ api, title, activeView, options }: ToolbarProps): VNode {\n const text = getLocaleText(options.locale);\n const startSlot = options.slots?.toolbarStart?.();\n const endSlot = options.slots?.toolbarEnd?.();\n const views = resolveViews(options);\n const monthMode = MONTH_VIEW_RE.test(activeView);\n const firstDay = options.firstDay ?? text.firstDay;\n\n const wrapRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n\n // Fecha seleccionada (para resaltar). Reactivo vía signals.\n const selected = dl.toDate(api.getDate());\n const nowRef = dl.toDate(options.now ? dl.from(options.now) : dl.now());\n\n // El mes/año mostrados en la rejilla (independientes de la navegación principal).\n const [viewYear, setViewYear] = useState(selected.getFullYear());\n const [viewMonth, setViewMonth] = useState(selected.getMonth());\n\n const monthShortFmt = new Intl.DateTimeFormat(options.locale, { month: \"short\" });\n const monthLongFmt = new Intl.DateTimeFormat(options.locale, { month: \"long\" });\n const dowFmt = new Intl.DateTimeFormat(options.locale, { weekday: \"short\" });\n const monthNames = Array.from({ length: 12 }, (_, i) =>\n monthShortFmt.format(new Date(2020, i, 1)),\n );\n\n const openPicker = (): void => {\n const d = dl.toDate(api.getDate());\n setViewYear(d.getFullYear());\n setViewMonth(d.getMonth());\n setOpen(true);\n };\n const shiftMonth = (delta: number): void => {\n const total = viewYear * 12 + viewMonth + delta;\n setViewYear(Math.floor(total / 12));\n setViewMonth(((total % 12) + 12) % 12);\n };\n const goto = (iso: string): void => {\n api.gotoDate(iso);\n setOpen(false);\n };\n\n // Ctrl+M abre · Esc cierra · clic fuera cierra.\n useEffect(() => {\n const onKey = (e: KeyboardEvent): void => {\n if ((e.ctrlKey || e.metaKey) && (e.key === \"m\" || e.key === \"M\")) {\n e.preventDefault();\n openPicker();\n } else if (e.key === \"Escape\") {\n setOpen(false);\n }\n };\n const onPointer = (e: MouseEvent): void => {\n if (wrapRef.current && !wrapRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"keydown\", onKey);\n document.addEventListener(\"mousedown\", onPointer);\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n document.removeEventListener(\"mousedown\", onPointer);\n };\n }, []);\n\n // Celdas (6×7) para el modo DÍA, alineadas a firstDay.\n const dayGrid = ((): { cells: Date[]; dows: string[] } => {\n if (monthMode) return { cells: [], dows: [] };\n const first = dl.from(`${viewYear}-${pad2(viewMonth + 1)}-01`);\n const offset = (dl.dayOfWeek(first) - firstDay + 7) % 7;\n const start = dl.subtract(first, { days: offset });\n const cells = Array.from({ length: 42 }, (_, i) => dl.toDate(dl.add(start, { days: i })));\n const dows = cells.slice(0, 7).map((d) => dowFmt.format(d));\n return { cells, dows };\n })();\n\n return (\n <div data-rsv=\"toolbar-wrap\" class={cx(options.classNames?.toolbar)} ref={wrapRef}>\n <div data-rsv=\"toolbar\">\n {/* Inicio: slot libre del anfitrión (Filtrar / Personal …) */}\n <div data-rsv=\"toolbar-section\" data-rsv-area=\"start\">\n {startSlot}\n </div>\n\n {/* Navegación: hoy · ‹ título › */}\n <div data-rsv=\"toolbar-section\" data-rsv-area=\"nav\">\n <button\n type=\"button\"\n data-rsv=\"button\"\n title={text.today}\n aria-label={text.today}\n onClick={() => api.today()}\n >\n {text.today}\n </button>\n <button\n type=\"button\"\n data-rsv=\"button\"\n data-rsv-nav=\"prev\"\n title={text.prev}\n aria-label={text.prev}\n onClick={() => api.prev()}\n >\n {NAV_SYMBOLS.prev}\n </button>\n\n {/* Título = disparador del datepicker */}\n <div data-rsv=\"datepicker-anchor\">\n <button\n type=\"button\"\n data-rsv=\"title\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n title={`${title} · Ctrl+M`}\n onClick={() => (open ? setOpen(false) : openPicker())}\n >\n <CalendarIcon />\n {title}\n </button>\n\n {open && (\n <div\n data-rsv=\"datepicker\"\n data-rsv-mode={monthMode ? \"month\" : \"day\"}\n role=\"dialog\"\n aria-label={title}\n >\n <div data-rsv=\"dp-head\">\n <button\n type=\"button\"\n data-rsv=\"dp-nav\"\n aria-label={text.prev}\n onClick={() => (monthMode ? setViewYear((y) => y - 1) : shiftMonth(-1))}\n >\n {NAV_SYMBOLS.prev}\n </button>\n <span data-rsv=\"dp-label\">\n {monthMode\n ? viewYear\n : `${monthLongFmt.format(new Date(viewYear, viewMonth, 1))} ${viewYear}`}\n </span>\n <button\n type=\"button\"\n data-rsv=\"dp-nav\"\n aria-label={text.next}\n onClick={() => (monthMode ? setViewYear((y) => y + 1) : shiftMonth(1))}\n >\n {NAV_SYMBOLS.next}\n </button>\n </div>\n\n {monthMode ? (\n <div data-rsv=\"dp-grid\">\n {monthNames.map((label, i) => (\n <button\n type=\"button\"\n data-rsv=\"dp-month\"\n key={label}\n data-active={String(\n viewYear === selected.getFullYear() && i === selected.getMonth(),\n )}\n data-today={String(\n viewYear === nowRef.getFullYear() && i === nowRef.getMonth(),\n )}\n onClick={() => goto(`${viewYear}-${pad2(i + 1)}-01`)}\n >\n {label}\n </button>\n ))}\n </div>\n ) : (\n <div data-rsv=\"dp-days\">\n {dayGrid.dows.map((d, i) => (\n <div data-rsv=\"dp-dow\" key={`dow-${i}`}>\n {d}\n </div>\n ))}\n {dayGrid.cells.map((d) => {\n const iso = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;\n return (\n <button\n type=\"button\"\n data-rsv=\"dp-day\"\n key={iso}\n data-other={String(d.getMonth() !== viewMonth)}\n data-active={String(\n d.getFullYear() === selected.getFullYear() &&\n d.getMonth() === selected.getMonth() &&\n d.getDate() === selected.getDate(),\n )}\n data-today={String(\n d.getFullYear() === nowRef.getFullYear() &&\n d.getMonth() === nowRef.getMonth() &&\n d.getDate() === nowRef.getDate(),\n )}\n onClick={() => goto(iso)}\n >\n {d.getDate()}\n </button>\n );\n })}\n </div>\n )}\n </div>\n )}\n </div>\n\n <button\n type=\"button\"\n data-rsv=\"button\"\n data-rsv-nav=\"next\"\n title={text.next}\n aria-label={text.next}\n onClick={() => api.next()}\n >\n {NAV_SYMBOLS.next}\n </button>\n </div>\n\n {/* Fin: slot libre + botón \"Añadir\" (solo si se pasa onAddClick) */}\n <div data-rsv=\"toolbar-section\" data-rsv-area=\"end\">\n {endSlot}\n {options.onAddClick && (\n <button\n type=\"button\"\n data-rsv=\"button\"\n data-rsv-variant=\"primary\"\n onClick={options.onAddClick}\n >\n <span data-rsv=\"add-icon\" aria-hidden=\"true\">\n +\n </span>\n {options.addButtonText}\n </button>\n )}\n </div>\n </div>\n\n {/* Fila 2: pestañas de vista */}\n {views.length > 0 && (\n <div data-rsv=\"toolbar-views\" role=\"tablist\">\n {views.map((v) => (\n <button\n type=\"button\"\n data-rsv=\"view-tab\"\n key={v}\n role=\"tab\"\n aria-selected={v === activeView}\n data-active={String(v === activeView)}\n onClick={() => api.changeView(v)}\n >\n {text.views[v] ?? v}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { dl, type CalendarApi, type RsvDate } from \"@reservi/core\";\n\n/**\n * Navegación de \"nav links\": dispara `navLinkDay` y, por defecto, va a la vista\n * de día (timeGridDay o dayGridDay, la que esté registrada) en esa fecha.\n */\nexport function navLinkToDay(api: CalendarApi, date: RsvDate): void {\n api.trigger(\"navLinkDay\", { date });\n const target = api.hasView(\"timeGridDay\")\n ? \"timeGridDay\"\n : api.hasView(\"dayGridDay\")\n ? \"dayGridDay\"\n : null;\n if (target) {\n api.gotoDate(dl.toISOString(date));\n api.changeView(target);\n }\n}\n","/**\n * Movimiento de eventos por teclado (accesibilidad WCAG). No necesita geometría\n * de píxeles: mueve por incrementos fijos (días o snap de minutos), por lo que\n * es plenamente testeable. Usa moveEvent (validado) del núcleo.\n */\nimport {\n computeDrop,\n dl,\n timeStringToMinutes,\n type CalendarApi,\n type EventDef,\n} from \"@reservi/core\";\n\nexport type GridKind = \"dayGrid\" | \"timeGrid\";\n\nconst DAY = 1440;\n\ninterface KeydownOptions {\n api: CalendarApi;\n event: EventDef;\n kind: GridKind;\n snap?: string | undefined;\n}\n\nexport function handleEventKeydown(e: KeyboardEvent, opts: KeydownOptions): void {\n const { api, event, kind } = opts;\n const snapMin = timeStringToMinutes(opts.snap ?? \"00:30\");\n\n let deltaMin = 0;\n switch (e.key) {\n case \"ArrowLeft\":\n deltaMin = -DAY;\n break;\n case \"ArrowRight\":\n deltaMin = DAY;\n break;\n case \"ArrowUp\":\n deltaMin = kind === \"timeGrid\" ? -snapMin : -DAY * 7;\n break;\n case \"ArrowDown\":\n deltaMin = kind === \"timeGrid\" ? snapMin : DAY * 7;\n break;\n case \"Enter\":\n case \" \":\n e.preventDefault();\n api.trigger(\"eventClick\", { event });\n return;\n default:\n return; // tecla no gestionada\n }\n\n e.preventDefault();\n const next = computeDrop(event.start, event.end, deltaMin, dl);\n if (api.moveEvent(event.id, next.start, next.end)) {\n const updated = api.getEventById(event.id);\n if (updated) api.trigger(\"eventDrop\", { event: updated });\n }\n}\n","/**\n * Drag por puntero para dayGrid/mes: mover un evento entre días y seleccionar\n * un rango de días arrastrando. El cálculo de fechas usa el núcleo (computeDrop\n * + dl); aquí solo se hace hit-testing del DOM para saber sobre qué día se está.\n */\nimport { computeDrop, dl, type CalendarApi, type EventDef } from \"@reservi/core\";\n\nconst DAY = 1440;\nconst THRESHOLD = 4;\n\n/** Fecha (ISO) de la celda de día bajo el punto, o null. */\nfunction dateAtPoint(x: number, y: number): string | null {\n const el = document.elementFromPoint(x, y) as HTMLElement | null;\n return el?.closest<HTMLElement>('[data-rsv=\"day\"]')?.dataset.date ?? null;\n}\n\ninterface EventDragOptions {\n api: CalendarApi;\n event: EventDef;\n /** Fecha (ISO) de la celda donde empezó el arrastre. */\n sourceDate: string;\n /** Se llama si hubo arrastre real (para suprimir el click posterior). */\n onMoved?: () => void;\n}\n\n/** Arrastra un evento entre días (dayGrid/mes). */\nexport function startDayGridEventDrag(ev: PointerEvent, opts: EventDragOptions): void {\n ev.stopPropagation();\n const { api, event, sourceDate } = opts;\n const startX = ev.clientX;\n const startY = ev.clientY;\n let dragging = false;\n\n const onMove = (e: PointerEvent): void => {\n if (!dragging && Math.hypot(e.clientX - startX, e.clientY - startY) > THRESHOLD) {\n dragging = true;\n document.body.style.cursor = \"grabbing\";\n }\n };\n const onUp = (e: PointerEvent): void => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n document.body.style.cursor = \"\";\n if (!dragging) return;\n opts.onMoved?.();\n const target = dateAtPoint(e.clientX, e.clientY);\n if (!target) return;\n const deltaDays = dl.diff(dl.from(sourceDate), dl.from(target), \"day\");\n if (deltaDays === 0) return;\n const next = computeDrop(event.start, event.end, deltaDays * DAY, dl);\n if (api.moveEvent(event.id, next.start, next.end)) {\n const updated = api.getEventById(event.id);\n if (updated) api.trigger(\"eventDrop\", { event: updated });\n }\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n\n/**\n * Selecciona un rango de días arrastrando. Solo actúa si hay arrastre real\n * (varios días); un click simple lo gestiona el `onClick` de la celda. Llama a\n * `onRangeSelect` cuando selecciona, para suprimir el click posterior.\n */\nexport function startDayRangeSelect(\n ev: PointerEvent,\n opts: { api: CalendarApi; startDate: string; onRangeSelect?: () => void },\n): void {\n const target = ev.target as HTMLElement;\n // No iniciar selección si se pulsa sobre un evento, el \"+N more\" o un nav-link.\n if (target.closest('[data-rsv=\"event\"], [data-rsv=\"more-anchor\"], [data-nav-link=\"true\"]')) {\n return;\n }\n const { api } = opts;\n let endStr = opts.startDate;\n let moved = false;\n\n const onMove = (e: PointerEvent): void => {\n const d = dateAtPoint(e.clientX, e.clientY);\n if (d && d !== opts.startDate) moved = true;\n if (d) endStr = d;\n };\n const onUp = (): void => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n if (!moved) return; // click simple → lo gestiona onClick\n opts.onRangeSelect?.();\n const a = dl.from(opts.startDate);\n const b = dl.from(endStr);\n const [lo, hi] = dl.isBefore(a, b) ? [a, b] : [b, a];\n // Fin exclusivo (+1 día), como FullCalendar.\n api.select(dl.toISOString(lo), dl.toISOString(dl.add(hi, { days: 1 })));\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n","import {\n dl,\n getLocaleText,\n type CalendarApi,\n type DayGridCell,\n type DayGridModel,\n type EventDef,\n} from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport { useEffect, useRef, useState } from \"preact/hooks\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { renderSlot, cx } from \"../../render/slots.js\";\nimport { navLinkToDay } from \"../../render/nav.js\";\nimport { handleEventKeydown } from \"../../interaction/keyboard.js\";\nimport { startDayGridEventDrag, startDayRangeSelect } from \"../../interaction/daygrid-drag.js\";\n\ninterface DayGridViewProps {\n api: CalendarApi;\n model: DayGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista de cuadrícula por días (mes/semana/día/año). */\nexport function DayGridView({ api, model, options }: DayGridViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const dowFmt = new Intl.DateTimeFormat(locale, { weekday: \"short\" });\n const headerDays = model.weeks[0]?.days ?? [];\n const showWeekNums = options.weekNumbers === true;\n\n return (\n <div\n data-rsv=\"daygrid\"\n data-weeknumbers={String(showWeekNums)}\n style={`--rsv-cols:${model.columnCount}`}\n >\n <div data-rsv=\"daygrid-header\" role=\"row\">\n {showWeekNums && <div data-rsv=\"daygrid-weeknum-header\" role=\"columnheader\" />}\n {headerDays.map((cell) => {\n const date = dl.toDate(cell.date);\n const text = dowFmt.format(date);\n return (\n <div data-rsv=\"daygrid-dow\" role=\"columnheader\" key={cell.dayOfWeek}>\n {renderSlot(options.slots?.dayHeaderContent, { date, text }, text)}\n </div>\n );\n })}\n </div>\n\n {model.weeks.map((week, wi) => (\n <div data-rsv=\"daygrid-week\" role=\"row\" key={wi}>\n {showWeekNums && (\n <div data-rsv=\"daygrid-weeknum\" role=\"rowheader\">\n {week.weekNumber}\n </div>\n )}\n {week.days.map((cell) => (\n <DayCell api={api} cell={cell} options={options} key={dl.toISOString(cell.date)} />\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nfunction DayCell({\n api,\n cell,\n options,\n}: {\n api: CalendarApi;\n cell: DayGridCell;\n options: ReserviCalendarOptions;\n}): VNode {\n const date = dl.toDate(cell.date);\n const dayNumber = dl.dayOfMonth(cell.date);\n const defaultNumber = options.navLinks ? (\n <a\n data-rsv=\"day-number\"\n data-nav-link=\"true\"\n role=\"link\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n navLinkToDay(api, cell.date);\n }}\n >\n {dayNumber}\n </a>\n ) : (\n <span data-rsv=\"day-number\">{dayNumber}</span>\n );\n const numberNode = renderSlot(\n options.slots?.dayCellContent,\n { date, dayNumber, isToday: cell.isToday, isOther: cell.isOther },\n defaultNumber,\n );\n\n const [moreOpen, setMoreOpen] = useState(false);\n\n const dateStr = dl.toISOString(cell.date);\n const rangeSelectedRef = useRef(false);\n\n const onDayClick = () => {\n // Suprime el click que sigue a una selección por arrastre.\n if (rangeSelectedRef.current) {\n rangeSelectedRef.current = false;\n return;\n }\n api.trigger(\"dateClick\", { date: cell.date });\n if (options.selectable) {\n api.select(dateStr, dl.toISOString(dl.add(cell.date, { days: 1 })));\n }\n };\n\n const openMore = (e: Event) => {\n e.stopPropagation();\n setMoreOpen(true);\n api.trigger(\"moreLinkClick\", {\n date: cell.date,\n allEvents: [...cell.events, ...cell.hiddenEvents],\n hiddenEvents: cell.hiddenEvents,\n });\n };\n\n return (\n <div\n data-rsv=\"day\"\n role=\"gridcell\"\n data-date={dateStr}\n data-today={String(cell.isToday)}\n data-other={String(cell.isOther)}\n data-weekend={String(cell.isWeekend)}\n data-business={String(cell.isBusiness)}\n data-selected={String(cell.isSelected)}\n onClick={onDayClick}\n onPointerDown={\n options.selectable\n ? (e) =>\n startDayRangeSelect(e, {\n api,\n startDate: dateStr,\n onRangeSelect: () => {\n rangeSelectedRef.current = true;\n },\n })\n : undefined\n }\n >\n {numberNode}\n {cell.events\n .filter((event) => event.display !== \"none\")\n .map((event) => (\n <EventChip\n api={api}\n event={event}\n options={options}\n sourceDate={dateStr}\n key={event.id}\n />\n ))}\n {cell.moreCount > 0 && (\n <div data-rsv=\"more-anchor\">\n <button type=\"button\" data-rsv=\"more-link\" onClick={openMore}>\n {getLocaleText(options.locale).more(cell.moreCount)}\n </button>\n {moreOpen && (\n <DayMorePopover\n api={api}\n cell={cell}\n options={options}\n onClose={() => setMoreOpen(false)}\n />\n )}\n </div>\n )}\n </div>\n );\n}\n\n/** Popover de \"+N more\": lista todos los eventos del día (visibles + ocultos). */\nfunction DayMorePopover({\n api,\n cell,\n options,\n onClose,\n}: {\n api: CalendarApi;\n cell: DayGridCell;\n options: ReserviCalendarOptions;\n onClose: () => void;\n}): VNode {\n const ref = useRef<HTMLDivElement>(null);\n const dayFmt = new Intl.DateTimeFormat(options.locale ?? \"en\", {\n weekday: \"long\",\n day: \"numeric\",\n month: \"long\",\n });\n const allEvents = [...cell.events, ...cell.hiddenEvents].filter((e) => e.display !== \"none\");\n\n useEffect(() => {\n const onPointer = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"mousedown\", onPointer);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"mousedown\", onPointer);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [onClose]);\n\n return (\n <div data-rsv=\"more-popover\" role=\"dialog\" ref={ref} onClick={(e) => e.stopPropagation()}>\n <div data-rsv=\"more-popover-header\">\n <span data-rsv=\"more-popover-title\">{dayFmt.format(dl.toDate(cell.date))}</span>\n <button type=\"button\" data-rsv=\"more-popover-close\" aria-label=\"✕\" onClick={onClose}>\n ✕\n </button>\n </div>\n <div data-rsv=\"more-popover-body\">\n {allEvents.map((event) => (\n <EventChip\n api={api}\n event={event}\n options={options}\n sourceDate={dl.toISOString(cell.date)}\n key={event.id}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction EventChip({\n api,\n event,\n options,\n sourceDate,\n}: {\n api: CalendarApi;\n event: EventDef;\n options: ReserviCalendarOptions;\n sourceDate: string;\n}): VNode {\n const editable = options.editable === true && event.editable !== false;\n const draggedRef = useRef(false);\n const timeText = event.allDay ? \"\" : dl.format(event.start, \"HH:mm\");\n const content = renderSlot(\n options.slots?.eventContent,\n { event, isAllDay: event.allDay, timeText },\n <span data-rsv=\"event-title\">\n {timeText ? `${timeText} ` : \"\"}\n {event.title}\n </span>,\n );\n\n return (\n <div\n data-rsv=\"event\"\n role=\"button\"\n tabIndex={0}\n class={cx(...event.classNames)}\n data-all-day={String(event.allDay)}\n data-display={event.display}\n data-event-id={event.id}\n data-editable={String(editable)}\n style={`--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor}`}\n onClick={(e) => {\n e.stopPropagation();\n // Suprime el click que sigue a un arrastre.\n if (draggedRef.current) {\n draggedRef.current = false;\n return;\n }\n api.trigger(\"eventClick\", { event });\n if (event.url) window.open(event.url, \"_self\");\n }}\n onPointerDown={\n editable\n ? (e) =>\n startDayGridEventDrag(e, {\n api,\n event,\n sourceDate,\n onMoved: () => {\n draggedRef.current = true;\n },\n })\n : undefined\n }\n onKeyDown={\n editable ? (e) => handleEventKeydown(e, { api, event, kind: \"dayGrid\" }) : undefined\n }\n >\n {content}\n </div>\n );\n}\n","/**\n * Controlador de drag/resize por puntero para timeGrid. Usa la geometría pura\n * del núcleo (testeada en @reservi/core) y mide la columna del DOM para obtener\n * px/min. El cálculo de fechas NO vive aquí (vive en core/interaction).\n */\nimport {\n computeDrop,\n computeResize,\n dl,\n pxToSnappedMinutes,\n timeStringToMinutes,\n type CalendarApi,\n type EventDef,\n type ResizeEdge,\n type RsvDate,\n type TimeGridModel,\n} from \"@reservi/core\";\n\ninterface DragOptions {\n api: CalendarApi;\n event: EventDef;\n model: TimeGridModel;\n columnEl: HTMLElement;\n snap?: string | undefined;\n /** Si se indica, redimensiona por ese borde; si no, mueve el evento. */\n edge?: ResizeEdge | undefined;\n}\n\nexport function startEventDrag(ev: PointerEvent, options: DragOptions): void {\n ev.preventDefault();\n ev.stopPropagation();\n const { api, event, model, columnEl, snap = \"00:15\", edge } = options;\n\n const rect = columnEl.getBoundingClientRect();\n const totalMinutes = model.maxMinutes - model.minMinutes;\n const ppm = rect.height === 0 ? 0 : rect.height / totalMinutes;\n const startY = ev.clientY;\n\n const onUp = (e: PointerEvent) => {\n document.removeEventListener(\"pointerup\", onUp);\n const deltaMin = pxToSnappedMinutes(e.clientY - startY, ppm, snap);\n if (deltaMin === 0) return;\n\n const next = edge\n ? computeResize(event.start, event.end, edge, deltaMin, dl)\n : computeDrop(event.start, event.end, deltaMin, dl);\n\n // moveEvent valida overlap/constraint/allow; si no es válido, se revierte.\n if (api.moveEvent(event.id, next.start, next.end)) {\n const updated = api.getEventById(event.id);\n if (updated) api.trigger(edge ? \"eventResize\" : \"eventDrop\", { event: updated });\n }\n };\n\n document.addEventListener(\"pointerup\", onUp);\n}\n\ninterface RangeSelectOptions {\n api: CalendarApi;\n date: RsvDate;\n model: TimeGridModel;\n columnEl: HTMLElement;\n snap?: string | undefined;\n}\n\n/** Selección de rango horario por arrastre en una columna de timeGrid. */\nexport function startTimeRangeSelect(ev: PointerEvent, options: RangeSelectOptions): void {\n // No iniciar si se pulsa sobre un evento existente.\n if ((ev.target as HTMLElement).closest('[data-rsv=\"event\"]')) return;\n const { api, date, model, columnEl, snap = \"00:15\" } = options;\n\n const rect = columnEl.getBoundingClientRect();\n const total = model.maxMinutes - model.minMinutes;\n const ppm = rect.height === 0 ? 0 : rect.height / total;\n const snapMin = timeStringToMinutes(snap) || 15;\n\n const yToMin = (clientY: number): number => {\n const raw = model.minMinutes + (ppm === 0 ? 0 : (clientY - rect.top) / ppm);\n const clamped = Math.max(model.minMinutes, Math.min(model.maxMinutes, raw));\n return Math.round(clamped / snapMin) * snapMin;\n };\n\n const startMin = yToMin(ev.clientY);\n let endMin = startMin;\n let moved = false;\n\n const onMove = (e: PointerEvent): void => {\n const m = yToMin(e.clientY);\n if (m !== startMin) moved = true;\n endMin = m;\n };\n const onUp = (): void => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n if (!moved) return; // un click simple lo gestiona dateClick\n const lo = Math.min(startMin, endMin);\n const hi = Math.max(startMin, endMin);\n const dayStart = dl.startOf(date, \"day\");\n api.select(\n dl.toISOString(dl.add(dayStart, { minutes: lo })),\n dl.toISOString(dl.add(dayStart, { minutes: hi })),\n );\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n","import {\n dl,\n getLocaleText,\n type CalendarApi,\n type TimeGridModel,\n type TimeGridSeg,\n} from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { renderSlot, cx } from \"../../render/slots.js\";\nimport { navLinkToDay } from \"../../render/nav.js\";\nimport { startEventDrag, startTimeRangeSelect } from \"../../interaction/drag.js\";\nimport { handleEventKeydown } from \"../../interaction/keyboard.js\";\n\ninterface TimeGridViewProps {\n api: CalendarApi;\n model: TimeGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista con eje temporal vertical (semana/día). */\nexport function TimeGridView({ api, model, options }: TimeGridViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const dowFmt = new Intl.DateTimeFormat(locale, { weekday: \"short\", day: \"numeric\" });\n const showAllDay = options.allDaySlot !== false;\n const bodyHeight = `calc(var(--spacing-rsv-slot, 2.5rem) * ${model.slots.length})`;\n\n return (\n <div data-rsv=\"timegrid\" style={`--rsv-tg-days:${model.days.length}`}>\n {/* Cabecera de días */}\n <div data-rsv=\"tg-header\" role=\"row\">\n <div data-rsv=\"tg-axis-corner\" />\n {model.days.map((d) => (\n <div\n data-rsv=\"tg-col-header\"\n role=\"columnheader\"\n data-today={String(d.isToday)}\n data-nav-link={options.navLinks ? \"true\" : undefined}\n key={dl.toISOString(d.date)}\n onClick={options.navLinks ? () => navLinkToDay(api, d.date) : undefined}\n >\n {dowFmt.format(dl.toDate(d.date))}\n </div>\n ))}\n </div>\n\n {/* Franja de todo el día */}\n {showAllDay && (\n <div data-rsv=\"tg-allday\" role=\"row\">\n <div data-rsv=\"tg-axis-label\">{getLocaleText(options.locale).allDay}</div>\n {model.days.map((d) => (\n <div data-rsv=\"tg-allday-cell\" key={dl.toISOString(d.date)}>\n {d.allDayEvents\n .filter((event) => event.display !== \"none\")\n .map((event) => (\n <div\n data-rsv=\"event\"\n data-all-day=\"true\"\n class={cx(...event.classNames)}\n data-display={event.display}\n key={event.id}\n style={`--rsv-event-bg:${event.backgroundColor}`}\n onClick={() => {\n api.trigger(\"eventClick\", { event });\n if (event.url) window.open(event.url, \"_self\");\n }}\n >\n {event.title}\n </div>\n ))}\n </div>\n ))}\n </div>\n )}\n\n {/* Cuerpo: eje + columnas de día */}\n <div data-rsv=\"tg-body\">\n <div data-rsv=\"tg-axis\" style={`height:${bodyHeight}`}>\n {model.slots.map((slot) => (\n <div data-rsv=\"tg-slot\" data-major={String(slot.isMajor)} key={slot.offsetMin}>\n <span data-rsv=\"tg-slot-label\">\n {renderSlot(\n options.slots?.slotLabelContent,\n { text: slot.label, minutes: slot.offsetMin, isMajor: slot.isMajor },\n slot.label,\n )}\n </span>\n </div>\n ))}\n </div>\n\n {model.days.map((d, dayIndex) => (\n <div\n data-rsv=\"tg-col\"\n data-today={String(d.isToday)}\n style={`height:${bodyHeight}`}\n key={dl.toISOString(d.date)}\n onClick={() => api.trigger(\"dateClick\", { date: d.date })}\n onPointerDown={\n options.selectable\n ? (e) =>\n startTimeRangeSelect(e, {\n api,\n date: d.date,\n model,\n columnEl: e.currentTarget as HTMLElement,\n snap: options.snapDuration ?? options.slotDuration,\n })\n : undefined\n }\n >\n {options.businessHours && !d.businessPct && (\n <div data-rsv=\"tg-nonbusiness\" style=\"top:0;height:100%\" />\n )}\n {d.businessPct && (\n <>\n <div data-rsv=\"tg-nonbusiness\" style={`top:0;height:${d.businessPct.topPct}%`} />\n <div\n data-rsv=\"tg-nonbusiness\"\n style={`top:${d.businessPct.bottomPct}%;height:${100 - d.businessPct.bottomPct}%`}\n />\n </>\n )}\n {d.timedSegs\n .filter((seg) => seg.event.display !== \"none\")\n .map((seg) => (\n <TimedEvent\n api={api}\n seg={seg}\n model={model}\n options={options}\n key={seg.event.id}\n />\n ))}\n {model.nowIndicator?.dayIndex === dayIndex && (\n <div data-rsv=\"now-indicator\" style={`top:${model.nowIndicator.topPct}%`} />\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction TimedEvent({\n api,\n seg,\n model,\n options,\n}: {\n api: CalendarApi;\n seg: TimeGridSeg;\n model: TimeGridModel;\n options: ReserviCalendarOptions;\n}): VNode {\n const { event } = seg;\n const editable = options.editable === true && event.editable !== false;\n const widthPct = 100 / seg.colCount;\n const timeText = dl.format(event.start, \"HH:mm\");\n const content = renderSlot(\n options.slots?.eventContent,\n { event, isAllDay: false, timeText },\n <span data-rsv=\"event-title\">\n {timeText} {event.title}\n </span>,\n );\n\n const getColumn = (el: HTMLElement): HTMLElement =>\n (el.closest('[data-rsv=\"tg-col\"]') as HTMLElement | null) ?? el;\n\n return (\n <div\n data-rsv=\"event\"\n data-all-day=\"false\"\n data-display={event.display}\n data-event-id={event.id}\n class={cx(...event.classNames)}\n role=\"button\"\n tabIndex={0}\n style={\n `position:absolute;` +\n `top:${seg.topPct}%;height:${seg.heightPct}%;` +\n `left:${seg.col * widthPct}%;width:${widthPct}%;` +\n `--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor}`\n }\n onClick={(e) => {\n e.stopPropagation();\n api.trigger(\"eventClick\", { event });\n if (event.url) window.open(event.url, \"_self\");\n }}\n onKeyDown={\n editable\n ? (e) =>\n handleEventKeydown(e, {\n api,\n event,\n kind: \"timeGrid\",\n snap: options.snapDuration ?? options.slotDuration,\n })\n : undefined\n }\n onPointerDown={\n editable\n ? (e) =>\n startEventDrag(e, {\n api,\n event,\n model,\n columnEl: getColumn(e.currentTarget as HTMLElement),\n snap: options.snapDuration,\n })\n : undefined\n }\n >\n {editable && (\n <span\n data-rsv=\"resize-handle\"\n data-edge=\"start\"\n onPointerDown={(e) =>\n startEventDrag(e, {\n api,\n event,\n model,\n columnEl: getColumn(e.currentTarget as HTMLElement),\n snap: options.snapDuration,\n edge: \"start\",\n })\n }\n />\n )}\n {content}\n {editable && (\n <span\n data-rsv=\"resize-handle\"\n data-edge=\"end\"\n onPointerDown={(e) =>\n startEventDrag(e, {\n api,\n event,\n model,\n columnEl: getColumn(e.currentTarget as HTMLElement),\n snap: options.snapDuration,\n edge: \"end\",\n })\n }\n />\n )}\n </div>\n );\n}\n","import { dl, getLocaleText, type CalendarApi, type ListModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { renderSlot, cx } from \"../../render/slots.js\";\n\ninterface ListViewProps {\n api: CalendarApi;\n model: ListModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista de agenda en lista (listDay/Week/Month/Year). */\nexport function ListView({ api, model, options }: ListViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const text = getLocaleText(options.locale);\n const dayFmt = new Intl.DateTimeFormat(locale, {\n weekday: \"long\",\n day: \"numeric\",\n month: \"long\",\n });\n\n if (model.isEmpty) {\n return (\n <div data-rsv=\"list\">\n <div data-rsv=\"list-empty\">{text.noEvents}</div>\n </div>\n );\n }\n\n return (\n <div data-rsv=\"list\" role=\"list\">\n {model.days.map((day) => (\n <div data-rsv=\"list-day\" data-today={String(day.isToday)} key={dl.toISOString(day.date)}>\n <div data-rsv=\"list-day-header\" role=\"heading\" aria-level={3}>\n {dayFmt.format(dl.toDate(day.date))}\n </div>\n {day.events\n .filter((event) => event.display !== \"none\")\n .map((event) => {\n const timeText = event.allDay ? text.allDay : dl.format(event.start, \"HH:mm\");\n return (\n <div\n data-rsv=\"list-item\"\n role=\"listitem\"\n tabIndex={0}\n key={event.id}\n class={cx(...event.classNames)}\n data-display={event.display}\n onClick={() => {\n api.trigger(\"eventClick\", { event });\n if (event.url) window.open(event.url, \"_self\");\n }}\n >\n <span data-rsv=\"list-item-time\">{timeText}</span>\n <span\n data-rsv=\"list-item-dot\"\n style={`--rsv-event-bg:${event.backgroundColor}`}\n />\n <span data-rsv=\"list-item-title\">\n {renderSlot(\n options.slots?.eventContent,\n { event, isAllDay: event.allDay, timeText },\n event.title,\n )}\n </span>\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n","import { dl, type CalendarApi, type MultiMonthModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { DayGridView } from \"../daygrid/DayGridView.js\";\n\ninterface MultiMonthViewProps {\n api: CalendarApi;\n model: MultiMonthModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista de varios meses (año): rejilla responsive de cuadrículas mensuales. */\nexport function MultiMonthView({ api, model, options }: MultiMonthViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const monthFmt = new Intl.DateTimeFormat(locale, { month: \"long\" });\n\n return (\n <div data-rsv=\"multimonth\">\n {model.months.map((month) => (\n <section data-rsv=\"mm-month\" key={dl.toISOString(month.date)}>\n <header data-rsv=\"mm-title\">{monthFmt.format(dl.toDate(month.date))}</header>\n <DayGridView api={api} model={month.dayGrid} options={options} />\n </section>\n ))}\n </div>\n );\n}\n","import { type CalendarApi, type TimelineModel, type TimelineSeg } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { renderSlot } from \"../../render/slots.js\";\n\nconst LANE_REM = 1.6;\n\ninterface TimelineViewProps {\n api: CalendarApi;\n model: TimelineModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista timeline: eje temporal horizontal con eventos apilados en carriles. */\nexport function TimelineView({ api, model, options }: TimelineViewProps): VNode {\n return (\n <div data-rsv=\"timeline\">\n <div data-rsv=\"tl-axis\" role=\"row\">\n {model.slots.map((slot) => (\n <div data-rsv=\"tl-slot\" style={`left:${slot.leftPct}%`} key={slot.leftPct}>\n {slot.label}\n </div>\n ))}\n </div>\n <div data-rsv=\"tl-body\" style={`height:${model.laneCount * LANE_REM + 0.5}rem`}>\n {model.segs.map((seg) => (\n <TimelineEvent api={api} seg={seg} options={options} key={seg.event.id} />\n ))}\n </div>\n </div>\n );\n}\n\nexport function TimelineEvent({\n api,\n seg,\n options,\n}: {\n api: CalendarApi;\n seg: TimelineSeg;\n options: ReserviCalendarOptions;\n}): VNode {\n const { event } = seg;\n return (\n <div\n data-rsv=\"event\"\n data-event-id={event.id}\n role=\"button\"\n tabIndex={0}\n style={\n `position:absolute;left:${seg.leftPct}%;width:${seg.widthPct}%;` +\n `top:${seg.lane * LANE_REM}rem;height:${LANE_REM - 0.2}rem;` +\n `--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor}`\n }\n onClick={() => api.trigger(\"eventClick\", { event })}\n >\n {renderSlot(\n options.slots?.eventContent,\n { event, isAllDay: event.allDay, timeText: \"\" },\n event.title,\n )}\n </div>\n );\n}\n","import { type CalendarApi, type ResourceTimelineModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { TimelineEvent } from \"../timeline/TimelineView.js\";\n\nconst LANE_REM = 1.6;\n\ninterface ResourceTimelineViewProps {\n api: CalendarApi;\n model: ResourceTimelineModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista resource-timeline (Scheduler): filas de recursos × eje temporal. */\nexport function ResourceTimelineView({ api, model, options }: ResourceTimelineViewProps): VNode {\n return (\n <div data-rsv=\"resource-timeline\">\n {/* Cabecera: área de recursos + eje temporal */}\n <div data-rsv=\"rt-header\" role=\"row\">\n <div data-rsv=\"resource-area-header\">\n {options.locale === \"es\" ? \"Recursos\" : \"Resources\"}\n </div>\n <div data-rsv=\"tl-axis\">\n {model.slots.map((slot) => (\n <div data-rsv=\"tl-slot\" style={`left:${slot.leftPct}%`} key={slot.leftPct}>\n {slot.label}\n </div>\n ))}\n </div>\n </div>\n\n {/* Filas de recursos */}\n {model.lanes.map((lane) => {\n const rowHeight = lane.laneCount * LANE_REM + 0.4;\n return (\n <div data-rsv=\"resource-row\" role=\"row\" key={lane.row.resource.id}>\n <div\n data-rsv=\"resource-label\"\n style={`padding-inline-start:${0.5 + lane.row.depth * 1}rem`}\n >\n {lane.row.hasChildren && (\n <button\n type=\"button\"\n data-rsv=\"resource-toggle\"\n aria-expanded={lane.row.expanded}\n onClick={() => api.toggleResource(lane.row.resource.id)}\n >\n {lane.row.expanded ? \"▾\" : \"▸\"}\n </button>\n )}\n <span data-rsv=\"resource-title\">{lane.row.resource.title}</span>\n </div>\n <div data-rsv=\"resource-lane\" style={`height:${rowHeight}rem`}>\n {lane.segs.map((seg) => (\n <TimelineEvent api={api} seg={seg} options={options} key={seg.event.id} />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n","import { dl, getLocaleText, type CalendarApi, type ResourceTimeGridModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\n\ninterface Props {\n api: CalendarApi;\n model: ResourceTimeGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista vertical de recursos: recursos como columnas sobre un eje de tiempo. */\nexport function ResourceTimeGridView({ api, model, options }: Props): VNode {\n const bodyHeight = `calc(var(--spacing-rsv-slot, 2.5rem) * ${model.slots.length})`;\n\n return (\n <div data-rsv=\"timegrid\" style={`--rsv-tg-days:${model.columns.length}`}>\n <div data-rsv=\"tg-header\" role=\"row\">\n <div data-rsv=\"tg-axis-corner\" />\n {model.columns.map((col) => (\n <div data-rsv=\"tg-col-header\" role=\"columnheader\" key={col.row.resource.id}>\n {col.row.resource.title}\n </div>\n ))}\n </div>\n\n <div data-rsv=\"tg-allday\" role=\"row\">\n <div data-rsv=\"tg-axis-label\">{getLocaleText(options.locale).allDay}</div>\n {model.columns.map((col) => (\n <div data-rsv=\"tg-allday-cell\" key={col.row.resource.id}>\n {col.allDayEvents.map((event) => (\n <div\n data-rsv=\"event\"\n data-all-day=\"true\"\n key={event.id}\n style={`--rsv-event-bg:${event.backgroundColor}`}\n onClick={() => api.trigger(\"eventClick\", { event })}\n >\n {event.title}\n </div>\n ))}\n </div>\n ))}\n </div>\n\n <div data-rsv=\"tg-body\">\n <div data-rsv=\"tg-axis\" style={`height:${bodyHeight}`}>\n {model.slots.map((slot) => (\n <div data-rsv=\"tg-slot\" data-major={String(slot.isMajor)} key={slot.offsetMin}>\n <span data-rsv=\"tg-slot-label\">{slot.label}</span>\n </div>\n ))}\n </div>\n\n {model.columns.map((col) => (\n <div\n data-rsv=\"tg-col\"\n data-rsv-resource-id={col.row.resource.id}\n style={`height:${bodyHeight}`}\n key={col.row.resource.id}\n >\n {col.timedSegs.map((seg) => {\n const widthPct = 100 / seg.colCount;\n return (\n <div\n data-rsv=\"event\"\n data-all-day=\"false\"\n data-event-id={seg.event.id}\n role=\"button\"\n tabIndex={0}\n key={seg.event.id}\n style={\n `position:absolute;top:${seg.topPct}%;height:${seg.heightPct}%;` +\n `left:${seg.col * widthPct}%;width:${widthPct}%;` +\n `--rsv-event-bg:${seg.event.backgroundColor};--rsv-event-fg:${seg.event.textColor}`\n }\n onClick={(e) => {\n e.stopPropagation();\n api.trigger(\"eventClick\", { event: seg.event });\n }}\n >\n {dl.format(seg.event.start, \"HH:mm\")} {seg.event.title}\n </div>\n );\n })}\n {model.nowTopPct != null && (\n <div data-rsv=\"now-indicator\" style={`top:${model.nowTopPct}%`} />\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { dl, type CalendarApi, type ResourceDayGridModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\n\ninterface Props {\n api: CalendarApi;\n model: ResourceDayGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Recursos como columnas en cuadrícula de día (eventos apilados por recurso). */\nexport function ResourceDayGridView({ api, model }: Props): VNode {\n return (\n <div data-rsv=\"resource-daygrid\" style={`--rsv-rdg-cols:${model.columns.length}`}>\n <div data-rsv=\"rdg-header\" role=\"row\">\n {model.columns.map((col) => (\n <div data-rsv=\"rdg-col-header\" role=\"columnheader\" key={col.row.resource.id}>\n {col.row.resource.title}\n </div>\n ))}\n </div>\n <div data-rsv=\"rdg-body\" role=\"row\">\n {model.columns.map((col) => (\n <div\n data-rsv=\"rdg-col\"\n data-rsv-resource-id={col.row.resource.id}\n key={col.row.resource.id}\n >\n {col.events.map((event) => (\n <div\n data-rsv=\"event\"\n data-all-day={String(event.allDay)}\n data-event-id={event.id}\n role=\"button\"\n tabIndex={0}\n key={event.id}\n style={`--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor}`}\n onClick={() => api.trigger(\"eventClick\", { event })}\n >\n {event.allDay ? \"\" : dl.format(event.start, \"HH:mm\") + \" \"}\n {event.title}\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","// Importar @preact/signals activa el seguimiento automático de signals en los\n// componentes: leer `api.viewModel.value` re-renderiza de forma granular.\nimport \"@preact/signals\";\nimport { getLocaleText, themeToStyle, type CalendarApi } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../types.js\";\nimport { cx } from \"../render/slots.js\";\nimport { Toolbar } from \"./Toolbar.js\";\nimport { DayGridView } from \"../views/daygrid/DayGridView.js\";\nimport { TimeGridView } from \"../views/timegrid/TimeGridView.js\";\nimport { ListView } from \"../views/list/ListView.js\";\nimport { MultiMonthView } from \"../views/multimonth/MultiMonthView.js\";\nimport { TimelineView } from \"../views/timeline/TimelineView.js\";\nimport { ResourceTimelineView } from \"../views/resource/ResourceTimelineView.js\";\nimport { ResourceTimeGridView } from \"../views/resource/ResourceTimeGridView.js\";\nimport { ResourceDayGridView } from \"../views/resource/ResourceDayGridView.js\";\n\ninterface CalendarProps {\n api: CalendarApi;\n options: ReserviCalendarOptions;\n}\n\n/** Componente raíz: lee el ViewModel reactivo y delega en la vista activa. */\nexport function Calendar({ api, options }: CalendarProps): VNode {\n const vm = api.viewModel.value; // reactivo (signals)\n const dir = options.direction ?? getLocaleText(options.locale).direction;\n const themeStyle = options.themeTokens ? themeToStyle(options.themeTokens) : undefined;\n\n return (\n <div\n data-rsv=\"root\"\n dir={dir}\n data-rsv-theme={options.theme}\n style={themeStyle}\n class={cx(options.classNames?.root)}\n >\n {options.headerToolbar !== false && (\n <Toolbar api={api} title={vm.title} activeView={vm.type} options={options} />\n )}\n <div data-rsv=\"view\" data-view={vm.type}>\n {vm.dayGrid ? (\n <DayGridView api={api} model={vm.dayGrid} options={options} />\n ) : vm.timeGrid ? (\n <TimeGridView api={api} model={vm.timeGrid} options={options} />\n ) : vm.list ? (\n <ListView api={api} model={vm.list} options={options} />\n ) : vm.multiMonth ? (\n <MultiMonthView api={api} model={vm.multiMonth} options={options} />\n ) : vm.resourceTimeGrid ? (\n <ResourceTimeGridView api={api} model={vm.resourceTimeGrid} options={options} />\n ) : vm.resourceDayGrid ? (\n <ResourceDayGridView api={api} model={vm.resourceDayGrid} options={options} />\n ) : vm.resourceTimeline ? (\n <ResourceTimelineView api={api} model={vm.resourceTimeline} options={options} />\n ) : vm.timeline ? (\n <TimelineView api={api} model={vm.timeline} options={options} />\n ) : (\n <div data-rsv=\"unsupported\">\n La vista \"{vm.type}\" se implementa en una fase posterior.\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { h, render } from \"preact\";\nimport { CalendarApi } from \"@reservi/core\";\nimport { Calendar } from \"./components/Calendar.js\";\nimport type { ReserviCalendarOptions } from \"./types.js\";\n\nexport interface ReserviCalendarHandle {\n /** API del calendario (navegación, eventos, callbacks). */\n readonly api: CalendarApi;\n /** Desmonta el calendario y libera recursos. */\n destroy(): void;\n}\n\n/**\n * Monta un calendario Reservi en un elemento del DOM. API agnóstica usada\n * directamente (vanilla/Preact) y por los wrappers de framework.\n */\nexport function mount(el: HTMLElement, options: ReserviCalendarOptions): ReserviCalendarHandle {\n const api = new CalendarApi(options);\n render(h(Calendar, { api, options }), el);\n\n return {\n api,\n destroy() {\n render(null, el);\n api.destroy();\n },\n };\n}\n","import { eventsToICS, type EventInput } from \"@reservi/core\";\n\n/**\n * Exporta eventos a un archivo `.ics` y dispara la descarga en el navegador.\n * Capa de UI (usa DOM); la serialización pura vive en `@reservi/core`.\n */\nexport function downloadICS(events: EventInput[], filename = \"calendar.ics\"): void {\n if (typeof document === \"undefined\") return;\n const ics = eventsToICS(events);\n const blob = new Blob([ics], { type: \"text/calendar;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(url);\n}\n\nexport { parseICS, eventsToICS } from \"@reservi/core\";\n"],"names":["renderSlot","slot","arg","fallback","cx","classes","NAV_SYMBOLS","NON_VIEW_TOKENS","MONTH_VIEW_RE","pad2","n","CalendarIcon","jsxs","jsx","resolveViews","options","_a","tb","s","g","t","Toolbar","api","title","activeView","text","getLocaleText","startSlot","_b","endSlot","_d","_c","views","monthMode","firstDay","wrapRef","useRef","open","setOpen","useState","selected","dl","nowRef","viewYear","setViewYear","viewMonth","setViewMonth","monthShortFmt","monthLongFmt","dowFmt","monthNames","_","i","openPicker","d","shiftMonth","delta","total","goto","iso","useEffect","onKey","e","onPointer","dayGrid","first","offset","start","cells","dows","_e","y","label","navLinkToDay","date","target","DAY","handleEventKeydown","opts","event","kind","snapMin","timeStringToMinutes","deltaMin","next","computeDrop","updated","THRESHOLD","dateAtPoint","x","el","startDayGridEventDrag","ev","sourceDate","startX","startY","dragging","onMove","onUp","deltaDays","startDayRangeSelect","endStr","moved","a","b","lo","hi","DayGridView","model","locale","headerDays","showWeekNums","cell","week","wi","DayCell","dayNumber","defaultNumber","numberNode","moreOpen","setMoreOpen","dateStr","rangeSelectedRef","onDayClick","openMore","EventChip","DayMorePopover","onClose","ref","dayFmt","allEvents","editable","draggedRef","timeText","content","startEventDrag","columnEl","snap","edge","rect","totalMinutes","ppm","pxToSnappedMinutes","computeResize","startTimeRangeSelect","yToMin","clientY","raw","clamped","startMin","endMin","m","dayStart","TimeGridView","showAllDay","bodyHeight","dayIndex","Fragment","seg","TimedEvent","widthPct","getColumn","ListView","day","MultiMonthView","monthFmt","month","LANE_REM","TimelineView","TimelineEvent","ResourceTimelineView","lane","rowHeight","ResourceTimeGridView","col","ResourceDayGridView","Calendar","vm","dir","themeStyle","themeToStyle","mount","CalendarApi","render","h","downloadICS","events","filename","ics","eventsToICS","blob","url"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/types.ts","../src/render/slots.tsx","../src/interaction/responsive.ts","../src/components/Toolbar.tsx","../src/render/format.ts","../src/render/nav.ts","../src/interaction/keyboard.ts","../src/interaction/daygrid-drag.ts","../src/views/daygrid/DayGridView.tsx","../src/interaction/auto-scroll.ts","../src/interaction/drag.ts","../src/views/timegrid/TimeGridView.tsx","../src/views/list/ListView.tsx","../src/views/multimonth/MultiMonthView.tsx","../src/views/timeline/TimelineView.tsx","../src/views/resource/ResourceTimelineView.tsx","../src/views/resource/ResourceTimeGridView.tsx","../src/views/resource/ResourceDayGridView.tsx","../src/views/resource/ResourceDayGridMonthView.tsx","../src/components/Calendar.tsx","../src/mount.ts","../src/ical.ts"],"sourcesContent":["import type { CalendarOptions, EventDef } from \"@reservi/core\";\nimport type { ComponentChildren } from \"preact\";\n\n/** Vista activa tal como la reciben los slots y los hooks `*DidMount`. */\nexport interface ViewArg {\n readonly type: string;\n}\n\n/** Argumento del slot del botón \"+N more\" (popover de eventos ocultos). */\nexport interface MoreLinkContentArg {\n date: Date;\n moreCount: number;\n allEvents: EventDef[];\n hiddenEvents: EventDef[];\n view: ViewArg;\n}\n\n/** Argumento del slot de contenido de evento. */\nexport interface EventContentArg {\n event: EventDef;\n isAllDay: boolean;\n /** Texto de hora ya formateado (vacío si allDay). */\n timeText: string;\n view: ViewArg;\n}\n\n/** Argumento del slot de celda de día. */\nexport interface DayCellContentArg {\n date: Date;\n dayNumber: number;\n isToday: boolean;\n isOther: boolean;\n view: ViewArg;\n}\n\n/** Argumento del slot de cabecera de día (nombre del día de la semana). */\nexport interface DayHeaderContentArg {\n date: Date;\n text: string;\n /** Día de la semana, 0 = domingo … 6 = sábado. */\n dayOfWeek: number;\n /** Día del mes (1–31). */\n dayNumber: number;\n isToday: boolean;\n view: ViewArg;\n}\n\n/** Argumento del slot de etiqueta del eje horario (timeGrid). */\nexport interface SlotLabelContentArg {\n /** Texto ya formateado (p. ej. \"09:00\"). */\n text: string;\n /** Minutos desde medianoche del slot. */\n minutes: number;\n /** Si es una marca mayor (etiquetada). */\n isMajor: boolean;\n view: ViewArg;\n}\n\n/**\n * Marcador que puede devolver un slot cuando el contenido lo pinta el\n * framework anfitrión (React, Vue…). La capa Preact NO interpreta `node`:\n * solo reserva un hueco en el DOM y delega en el `hostBridge`.\n */\nexport interface HostSlotResult {\n readonly __rsvHost: true;\n /** Nodo del framework anfitrión (opaco para esta capa). */\n readonly node: unknown;\n}\n\n/** Crea el marcador de contenido delegado al framework anfitrión. */\nexport function hostSlot(node: unknown): HostSlotResult {\n return { __rsvHost: true, node };\n}\n\n/** ¿El resultado de un slot delega el render en el anfitrión? */\nexport function isHostSlot(value: unknown): value is HostSlotResult {\n return typeof value === \"object\" && value !== null && (value as HostSlotResult).__rsvHost === true;\n}\n\n/**\n * Puente para pintar contenido del framework anfitrión dentro del árbol de\n * Preact. Lo implementan los wrappers (p. ej. `@reservi/react` con portales).\n */\nexport interface HostBridge {\n /** Un hueco ha entrado en el DOM: pinta `node` dentro de `el`. */\n mount(id: string, el: HTMLElement, node: unknown): void;\n /** El contenido del hueco `id` ha cambiado. */\n update(id: string, node: unknown): void;\n /** El hueco `id` ha salido del DOM: libera lo que se pintó en él. */\n unmount(id: string): void;\n}\n\nexport type SlotResult = ComponentChildren | string | HostSlotResult;\n\n/**\n * Slots de render (patrón de \"content\" de FullCalendar). Cada slot devuelve\n * contenido Preact, una cadena, o `hostSlot(...)` para delegar en el anfitrión.\n */\nexport interface ReserviSlots {\n eventContent?: (arg: EventContentArg) => SlotResult;\n dayCellContent?: (arg: DayCellContentArg) => SlotResult;\n dayHeaderContent?: (arg: DayHeaderContentArg) => SlotResult;\n /** Personaliza la etiqueta del eje horario (timeGrid). */\n slotLabelContent?: (arg: SlotLabelContentArg) => SlotResult;\n /**\n * Personaliza el contenido del botón \"+N more\" (dayGrid/multiMonth). El\n * `<button>` que abre el popover se conserva; el slot solo reemplaza su\n * contenido interno (mismo patrón que `dayCellContent`).\n */\n moreLinkContent?: (arg: MoreLinkContentArg) => SlotResult;\n /**\n * Contenido libre al inicio de la toolbar (zona \"Filtrar/Personal\" del diseño).\n * El usuario decide qué botones poner y qué hacen; si no se define, no se\n * renderiza nada en esa zona.\n */\n toolbarStart?: () => SlotResult;\n /**\n * Contenido libre al final de la toolbar, antes del botón \"Añadir\".\n * Útil para acciones extra propias del anfitrión.\n */\n toolbarEnd?: () => SlotResult;\n}\n\n/**\n * Hooks de ciclo de vida sobre el DOM ya montado (equivalentes a los\n * `*DidMount` de FullCalendar). Se invocan UNA vez por elemento del DOM.\n */\nexport interface ReserviHooks {\n eventDidMount?: (arg: EventContentArg & { el: HTMLElement }) => void;\n dayCellDidMount?: (arg: DayCellContentArg & { el: HTMLElement }) => void;\n dayHeaderDidMount?: (arg: DayHeaderContentArg & { el: HTMLElement }) => void;\n slotLabelDidMount?: (arg: SlotLabelContentArg & { el: HTMLElement }) => void;\n}\n\n/** Clases por slot, fusionadas con las base. */\nexport interface ReserviClassNames {\n root?: string;\n toolbar?: string;\n /** Celda de día (dayGrid/multiMonth). */\n day?: string;\n event?: string;\n /** Cabecera de día (nombre del día / columna). */\n dayHeader?: string;\n /** Etiqueta del eje horario (timeGrid). */\n slotLabel?: string;\n}\n\n/** Opciones de la capa Preact = opciones de núcleo + presentación. */\nexport interface ReserviCalendarOptions extends CalendarOptions {\n slots?: ReserviSlots;\n hooks?: ReserviHooks;\n classNames?: ReserviClassNames;\n /**\n * Puente de render del framework anfitrión. Lo inyecta el wrapper; no es\n * necesario configurarlo a mano en uso vanilla/Preact.\n */\n hostBridge?: HostBridge;\n /**\n * Vistas a mostrar como pestañas en la segunda fila de la toolbar\n * (p. ej. [\"dayGridMonth\", \"timeGridWeek\", \"listWeek\"]). Si se omite, se\n * derivan de los tokens de `headerToolbar`; si tampoco hay, no se muestra la fila.\n */\n views?: string[];\n /**\n * Callback del botón \"Añadir\". Solo si se define se renderiza el botón; el\n * anfitrión decide qué ocurre al pulsarlo (abrir un modal, navegar, etc.).\n */\n onAddClick?: () => void;\n /** Texto del botón \"Añadir\" (def. \"+\" sin etiqueta). */\n addButtonText?: string;\n /**\n * Cambia de vista automáticamente al redimensionar el contenedor (p. ej.\n * mes → lista en mobile). Se evalúa el `breakpoint` más alto que sea\n * `<= ancho actual` (estilo media query `min-width`).\n */\n responsiveViews?: { breakpoint: number; view: string }[];\n}\n","import type { ComponentChildren, VNode } from \"preact\";\nimport { useLayoutEffect, useRef } from \"preact/hooks\";\nimport { isHostSlot, type HostBridge, type SlotResult } from \"../types.js\";\n\n/**\n * Resuelve un slot de contenido: si el usuario aportó una función, usa su\n * resultado; si no, usa el contenido por defecto. Unifica el contrato de los\n * render hooks para todos los frameworks (en wrappers se adapta a su idioma).\n *\n * Si el slot devuelve `hostSlot(node)`, se reserva un hueco en el DOM y el\n * `bridge` del framework anfitrión pinta el contenido dentro (React usa\n * portales). Sin bridge se cae al contenido por defecto.\n */\nexport function renderSlot<Arg>(\n slot: ((arg: Arg) => SlotResult) | undefined,\n arg: Arg,\n fallback: ComponentChildren,\n bridge?: HostBridge | undefined,\n): ComponentChildren {\n if (!slot) return fallback;\n const result = slot(arg);\n // Como en FullCalendar, `undefined` significa \"usa el contenido por defecto\"\n // (los wrappers lo devuelven cuando el anfitrion no aporta ese render prop).\n if (result === undefined) return fallback;\n if (isHostSlot(result)) {\n if (!bridge) return fallback;\n return <HostSlotOutlet bridge={bridge} node={result.node} />;\n }\n return result as ComponentChildren;\n}\n\nlet hostSeq = 0;\n\n/**\n * Hueco en el DOM cuyo contenido pinta el framework anfitrión. Se identifica\n * por posición (un id por instancia montada), así que eventos repetidos en\n * varias celdas o en el popover no colisionan.\n */\nfunction HostSlotOutlet({ bridge, node }: { bridge: HostBridge; node: unknown }): VNode {\n const idRef = useRef(\"\");\n if (!idRef.current) idRef.current = `rsv-host-${++hostSeq}`;\n const elRef = useRef<HTMLDivElement>(null);\n const nodeRef = useRef(node);\n nodeRef.current = node;\n const liveRef = useRef(false);\n\n // useLayoutEffect y no useEffect: el hueco debe registrarse en el mismo\n // commit en que entra en el DOM, para que el anfitrion pinte su contenido sin\n // un frame intermedio en blanco.\n useLayoutEffect(() => {\n const el = elRef.current;\n if (!el) return;\n const id = idRef.current;\n liveRef.current = true;\n bridge.mount(id, el, nodeRef.current);\n return () => {\n liveRef.current = false;\n bridge.unmount(id);\n };\n // El hueco se monta una sola vez; los cambios de contenido van por `update`.\n }, []);\n\n // Sin deps a proposito: el nodo del anfitrion es un objeto nuevo en cada\n // render, asi que se reenvia siempre y el bridge decide si hay cambio real.\n useLayoutEffect(() => {\n if (liveRef.current) bridge.update(idRef.current, node);\n });\n\n return <div data-rsv=\"host\" ref={elRef} />;\n}\n\n/** Une clases base con las del usuario (filtra vacíos). */\nexport function cx(...classes: (string | undefined | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Invoca un hook `*DidMount` una única vez por elemento del DOM. Preact vuelve\n * a llamar a los callback refs en cada render, así que hace falta recordar qué\n * elementos ya se notificaron (FullCalendar tampoco re-dispara `*DidMount`).\n */\nconst notified = new WeakSet<HTMLElement>();\n\nexport function callDidMount<Arg extends { el: HTMLElement }>(\n el: Element | null,\n hook: ((arg: Arg) => void) | undefined,\n buildArg: () => Omit<Arg, \"el\">,\n): void {\n if (!el || !hook) return;\n const html = el as HTMLElement;\n if (notified.has(html)) return;\n notified.add(html);\n hook(Object.assign(buildArg(), { el: html }) as Arg);\n}\n","/** Entrada de `responsiveViews`: a partir de `breakpoint` px de ancho, usa `view`. */\nexport interface ResponsiveViewEntry {\n breakpoint: number;\n view: string;\n}\n\n/**\n * Resuelve qué vista corresponde a un ancho dado: el `breakpoint` más alto que\n * sea `<= width` (estilo media query `min-width`). Si `width` es menor que\n * todos los breakpoints, usa la vista del breakpoint más bajo (piso \"mobile\").\n */\nexport function pickResponsiveView(entries: ResponsiveViewEntry[], width: number): string | null {\n if (!entries.length) return null;\n const sorted = [...entries].sort((a, b) => a.breakpoint - b.breakpoint);\n let chosen = sorted[0]!.view;\n for (const entry of sorted) {\n if (width >= entry.breakpoint) chosen = entry.view;\n }\n return chosen;\n}\n","import { dl, getLocaleText, type CalendarApi } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport { useEffect, useRef, useState } from \"preact/hooks\";\nimport type { ReserviCalendarOptions } from \"../types.js\";\nimport { cx } from \"../render/slots.js\";\n\nconst NAV_SYMBOLS = { prev: \"‹\", next: \"›\" } as const;\n/** Tokens que NO son vistas (no aparecen como pestañas). */\nconst NON_VIEW_TOKENS = new Set([\"\", \"title\", \"today\", \"prev\", \"next\"]);\n/** Vistas cuyo datepicker elige MES (resto: elige DÍA). */\nconst MONTH_VIEW_RE = /month|year/i;\n\nconst pad2 = (n: number): string => String(n).padStart(2, \"0\");\n\n/** Icono de calendario junto al título. */\nfunction CalendarIcon(): VNode {\n return (\n <svg\n data-rsv=\"title-icon\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"1\" y=\"2.5\" width=\"12\" height=\"10.5\" rx=\"1.5\" />\n <line x1=\"1\" y1=\"5.5\" x2=\"13\" y2=\"5.5\" />\n <line x1=\"4.5\" y1=\"1\" x2=\"4.5\" y2=\"3.5\" />\n <line x1=\"9.5\" y1=\"1\" x2=\"9.5\" y2=\"3.5\" />\n </svg>\n );\n}\n\ninterface ToolbarProps {\n api: CalendarApi;\n title: string;\n activeView: string;\n options: ReserviCalendarOptions;\n}\n\n/** Vistas para la fila de pestañas: prop `views` o, en su defecto, tokens de `headerToolbar`. */\nfunction resolveViews(options: ReserviCalendarOptions): string[] {\n if (options.views?.length) return options.views;\n const tb = options.headerToolbar;\n if (!tb) return [];\n return [tb.start, tb.center, tb.end]\n .filter((s): s is string => Boolean(s))\n .flatMap((s) => s.split(/\\s+/))\n .flatMap((g) => g.split(\",\"))\n .filter((t) => !NON_VIEW_TOKENS.has(t));\n}\n\n/**\n * Toolbar de dos filas:\n * - Fila 1: slot de inicio (Filtrar/Personal del anfitrión) · navegación\n * (hoy ‹ título ›) · slot de fin + botón \"Añadir\" (opcional, vía props).\n * - Fila 2: pestañas de vista.\n *\n * El título abre un datepicker para saltar de fecha. En vistas de mes/año la\n * rejilla elige MES; en el resto (semana/día/lista) elige DÍA. Se abre también\n * con Ctrl+M y se cierra con Esc o clic fuera.\n */\nexport function Toolbar({ api, title, activeView, options }: ToolbarProps): VNode {\n const text = getLocaleText(options.locale);\n const startSlot = options.slots?.toolbarStart?.();\n const endSlot = options.slots?.toolbarEnd?.();\n const views = resolveViews(options);\n const monthMode = MONTH_VIEW_RE.test(activeView);\n const firstDay = options.firstDay ?? text.firstDay;\n\n const wrapRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n\n // Fecha seleccionada (para resaltar). Reactivo vía signals.\n const selected = dl.toDate(api.getDate());\n const nowRef = dl.toDate(options.now ? dl.from(options.now) : dl.now());\n\n // El mes/año mostrados en la rejilla (independientes de la navegación principal).\n const [viewYear, setViewYear] = useState(selected.getFullYear());\n const [viewMonth, setViewMonth] = useState(selected.getMonth());\n\n const monthShortFmt = new Intl.DateTimeFormat(options.locale, { month: \"short\" });\n const monthLongFmt = new Intl.DateTimeFormat(options.locale, { month: \"long\" });\n const dowFmt = new Intl.DateTimeFormat(options.locale, { weekday: \"short\" });\n const monthNames = Array.from({ length: 12 }, (_, i) =>\n monthShortFmt.format(new Date(2020, i, 1)),\n );\n\n const openPicker = (): void => {\n const d = dl.toDate(api.getDate());\n setViewYear(d.getFullYear());\n setViewMonth(d.getMonth());\n setOpen(true);\n };\n const shiftMonth = (delta: number): void => {\n const total = viewYear * 12 + viewMonth + delta;\n setViewYear(Math.floor(total / 12));\n setViewMonth(((total % 12) + 12) % 12);\n };\n const goto = (iso: string): void => {\n api.gotoDate(iso);\n setOpen(false);\n };\n\n // Ctrl+M abre · Esc cierra · clic fuera cierra.\n useEffect(() => {\n const onKey = (e: KeyboardEvent): void => {\n if ((e.ctrlKey || e.metaKey) && (e.key === \"m\" || e.key === \"M\")) {\n e.preventDefault();\n openPicker();\n } else if (e.key === \"Escape\") {\n setOpen(false);\n }\n };\n const onPointer = (e: MouseEvent): void => {\n if (wrapRef.current && !wrapRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"keydown\", onKey);\n document.addEventListener(\"mousedown\", onPointer);\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n document.removeEventListener(\"mousedown\", onPointer);\n };\n }, []);\n\n // Celdas (6×7) para el modo DÍA, alineadas a firstDay.\n const dayGrid = ((): { cells: Date[]; dows: string[] } => {\n if (monthMode) return { cells: [], dows: [] };\n const first = dl.from(`${viewYear}-${pad2(viewMonth + 1)}-01`);\n const offset = (dl.dayOfWeek(first) - firstDay + 7) % 7;\n const start = dl.subtract(first, { days: offset });\n const cells = Array.from({ length: 42 }, (_, i) => dl.toDate(dl.add(start, { days: i })));\n const dows = cells.slice(0, 7).map((d) => dowFmt.format(d));\n return { cells, dows };\n })();\n\n return (\n <div data-rsv=\"toolbar-wrap\" class={cx(options.classNames?.toolbar)} ref={wrapRef}>\n <div data-rsv=\"toolbar\">\n {/* Inicio: slot libre del anfitrión (Filtrar / Personal …) */}\n <div data-rsv=\"toolbar-section\" data-rsv-area=\"start\">\n {startSlot}\n </div>\n\n {/* Navegación: hoy · ‹ título › */}\n <div data-rsv=\"toolbar-section\" data-rsv-area=\"nav\">\n <button\n type=\"button\"\n data-rsv=\"button\"\n title={text.todayHint}\n aria-label={text.todayHint}\n onClick={() => api.today()}\n >\n {text.today}\n </button>\n <button\n type=\"button\"\n data-rsv=\"button\"\n data-rsv-nav=\"prev\"\n title={text.prevHint}\n aria-label={text.prevHint}\n onClick={() => api.prev()}\n >\n {NAV_SYMBOLS.prev}\n </button>\n\n {/* Título = disparador del datepicker */}\n <div data-rsv=\"datepicker-anchor\">\n <button\n type=\"button\"\n data-rsv=\"title\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n title={`${title} · Ctrl+M`}\n onClick={() => (open ? setOpen(false) : openPicker())}\n >\n <CalendarIcon />\n {title}\n </button>\n\n {open && (\n <div\n data-rsv=\"datepicker\"\n data-rsv-mode={monthMode ? \"month\" : \"day\"}\n role=\"dialog\"\n aria-label={title}\n >\n <div data-rsv=\"dp-head\">\n <button\n type=\"button\"\n data-rsv=\"dp-nav\"\n aria-label={text.prev}\n onClick={() => (monthMode ? setViewYear((y) => y - 1) : shiftMonth(-1))}\n >\n {NAV_SYMBOLS.prev}\n </button>\n <span data-rsv=\"dp-label\">\n {monthMode\n ? viewYear\n : `${monthLongFmt.format(new Date(viewYear, viewMonth, 1))} ${viewYear}`}\n </span>\n <button\n type=\"button\"\n data-rsv=\"dp-nav\"\n aria-label={text.next}\n onClick={() => (monthMode ? setViewYear((y) => y + 1) : shiftMonth(1))}\n >\n {NAV_SYMBOLS.next}\n </button>\n </div>\n\n {monthMode ? (\n <div data-rsv=\"dp-grid\">\n {monthNames.map((label, i) => (\n <button\n type=\"button\"\n data-rsv=\"dp-month\"\n key={label}\n data-active={String(\n viewYear === selected.getFullYear() && i === selected.getMonth(),\n )}\n data-today={String(\n viewYear === nowRef.getFullYear() && i === nowRef.getMonth(),\n )}\n onClick={() => goto(`${viewYear}-${pad2(i + 1)}-01`)}\n >\n {label}\n </button>\n ))}\n </div>\n ) : (\n <div data-rsv=\"dp-days\">\n {dayGrid.dows.map((d, i) => (\n <div data-rsv=\"dp-dow\" key={`dow-${i}`}>\n {d}\n </div>\n ))}\n {dayGrid.cells.map((d) => {\n const iso = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;\n return (\n <button\n type=\"button\"\n data-rsv=\"dp-day\"\n key={iso}\n data-other={String(d.getMonth() !== viewMonth)}\n data-active={String(\n d.getFullYear() === selected.getFullYear() &&\n d.getMonth() === selected.getMonth() &&\n d.getDate() === selected.getDate(),\n )}\n data-today={String(\n d.getFullYear() === nowRef.getFullYear() &&\n d.getMonth() === nowRef.getMonth() &&\n d.getDate() === nowRef.getDate(),\n )}\n onClick={() => goto(iso)}\n >\n {d.getDate()}\n </button>\n );\n })}\n </div>\n )}\n </div>\n )}\n </div>\n\n <button\n type=\"button\"\n data-rsv=\"button\"\n data-rsv-nav=\"next\"\n title={text.nextHint}\n aria-label={text.nextHint}\n onClick={() => api.next()}\n >\n {NAV_SYMBOLS.next}\n </button>\n </div>\n\n {/* Fin: slot libre + botón \"Añadir\" (solo si se pasa onAddClick) */}\n <div data-rsv=\"toolbar-section\" data-rsv-area=\"end\">\n {endSlot}\n {options.onAddClick && (\n <button\n type=\"button\"\n data-rsv=\"button\"\n data-rsv-variant=\"primary\"\n onClick={options.onAddClick}\n >\n <span data-rsv=\"add-icon\" aria-hidden=\"true\">\n +\n </span>\n {options.addButtonText}\n </button>\n )}\n </div>\n </div>\n\n {/* Fila 2: pestañas de vista */}\n {views.length > 0 && (\n <div data-rsv=\"toolbar-views\" role=\"tablist\">\n {views.map((v) => (\n <button\n type=\"button\"\n data-rsv=\"view-tab\"\n key={v}\n role=\"tab\"\n aria-selected={v === activeView}\n data-active={String(v === activeView)}\n title={text.viewHint(text.views[v] ?? v)}\n onClick={() => api.changeView(v)}\n >\n {text.views[v] ?? v}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Formateadores de hora compartidos por las vistas. Por defecto Reservi usa\n * 24h (\"HH:mm\"); si el usuario aporta opciones de `Intl.DateTimeFormat`\n * (`eventTimeFormat` / `slotLabelFormat`), manda su formato.\n */\n\n/** Rellena a dos dígitos. */\nexport function pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\n/** \"HH:mm\" a partir de minutos desde medianoche. */\nexport function minutesToLabel(minutes: number): string {\n const total = ((Math.round(minutes) % 1440) + 1440) % 1440;\n return `${pad2(Math.floor(total / 60))}:${pad2(total % 60)}`;\n}\n\n/** \"HH:mm:ss\" a partir de minutos desde medianoche (sin envolver a 24h). */\nexport function minutesToTimeString(minutes: number): string {\n const m = Math.max(0, Math.round(minutes));\n return `${pad2(Math.floor(m / 60))}:${pad2(m % 60)}:00`;\n}\n\n/**\n * Formateador de hora: usa `Intl` si hay opciones, y si no el 24h por defecto\n * que ya produce el núcleo. Devuelve null si no hay que sobreescribir nada.\n */\nexport function timeFormatter(\n locale: string,\n options: Intl.DateTimeFormatOptions | undefined,\n): ((date: Date) => string) | null {\n if (!options) return null;\n const fmt = new Intl.DateTimeFormat(locale, options);\n return (date: Date) => fmt.format(date);\n}\n\n/** Formateador de fecha para cabeceras; `false` significa \"sin texto\". */\nexport function dateFormatter(\n locale: string,\n options: Intl.DateTimeFormatOptions | false | undefined,\n fallback: Intl.DateTimeFormatOptions,\n): ((date: Date) => string) | null {\n if (options === false) return null;\n const fmt = new Intl.DateTimeFormat(locale, options ?? fallback);\n return (date: Date) => fmt.format(date);\n}\n","import { dl, type CalendarApi, type RsvDate } from \"@reservi/core\";\n\n/**\n * Navegación de \"nav links\": dispara `navLinkDay` y, por defecto, va a la vista\n * de día (timeGridDay o dayGridDay, la que esté registrada) en esa fecha.\n */\nexport function navLinkToDay(api: CalendarApi, date: RsvDate): void {\n api.trigger(\"navLinkDay\", { date });\n const target = api.hasView(\"timeGridDay\")\n ? \"timeGridDay\"\n : api.hasView(\"dayGridDay\")\n ? \"dayGridDay\"\n : null;\n if (target) {\n api.gotoDate(dl.toISOString(date));\n api.changeView(target);\n }\n}\n","/**\n * Movimiento de eventos por teclado (accesibilidad WCAG). No necesita geometría\n * de píxeles: mueve por incrementos fijos (días o snap de minutos), por lo que\n * es plenamente testeable. Usa moveEvent (validado) del núcleo.\n */\nimport {\n computeDrop,\n dl,\n timeStringToMinutes,\n type CalendarApi,\n type EventDef,\n type KeyboardAction,\n} from \"@reservi/core\";\n\nexport type GridKind = \"dayGrid\" | \"timeGrid\";\n\nconst DAY = 1440;\n\n/** Atajos por defecto (usados para cualquier acción sin override del usuario). */\nconst DEFAULT_SHORTCUTS: Record<KeyboardAction, string[]> = {\n moveLeft: [\"ArrowLeft\"],\n moveRight: [\"ArrowRight\"],\n moveUp: [\"ArrowUp\"],\n moveDown: [\"ArrowDown\"],\n activate: [\"Enter\", \" \"],\n};\n\ninterface KeydownOptions {\n api: CalendarApi;\n event: EventDef;\n kind: GridKind;\n snap?: string | undefined;\n /** Override de atajos (se mergea sobre `DEFAULT_SHORTCUTS` por acción). */\n shortcuts?: Partial<Record<KeyboardAction, string[]>> | undefined;\n}\n\n/** Resuelve qué acción corresponde a la tecla pulsada, según el mapa efectivo. */\nfunction resolveAction(\n key: string,\n shortcuts: Partial<Record<KeyboardAction, string[]>> | undefined,\n): KeyboardAction | null {\n const entries = Object.entries(DEFAULT_SHORTCUTS) as [KeyboardAction, string[]][];\n for (const [action, defaultKeys] of entries) {\n const keys = shortcuts?.[action] ?? defaultKeys;\n if (keys.includes(key)) return action;\n }\n return null;\n}\n\nexport function handleEventKeydown(e: KeyboardEvent, opts: KeydownOptions): void {\n const { api, event, kind } = opts;\n const snapMin = timeStringToMinutes(opts.snap ?? \"00:30\");\n const action = resolveAction(e.key, opts.shortcuts);\n if (!action) return; // tecla no gestionada\n\n if (action === \"activate\") {\n e.preventDefault();\n api.trigger(\"eventClick\", { event });\n return;\n }\n\n let deltaMin = 0;\n switch (action) {\n case \"moveLeft\":\n deltaMin = -DAY;\n break;\n case \"moveRight\":\n deltaMin = DAY;\n break;\n case \"moveUp\":\n deltaMin = kind === \"timeGrid\" ? -snapMin : -DAY * 7;\n break;\n case \"moveDown\":\n deltaMin = kind === \"timeGrid\" ? snapMin : DAY * 7;\n break;\n }\n\n e.preventDefault();\n const next = computeDrop(event.start, event.end, deltaMin, dl);\n if (api.moveEvent(event.id, next.start, next.end)) {\n const updated = api.getEventById(event.id);\n if (updated) api.trigger(\"eventDrop\", { event: updated });\n }\n}\n","/**\n * Drag por puntero para dayGrid/mes: mover un evento entre días y seleccionar\n * un rango de días arrastrando. El cálculo de fechas usa el núcleo (computeDrop\n * + dl); aquí solo se hace hit-testing del DOM para saber sobre qué día se está.\n */\nimport { computeDrop, dl, type CalendarApi, type EventDef } from \"@reservi/core\";\n\nconst DAY = 1440;\nconst THRESHOLD = 4;\n\n/** Fecha (ISO) de la celda de día bajo el punto, o null. */\nfunction dateAtPoint(x: number, y: number): string | null {\n const el = document.elementFromPoint(x, y) as HTMLElement | null;\n return el?.closest<HTMLElement>('[data-rsv=\"day\"]')?.dataset.date ?? null;\n}\n\ninterface EventDragOptions {\n api: CalendarApi;\n event: EventDef;\n /** Fecha (ISO) de la celda donde empezó el arrastre. */\n sourceDate: string;\n /** Se llama si hubo arrastre real (para suprimir el click posterior). */\n onMoved?: () => void;\n}\n\n/** Arrastra un evento entre días (dayGrid/mes). */\nexport function startDayGridEventDrag(ev: PointerEvent, opts: EventDragOptions): void {\n ev.stopPropagation();\n const { api, event, sourceDate } = opts;\n const startX = ev.clientX;\n const startY = ev.clientY;\n let dragging = false;\n\n const onMove = (e: PointerEvent): void => {\n if (!dragging && Math.hypot(e.clientX - startX, e.clientY - startY) > THRESHOLD) {\n dragging = true;\n document.body.style.cursor = \"grabbing\";\n }\n };\n const onUp = (e: PointerEvent): void => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n document.body.style.cursor = \"\";\n if (!dragging) return;\n opts.onMoved?.();\n const target = dateAtPoint(e.clientX, e.clientY);\n if (!target) return;\n const deltaDays = dl.diff(dl.from(sourceDate), dl.from(target), \"day\");\n if (deltaDays === 0) return;\n const next = computeDrop(event.start, event.end, deltaDays * DAY, dl);\n if (api.moveEvent(event.id, next.start, next.end)) {\n const updated = api.getEventById(event.id);\n if (updated) api.trigger(\"eventDrop\", { event: updated });\n }\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n\n/**\n * Selecciona un rango de días arrastrando. Solo actúa si hay arrastre real\n * (varios días); un click simple lo gestiona el `onClick` de la celda. Llama a\n * `onRangeSelect` cuando selecciona, para suprimir el click posterior.\n */\nexport function startDayRangeSelect(\n ev: PointerEvent,\n opts: { api: CalendarApi; startDate: string; onRangeSelect?: () => void },\n): void {\n const target = ev.target as HTMLElement;\n // No iniciar selección si se pulsa sobre un evento, el \"+N more\" o un nav-link.\n if (target.closest('[data-rsv=\"event\"], [data-rsv=\"more-anchor\"], [data-nav-link=\"true\"]')) {\n return;\n }\n const { api } = opts;\n let endStr = opts.startDate;\n let moved = false;\n\n const onMove = (e: PointerEvent): void => {\n const d = dateAtPoint(e.clientX, e.clientY);\n if (d && d !== opts.startDate) moved = true;\n if (d) endStr = d;\n };\n const onUp = (): void => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n if (!moved) return; // click simple → lo gestiona onClick\n opts.onRangeSelect?.();\n const a = dl.from(opts.startDate);\n const b = dl.from(endStr);\n const [lo, hi] = dl.isBefore(a, b) ? [a, b] : [b, a];\n // Fin exclusivo (+1 día), como FullCalendar.\n api.select(dl.toISOString(lo), dl.toISOString(dl.add(hi, { days: 1 })));\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n","import {\n dl,\n getLocaleText,\n type CalendarApi,\n type DayGridCell,\n type DayGridModel,\n type EventDef,\n} from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport { useEffect, useRef, useState } from \"preact/hooks\";\nimport type { ReserviCalendarOptions, ViewArg } from \"../../types.js\";\nimport { renderSlot, cx, callDidMount } from \"../../render/slots.js\";\nimport { dateFormatter, timeFormatter } from \"../../render/format.js\";\nimport { navLinkToDay } from \"../../render/nav.js\";\nimport { handleEventKeydown } from \"../../interaction/keyboard.js\";\nimport { startDayGridEventDrag, startDayRangeSelect } from \"../../interaction/daygrid-drag.js\";\n\ninterface DayGridViewProps {\n api: CalendarApi;\n model: DayGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista de cuadrícula por días (mes/semana/día/año). */\nexport function DayGridView({ api, model, options }: DayGridViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const view: ViewArg = { type: api.getView().type };\n const dowFmt = dateFormatter(locale, options.dayHeaderFormat, { weekday: \"short\" });\n const headerDays = model.weeks[0]?.days ?? [];\n const showWeekNums = options.weekNumbers === true;\n\n return (\n <div\n data-rsv=\"daygrid\"\n data-weeknumbers={String(showWeekNums)}\n style={`--rsv-cols:${model.columnCount}`}\n >\n <div data-rsv=\"daygrid-header\" role=\"row\">\n {showWeekNums && <div data-rsv=\"daygrid-weeknum-header\" role=\"columnheader\" />}\n {headerDays.map((cell) => {\n const date = dl.toDate(cell.date);\n const text = dowFmt ? dowFmt(date) : \"\";\n const headerArg = {\n date,\n text,\n dayOfWeek: cell.dayOfWeek,\n dayNumber: dl.dayOfMonth(cell.date),\n isToday: cell.isToday,\n view,\n };\n return (\n <div\n data-rsv=\"daygrid-dow\"\n role=\"columnheader\"\n data-dow={String(cell.dayOfWeek)}\n class={cx(options.classNames?.dayHeader)}\n key={cell.dayOfWeek}\n ref={(el) => callDidMount(el, options.hooks?.dayHeaderDidMount, () => headerArg)}\n >\n {renderSlot(options.slots?.dayHeaderContent, headerArg, text, options.hostBridge)}\n </div>\n );\n })}\n </div>\n\n {model.weeks.map((week, wi) => (\n <div data-rsv=\"daygrid-week\" role=\"row\" key={wi}>\n {showWeekNums && (\n <div data-rsv=\"daygrid-weeknum\" role=\"rowheader\">\n {week.weekNumber}\n </div>\n )}\n {week.days.map((cell) => (\n <DayCell\n api={api}\n cell={cell}\n options={options}\n view={view}\n key={dl.toISOString(cell.date)}\n />\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nfunction DayCell({\n api,\n cell,\n options,\n view,\n}: {\n api: CalendarApi;\n cell: DayGridCell;\n options: ReserviCalendarOptions;\n view: ViewArg;\n}): VNode {\n const date = dl.toDate(cell.date);\n const dayNumber = dl.dayOfMonth(cell.date);\n const defaultNumber = options.navLinks ? (\n <a\n data-rsv=\"day-number\"\n data-nav-link=\"true\"\n role=\"link\"\n tabIndex={0}\n title={getLocaleText(options.locale).navLinkHint(\n new Intl.DateTimeFormat(options.locale, { dateStyle: \"long\" }).format(date),\n )}\n onClick={(e) => {\n e.stopPropagation();\n navLinkToDay(api, cell.date);\n }}\n >\n {dayNumber}\n </a>\n ) : (\n <span data-rsv=\"day-number\">{dayNumber}</span>\n );\n const cellArg = { date, dayNumber, isToday: cell.isToday, isOther: cell.isOther, view };\n const numberNode = renderSlot(\n options.slots?.dayCellContent,\n cellArg,\n defaultNumber,\n options.hostBridge,\n );\n\n const [moreOpen, setMoreOpen] = useState(false);\n\n const dateStr = dl.toISOString(cell.date);\n const rangeSelectedRef = useRef(false);\n\n const onDayClick = () => {\n // Suprime el click que sigue a una selección por arrastre.\n if (rangeSelectedRef.current) {\n rangeSelectedRef.current = false;\n return;\n }\n api.trigger(\"dateClick\", { date: cell.date });\n if (options.selectable) {\n api.select(dateStr, dl.toISOString(dl.add(cell.date, { days: 1 })));\n }\n };\n\n const openMore = (e: Event) => {\n e.stopPropagation();\n setMoreOpen(true);\n api.trigger(\"moreLinkClick\", {\n date: cell.date,\n allEvents: [...cell.events, ...cell.hiddenEvents],\n hiddenEvents: cell.hiddenEvents,\n });\n };\n\n return (\n <div\n data-rsv=\"day\"\n role=\"gridcell\"\n data-date={dateStr}\n data-today={String(cell.isToday)}\n data-other={String(cell.isOther)}\n data-weekend={String(cell.isWeekend)}\n data-business={String(cell.isBusiness)}\n data-selected={String(cell.isSelected)}\n class={cx(options.classNames?.day)}\n ref={(el) => callDidMount(el, options.hooks?.dayCellDidMount, () => cellArg)}\n onClick={onDayClick}\n onPointerDown={\n options.selectable\n ? (e) =>\n startDayRangeSelect(e, {\n api,\n startDate: dateStr,\n onRangeSelect: () => {\n rangeSelectedRef.current = true;\n },\n })\n : undefined\n }\n >\n {numberNode}\n {cell.events\n .filter((event) => event.display !== \"none\")\n .map((event) => (\n <EventChip\n api={api}\n event={event}\n options={options}\n view={view}\n sourceDate={dateStr}\n key={event.id}\n />\n ))}\n {cell.moreCount > 0 && (\n <div data-rsv=\"more-anchor\">\n <button type=\"button\" data-rsv=\"more-link\" onClick={openMore}>\n {renderSlot(\n options.slots?.moreLinkContent,\n {\n date,\n moreCount: cell.moreCount,\n allEvents: [...cell.events, ...cell.hiddenEvents],\n hiddenEvents: cell.hiddenEvents,\n view,\n },\n getLocaleText(options.locale).more(cell.moreCount),\n options.hostBridge,\n )}\n </button>\n {moreOpen && (\n <DayMorePopover\n api={api}\n cell={cell}\n options={options}\n view={view}\n onClose={() => setMoreOpen(false)}\n />\n )}\n </div>\n )}\n </div>\n );\n}\n\n/** Popover de \"+N more\": lista todos los eventos del día (visibles + ocultos). */\nfunction DayMorePopover({\n api,\n cell,\n options,\n view,\n onClose,\n}: {\n api: CalendarApi;\n cell: DayGridCell;\n options: ReserviCalendarOptions;\n view: ViewArg;\n onClose: () => void;\n}): VNode {\n const ref = useRef<HTMLDivElement>(null);\n const dayFmt = new Intl.DateTimeFormat(options.locale ?? \"en\", {\n weekday: \"long\",\n day: \"numeric\",\n month: \"long\",\n });\n const allEvents = [...cell.events, ...cell.hiddenEvents].filter((e) => e.display !== \"none\");\n\n useEffect(() => {\n const onPointer = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"mousedown\", onPointer);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"mousedown\", onPointer);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [onClose]);\n\n return (\n <div data-rsv=\"more-popover\" role=\"dialog\" ref={ref} onClick={(e) => e.stopPropagation()}>\n <div data-rsv=\"more-popover-header\">\n <span data-rsv=\"more-popover-title\">{dayFmt.format(dl.toDate(cell.date))}</span>\n <button type=\"button\" data-rsv=\"more-popover-close\" aria-label=\"✕\" onClick={onClose}>\n ✕\n </button>\n </div>\n <div data-rsv=\"more-popover-body\">\n {allEvents.map((event) => (\n <EventChip\n api={api}\n event={event}\n options={options}\n view={view}\n sourceDate={dl.toISOString(cell.date)}\n key={event.id}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction EventChip({\n api,\n event,\n options,\n view,\n sourceDate,\n}: {\n api: CalendarApi;\n event: EventDef;\n options: ReserviCalendarOptions;\n view: ViewArg;\n sourceDate: string;\n}): VNode {\n const editable = options.editable === true && event.editable !== false;\n const selected = api.selectedEventIds.value.has(event.id);\n const draggedRef = useRef(false);\n const eventFmt = timeFormatter(options.locale ?? \"en\", options.eventTimeFormat);\n const timeText = event.allDay\n ? \"\"\n : eventFmt\n ? eventFmt(dl.toDate(event.start))\n : dl.format(event.start, \"HH:mm\");\n const contentArg = { event, isAllDay: event.allDay, timeText, view };\n const content = renderSlot(\n options.slots?.eventContent,\n contentArg,\n <span data-rsv=\"event-title\">\n {timeText ? `${timeText} ` : \"\"}\n {event.title}\n </span>,\n options.hostBridge,\n );\n\n return (\n <div\n data-rsv=\"event\"\n role=\"button\"\n tabIndex={0}\n class={cx(options.classNames?.event, ...event.classNames)}\n data-all-day={String(event.allDay)}\n data-display={event.display}\n data-event-id={event.id}\n data-editable={String(editable)}\n data-rsv-selected={String(selected)}\n ref={(el) => callDidMount(el, options.hooks?.eventDidMount, () => contentArg)}\n style={\n `--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor};` +\n `--rsv-event-border:${event.borderColor}`\n }\n onClick={(e) => {\n e.stopPropagation();\n // Suprime el click que sigue a un arrastre.\n if (draggedRef.current) {\n draggedRef.current = false;\n return;\n }\n // Ctrl/Cmd-click: alterna selección múltiple (bulk ops) en vez de eventClick.\n if (e.ctrlKey || e.metaKey) {\n api.toggleEventSelection(event.id);\n return;\n }\n api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement });\n if (event.url) window.open(event.url, \"_self\");\n }}\n onPointerDown={\n editable\n ? (e) =>\n startDayGridEventDrag(e, {\n api,\n event,\n sourceDate,\n onMoved: () => {\n draggedRef.current = true;\n },\n })\n : undefined\n }\n onKeyDown={\n editable\n ? (e) =>\n handleEventKeydown(e, {\n api,\n event,\n kind: \"dayGrid\",\n shortcuts: options.keyboardShortcuts,\n })\n : undefined\n }\n >\n {content}\n </div>\n );\n}\n","/**\n * Auto-scroll de un contenedor scrolleable mientras el puntero está cerca de\n * su borde superior/inferior durante un drag. `update()` se llama en cada\n * `pointermove`; el propio scroll corre por rAF mientras el drag sigue activo.\n */\nconst EDGE_PX = 40;\nconst MAX_SPEED_PX = 16;\n\nexport interface AutoScroller {\n /** Llamar en cada pointermove con la posición Y actual del puntero. */\n update(clientY: number): void;\n /** Total de px que el auto-scroll desplazó el contenedor (sumar al delta del drag). */\n getScrolled(): number;\n /** Detener el loop (llamar en pointerup/pointercancel). */\n stop(): void;\n}\n\nconst NOOP_SCROLLER: AutoScroller = {\n update() {},\n getScrolled: () => 0,\n stop() {},\n};\n\nexport function startAutoScroll(container: HTMLElement | null): AutoScroller {\n if (!container) return NOOP_SCROLLER;\n\n let lastY = 0;\n let scrolled = 0;\n let raf = 0;\n\n const tick = (): void => {\n const rect = container.getBoundingClientRect();\n let delta = 0;\n if (lastY < rect.top + EDGE_PX) {\n delta = -MAX_SPEED_PX * (1 - Math.max(0, lastY - rect.top) / EDGE_PX);\n } else if (lastY > rect.bottom - EDGE_PX) {\n delta = MAX_SPEED_PX * (1 - Math.max(0, rect.bottom - lastY) / EDGE_PX);\n }\n if (delta !== 0) {\n const before = container.scrollTop;\n container.scrollTop += delta;\n scrolled += container.scrollTop - before; // ya clampeado a los límites de scroll\n }\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n\n return {\n update(clientY) {\n lastY = clientY;\n },\n getScrolled: () => scrolled,\n stop() {\n cancelAnimationFrame(raf);\n },\n };\n}\n","/**\n * Controlador de drag/resize por puntero para timeGrid. Usa la geometría pura\n * del núcleo (testeada en @reservi/core) y mide la columna del DOM para obtener\n * px/min. El cálculo de fechas NO vive aquí (vive en core/interaction).\n */\nimport {\n computeDrop,\n computeResize,\n dl,\n pxToSnappedMinutes,\n timeStringToMinutes,\n type CalendarApi,\n type EventDef,\n type ResizeEdge,\n type RsvDate,\n type TimeGridModel,\n} from \"@reservi/core\";\nimport { startAutoScroll } from \"./auto-scroll.js\";\n\n/** Contenedor scrolleable de timeGrid (ver `[data-rsv=\"tg-body\"]` en TimeGridView). */\nfunction scrollAncestor(el: HTMLElement): HTMLElement | null {\n return el.closest<HTMLElement>('[data-rsv=\"tg-body\"]');\n}\n\ninterface DragOptions {\n api: CalendarApi;\n event: EventDef;\n model: TimeGridModel;\n columnEl: HTMLElement;\n snap?: string | undefined;\n /** Si se indica, redimensiona por ese borde; si no, mueve el evento. */\n edge?: ResizeEdge | undefined;\n}\n\nexport function startEventDrag(ev: PointerEvent, options: DragOptions): void {\n ev.preventDefault();\n ev.stopPropagation();\n const { api, event, model, columnEl, snap = \"00:15\", edge } = options;\n\n const rect = columnEl.getBoundingClientRect();\n const totalMinutes = model.maxMinutes - model.minMinutes;\n const ppm = rect.height === 0 ? 0 : rect.height / totalMinutes;\n const startY = ev.clientY;\n\n // Auto-scroll del cuerpo de timeGrid al arrastrar cerca de su borde superior/inferior.\n const scroller = startAutoScroll(scrollAncestor(columnEl));\n scroller.update(ev.clientY);\n\n const onMove = (e: PointerEvent): void => {\n scroller.update(e.clientY);\n };\n const onUp = (e: PointerEvent) => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n scroller.stop();\n // Suma el desplazamiento que el propio auto-scroll aplicó al contenedor:\n // el puntero no se movió más, pero el contenido sí, así que cuenta como drag extra.\n const deltaMin = pxToSnappedMinutes(e.clientY - startY + scroller.getScrolled(), ppm, snap);\n if (deltaMin === 0) return;\n\n const next = edge\n ? computeResize(event.start, event.end, edge, deltaMin, dl)\n : computeDrop(event.start, event.end, deltaMin, dl);\n\n // moveEvent valida overlap/constraint/allow; si no es válido, se revierte.\n if (api.moveEvent(event.id, next.start, next.end)) {\n const updated = api.getEventById(event.id);\n if (updated) api.trigger(edge ? \"eventResize\" : \"eventDrop\", { event: updated });\n }\n };\n\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n\n/** Rango en curso (minutos absolutos del dia) para dibujar el `selectMirror`. */\nexport interface RangePreview {\n startMin: number;\n endMin: number;\n}\n\ninterface RangeSelectOptions {\n api: CalendarApi;\n date: RsvDate;\n model: TimeGridModel;\n columnEl: HTMLElement;\n snap?: string | undefined;\n /**\n * Se llama con el rango en curso mientras se arrastra y con `null` al\n * terminar. La vista lo usa para pintar el \"fantasma\" (`selectMirror`).\n */\n onPreview?: ((range: RangePreview | null) => void) | undefined;\n}\n\n/** Selección de rango horario por arrastre en una columna de timeGrid. */\nexport function startTimeRangeSelect(ev: PointerEvent, options: RangeSelectOptions): void {\n // No iniciar si se pulsa sobre un evento existente.\n if ((ev.target as HTMLElement).closest('[data-rsv=\"event\"]')) return;\n const { api, date, model, columnEl, snap = \"00:15\" } = options;\n\n const total = model.maxMinutes - model.minMinutes;\n const snapMin = timeStringToMinutes(snap) || 15;\n\n // Recalcula la geometría en cada llamada: si el contenedor hizo auto-scroll,\n // `columnEl` cambió de posición y un `rect` capturado una sola vez quedaría obsoleto.\n const yToMin = (clientY: number): number => {\n const rect = columnEl.getBoundingClientRect();\n const ppm = rect.height === 0 ? 0 : rect.height / total;\n const raw = model.minMinutes + (ppm === 0 ? 0 : (clientY - rect.top) / ppm);\n const clamped = Math.max(model.minMinutes, Math.min(model.maxMinutes, raw));\n return Math.round(clamped / snapMin) * snapMin;\n };\n\n const startMin = yToMin(ev.clientY);\n let endMin = startMin;\n let moved = false;\n\n // Auto-scroll del cuerpo de timeGrid al arrastrar cerca de su borde superior/inferior.\n const scroller = startAutoScroll(scrollAncestor(columnEl));\n scroller.update(ev.clientY);\n\n const onMove = (e: PointerEvent): void => {\n scroller.update(e.clientY);\n const m = yToMin(e.clientY);\n if (m !== startMin) moved = true;\n endMin = m;\n if (moved) {\n options.onPreview?.({\n startMin: Math.min(startMin, endMin),\n endMin: Math.max(startMin, endMin),\n });\n }\n };\n const onUp = (): void => {\n document.removeEventListener(\"pointermove\", onMove);\n document.removeEventListener(\"pointerup\", onUp);\n scroller.stop();\n options.onPreview?.(null);\n if (!moved) return; // un click simple lo gestiona dateClick\n const lo = Math.min(startMin, endMin);\n const hi = Math.max(startMin, endMin);\n const dayStart = dl.startOf(date, \"day\");\n api.select(\n dl.toISOString(dl.add(dayStart, { minutes: lo })),\n dl.toISOString(dl.add(dayStart, { minutes: hi })),\n );\n };\n document.addEventListener(\"pointermove\", onMove);\n document.addEventListener(\"pointerup\", onUp);\n}\n","import {\n dl,\n getLocaleText,\n timeStringToMinutes,\n type CalendarApi,\n type CalendarViewAdapter,\n type TimeGridModel,\n type TimeGridSeg,\n} from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport { useEffect, useRef, useState } from \"preact/hooks\";\nimport type { ReserviCalendarOptions, ViewArg } from \"../../types.js\";\nimport { renderSlot, cx, callDidMount } from \"../../render/slots.js\";\nimport {\n dateFormatter,\n minutesToLabel,\n minutesToTimeString,\n timeFormatter,\n} from \"../../render/format.js\";\nimport { navLinkToDay } from \"../../render/nav.js\";\nimport { startEventDrag, startTimeRangeSelect } from \"../../interaction/drag.js\";\nimport { handleEventKeydown } from \"../../interaction/keyboard.js\";\n\ninterface TimeGridViewProps {\n api: CalendarApi;\n model: TimeGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Rango de selección en curso (minutos absolutos del día), para el mirror. */\ninterface PreviewRange {\n dayIndex: number;\n startMin: number;\n endMin: number;\n}\n\n/** Vista con eje temporal vertical (semana/día). */\nexport function TimeGridView({ api, model, options }: TimeGridViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const view: ViewArg = { type: api.getView().type };\n const headerFmt = dateFormatter(locale, options.dayHeaderFormat, {\n weekday: \"short\",\n day: \"numeric\",\n });\n const slotFmt = timeFormatter(locale, options.slotLabelFormat);\n const showAllDay = options.allDaySlot !== false;\n const bodyHeight = `calc(var(--spacing-rsv-slot, 2.5rem) * ${model.slots.length})`;\n const total = model.maxMinutes - model.minMinutes;\n const snapMin =\n timeStringToMinutes(options.snapDuration ?? options.slotDuration ?? \"00:15\") || 15;\n\n const bodyRef = useRef<HTMLDivElement>(null);\n // El modelo cambia en cada render; el adaptador de scroll se instala una vez\n // y lee siempre el modelo vigente a traves de esta ref.\n const modelRef = useRef(model);\n modelRef.current = model;\n\n const [preview, setPreview] = useState<PreviewRange | null>(null);\n\n // Adaptador de scroll: expone scrollToTime/getScrollTime a la CalendarApi.\n useEffect(() => {\n const body = bodyRef.current;\n if (!body) return;\n const adapter: CalendarViewAdapter = {\n scrollToTime(time: string): void {\n const m = modelRef.current;\n const span = m.maxMinutes - m.minMinutes;\n const content = body.scrollHeight;\n if (span <= 0 || content <= 0) return;\n const target = Math.max(m.minMinutes, Math.min(m.maxMinutes, timeStringToMinutes(time)));\n const top = ((target - m.minMinutes) / span) * content;\n body.scrollTop = Math.max(0, Math.min(top, content - body.clientHeight));\n },\n getScrollTime(): string | null {\n const m = modelRef.current;\n const span = m.maxMinutes - m.minMinutes;\n const content = body.scrollHeight;\n if (span <= 0 || content <= 0) return null;\n return minutesToTimeString(m.minMinutes + (body.scrollTop / content) * span);\n },\n };\n api.setViewAdapter(adapter);\n return () => api.setViewAdapter(null);\n }, [api]);\n\n // Posicion inicial del scroll (`scrollTime`). Solo al montar: a partir de ahi\n // el anfitrion controla el scroll con `api.scrollToTime(...)`.\n const scrollTime = options.scrollTime;\n useEffect(() => {\n if (!scrollTime) return;\n // Dos frames: el primero deja que el layout fije el alto del contenido.\n let inner = 0;\n const outer = requestAnimationFrame(() => {\n inner = requestAnimationFrame(() => api.scrollToTime(scrollTime));\n });\n return () => {\n cancelAnimationFrame(outer);\n cancelAnimationFrame(inner);\n };\n // Solo `api`: `scrollTime` es la posicion INICIAL. Incluirlo reposicionaria\n // el scroll cada vez que el anfitrion cambiase la opcion, peleandose con\n // el scroll manual del usuario.\n }, [api]);\n\n /** Minutos (ajustados al snap) del punto vertical del cursor en una columna. */\n const minutesAtPointer = (colEl: HTMLElement, clientY: number): number => {\n const rect = colEl.getBoundingClientRect();\n if (rect.height === 0 || total <= 0) return model.minMinutes;\n const raw = ((clientY - rect.top) / rect.height) * total;\n const snapped = Math.floor(Math.max(0, Math.min(total, raw)) / snapMin) * snapMin;\n return model.minMinutes + snapped;\n };\n\n const axisDay = model.days[0];\n\n return (\n <div data-rsv=\"timegrid\" style={`--rsv-tg-days:${model.days.length}`}>\n {/* Cabecera de dias */}\n <div data-rsv=\"tg-header\" role=\"row\">\n <div data-rsv=\"tg-axis-corner\" />\n {model.days.map((d) => {\n const date = dl.toDate(d.date);\n const text = headerFmt ? headerFmt(date) : \"\";\n const headerArg = {\n date,\n text,\n dayOfWeek: dl.dayOfWeek(d.date),\n dayNumber: dl.dayOfMonth(d.date),\n isToday: d.isToday,\n view,\n };\n return (\n <div\n data-rsv=\"tg-col-header\"\n role=\"columnheader\"\n data-today={String(d.isToday)}\n data-date={dl.toISOString(d.date)}\n data-nav-link={options.navLinks ? \"true\" : undefined}\n class={cx(options.classNames?.dayHeader)}\n key={dl.toISOString(d.date)}\n ref={(el) => callDidMount(el, options.hooks?.dayHeaderDidMount, () => headerArg)}\n onClick={options.navLinks ? () => navLinkToDay(api, d.date) : undefined}\n >\n {renderSlot(options.slots?.dayHeaderContent, headerArg, text, options.hostBridge)}\n </div>\n );\n })}\n </div>\n\n {/* Franja de todo el dia */}\n {showAllDay && (\n <div data-rsv=\"tg-allday\" role=\"row\">\n <div data-rsv=\"tg-axis-label\">{getLocaleText(options.locale).allDay}</div>\n {model.days.map((d) => (\n <div\n data-rsv=\"tg-allday-cell\"\n key={dl.toISOString(d.date)}\n onClick={() => api.trigger(\"dateClick\", { date: d.date, allDay: true })}\n >\n {d.allDayEvents\n .filter((event) => event.display !== \"none\")\n .map((event) => (\n <div\n data-rsv=\"event\"\n data-all-day=\"true\"\n data-event-id={event.id}\n class={cx(options.classNames?.event, ...event.classNames)}\n data-display={event.display}\n key={event.id}\n style={\n `--rsv-event-bg:${event.backgroundColor};` +\n `--rsv-event-fg:${event.textColor};` +\n `--rsv-event-border:${event.borderColor}`\n }\n onClick={(e) => {\n e.stopPropagation();\n api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement });\n if (event.url) window.open(event.url, \"_self\");\n }}\n >\n {renderSlot(\n options.slots?.eventContent,\n { event, isAllDay: true, timeText: \"\", view },\n event.title,\n options.hostBridge,\n )}\n </div>\n ))}\n </div>\n ))}\n </div>\n )}\n\n {/* Cuerpo: eje + columnas de dia */}\n <div data-rsv=\"tg-body\" ref={bodyRef}>\n <div data-rsv=\"tg-axis\" style={`height:${bodyHeight}`}>\n {model.slots.map((slot) => {\n const minutes = model.minMinutes + slot.offsetMin;\n let text = \"\";\n if (slot.isMajor) {\n text =\n slotFmt && axisDay\n ? slotFmt(dl.toDate(dl.add(dl.startOf(axisDay.date, \"day\"), { minutes })))\n : slot.label || minutesToLabel(minutes);\n }\n const labelArg = { text, minutes, isMajor: slot.isMajor, view };\n return (\n <div data-rsv=\"tg-slot\" data-major={String(slot.isMajor)} key={slot.offsetMin}>\n <span\n data-rsv=\"tg-slot-label\"\n class={cx(options.classNames?.slotLabel)}\n ref={(el) => callDidMount(el, options.hooks?.slotLabelDidMount, () => labelArg)}\n >\n {renderSlot(options.slots?.slotLabelContent, labelArg, text, options.hostBridge)}\n </span>\n </div>\n );\n })}\n </div>\n\n {model.days.map((d, dayIndex) => (\n <div\n data-rsv=\"tg-col\"\n data-today={String(d.isToday)}\n data-date={dl.toISOString(d.date)}\n style={`height:${bodyHeight}`}\n key={dl.toISOString(d.date)}\n onClick={(e) => {\n // FullCalendar entrega en `dateClick` la hora del slot pulsado,\n // no el inicio del dia: se deriva de la posicion del cursor.\n const minutes = minutesAtPointer(e.currentTarget as HTMLElement, e.clientY);\n api.trigger(\"dateClick\", {\n date: dl.add(dl.startOf(d.date, \"day\"), { minutes }),\n allDay: false,\n });\n }}\n onPointerDown={\n options.selectable\n ? (e) =>\n startTimeRangeSelect(e, {\n api,\n date: d.date,\n model,\n columnEl: e.currentTarget as HTMLElement,\n snap: options.snapDuration ?? options.slotDuration,\n onPreview: options.selectMirror\n ? (range) =>\n setPreview(\n range\n ? { dayIndex, startMin: range.startMin, endMin: range.endMin }\n : null,\n )\n : undefined,\n })\n : undefined\n }\n >\n {options.businessHours && !d.businessPct && (\n <div data-rsv=\"tg-nonbusiness\" style=\"top:0;height:100%\" />\n )}\n {d.businessPct && (\n <>\n <div data-rsv=\"tg-nonbusiness\" style={`top:0;height:${d.businessPct.topPct}%`} />\n <div\n data-rsv=\"tg-nonbusiness\"\n style={`top:${d.businessPct.bottomPct}%;height:${100 - d.businessPct.bottomPct}%`}\n />\n </>\n )}\n {preview?.dayIndex === dayIndex && total > 0 && (\n <div\n data-rsv=\"select-mirror\"\n style={\n `top:${((preview.startMin - model.minMinutes) / total) * 100}%;` +\n `height:${((preview.endMin - preview.startMin) / total) * 100}%`\n }\n />\n )}\n {d.timedSegs\n .filter((seg) => seg.event.display !== \"none\")\n .map((seg) => (\n <TimedEvent\n api={api}\n seg={seg}\n model={model}\n options={options}\n view={view}\n key={seg.event.id}\n />\n ))}\n {model.nowIndicator?.dayIndex === dayIndex && (\n <div data-rsv=\"now-indicator\" style={`top:${model.nowIndicator.topPct}%`} />\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction TimedEvent({\n api,\n seg,\n model,\n options,\n view,\n}: {\n api: CalendarApi;\n seg: TimeGridSeg;\n model: TimeGridModel;\n options: ReserviCalendarOptions;\n view: ViewArg;\n}): VNode {\n const { event } = seg;\n const editable = options.editable === true && event.editable !== false;\n const selected = api.selectedEventIds.value.has(event.id);\n const widthPct = 100 / seg.colCount;\n const eventFmt = timeFormatter(options.locale ?? \"en\", options.eventTimeFormat);\n const timeText = eventFmt ? eventFmt(dl.toDate(event.start)) : dl.format(event.start, \"HH:mm\");\n const contentArg = { event, isAllDay: false, timeText, view };\n const content = renderSlot(\n options.slots?.eventContent,\n contentArg,\n <span data-rsv=\"event-title\">\n {timeText} {event.title}\n </span>,\n options.hostBridge,\n );\n\n const getColumn = (el: HTMLElement): HTMLElement =>\n (el.closest('[data-rsv=\"tg-col\"]') as HTMLElement | null) ?? el;\n\n return (\n <div\n data-rsv=\"event\"\n data-all-day=\"false\"\n data-display={event.display}\n data-event-id={event.id}\n data-rsv-selected={String(selected)}\n class={cx(options.classNames?.event, ...event.classNames)}\n role=\"button\"\n tabIndex={0}\n ref={(el) => callDidMount(el, options.hooks?.eventDidMount, () => contentArg)}\n style={\n `position:absolute;` +\n `top:${seg.topPct}%;height:${seg.heightPct}%;` +\n `left:${seg.col * widthPct}%;width:${widthPct}%;` +\n `--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor};` +\n `--rsv-event-border:${event.borderColor}`\n }\n onClick={(e) => {\n e.stopPropagation();\n if (e.ctrlKey || e.metaKey) {\n api.toggleEventSelection(event.id);\n return;\n }\n api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement });\n if (event.url) window.open(event.url, \"_self\");\n }}\n onKeyDown={\n editable\n ? (e) =>\n handleEventKeydown(e, {\n api,\n event,\n kind: \"timeGrid\",\n snap: options.snapDuration ?? options.slotDuration,\n shortcuts: options.keyboardShortcuts,\n })\n : undefined\n }\n onPointerDown={\n editable\n ? (e) =>\n startEventDrag(e, {\n api,\n event,\n model,\n columnEl: getColumn(e.currentTarget as HTMLElement),\n snap: options.snapDuration,\n })\n : undefined\n }\n >\n {editable && (\n <span\n data-rsv=\"resize-handle\"\n data-edge=\"start\"\n onPointerDown={(e) =>\n startEventDrag(e, {\n api,\n event,\n model,\n columnEl: getColumn(e.currentTarget as HTMLElement),\n snap: options.snapDuration,\n edge: \"start\",\n })\n }\n />\n )}\n {content}\n {editable && (\n <span\n data-rsv=\"resize-handle\"\n data-edge=\"end\"\n onPointerDown={(e) =>\n startEventDrag(e, {\n api,\n event,\n model,\n columnEl: getColumn(e.currentTarget as HTMLElement),\n snap: options.snapDuration,\n edge: \"end\",\n })\n }\n />\n )}\n </div>\n );\n}\n","import { dl, getLocaleText, type CalendarApi, type ListModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions, ViewArg } from \"../../types.js\";\nimport { renderSlot, cx, callDidMount } from \"../../render/slots.js\";\nimport { dateFormatter, timeFormatter } from \"../../render/format.js\";\n\ninterface ListViewProps {\n api: CalendarApi;\n model: ListModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista de agenda en lista (listDay/Week/Month/Year). */\nexport function ListView({ api, model, options }: ListViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const view: ViewArg = { type: api.getView().type };\n const text = getLocaleText(options.locale);\n const dayFmt = dateFormatter(locale, options.listDayFormat, {\n weekday: \"long\",\n day: \"numeric\",\n month: \"long\",\n });\n // Texto secundario de la cabecera (a la derecha); solo si se pide.\n const daySideFmt = options.listDaySideFormat\n ? dateFormatter(locale, options.listDaySideFormat, { month: \"short\", day: \"2-digit\" })\n : null;\n const eventFmt = timeFormatter(locale, options.eventTimeFormat);\n\n if (model.isEmpty) {\n return (\n <div data-rsv=\"list\">\n <div data-rsv=\"list-empty\">{text.noEvents}</div>\n </div>\n );\n }\n\n return (\n <div data-rsv=\"list\" role=\"list\">\n {model.days.map((day) => (\n <div data-rsv=\"list-day\" data-today={String(day.isToday)} key={dl.toISOString(day.date)}>\n <div data-rsv=\"list-day-header\" role=\"heading\" aria-level={3}>\n <span data-rsv=\"list-day-text\">\n {dayFmt ? dayFmt(dl.toDate(day.date)) : \"\"}\n </span>\n {daySideFmt && (\n <span data-rsv=\"list-day-side-text\">{daySideFmt(dl.toDate(day.date))}</span>\n )}\n </div>\n {day.events\n .filter((event) => event.display !== \"none\")\n .map((event) => {\n const timeText = event.allDay\n ? text.allDay\n : eventFmt\n ? eventFmt(dl.toDate(event.start))\n : dl.format(event.start, \"HH:mm\");\n const contentArg = { event, isAllDay: event.allDay, timeText, view };\n return (\n <div\n data-rsv=\"list-item\"\n role=\"listitem\"\n tabIndex={0}\n key={event.id}\n data-event-id={event.id}\n class={cx(options.classNames?.event, ...event.classNames)}\n data-display={event.display}\n ref={(el) => callDidMount(el, options.hooks?.eventDidMount, () => contentArg)}\n style={\n `--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor};` +\n `--rsv-event-border:${event.borderColor}`\n }\n onClick={(e) => {\n api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement });\n if (event.url) window.open(event.url, \"_self\");\n }}\n >\n <span data-rsv=\"list-item-time\">{timeText}</span>\n <span\n data-rsv=\"list-item-dot\"\n style={`--rsv-event-bg:${event.backgroundColor}`}\n />\n {/* div y no span: el `eventContent` del anfitrion suele\n devolver contenido de bloque. */}\n <div data-rsv=\"list-item-title\">\n {renderSlot(\n options.slots?.eventContent,\n contentArg,\n event.title,\n options.hostBridge,\n )}\n </div>\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n","import { dl, type CalendarApi, type MultiMonthModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { DayGridView } from \"../daygrid/DayGridView.js\";\n\ninterface MultiMonthViewProps {\n api: CalendarApi;\n model: MultiMonthModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista de varios meses (año): rejilla responsive de cuadrículas mensuales. */\nexport function MultiMonthView({ api, model, options }: MultiMonthViewProps): VNode {\n const locale = options.locale ?? \"en\";\n const monthFmt = new Intl.DateTimeFormat(locale, { month: \"long\" });\n\n return (\n <div data-rsv=\"multimonth\">\n {model.months.map((month) => (\n <section data-rsv=\"mm-month\" key={dl.toISOString(month.date)}>\n <header data-rsv=\"mm-title\">{monthFmt.format(dl.toDate(month.date))}</header>\n <DayGridView api={api} model={month.dayGrid} options={options} />\n </section>\n ))}\n </div>\n );\n}\n","import { type CalendarApi, type TimelineModel, type TimelineSeg } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { renderSlot } from \"../../render/slots.js\";\n\nconst LANE_REM = 1.6;\n\ninterface TimelineViewProps {\n api: CalendarApi;\n model: TimelineModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista timeline: eje temporal horizontal con eventos apilados en carriles. */\nexport function TimelineView({ api, model, options }: TimelineViewProps): VNode {\n return (\n <div data-rsv=\"timeline\">\n <div data-rsv=\"tl-axis\" role=\"row\">\n {model.slots.map((slot) => (\n <div data-rsv=\"tl-slot\" style={`left:${slot.leftPct}%`} key={slot.leftPct}>\n {slot.label}\n </div>\n ))}\n </div>\n <div data-rsv=\"tl-body\" style={`height:${model.laneCount * LANE_REM + 0.5}rem`}>\n {model.segs.map((seg) => (\n <TimelineEvent api={api} seg={seg} options={options} key={seg.event.id} />\n ))}\n </div>\n </div>\n );\n}\n\nexport function TimelineEvent({\n api,\n seg,\n options,\n}: {\n api: CalendarApi;\n seg: TimelineSeg;\n options: ReserviCalendarOptions;\n}): VNode {\n const { event } = seg;\n return (\n <div\n data-rsv=\"event\"\n data-event-id={event.id}\n role=\"button\"\n tabIndex={0}\n style={\n `position:absolute;left:${seg.leftPct}%;width:${seg.widthPct}%;` +\n `top:${seg.lane * LANE_REM}rem;height:${LANE_REM - 0.2}rem;` +\n `--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor};` +\n `--rsv-event-border:${event.borderColor}`\n }\n onClick={(e) => api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement })}\n >\n {renderSlot(\n options.slots?.eventContent,\n { event, isAllDay: event.allDay, timeText: \"\", view: { type: api.getView().type } },\n event.title,\n options.hostBridge,\n )}\n </div>\n );\n}\n","import { type CalendarApi, type ResourceTimelineModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\nimport { TimelineEvent } from \"../timeline/TimelineView.js\";\n\nconst LANE_REM = 1.6;\n\ninterface ResourceTimelineViewProps {\n api: CalendarApi;\n model: ResourceTimelineModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista resource-timeline (Scheduler): filas de recursos × eje temporal. */\nexport function ResourceTimelineView({ api, model, options }: ResourceTimelineViewProps): VNode {\n return (\n <div data-rsv=\"resource-timeline\">\n {/* Cabecera: área de recursos + eje temporal */}\n <div data-rsv=\"rt-header\" role=\"row\">\n <div data-rsv=\"resource-area-header\">\n {options.locale === \"es\" ? \"Recursos\" : \"Resources\"}\n </div>\n <div data-rsv=\"tl-axis\">\n {model.slots.map((slot) => (\n <div data-rsv=\"tl-slot\" style={`left:${slot.leftPct}%`} key={slot.leftPct}>\n {slot.label}\n </div>\n ))}\n </div>\n </div>\n\n {/* Filas de recursos */}\n {model.lanes.map((lane) => {\n const rowHeight = lane.laneCount * LANE_REM + 0.4;\n return (\n <div data-rsv=\"resource-row\" role=\"row\" key={lane.row.resource.id}>\n <div\n data-rsv=\"resource-label\"\n style={`padding-inline-start:${0.5 + lane.row.depth * 1}rem`}\n >\n {lane.row.hasChildren && (\n <button\n type=\"button\"\n data-rsv=\"resource-toggle\"\n aria-expanded={lane.row.expanded}\n onClick={() => api.toggleResource(lane.row.resource.id)}\n >\n {lane.row.expanded ? \"▾\" : \"▸\"}\n </button>\n )}\n <span data-rsv=\"resource-title\">{lane.row.resource.title}</span>\n </div>\n <div data-rsv=\"resource-lane\" style={`height:${rowHeight}rem`}>\n {lane.segs.map((seg) => (\n <TimelineEvent api={api} seg={seg} options={options} key={seg.event.id} />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n","import { dl, getLocaleText, type CalendarApi, type ResourceTimeGridModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\n\ninterface Props {\n api: CalendarApi;\n model: ResourceTimeGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista vertical de recursos: recursos como columnas sobre un eje de tiempo. */\nexport function ResourceTimeGridView({ api, model, options }: Props): VNode {\n const bodyHeight = `calc(var(--spacing-rsv-slot, 2.5rem) * ${model.slots.length})`;\n\n return (\n <div data-rsv=\"timegrid\" style={`--rsv-tg-days:${model.columns.length}`}>\n <div data-rsv=\"tg-header\" role=\"row\">\n <div data-rsv=\"tg-axis-corner\" />\n {model.columns.map((col) => (\n <div data-rsv=\"tg-col-header\" role=\"columnheader\" key={col.row.resource.id}>\n {col.row.resource.title}\n </div>\n ))}\n </div>\n\n <div data-rsv=\"tg-allday\" role=\"row\">\n <div data-rsv=\"tg-axis-label\">{getLocaleText(options.locale).allDay}</div>\n {model.columns.map((col) => (\n <div data-rsv=\"tg-allday-cell\" key={col.row.resource.id}>\n {col.allDayEvents.map((event) => (\n <div\n data-rsv=\"event\"\n data-all-day=\"true\"\n key={event.id}\n style={`--rsv-event-bg:${event.backgroundColor}`}\n onClick={(e) => api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement })}\n >\n {event.title}\n </div>\n ))}\n </div>\n ))}\n </div>\n\n <div data-rsv=\"tg-body\">\n <div data-rsv=\"tg-axis\" style={`height:${bodyHeight}`}>\n {model.slots.map((slot) => (\n <div data-rsv=\"tg-slot\" data-major={String(slot.isMajor)} key={slot.offsetMin}>\n <span data-rsv=\"tg-slot-label\">{slot.label}</span>\n </div>\n ))}\n </div>\n\n {model.columns.map((col) => (\n <div\n data-rsv=\"tg-col\"\n data-rsv-resource-id={col.row.resource.id}\n style={`height:${bodyHeight}`}\n key={col.row.resource.id}\n >\n {col.timedSegs.map((seg) => {\n const widthPct = 100 / seg.colCount;\n return (\n <div\n data-rsv=\"event\"\n data-all-day=\"false\"\n data-event-id={seg.event.id}\n role=\"button\"\n tabIndex={0}\n key={seg.event.id}\n style={\n `position:absolute;top:${seg.topPct}%;height:${seg.heightPct}%;` +\n `left:${seg.col * widthPct}%;width:${widthPct}%;` +\n `--rsv-event-bg:${seg.event.backgroundColor};--rsv-event-fg:${seg.event.textColor}`\n }\n onClick={(e) => {\n e.stopPropagation();\n api.trigger(\"eventClick\", { event: seg.event });\n }}\n >\n {dl.format(seg.event.start, \"HH:mm\")} {seg.event.title}\n </div>\n );\n })}\n {model.nowTopPct != null && (\n <div data-rsv=\"now-indicator\" style={`top:${model.nowTopPct}%`} />\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { dl, type CalendarApi, type ResourceDayGridModel } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\n\ninterface Props {\n api: CalendarApi;\n model: ResourceDayGridModel;\n options: ReserviCalendarOptions;\n}\n\n/** Recursos como columnas en cuadrícula de día (eventos apilados por recurso). */\nexport function ResourceDayGridView({ api, model }: Props): VNode {\n return (\n <div data-rsv=\"resource-daygrid\" style={`--rsv-rdg-cols:${model.columns.length}`}>\n <div data-rsv=\"rdg-header\" role=\"row\">\n {model.columns.map((col) => (\n <div data-rsv=\"rdg-col-header\" role=\"columnheader\" key={col.row.resource.id}>\n {col.row.resource.title}\n </div>\n ))}\n </div>\n <div data-rsv=\"rdg-body\" role=\"row\">\n {model.columns.map((col) => (\n <div\n data-rsv=\"rdg-col\"\n data-rsv-resource-id={col.row.resource.id}\n key={col.row.resource.id}\n >\n {col.events.map((event) => (\n <div\n data-rsv=\"event\"\n data-all-day={String(event.allDay)}\n data-event-id={event.id}\n role=\"button\"\n tabIndex={0}\n key={event.id}\n style={`--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor};--rsv-event-border:${event.borderColor}`}\n onClick={(e) => api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement })}\n >\n {event.allDay ? \"\" : dl.format(event.start, \"HH:mm\") + \" \"}\n {event.title}\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import {\n dl,\n getLocaleText,\n type CalendarApi,\n type ResourceDayGridMonthCell,\n type ResourceDayGridMonthModel,\n} from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport type { ReserviCalendarOptions } from \"../../types.js\";\n\ninterface Props {\n api: CalendarApi;\n model: ResourceDayGridMonthModel;\n options: ReserviCalendarOptions;\n}\n\n/** Vista mensual con recursos como columnas anidadas dentro de cada día. */\nexport function ResourceDayGridMonthView({ api, model, options }: Props): VNode {\n return (\n <div data-rsv=\"resource-daygrid-month\" style={`--rsv-rdgm-cols:${model.columnCount}`}>\n {model.weeks.map((week, wi) => (\n <div data-rsv=\"rdgm-week\" role=\"row\" key={`week-${wi}`}>\n {week.days.map((cell) => (\n <ResourceMonthCell\n api={api}\n cell={cell}\n options={options}\n key={dl.toISOString(cell.date)}\n />\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nfunction ResourceMonthCell({\n api,\n cell,\n options,\n}: {\n api: CalendarApi;\n cell: ResourceDayGridMonthCell;\n options: ReserviCalendarOptions;\n}): VNode {\n const dayNumber = dl.dayOfMonth(cell.date);\n return (\n <div\n data-rsv=\"day\"\n role=\"gridcell\"\n data-date={dl.toISOString(cell.date)}\n data-today={String(cell.isToday)}\n data-other={String(cell.isOther)}\n >\n <span data-rsv=\"day-number\">{dayNumber}</span>\n <div data-rsv=\"rdgm-columns\">\n {cell.columns.map((col) => (\n <div data-rsv=\"rdgm-col\" data-rsv-resource-id={col.row.resource.id} key={col.row.resource.id}>\n <span data-rsv=\"rdgm-col-label\">{col.row.resource.title}</span>\n {col.events.map((event) => {\n const selected = api.selectedEventIds.value.has(event.id);\n return (\n <div\n data-rsv=\"event\"\n data-all-day={String(event.allDay)}\n data-event-id={event.id}\n data-rsv-selected={String(selected)}\n role=\"button\"\n tabIndex={0}\n key={event.id}\n style={`--rsv-event-bg:${event.backgroundColor};--rsv-event-fg:${event.textColor};--rsv-event-border:${event.borderColor}`}\n onClick={(e) => {\n e.stopPropagation();\n if (e.ctrlKey || e.metaKey) {\n api.toggleEventSelection(event.id);\n return;\n }\n api.trigger(\"eventClick\", { event, el: e.currentTarget as HTMLElement });\n if (event.url) window.open(event.url, \"_self\");\n }}\n >\n {event.allDay ? \"\" : `${dl.format(event.start, \"HH:mm\")} `}\n {event.title}\n </div>\n );\n })}\n {col.moreCount > 0 && (\n <span\n data-rsv=\"rdgm-more\"\n onClick={(e) => {\n e.stopPropagation();\n api.trigger(\"moreLinkClick\", {\n date: cell.date,\n allEvents: [...col.events, ...col.hiddenEvents],\n hiddenEvents: col.hiddenEvents,\n });\n }}\n >\n {getLocaleText(options.locale).more(col.moreCount)}\n </span>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","// Importar @preact/signals activa el seguimiento automático de signals en los\n// componentes: leer `api.viewModel.value` re-renderiza de forma granular.\nimport \"@preact/signals\";\nimport { getLocaleText, themeToStyle, THEME_TOKEN_VARS, type CalendarApi } from \"@reservi/core\";\nimport type { VNode } from \"preact\";\nimport { useEffect, useRef } from \"preact/hooks\";\nimport type { ReserviCalendarOptions } from \"../types.js\";\nimport { cx } from \"../render/slots.js\";\nimport { pickResponsiveView } from \"../interaction/responsive.js\";\nimport { Toolbar } from \"./Toolbar.js\";\nimport { DayGridView } from \"../views/daygrid/DayGridView.js\";\nimport { TimeGridView } from \"../views/timegrid/TimeGridView.js\";\nimport { ListView } from \"../views/list/ListView.js\";\nimport { MultiMonthView } from \"../views/multimonth/MultiMonthView.js\";\nimport { TimelineView } from \"../views/timeline/TimelineView.js\";\nimport { ResourceTimelineView } from \"../views/resource/ResourceTimelineView.js\";\nimport { ResourceTimeGridView } from \"../views/resource/ResourceTimeGridView.js\";\nimport { ResourceDayGridView } from \"../views/resource/ResourceDayGridView.js\";\nimport { ResourceDayGridMonthView } from \"../views/resource/ResourceDayGridMonthView.js\";\n\ninterface CalendarProps {\n api: CalendarApi;\n options: ReserviCalendarOptions;\n}\n\n/** Componente raíz: lee el ViewModel reactivo y delega en la vista activa. */\nexport function Calendar({ api, options }: CalendarProps): VNode {\n const vm = api.viewModel.value; // reactivo (signals)\n const dir = options.direction ?? getLocaleText(options.locale).direction;\n const hourHeight = api.getEffectiveOption(\"hourHeight\", vm.type);\n const height = api.getEffectiveOption(\"height\", vm.type);\n const themeStyle =\n [\n options.themeTokens ? themeToStyle(options.themeTokens) : \"\",\n hourHeight ? `${THEME_TOKEN_VARS.slotHeight}:${hourHeight}px` : \"\",\n height != null && height !== \"auto\"\n ? `height:${typeof height === \"number\" ? `${height}px` : height}`\n : \"\",\n ]\n .filter(Boolean)\n .join(\";\") || undefined;\n\n const rootRef = useRef<HTMLDivElement>(null);\n\n // La CalendarApi expone `el` (como FullCalendar) para que el anfitrion pueda\n // aplicar clases o medir el contenedor.\n useEffect(() => {\n api.setRootEl(rootRef.current);\n return () => api.setRootEl(null);\n }, [api]);\n // Ref para leer siempre el `responsiveViews` más reciente sin re-crear el\n // ResizeObserver en cada render (solo se monta una vez por instancia de `api`).\n const responsiveViewsRef = useRef(options.responsiveViews);\n responsiveViewsRef.current = options.responsiveViews;\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root || typeof ResizeObserver === \"undefined\") return;\n let frame = 0;\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0];\n const width = entry?.contentRect.width ?? root.clientWidth;\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(() => {\n const config = responsiveViewsRef.current;\n if (!config?.length) return;\n const next = pickResponsiveView(config, width);\n if (next && next !== api.getView().type && api.hasView(next)) api.changeView(next);\n });\n });\n observer.observe(root);\n return () => {\n cancelAnimationFrame(frame);\n observer.disconnect();\n };\n }, [api]);\n\n return (\n <div\n ref={rootRef}\n data-rsv=\"root\"\n dir={dir}\n data-rsv-theme={options.theme}\n data-rsv-autoheight={height === \"auto\" ? \"true\" : undefined}\n style={themeStyle}\n class={cx(options.classNames?.root)}\n >\n {options.headerToolbar !== false && (\n <Toolbar api={api} title={vm.title} activeView={vm.type} options={options} />\n )}\n <div data-rsv=\"view\" data-view={vm.type}>\n {vm.dayGrid ? (\n <DayGridView api={api} model={vm.dayGrid} options={options} />\n ) : vm.timeGrid ? (\n <TimeGridView api={api} model={vm.timeGrid} options={options} />\n ) : vm.list ? (\n <ListView api={api} model={vm.list} options={options} />\n ) : vm.multiMonth ? (\n <MultiMonthView api={api} model={vm.multiMonth} options={options} />\n ) : vm.resourceTimeGrid ? (\n <ResourceTimeGridView api={api} model={vm.resourceTimeGrid} options={options} />\n ) : vm.resourceDayGrid ? (\n <ResourceDayGridView api={api} model={vm.resourceDayGrid} options={options} />\n ) : vm.resourceDayGridMonth ? (\n <ResourceDayGridMonthView api={api} model={vm.resourceDayGridMonth} options={options} />\n ) : vm.resourceTimeline ? (\n <ResourceTimelineView api={api} model={vm.resourceTimeline} options={options} />\n ) : vm.timeline ? (\n <TimelineView api={api} model={vm.timeline} options={options} />\n ) : (\n <div data-rsv=\"unsupported\">\n La vista \"{vm.type}\" se implementa en una fase posterior.\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { h, render } from \"preact\";\nimport { CalendarApi } from \"@reservi/core\";\nimport { Calendar } from \"./components/Calendar.js\";\nimport type { ReserviCalendarOptions } from \"./types.js\";\n\nexport interface ReserviCalendarHandle {\n /** API del calendario (navegación, eventos, callbacks). */\n readonly api: CalendarApi;\n /** Desmonta el calendario y libera recursos. */\n destroy(): void;\n}\n\n/**\n * Monta un calendario Reservi en un elemento del DOM. API agnóstica usada\n * directamente (vanilla/Preact) y por los wrappers de framework.\n */\nexport function mount(el: HTMLElement, options: ReserviCalendarOptions): ReserviCalendarHandle {\n const api = new CalendarApi(options);\n render(h(Calendar, { api, options }), el);\n\n return {\n api,\n destroy() {\n render(null, el);\n api.destroy();\n },\n };\n}\n","import { eventsToICS, type EventInput } from \"@reservi/core\";\n\n/**\n * Exporta eventos a un archivo `.ics` y dispara la descarga en el navegador.\n * Capa de UI (usa DOM); la serialización pura vive en `@reservi/core`.\n */\nexport function downloadICS(events: EventInput[], filename = \"calendar.ics\"): void {\n if (typeof document === \"undefined\") return;\n const ics = eventsToICS(events);\n const blob = new Blob([ics], { type: \"text/calendar;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(url);\n}\n\nexport { parseICS, eventsToICS } from \"@reservi/core\";\n"],"names":["hostSlot","node","isHostSlot","value","renderSlot","slot","arg","fallback","bridge","result","jsx","HostSlotOutlet","hostSeq","idRef","useRef","elRef","nodeRef","liveRef","useLayoutEffect","el","id","cx","classes","notified","callDidMount","hook","buildArg","html","pickResponsiveView","entries","width","sorted","a","b","chosen","entry","NAV_SYMBOLS","NON_VIEW_TOKENS","MONTH_VIEW_RE","pad2","n","CalendarIcon","jsxs","resolveViews","options","_a","tb","s","g","t","Toolbar","api","title","activeView","text","getLocaleText","startSlot","_b","endSlot","_d","_c","views","monthMode","firstDay","wrapRef","open","setOpen","useState","selected","dl","nowRef","viewYear","setViewYear","viewMonth","setViewMonth","monthShortFmt","monthLongFmt","dowFmt","monthNames","_","i","openPicker","d","shiftMonth","delta","total","goto","iso","useEffect","onKey","e","onPointer","dayGrid","first","offset","start","cells","dows","_e","y","label","v","minutesToLabel","minutes","minutesToTimeString","m","timeFormatter","locale","fmt","date","dateFormatter","navLinkToDay","target","DAY","DEFAULT_SHORTCUTS","resolveAction","key","shortcuts","action","defaultKeys","handleEventKeydown","opts","event","kind","snapMin","timeStringToMinutes","deltaMin","next","computeDrop","updated","THRESHOLD","dateAtPoint","x","startDayGridEventDrag","ev","sourceDate","startX","startY","dragging","onMove","onUp","deltaDays","startDayRangeSelect","endStr","moved","lo","hi","DayGridView","model","view","headerDays","showWeekNums","cell","headerArg","week","wi","DayCell","dayNumber","defaultNumber","cellArg","numberNode","moreOpen","setMoreOpen","dateStr","rangeSelectedRef","onDayClick","openMore","EventChip","DayMorePopover","onClose","ref","dayFmt","allEvents","editable","draggedRef","eventFmt","timeText","contentArg","content","EDGE_PX","MAX_SPEED_PX","NOOP_SCROLLER","startAutoScroll","container","lastY","scrolled","raf","tick","rect","before","clientY","scrollAncestor","startEventDrag","columnEl","snap","edge","totalMinutes","ppm","scroller","pxToSnappedMinutes","computeResize","startTimeRangeSelect","yToMin","raw","clamped","startMin","endMin","dayStart","TimeGridView","headerFmt","slotFmt","showAllDay","bodyHeight","bodyRef","modelRef","preview","setPreview","body","adapter","time","span","top","scrollTime","inner","outer","minutesAtPointer","colEl","snapped","axisDay","labelArg","dayIndex","range","Fragment","seg","TimedEvent","widthPct","getColumn","ListView","daySideFmt","day","MultiMonthView","monthFmt","month","LANE_REM","TimelineView","TimelineEvent","ResourceTimelineView","lane","rowHeight","ResourceTimeGridView","col","ResourceDayGridView","ResourceDayGridMonthView","ResourceMonthCell","Calendar","vm","dir","hourHeight","height","themeStyle","themeToStyle","THEME_TOKEN_VARS","rootRef","responsiveViewsRef","root","frame","observer","config","mount","CalendarApi","render","h","downloadICS","events","filename","ics","eventsToICS","blob","url"],"mappings":"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"}
|