
Product
Introducing Socket Firewall Enterprise: Flexible, Configurable Protection for Modern Package Ecosystems
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.
@acusti/date-picker
Advanced tools
React component that renders a date picker with support for date ranges
A comprehensive React date picker library with support for single date selection, date ranges, and two-up month calendar views. Built with accessibility and user experience in mind, featuring smooth navigation, intelligent date range handling, and customizable styling.
npm install @acusti/date-picker
# or
yarn add @acusti/date-picker
import { DatePicker } from '@acusti/date-picker';
import { useState } from 'react';
// Simple single date picker
function SimpleDatePicker() {
const [selectedDate, setSelectedDate] = useState('');
return (
<DatePicker
onChange={({ dateStart }) => setSelectedDate(dateStart)}
dateStart={selectedDate}
/>
);
}
// Date range picker
function DateRangePicker() {
const [dateRange, setDateRange] = useState({ start: '', end: '' });
const handleChange = ({ dateStart, dateEnd }) => {
setDateRange({ start: dateStart, end: dateEnd || '' });
};
return (
<DatePicker
isRange
isTwoUp
onChange={handleChange}
dateStart={dateRange.start}
dateEnd={dateRange.end}
useMonthAbbreviations
/>
);
}
type Props = {
/** Additional CSS class name for styling */
className?: string;
/** End date for range selection (Date object, ISO string, timestamp, or null) */
dateEnd?: Date | string | number | null;
/** Start date for single or range selection (Date object, ISO string, timestamp, or null) */
dateStart?: Date | string | number | null;
/** Initial month to display (number of months since January 1970) */
initialMonth?: number;
/** Enable date range selection mode */
isRange?: boolean;
/** Display two months side-by-side */
isTwoUp?: boolean;
/** Earliest month that can be navigated to */
monthLimitFirst?: number;
/** Latest month that can be navigated to */
monthLimitLast?: number;
/** Callback when dates are selected */
onChange: (payload: {
dateEnd?: string | null;
dateStart: string;
}) => void;
/** Show end date’s month initially (when both start and end dates exist) */
showEndInitially?: boolean;
/** Use abbreviated month names (Jan, Feb, etc.) */
useMonthAbbreviations?: boolean;
};
For advanced use cases, you can use the individual month calendar:
import { MonthCalendar } from '@acusti/date-picker';
type MonthCalendarProps = {
className?: string;
dateEnd?: Date | string | number | null;
dateEndPreview?: string | null;
dateStart?: Date | string | number | null;
isRange?: boolean;
month: number; // Months since January 1970
onChange?: (date: string) => void;
onChangeEndPreview?: (date: string) => void;
title?: string;
};
import {
getMonthFromDate,
getYearFromMonth,
getMonthNameFromMonth,
getMonthAbbreviationFromMonth,
} from '@acusti/date-picker';
// Convert Date to month number (months since Jan 1970)
const monthNumber = getMonthFromDate(new Date());
// Convert month number to calendar year
const year = getYearFromMonth(monthNumber);
// Get full month name
const monthName = getMonthNameFromMonth(monthNumber); // "January"
// Get abbreviated month name
const monthAbbr = getMonthAbbreviationFromMonth(monthNumber); // "Jan"
import { DatePicker } from '@acusti/date-picker';
import { useState } from 'react';
function BookingDatePicker() {
const [checkIn, setCheckIn] = useState('');
const [checkOut, setCheckOut] = useState('');
const isValid = checkIn && checkOut;
// Limit to next 12 months only
const today = new Date();
const monthLimitFirst = getMonthFromDate(today);
const monthLimitLast = monthLimitFirst + 12;
return (
<div className="booking-date-picker">
<h3>Select Your Stay</h3>
<DatePicker
className="booking-date-picker-story"
isRange
isTwoUp
monthLimitFirst={monthLimitFirst}
monthLimitLast={monthLimitLast}
onChange={({ dateStart, dateEnd }) => {
setCheckIn(dateStart);
setCheckOut(dateEnd ?? '');
}}
dateStart={checkIn}
dateEnd={checkOut}
useMonthAbbreviations
/>
{isValid ? (
<div
className="booking-summary"
style={{
marginTop: '16px',
padding: '16px',
border: '1px solid #e1e5e9',
borderRadius: '8px',
backgroundColor: '#f8f9fa',
}}
>
<p>
<strong>Check-in:</strong>{' '}
{new Date(checkIn).toLocaleDateString()}
</p>
<p>
<strong>Check-out:</strong>{' '}
{new Date(checkOut).toLocaleDateString()}
</p>
<p>
<strong>Duration:</strong>{' '}
{(() => {
const checkInTime = new Date(
checkIn,
).getTime();
const checkOutTime = new Date(
checkOut,
).getTime();
const diffTime = checkOutTime - checkInTime;
const diffDays = Math.ceil(
diffTime / (1000 * 60 * 60 * 24),
);
return Math.max(0, diffDays);
})()}{' '}
nights
</p>
</div>
) : null}
</div>
);
}
import { DatePicker } from '@acusti/date-picker';
import { useState } from 'react';
function EventScheduler() {
const [eventDate, setEventDate] = useState('');
const [showPicker, setShowPicker] = useState(false);
// Only allow future dates
const monthLimitFirst = getMonthFromDate(new Date());
return (
<div className="event-scheduler">
<div style={{ marginBottom: '16px' }}>
<label
htmlFor="event-date"
style={{
display: 'block',
marginBottom: '8px',
fontWeight: 500,
}}
>
Event Date:
</label>
<input
id="event-date"
type="text"
value={
eventDate
? new Date(eventDate).toLocaleDateString()
: ''
}
onClick={() => setShowPicker(true)}
placeholder="Click to select date"
readOnly
style={{
padding: '8px 12px',
border: '2px solid #e1e5e9',
borderRadius: '6px',
cursor: 'pointer',
width: '200px',
}}
/>
</div>
{showPicker ? (
<div
style={{
position: 'relative',
zIndex: 1000,
marginTop: '8px',
}}
>
<div
style={{
padding: '16px',
border: '1px solid #e1e5e9',
borderRadius: '8px',
backgroundColor: 'white',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
}}
>
<DatePicker
className="event-scheduler-story"
monthLimitFirst={monthLimitFirst}
onChange={({ dateStart }) => {
setEventDate(dateStart);
setShowPicker(false);
}}
dateStart={eventDate}
/>
<button
onClick={() => setShowPicker(false)}
style={{
marginTop: '12px',
padding: '8px 16px',
border: '1px solid #ccc',
borderRadius: '4px',
cursor: 'pointer',
}}
>
Cancel
</button>
</div>
</div>
) : null}
</div>
);
}
import { DatePicker } from '@acusti/date-picker';
import { useState, useEffect } from 'react';
function ReportFilter() {
const [dateRange, setDateRange] = useState({
start: '',
end: '',
});
const [isOpen, setIsOpen] = useState(false);
// Limit to past 2 years for historical reports
const today = new Date();
const monthLimitLast = getMonthFromDate(today);
const monthLimitFirst = monthLimitLast - 24;
const handleApplyRange = ({ dateStart, dateEnd }) => {
setDateRange({
start: dateStart,
end: dateEnd || dateStart,
});
if (dateEnd) {
setIsOpen(false);
}
};
const formatDateRange = () => {
if (!dateRange.start) return 'Select date range';
const startDate = new Date(dateRange.start).toLocaleDateString();
const endDate = dateRange.end
? new Date(dateRange.end).toLocaleDateString()
: startDate;
return `${startDate} - ${endDate}`;
};
return (
<div className="report-filter">
<button
className="date-range-button"
onClick={() => setIsOpen(!isOpen)}
>
đź“… {formatDateRange()}
</button>
{isOpen ? (
<div className="date-picker-dropdown">
<DatePicker
isRange
isTwoUp
monthLimitFirst={monthLimitFirst}
monthLimitLast={monthLimitLast}
onChange={handleApplyRange}
dateStart={dateRange.start}
dateEnd={dateRange.end}
showEndInitially={!!dateRange.end}
/>
</div>
) : null}
</div>
);
}
import { DatePicker, getMonthFromDate } from '@acusti/date-picker';
import { useState } from 'react';
function BirthdayPicker() {
const [birthday, setBirthday] = useState('');
// Reasonable age limits: 13 to 120 years ago
const today = new Date();
const maxAge = new Date(
today.getFullYear() - 120,
today.getMonth(),
today.getDate(),
);
const minAge = new Date(
today.getFullYear() - 13,
today.getMonth(),
today.getDate(),
);
const monthLimitFirst = getMonthFromDate(maxAge);
const monthLimitLast = getMonthFromDate(minAge);
// Start showing calendar at a reasonable age (25 years ago)
const defaultMonth = getMonthFromDate(
new Date(
today.getFullYear() - 25,
today.getMonth(),
today.getDate(),
),
);
return (
<div className="birthday-picker">
<h3>Enter Your Birthday</h3>
<DatePicker
initialMonth={defaultMonth}
monthLimitFirst={monthLimitFirst}
monthLimitLast={monthLimitLast}
onChange={({ dateStart }) => setBirthday(dateStart)}
dateStart={birthday}
/>
{birthday ? (
<p
style={{
marginTop: '16px',
padding: '12px',
backgroundColor: '#e3f2fd',
borderRadius: '6px',
}}
>
<strong>
You are{' '}
{Math.floor(
(today.getTime() -
new Date(birthday).getTime()) /
(1000 * 60 * 60 * 24 * 365.25),
)}{' '}
years old
</strong>
</p>
) : null}
</div>
);
}
import { DatePicker, getMonthFromDate } from '@acusti/date-picker';
import { useState } from 'react';
function FlexibleDatePicker() {
const [selectedDate, setSelectedDate] = useState('');
const [viewMode, setViewMode] = useState<'single' | 'double'>(
'single',
);
return (
<div className="flexible-date-picker">
<div style={{ marginBottom: '16px' }}>
<label style={{ marginRight: '16px' }}>
<input
type="radio"
checked={viewMode === 'single'}
onChange={() => setViewMode('single')}
style={{ marginRight: '4px' }}
/>
Single Month
</label>
<label>
<input
type="radio"
checked={viewMode === 'double'}
onChange={() => setViewMode('double')}
style={{ marginRight: '4px' }}
/>
Two Months
</label>
</div>
<DatePicker
isTwoUp={viewMode === 'double'}
useMonthAbbreviations={viewMode === 'double'}
onChange={({ dateStart }) => setSelectedDate(dateStart)}
dateStart={selectedDate}
/>
{selectedDate ? (
<div
style={{
marginTop: '16px',
padding: '12px',
border: '1px solid #e1e5e9',
borderRadius: '6px',
}}
>
<strong>Selected:</strong>{' '}
{new Date(selectedDate).toLocaleDateString()}
<br />
<strong>Day of week:</strong>{' '}
{new Date(selectedDate).toLocaleDateString('en', {
weekday: 'long',
})}
</div>
) : null}
</div>
);
}
import { MonthCalendar, getMonthFromDate } from '@acusti/date-picker';
import { useState } from 'react';
function CustomCalendarGrid() {
const [selectedDates, setSelectedDates] = useState<string[]>([]);
const currentMonth = getMonthFromDate(new Date());
const handleDateSelect = (date: string) => {
setSelectedDates((prev) =>
prev.includes(date)
? prev.filter((d) => d !== date)
: [...prev, date],
);
};
return (
<div>
<h3>Multi-Select Calendar</h3>
<p>Click dates to select/deselect multiple dates</p>
<MonthCalendar
month={currentMonth}
onChange={handleDateSelect}
title="Select Multiple Dates"
/>
<div className="selected-dates">
<h4>Selected Dates ({selectedDates.length}):</h4>
<ul>
{selectedDates.map((date) => (
<li key={date}>
{new Date(date).toLocaleDateString()}
</li>
))}
</ul>
</div>
</div>
);
}
The date picker uses CSS custom properties for easy theming:
.date-picker {
/* Calendar colors */
--date-picker-bg: #ffffff;
--date-picker-border: #e0e0e0;
--date-picker-text: #333333;
/* Selected date colors */
--date-picker-selected-bg: #007bff;
--date-picker-selected-text: #ffffff;
/* Range selection colors */
--date-picker-range-bg: #e3f2fd;
--date-picker-range-border: #2196f3;
/* Hover states */
--date-picker-hover-bg: #f5f5f5;
/* Navigation arrows */
--date-picker-arrow-color: #666666;
--date-picker-arrow-hover: #333333;
/* Month header */
--date-picker-header-text: #333333;
--date-picker-header-bg: #f8f9fa;
}
/* Custom styling example */
.booking-calendar {
--date-picker-selected-bg: #28a745;
--date-picker-range-bg: #d4edda;
--date-picker-range-border: #28a745;
}
.event-calendar {
--date-picker-selected-bg: #6f42c1;
--date-picker-range-bg: #e2d9f3;
}
The date picker uses an internal month numbering system where months are represented as the number of months since January 1970:
This system allows for efficient month calculations and navigation. The utility functions handle the conversion between this system and standard dates.
See the Storybook documentation and examples for interactive demonstrations of all date picker features and configurations.
FAQs
React component that renders a date picker with support for date ranges
The npm package @acusti/date-picker receives a total of 66 weekly downloads. As such, @acusti/date-picker popularity was classified as not popular.
We found that @acusti/date-picker demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.

Security News
Open source dashboard CNAPulse tracks CVE Numbering Authorities’ publishing activity, highlighting trends and transparency across the CVE ecosystem.

Product
Detect malware, unsafe data flows, and license issues in GitHub Actions with Socket’s new workflow scanning support.