0.2.4 โ€ข Published 1 month ago

@symbiot.dev/react-native-timegrid v0.2.4

Weekly downloads
-
License
MIT
Repository
github
Last release
1 month ago

A powerful and flexible time grid and calendar component for React Native, designed to work seamlessly across iOS, Android, Web, Expo, and Expo Go. Built for performance and customization, react-native-timegrid enables developers to implement rich, interactive calendar views for a wide range of scheduling and planning needs.


๐Ÿ“ฑ Demo


โœจ Key Features

๐Ÿ“† Time-Based Grid Layout โ€“ Intuitive hourly/daily layout ideal for agenda, schedule, or shift views.

๐ŸŽจ Fully Customizable โ€“ Modify headers, time slots, event appearance, and grid styling to fit any design system.

๐Ÿง  Lightweight โ€“ Minimal dependencies and optimized bundle size for faster load times and efficient performance.

๐Ÿš€ Cross-Platform Compatibility โ€“ Works out of the box with:

  • React Native CLI
  • Expo
  • Expo Go
  • React Native Web for browser support

โš™๏ธ Optimized Performance โ€“ Supports virtual scrolling and large datasets with smooth interactions.

โœ‹ Interactive Features โ€“ Tap, drag, and dynamic updates for real-time scheduling apps.

๐Ÿ“ฑ Responsive Design โ€“ Adapts to various screen sizes and device orientations.

๐Ÿงฉ Modular Integration โ€“ Use as a standalone calendar or integrate into more complex scheduling systems.


๐Ÿ›  Ideal For

  • ๐Ÿ“… Personal or team calendars
  • ๐Ÿ›Ž๏ธ Booking and reservation systems (salons, gyms, clinics)
  • ๐Ÿ‘ฅ Employee shift and availability planners
  • ๐Ÿ“† Event timeline visualizations
  • ๐Ÿง‘โ€๐Ÿซ Class schedules and academic timetables
  • ๐Ÿง  Task and time management tools
  • ๐Ÿฅ Appointment scheduling for healthcare or therapy
  • ๐Ÿ“ฆ Delivery or logistics scheduling
  • ๐Ÿ’ผ Project planning dashboards with time allocation
  • ๐Ÿ›  Maintenance or service job assignment trackers
  • ๐ŸŽ“ Student agendas or learning planners
  • ๐ŸŽค Conference session planners and expo booth schedules
  • ๐Ÿ”ฅ and more ...

Whether you're building a cross-platform scheduling app or integrating a responsive calendar view into an existing project, react-native-timegrid provides a modern, customizable, and performant solution for all major platforms.


๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ’ป Installation

npm install @symbiot.dev/react-native-timegrid react-native-reanimated react-native-gesture-handler date-fns
# or
yarn add @symbiot.dev/react-native-timegrid react-native-reanimated react-native-gesture-handler date-fns

# for web support
npm i react-native-web
# or
yarn add react-native-web

# to support recurring events
npm i rrule
# or
yarn add rrule
import { TimeGrid } from '@symbiot.dev/react-native-timegrid';

// ... and voilร  ๐Ÿ’ซ
<TimeGrid />

Just import it and boom โ€” youโ€™ve got a slick, cross-platform calendar view. Fast setup, full control, and zero headaches. ๐Ÿ’ช๐Ÿป๐Ÿ’ฅ


๐ŸŽจ TimeGridThemeProps โ€“ Theming & Appearance

Customize the look and feel of the TimeGrid with flexible styling options. You can define global styles, override them based on theme (light or dark), or combine both approaches.

๐Ÿงฉ Structure

The TimeGridThemeProps type supports three layers:

  1. Global Styling (applies to all schemes unless overridden)
  2. Per-scheme Overrides โ€“ Use light and dark keys to define specific values
  3. Theme Scheme Selector โ€“ Control active theme using scheme
type TimeGridThemeProps = TimeGridStyling & {
  scheme?: 'light' | 'dark'; // system default
  light?: TimeGridStyling;
  dark?: TimeGridStyling;
};

