@widgetkit/booking-react@widgetkit/booking-vue

Booking

A date and time slot picker with a month calendar view, day slots view, and three flexible layout modes. Pass your availability data and receive a typed selection — no state management required.

Introduction

BookingScheduler renders a calendar for date selection and a time slot list for hour picking. Switch between three modes — side-by-side, calendar only, or slots only — and toggle price and duration display with boolean props.

Mode
Display
April 2026
Mo
Tu
We
Th
Fr
Sa
Su

Getting started

Install the package from npm:

npm install @widgetkit/booking-react
# or
pnpm add @widgetkit/booking-react

Import the component and its stylesheet:

import { BookingScheduler } from "@widgetkit/booking-react";
import "@widgetkit/booking-react/styles.css";

Pass availability — the only required prop. Use onSelect to receive the user's selection:

import { useState } from "react";
import { BookingScheduler } from "@widgetkit/booking-react";
import "@widgetkit/booking-react/styles.css";
import type { AvailabilityDay, BookingSelection } from "@widgetkit/booking-react";

const availability: AvailabilityDay[] = [
  {
    date: "2024-06-10",
    available: true,
    price: "€40",
    slots: [
      { time: "09:00", available: true,  duration: 60, price: "€40" },
      { time: "10:00", available: true,  duration: 60, price: "€40" },
      { time: "11:00", available: false, duration: 60 },
      { time: "14:00", available: true,  duration: 90, price: "€55" },
    ],
  },
];

export function App() {
  const [selection, setSelection] = useState<BookingSelection | null>(null);

  return (
    <BookingScheduler
      availability={availability}
      onSelect={setSelection}
    />
  );
}

Month + Day

The default mode. The calendar and time slot list are shown side by side — the user first picks a date, then a time slot. On narrow viewports they stack vertically.

April 2026
Mo
Tu
We
Th
Fr
Sa
Su
import { useState } from "react";
import { BookingScheduler } from "@widgetkit/booking-react";
import "@widgetkit/booking-react/styles.css";
import type { AvailabilityDay, BookingSelection } from "@widgetkit/booking-react";

// availability comes from your API
const availability: AvailabilityDay[] = [...];

export function App() {
  const [selection, setSelection] = useState<BookingSelection | null>(null);

  return (
    <BookingScheduler
      availability={availability}
      onSelect={setSelection}
    />
  );
}

Month only

Shows the calendar without any time slot step. Useful for date-only bookings, event registrations, or when you handle time selection in a separate step. onSelect fires with date and duration: 0 — no time field.

April 2026
Mo
Tu
We
Th
Fr
Sa
Su
// Calendar-only — user picks a date, no time slot step
<BookingScheduler
  availability={availability}
  mode="month-only"
  onSelect={(s) => console.log("Date:", s.date)}
/>

Day only

Shows only the time slot list for a specific day. Use this when the date is already known — for example inside a calendar cell, a resource detail panel, or a multi-step flow where the date was chosen in a previous step. Control which day is shown via the date prop.

Friday, 3. April
// Time slots only — pass date to control which day is shown
<BookingScheduler
  availability={availability}
  mode="day-only"
  date={new Date("2024-06-10")}
  onSelect={(s) => console.log("Slot:", s.time, "·", s.duration, "min")}
/>

Generate slots

generateSlots is a utility exported from all three packages. Give it one or more time windows and a duration — it returns a list of AvailabilitySlot objects ready to drop into an AvailabilityDay. Use it server-side to build your availability array from your calendar or booking rules.

import { generateSlots } from "@widgetkit/booking-react";
// also available from "@widgetkit/booking-vue" or "@widgetkit/booking"

// Two availability windows: 09:00–12:00 and 13:00–17:00
// 60-minute slots, 30-minute intervals
const slots = generateSlots(
  [
    { from: "09:00", to: "12:00" },
    { from: "13:00", to: "17:00" },
  ],
  60,  // duration in minutes
  30,  // interval (optional — defaults to duration)
);

// Each slot starts within a window and its full duration fits before the window ends.
// [
//   { time: "09:00", available: true, duration: 60 },
//   { time: "09:30", available: true, duration: 60 },
//   { time: "10:00", available: true, duration: 60 },
//   { time: "10:30", available: true, duration: 60 },
//   { time: "11:00", available: true, duration: 60 },
//   { time: "13:00", available: true, duration: 60 },
//   ...
// ]

Props

All props except availability are optional. Props marked * are required.

PropTypeDefaultDescription
Data
availability*AvailabilityDay[]Array of days defining which dates and time slots are bookable
Mode
mode"month-day" | "month-only" | "day-only""month-day"Layout — calendar + slots side by side, calendar only, or slots only
dateDateDay to display in day-only mode
initialMonthDatecurrent monthMonth shown on first render
minDateDateEarliest selectable date
maxDateDateLatest selectable date
Display
showPricebooleantrueShow price label on day cells and slot rows
showDurationbooleantrueShow duration label inside slot rows
Callbacks
onSelect(selection: BookingSelection) => voidCalled when a date (month-only) or time slot is confirmed

TypeScript types

All types are exported from both @widgetkit/booking-react and @widgetkit/booking-vue. The @widgetkit/booking core package also exports them if you need them framework-agnostically.

import type {
  AvailabilityDay,
  AvailabilitySlot,
  BookingMode,
  BookingSelection,
  TimeWindow,
} from "@widgetkit/booking-react";
type BookingMode = "month-day" | "month-only" | "day-only";

interface AvailabilitySlot {
  time:       string;           // "HH:mm"
  available:  boolean;
  duration?:  number;           // minutes
  price?:     number | string;
}

interface AvailabilityDay {
  date:      string;            // "YYYY-MM-DD"
  available: boolean;
  price?:    number | string;
  slots?:    AvailabilitySlot[];
}

// Returned by onSelect / emitted by @select
interface BookingSelection {
  date:     string;             // "YYYY-MM-DD" — always present
  time?:    string;             // "HH:mm" — absent in month-only mode
  duration: number;             // minutes
}

// Used with generateSlots()
interface TimeWindow {
  from: string;                 // "HH:mm"
  to:   string;                 // "HH:mm"
}