twinrange-calender
v1.5.0
Published
A fully customized, self-built date range SDK for ReactJS, React Native, and TypeScript. Built by Pradeep Kumar Sheoran (Developer) at BSG Technologies.
Maintainers
Keywords
Readme
TwinRangeCalender
TwinRangeCalender is a fully customized, self-built ReactJS, React Native, and TypeScript SDK for date range selection. ReactJS gets ready-made web components. React Native gets the same custom-owned headless date/range engine so you can render native View, Text, and Pressable UI in your own mobile design.
Built by Pradeep Kumar Sheoran (Developer) at BSG Technologies.
Official website: https://bsgtechnologies.com
Visit here to meet, learn, contribute, and discuss new topics with us.
Contact: +91-8595147850 (also WhatsApp)
Donation / support UPI: +91-8595147850
Custom-Owned SDK
This package does not wrap another calendar/date-picker library. The date helpers, range selection logic, keyboard handling, theming system, rendering hooks, presets, and UI components are owned source code in this SDK. React, ReactDOM, and React Native are peer dependencies only. ReactDOM is used for web apps, while React Native can use the twinrange-calender/native export without importing DOM components or CSS.
Features
- Dual-calendar date range picker with responsive single-column mobile layout
- Inline calendar and popover date-picker modes
- Controlled and uncontrolled state support
- Range and single-date selection flows
- Custom labels for buttons, ARIA text, and input placeholder
- Configurable months, initial month, locale, RTL, and week start day
- Min/max date limits, disabled dates, available dates, and callback-based rules
- Presets for quick ranges like today, this week, this month, or custom ranges
- Custom day renderer with metadata for price, events, availability, badges, and business rules
- Theme tokens for colors, radius, spacing, day size, weekend color, and selected state
- Keyboard navigation for arrow keys, page navigation, home/end, enter, space, and escape
- TypeScript exports for props, range shape, theme, presets, and render contracts
- React 18+ compatible and ready for modern React 19 applications
- React Native compatible through a headless
./nativeexport - Multiple-date selection with
mode="multiple" - Time-slot and time-range helpers for hourly booking
- Built-in theme packs, holiday helpers, form adapters, and ISO payload utilities
- Timezone-safe serialization, recurring rules, pricing/inventory, plugins, and server utilities
Install
npm install twinrange-calenderImport the stylesheet once:
import "twinrange-calender/styles.css";Quickstart
import { useState } from "react";
import { TwinRangeCalendar, type DateRange } from "twinrange-calender";
import "twinrange-calender/styles.css";
export default function BookingPage() {
const [range, setRange] = useState<DateRange>({ startDate: null, endDate: null });
return (
<TwinRangeCalendar
value={range}
onChange={setRange}
months={2}
minDate={new Date()}
showPresets
labels={{
apply: "Confirm dates",
clear: "Reset",
selectedRange: "Trip dates"
}}
/>
);
}Date Picker Example
import { TwinRangeDatePicker, addDays, type DateRange } from "twinrange-calender";
import "twinrange-calender/styles.css";
export function HotelSearch({ value, onChange }: { value: DateRange; onChange: (range: DateRange) => void }) {
return (
<TwinRangeDatePicker
value={value}
onChange={onChange}
minDate={new Date()}
maxDate={addDays(new Date(), 365)}
showPresets
placeholder="Check-in - Check-out"
labels={{
inputPlaceholder: "Select travel dates",
apply: "Apply stay",
cancel: "Close"
}}
/>
);
}React Native
Use twinrange-calender/native in React Native. This export avoids DOM elements and CSS.
import { Pressable, Text, View } from "react-native";
import { useTwinRangeEngine } from "twinrange-calender/native";
export function NativeBookingCalendar() {
const calendar = useTwinRangeEngine({
months: 1,
minDate: new Date(),
allowOneWaySelection: false
});
return (
<View>
{calendar.months.map((month) => (
<View key={month.label}>
<Text>{month.label}</Text>
<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{month.days.map((day) => (
<Pressable key={day.key} disabled={day.isDisabled} onPress={day.select} style={{ width: "14.28%", padding: 8 }}>
<Text>{day.date.getDate()}</Text>
</Pressable>
))}
</View>
</View>
))}
</View>
);
}More details: React Native guide.
Advanced Modules
Granular imports are available for apps that want only the custom engine:
import { createAdvancedPresets, createIndiaHolidayList, generateTimeSlots } from "twinrange-calender/core";
import { createFormikAdapter, toIsoDateRange } from "twinrange-calender/adapters";
import { getTwinRangeTheme } from "twinrange-calender/themes";Useful advanced features:
mode="multiple"for event calendars and multi-day selectionsuseTimeRangeandgenerateTimeSlotsfor hourly bookingcreateAdvancedPresetsfor financial year, quarter, weekend, month, and week presetscreateIndiaHolidayListandcreateHolidayDisabledMatcherfor holiday blockingtwinRangeThemesandgetTwinRangeThemefor hotel, travel, admin, and dark themestoIsoDateRange,createReactHookFormAdapter, andcreateFormikAdapterfor forms and APIsserializeDateRange,createRecurringMatcher,validateRangeConstraints, andcalculateRangePricefor booking engines
Business Rules and Server Utilities
import {
calculateRangePrice,
createInventoryMap,
createRecurringMatcher,
minStayPlugin,
runCalendarPlugins,
serializeDateRange,
validateBookingPayload
} from "twinrange-calender/core";
const payload = serializeDateRange(range, "utc");
const validation = runCalendarPlugins([minStayPlugin(2)], range);
const price = calculateRangePrice(range, inventory);
const bookingCheck = validateBookingPayload(range, { minNights: 2 }, inventory);Customization
<TwinRangeCalendar
months={2}
weekStartsOn={1}
locale="en-IN"
allowSameDayRange={false}
allowOneWaySelection={false}
theme={{
fontFamily: "Inter, Arial, sans-serif",
primaryColor: "#0f766e",
rangeColor: "#ccfbf1",
rangeHoverColor: "#99f6e4",
startDateColor: "#0f766e",
endDateColor: "#0f766e",
selectedTextColor: "#ffffff",
todayBorderColor: "#f59e0b",
weekendTextColor: "#dc2626",
borderRadius: "10px",
daySize: 42,
spacing: 8
}}
disabledDates={[new Date("2026-08-15")]}
dateMetadata={{
"2026-08-10": { price: 2499, status: "Best price" }
}}
renderDay={(day) => (
<span>
{day.date.getDate()}
{typeof day.metadata === "object" && day.metadata ? <small>Deal</small> : null}
</span>
)}
/>Live Demo
- Live demo source: examples/live-demo.tsx
- React Native example: examples/native-calendar.example.tsx
- Time range example: examples/time-range.example.tsx
- Form adapters example: examples/form-adapters.example.tsx
- Basic usage: examples/basic.example.tsx
- Booking flow: examples/booking-calendar.example.tsx
- Custom theme: examples/custom-theme.example.tsx
- Custom day renderer: examples/custom-day-renderer.example.tsx
- Reports filter: examples/reports-filter.example.tsx
Use any React setup:
import { createRoot } from "react-dom/client";
import { TwinRangeLiveDemo } from "./examples/live-demo";
createRoot(document.getElementById("root")!).render(<TwinRangeLiveDemo />);Documentation
- Implementation guide
- API reference / calling functions
- React Native guide
- Feature overview
- Response and payload guide
- Keywords and hashtags
- FAQ
- Support and donation
- Changelog
Publish Checklist
npm run typecheck
npm run build
npm run pack:dry
npm publishDeveloper Profile
- Developer: Pradeep Kumar Sheoran
- Company: BSG Technologies
- Looking for a job change: Reactjs, React Native, Android Java, Nodejs, TypeScript, custom packages, and scripts
- Contact / WhatsApp: +91-8595147850
- Website: https://bsgtechnologies.com
For feature requests, updates, improvements, or new ideas, leave a comment in your package discussion, issue tracker, or contribution channel.