๐Ÿงฑ Available Styling Props

Prop NameDescriptioniOSAndroidWebDefault Value
backgroundColorMain background color of the grid viewโœ…โœ…โœ…light: #FFFFFF, dark: #000000
dayHeaderBackgroundColorBackground for the day-of-week header barโœ…โœ…โœ…light: #FFFFFF, dark: #000000
dayHeaderTextColorText color for day-of-week labelsโœ…โœ…โœ…light: #000000, dark: #FFFFFF
headerSafeAreaBackgroundColorBackground for top safe area (e.g., notch spacing)โœ…โœ…โœ…light: #FFFFFF, dark: #000000
allDayEventsSafeAreaBackgroundColorBackground for all-day events safe areaโœ…โœ…โœ…light: #FFFFFF, dark: #000000
allDayEventsSafeAreaTextColorText color for all-day events safe areaโœ…โœ…โœ…light: #000000, dark: #FFFFFF
timelineBackgroundColorBackground color for timeline columnโœ…โœ…โœ…light: #FFFFFF, dark: #000000
timelineTextColorText color for hour/time labelsโœ…โœ…โœ…light: #A9A9A9, dark: #A9A9A9
verticalLineColorColor of vertical time slot dividersโœ…โœ…โœ…light: #F1F1F1, dark: #303030
horizontalLineColorColor of horizontal grid linesโœ…โœ…โœ…light: #F1F1F1, dark: #303030
nowIndicatorColorColor of the โ€œnowโ€ line showing current timeโœ…โœ…โœ…#FF6F61
unavailableTimeBackgroundColorColor for visually marking unavailable time blocksโœ…โœ…โœ…light: #F1F1F170, dark: #30303070
dropZoneBackgroundColorBackground for areas that accept dragged eventsโœ…โœ…โœ…transparent
eventBackgroundColorDefault background for event blocksโœ…โœ…โœ…light: #D8E4F1, dark: #475867
eventTextColorText color used in event blocksโœ…โœ…โœ…light: #000000, dark: #FFFFFF
eventBorderColorBorder color for eventsโœ…โœ…โœ…light: #FFFFFF, dark: #000000
<TimeGrid
  //...
  theme={{
    backgroundColor: '#f0f0f0', // for light and dark mode
  }}
/>

// ----

<TimeGrid
  //...
  theme={{
    backgroundColor: '#f0f0f0', // only applies to light mode
    eventTextColor: '#323232', // only applies to dark mode
    dark: {
      backgroundColor: '#020202',
    },
    light: {
      eventTextColor: '#505050',
    }
  }}
/>

๐Ÿ“ TimeGridDimensionsProps โ€“ Layout & Dimensions

Control the physical dimensions of key areas inside the TimeGrid. All values are in pixels and optional โ€” sensible defaults are provided.

๐Ÿงฑ Available Dimension Props

Prop NameDescriptioniOSAndroidWebDefault Value
widthTimeGrid widthโœ…โœ…โœ…system
dayHeaderHeightHeight of the day header (weekday labels)โœ…โœ…โœ…50
allDayEventHeightHeight for all-day eventsโœ…โœ…โœ…25
timelineWidthWidth of the left-side timeline areaโœ…โœ…โœ…58
horizontalLineSizeHeight of horizontal divider linesโœ…โœ…โœ…0.5
nowIndicatorHeightThickness of the โ€œnowโ€ lineโœ…โœ…โœ…0.5
gridVerticalPaddingDefines the vertical spacing (top and bottom padding)โœ…โœ…โœ…0
eventBorderWidthWidth of the border around an event elementโœ…โœ…โœ…1
eventBorderRadiusRadius of the border corners for an event elementโœ…โœ…โœ…5
<TimeGrid
  //...
  timelineWidth={60}
/>

๐Ÿ“… TimeGridDatetimeProps โ€“ Date & Time Configuration

Set the visible time range, number of days, start date, timezone, and other calendar-related behaviors.
These props give you precise control over how the TimeGrid renders days and time slots.

๐Ÿงฑ Available Datetime Props

