Skip to content

Utilities and hooks

All of these are exported from resource-scheduler. The pure functions among them (and the layout ones that are not on this page, such as layoutEvents and getRowHeights) are also exported without React from resource-scheduler/headless: see the Headless API.

  • isPlacementAllowed(event, placement, resources, rules) returns boolean. The same check the component runs. Works anywhere, so use it before saving on the server.
  • rangesOverlap(aStart, aEnd, bStart, bEnd) returns boolean. End times are exclusive; a zero-length range is one instant.
  • expandRecurrence(event, from, to) returns the occurrences of one event that touch from to to (end exclusive). A plain event comes back as is, or not at all when it is outside the window.
  • expandEvents(events, from, to) expands the recurring events in a list and passes the others through. See Recurring events.
  • splitRecurrence(event, occurrence, edits?) returns { before, after } for “edit this and following”: the series ended the day before (null when occurrence is the first one) and a new series from the occurrence with edits applied.
  • editOccurrence(event, occurrence, edits?) returns { series, changed } for “this occurrence only”: the series with an exception, and a one-off event for that day.
  • getRowWindow(heights, top, height, overscan?, offset?) returns { start, end }, the rows worth rendering for a scroll position (end exclusive). What row virtualization uses.
  • withEvents(resources, events?) returns Resource[]. Adds a flat event list to the resources it names, as the events prop does. Resources without an events array get an empty one.
  • isCellUnavailable(resource, cell, { businessHours, viewType, slotMinutes? }) returns boolean. Whether the slot (day view) or day (other views) starting at cell is shaded for that resource.
  • touchesUnavailable(resource, { start, end }, context) returns boolean. Whether a placement would touch a shaded cell. This is what blockUnavailable runs.
  • resolveBusinessHours(hours) returns the hours with the defaults filled in.
  • findAvailableSlots(resource | resources, { from, to, duration, step?, businessHours?, limit? }) returns { start, end }[], the free slots earliest first. With several resources, only times when all are free. See Business hours and availability.
  • suggestResources(resources, request, options?) returns { resourceId, start, end, score, utilization }[], the resources that can take a job, best first. request is a fixed time { start, end } or a window to search { from, to, duration, step? }, each with an optional event (the job). options are businessHours, resourceIds, eventOverlap, isValidDrop, strategy ("earliest", "least-booked", "most-booked" or a score function), limit and perResource. A placement is suggested only inside the resource’s hours and outside its unavailable time, with fewer bookings at once than its capacity, and when the placement rules accept it. See Suggest who takes a job.

Imported from resource-scheduler/exchange, not from the main entry point.

  • parseRRule(rrule, { start? }) reads the value of an iCalendar RRULE (FREQ=MONTHLY;BYDAY=-1FR) as a Recurrence, and toRRule(recurrence, { start?, allDay? }) writes one. Both throw a RangeError that names what they cannot read or write (see Export).
  • icsToEvents(text, { resources?, resourceId?, onWarning? }) reads the events of an iCalendar file into scheduler events: UTC, TZID (IANA) and floating times, all-day dates, RRULE/EXDATE, changed occurrences, and LOCATION matched to resources (resourceId for the rest). Cancelled events are left out, and a rule the scheduler cannot show is imported once with a message to onWarning. See Export and import.
  • eventsToICS(events, { resources?, name?, now? }) returns an iCalendar file as a string. Timed events in UTC, whole local days as all-day events, recurrence as RRULE and exceptions as EXDATE; resources writes the resource name as LOCATION.
  • eventsToCSV(events, { resources? }) returns id,title,resource,start,end,description as a CSV string, one row per resource of an event, with cells that start with =, +, - or @ defused against spreadsheet formulas. See Export.
  • getUtilization(resource, { start, end }, { businessHours? }) returns { bookedMinutes, availableMinutes, ratio }. Booked time inside the available time (business hours minus unavailable, times capacity) over a range (end exclusive); ratio is null when nothing is available. What showUtilization draws. See Utilization.
  • columnUtilization(resources, columns, { businessHours? }) adds up the utilization of several resources for each of columns (ranges in order, end exclusive) and returns one { bookedMinutes, availableMinutes, ratio } per column. What showColumnUtilization draws.
  • groupUtilization(resources, { start, end }, { businessHours? }) returns a Map from a group header’s id ("rs-group:" + the group's key) to the same { bookedMinutes, availableMinutes, ratio }, summed over every resource below the group, nested ones included. What a group header shows. See Resource groups.

What you apply the reorder callbacks with. Both are pure, return a new array in the order it is shown, and return the array you passed in when nothing would change or a key or id is unknown.

  • reorderGroup(resources, groupKey, beforeGroupKey) moves a group, with all its resources and nested groups, to just before the sibling group beforeGroupKey, or to the end of its siblings when that is null. A group only moves among the groups with the same parent. Keys are a group’s name, or its path joined with “ / “.
  • moveResource(resources, resourceId, beforeResourceId, group?) moves a resource to just before beforeResourceId, or to the end of its group when that is null. group is the key of the group it lands in: leave it out to keep its own, pass null for none. A resource that changes group is copied with its group set to that group’s path; passing its own id as beforeResourceId changes only the group.

The timeZone prop uses these; they are exported for your own conversions. See Time zones.

  • utcToZoned(date, timeZone) returns a Date whose local fields (getHours() and so on) are the wall-clock time in the zone at that instant, so format shows the zone’s time. It is not an instant: convert back before storing it.
  • zonedToUtc(date, timeZone) returns the instant at which a clock in the zone shows the local fields of date. A time a clock change skips gets the offset from before it; one that happens twice gets the first.
  • isValidTimeZone(name) says whether the browser knows an IANA zone name.
  • getTimeSlots(date, viewType, options?) returns the slots of the day view as Date[].
  • getDatesInView(date, viewType, viewOptions?) returns the days shown. viewOptions is { weekStartsOn?, hideWeekends? }.
  • getVisibleRange(date, viewType, options?) returns { start, end } for what the grid covers (end exclusive). options takes the slot and view options.
  • navigateDate(date, viewType, "prev" | "next")
  • resolveSlotOptions(options) returns sanitised slotMinutes, dayStartHour and dayEndHour, falling back to the defaults for invalid values.
  • getVisibleEvents(events, date, viewType, slotOptions?, viewOptions?)
  • getDropRange(event, slot, viewType), getResizeRange(event, edge, slot, viewType, slotMinutes?) and getSelectionBounds(a, b, viewType, slotMinutes?): the range arithmetic behind move, resize and select.
  • isSlotInRange(slot, range, viewType, slotMinutes?)
  • formatEventTime(event), formatSlotLabel(slot, viewType) and formatRangeLabel(start, end, viewType): the labels the component uses.
  • scrollToDate(date, viewType, scroller, timeColumnWidth, dateColumnWidth, stickyOffset?, slotOptions?, viewOptions?)
  • useScheduler, useEventCreation: the state hooks behind the component, for building your own layout.
  • ResourceColumn, SchedulerControls, TimelineHeader, TimelineGrid, EventItem, EmptySlotItem: the building blocks, exported for custom composition. Most apps only need ResourceScheduler.
  • useMediaQuery, useIsMobile, useHeadsObserver: small shared hooks.

These lower-level exports follow the same semver as the component, but the component is the supported surface. If you find yourself composing the parts, consider the shadcn install and edit the source instead.