Prop NameDescriptioniOSAndroidWebDefault Value
startDateThe starting datetime for the visible grid (defaults to current date)โœ…โœ…โœ…new Date()
weekStartsOnDay the week starts on (0=Sun, 1=Mon, etc.)โœ…โœ…โœ…0 (Sunday)
hiddenDaysDays of the week to hide (e.g., [0, 6] to hide Sun & Sat)โœ…โœ…โœ…[]
numberOfDaysNumber of days to render in the viewโœ…โœ…โœ…1
timeFromStart of the visible time range (in minutes, e.g., 480 = 8:00 AM)โœ…โœ…โœ…0
timeToEnd of the visible time range (in minutes, e.g., 1200 = 8:00 PM)โœ…โœ…โœ…1440
timeIntervalMinutes between each horizontal time lineโœ…โœ…โœ…60
timeStepTime rounding when placing events (in minutes)โœ…โœ…โœ…15
minDateEarliest date to allow navigationโœ…โœ…โœ…โ€”
maxDateLatest date to allow navigationโœ…โœ…โœ…โ€”
timezoneTimezone name (e.g., 'America/New_York', '+02:00') for offset handlingโœ…โœ…โœ…local
<TimeGrid
  //...
  weekStartsOn={1} // starts on Monday
  numberOfDays={3}
  hiddenDays={[0, 6]} // exclude weekends (Sun,Sut)
/>

๐Ÿ—“๏ธ TimeGridEventsProps โ€“ Events, Rendering & Recurrence

Configure how events appear and behave inside the calendar. Supports custom colors, recurring events, readonly mode, and timezone-specific scheduling.

๐ŸŸฆ๐ŸŸจ Overlapping Events
Events that share time ranges are fully supported out-of-the-box.
The grid will automatically stack or split them side-by-side depending on layout space.

๐Ÿงฑ Available Event Props

Prop NameDescriptioniOSAndroidWebDefault Value
createEventDurationDuration (in minutes) to assign when user creates a new event.โœ…โœ…โœ…60
allDayEventsSafeAreaTextPlaceholder for all-day events safe areaโœ…โœ…โœ…All-day
eventsArray of TimeGridEvent to render inside the time gridโœ…โœ…โœ…[]

TimeGridEvent

Field NameDescriptionTypeRequiredDefault
idUnique identifier for the eventstringโœ…โ€”
startStart datetime of the eventDate \| string \| numberโœ…โ€”
endEnd datetime of the eventDate \| string \| numberโœ…โ€”
textEvent title or descriptionstringoptionaldatetime
backgroundColorOverride default event background colorstringoptionaltheme
textColorOverride text color inside the eventstringoptionaltheme
timezoneIANA timezone name for localized event handlingstringoptionalgrid-level
readonlyPrevent this event from being draggedbooleanoptionalfalse
rruleRRULE string (e.g., 'RRULE:FREQ=DAILY')stringoptionalโ€”

โ„น๏ธ Need help creating a recurrence rule?
Use the visual generator at rrule.js playground to quickly create and test valid RRULE strings.

<TimeGrid
  //...
  createEventDuration={30} // new created events equals 30 mins
  events={[
    //...
    {
      id: 'timestamp',
      start: '2025-04-25T18:00:00.500Z',
      end: '2025-04-25T19:00:00.800Z',
      backgroundColor: '#DDDDDD',
      textColor: '#000000',
      readonly: true // prevent from being dragged
    }
  ]}
/>

๐Ÿšซ TimeGridUnavailableTimeProps โ€“ Blocking Unavailable Times

Mark specific time ranges as unavailable โ€” either for a specific date or recurring on weekdays.
These periods can block event creation, display with a distinct background and could be used with a different combinations.

export type TimeGridUnavailableTime = {
  from: number; // in minutes (e.g. 480 = 8:00 AM)
  to: number;   // in minutes (e.g. 1020 = 5:00 PM)
  start?: Date | string;
  end?: Date | string;
} & (
  | {
  weekday?: Day;   // 0 (Sunday) to 6 (Saturday)
  date?: never;
}
  | {
  date?: Date | string;
  weekday?: never;
}
  );

export type TimeGridUnavailableTimeProps = {
  unavailableTime?: TimeGridUnavailableTime[];
};

๐Ÿงฑ Available Unavailable Time Props

Prop NameDescriptioniOSAndroidWebDefault Value
unavailableTimeArray of time rules (by weekday or specific date). Uses from/to in minutes; Priority: date, weekday;โœ…โœ…โœ…[]
<TimeGrid
  //...
  unavailableTime={[
    { from: 0, to: 480 } // everyday 00:00 (12:00 AM) -> 08:00 AM
  ]}
/>

// ----

<TimeGrid
  //...
  unavailableTime={[
    { from: 0, to: 480, start: '2025-04-25T18:00:00.500Z' } // daily, starting April 25
  ]}
/>

// ----

<TimeGrid
  //...
  unavailableTime={[
    { from: 0, to: 480, start: '2025-04-25T00:00:00.500Z', end: '2025-04-26T00:00:00.500Z' } // only 2 days - April 25 and 26
  ]}
/>

// ----
// Priority behaviour

<TimeGrid
  //...
  unavailableTime={[
    { from: 0, to: 480 }, // daily
    { from: 1020, to: 1440, weekday: 1 }, // ignore the first element of the array and apply every Monday
    { from: 480, to: 900, date: '2025-04-28T18:00:00.500Z' } // ignore the first and second rules for Monday, April 28th
  ]}
/>

// ----
// Save behaviour

<TimeGrid
  //...
  unavailableTime={[
    { from: 0, to: 480 }, // daily
    { from: 0, to: 480, date: '2025-04-28T18:00:00.500Z' }, // save the daily rule for April 28
    { from: 480, to: 900, date: '2025-04-28T18:00:00.500Z' } // ignore the first and second rules for Monday, April 28th
  ]}
/>

๐ŸŽฎ TimeGridControllerProps โ€“ Interaction & Display Toggles

Control user interaction features like swiping, dragging, snapping, and visibility of UI components like the timeline, all-day events etc.

๐Ÿงฑ Available Controller Props

Prop NameDescriptioniOSAndroidWebDefault Value
lazyEnable to improve performance on the slow devicesโœ…โœ…โœ…true
swipeableEnable swiping between days or weeksโœ…โœ…โœ…false
snappableSnap scroll/drag to the nearest dateโœ…โœ…โœ…false
draggableAllow dragging events to create/reschedule themโœ…โœ…โœ…true
debounceableDelays date change handler to avoid rapid successive triggers.โœ…โœ…โœ…false
rtlEnable right-to-left layout (for RTL languages)โœ…โœ…โœ…false
isDayHeaderVisibleToggle visibility of the top day-of-week headerโœ…โœ…โœ…true
isTimelineVisibleToggle visibility of the left-side timelineโœ…โœ…โœ…true
isNowIndicatorVisibleShow/hide the "now" indicator lineโœ…โœ…โœ…true
isAllDayEventsEnabledEnable support for all-day eventsโœ…โœ…โœ…true
isAllDayEventsVisibleToggle visibility of the all-day eventsโœ…โœ…โœ…true
<TimeGrid
  //...
  swipeable // swipe actions turned on
  draggable // user can drag events
  snappable // date snapping enabled
/>

โฑ TimeGridFormatterProps โ€“ Text Formatting

Customize how dates and times appear within the TimeGrid component using format strings (e.g., dd, HH:mm, EEE).
These follow date-fns formatting syntax.

๐Ÿงฑ Available Formatter Props

Prop NameDescriptioniOSAndroidWebDefault Value
dayHeaderTextFormatFormat for the day header labels (e.g., Mon, Apr 20)โœ…โœ…โœ…EEEEEE dd
timelineTextFormatFormat for the left-side time labels (e.g., 08:00)โœ…โœ…โœ…p
localeLocale object from date-fns for internationalized formattingโœ…โœ…โœ…en
import { zhCN } from 'date-fns/locale/zh-CN';

<TimeGrid
  //...
  locale={zhCN} // Chinese localization
/>

๐ŸŽฏ TimeGridActionsProps โ€“ User Interaction Callbacks

Listen and respond to interactions like taps, long presses, event edits, and grid context menus.

๐Ÿงฑ Available Action Callbacks

Prop NameDescriptioniOSAndroidWeb
onChangeDateCalled when the grid's date range changesโœ…โœ…โœ…
onHeaderSafeAreaPressTriggered when the top header area is tappedโœ…โœ…โœ…
onAllDayEventsSafeAreaPressTriggered when the all-day events header area is tappedโœ…โœ…โœ…
onDayHeaderPressCalled when a specific day header is pressedโœ…โœ…โœ…
onLoadCalled once the grid is initialized and readyโœ…โœ…โœ…
onUnavailableTimePressFired on tap inside an unavailable time blockโœ…โœ…โœ…
onUnavailableTimeLongPressFired on long press inside an unavailable time blockโœ…โœ…โœ…
onDatetimeContextMenuRight-click/context menu trigger at specific date/time (with x/y coords)๐Ÿšซ๐Ÿšซโœ…
onDatetimePressTriggered on a tap inside an available time cellโœ…โœ…โœ…
onDatetimeLongPressTriggered on long press inside an available time cellโœ…โœ…โœ…
onEventPressCalled when an event is tappedโœ…โœ…โœ…
onEventLongPressCalled when an event is long-pressedโœ…โœ…โœ…
onEventUpdatedTriggered when an event is changed (drag); return false to keep updating, reject to cancelโœ…โœ…โœ…
onEventCreatedTriggered when a new event is created by the userโœ…โœ…โœ…
import { useState } from 'react';

const [selectedDate, setSelectedDate] = useState(new Date());

<TimeGrid
  //...
  onChangeDate={setSelectedDate} // selectedDate updated
/>

๐Ÿ”ง TimeGridRef โ€“ Imperative Control API

Control and interact with the TimeGrid instance programmatically using a React ref.
Great for custom toolbars, buttons, or dynamic navigation.

๐Ÿงฑ Available Ref Methods

MethodDescriptionReturns
getPrevDate()Returns the previous valid date range (optionally ignoring minDate/maxDate)Date \| undefined
getNextDate()Returns the next valid date range (optionally ignoring minDate/maxDate)Date \| undefined
prevDate()Navigate to the previous available datevoid
nextDate()Navigate to the next available datevoid
back()Navigate backward through a specified number of days (numberOfDays)void
forward()Navigate forward through a specified number of days (numberOfDays)void
toDatetime()Scroll or jump to a specific date/timevoid
createEvent()Programmatically create a new event at a given datetimevoid
import { useRef } from 'react';
import { TimeGrid, TimeGridRef } from '@symbiot.dev/react-native-timegrid';

const timeGridRef = useRef<TimeGridRef>(null);

<TimeGrid
  //...
  ref={timeGridRef}
  onDatetimeLongPress={(params) => timeGridRef.current?.createEvent(params)}
/>

๐ŸŒ Platform Support

  • โœ… iOS
  • โœ… Android
  • โœ… Web
  • โœ… Expo & Expo Go

๐Ÿ“ฆ Bundle Size

Lightweight and fast โ€” see actual size on Bundlephobia.


๐Ÿ’ฌ Contributing

Contributions welcome! Feel free to open issues, discussions, or suggestions.


๐ŸŒŸ Who's Using This?

Using react-native-timegrid in your app or product?
Feel free to share your project โ€” it might be featured in this section!

โœ‰๏ธ Open pull request, or reach out directly to get included.


๐Ÿš€ Got Ideas or Gaps to Fill?

Know of existing libraries or functionality that could be improved?
Have an idea for something completely new?

Symbiot is ready to take on the challenge โ€” feedback, feature requests, or collaboration ideas are always welcome!

๐Ÿง  Letโ€™s build better tools together. Start the conversation or contact via email.


๐Ÿงพ License

MIT โ€” Made with โค๏ธ by Symbiot