@archpublicwebsite/rangepicker
| Install | |
|---|---|
npm install @archpublicwebsite/rangepicker |
|
| Latest Version: | 1.7.3 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Sep 13, 2026 |
| Links: | npm |
@archpublicwebsite/rangepicker
A lightweight Vue 3 date range picker with Tailwind CSS support, built for Archipelago hotel booking flows.
Overview
@archpublicwebsite/rangepicker gives you a calendar date picker that handles both date-range
and single-date selection, per-day pricing, holiday/weekend styling, and desktop, mobile
bottom-sheet, and full-screen display variants.
Import the named Datepicker export to get a complete input + calendar out of the box (the
default export remains available for compatibility), or
compose Rangepicker directly if you need to manage the trigger element and open state
yourself.
Datepicker also accepts the deprecated Litepicker-shaped options object so existing 1.6.x
consumers can upgrade without an immediate call-site rewrite. This compatibility surface is
scheduled for removal in 1.7.0; new code should pass canonical props directly.
Features
- Range or single-date selection in one component (
singleMode) - Tailwind utility classes prefixed with
arch-so they never collide with your app's own Tailwind, Bootstrap, or Vuetify styles - Desktop dropdown, mobile bottom sheet, and full-screen variants, with viewport-aware positioning and scroll clamping for tall content
- Per-day pricing: currency formatting, a loading skeleton, and a low-price legend
- Configurable weekend days and holiday markers
- Themeable via HEX color props
- Full TypeScript definitions
- Keyboard and screen-reader support
- Works in Vue 3 and Nuxt 3
Installation
pnpm add @archpublicwebsite/rangepicker vue dayjs @vueuse/core
vue, dayjs, and @vueuse/core are peer dependencies — install them alongside the package.
Quick start
Import the component and its stylesheet:
<script setup lang="ts">
import { ref } from 'vue'
import { Datepicker } from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const dates = ref('')
</script>
<template>
<Datepicker v-model="dates" primary-color="#3b82f6" placeholder="Check in / Check out" />
</template>
What's new
The most recent release adds:
weekendDays— pick which days of the week render as "weekend" (red day number). Defaults to['saturday', 'sunday'].showOtherMonthDays— set tofalseto blank out leading/trailing adjacent-month cells instead of rendering them.mobileTopPositiondefault behavior changed — left unset, the mobile popup now anchors below the trigger input, matching desktop, instead of always centering. Pass'center'to keep the old behavior.variant="full"— a full-screen takeover variant, alongsidedesktop/mobile.monthChangeevent — fires with all currently visible months on prev/next navigation.- Desktop popups now clamp to the viewport height and scroll, matching mobile — tall calendars and price lists no longer clip.
See CHANGELOG.md for the full release history.
Public API
Components
| Export | Notes |
|---|---|
Datepicker |
Named and default export. Range or single-date via singleMode. Use this unless you need advanced composition. |
Rangepicker |
The underlying calendar/popup Datepicker wraps. Use it directly only when you manage triggerElement and isOpen yourself. |
RangepickerInput, DatepickerInput |
Deprecated — use Datepicker instead. Retained throughout 1.x; earliest planned removal is v2.0. |
Composable
useDatePicker(triggerRef, options)— primary composable. ReturnsisOpen,dateRange, andopen/close/togglehelpers.useDatepicker,useRangepicker, anduseRangePicker— deprecated compatibility spellings. UseuseDatePickerfor new implementations; the earliest planned removal of an alias is v2.0.
Types
DateRange, DatepickerProps, RangepickerProps, RangepickerEmits, RangepickerInputProps,
DatepickerInputProps, DayPrice, PriceFormat, WeekendDay, CalendarDay, CalendarMonth,
MonthChangePayload, DisabledDateConfig, DisabledDateInput, HolidayConfig, HolidayInput,
HolidayType, HolidayLegendCategory, HolidayLegendLabels, LegacyDatepickerOptions.
LegacyDatepickerOptions and the DatepickerProps.options prop are deprecated and scheduled for
removal in 1.7.0.
numberOfColumns is retained on the deprecated RangepickerInput compatibility shim and inside
the deprecated options object until 1.7.0. Use numberOfMonths with Datepicker for new code.
Usage
Type-safe options
<script setup lang="ts">
import { ref } from 'vue'
import { Datepicker, type DatepickerProps } from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const dates = ref('')
const pickerOptions: Partial<DatepickerProps> = {
format: 'DD/MM/YYYY',
autoApply: true,
minDays: 2,
maxDays: 30,
weekendDays: ['friday', 'saturday'],
}
</script>
<template>
<Datepicker v-model="dates" v-bind="pickerOptions" primary-color="#3b82f6" />
</template>
Legacy options object
The deprecated Litepicker-shaped options object remains accepted for existing 1.6.x consumers.
It is scheduled for removal in 1.7.0:
<Datepicker
v-model="dates"
:options="{
autoApply: true,
minDate: new Date(),
format: 'DD MMM YYYY',
numberOfColumns: 2,
numberOfMonths: 2,
singleMode: false,
}"
primary-color="#3b82f6"
/>
Supported values are normalized into the canonical Datepicker props, and an explicitly passed
canonical prop wins over its legacy options value. startDate sets the initial visible month;
numberOfColumns remains available inside the legacy object for old independent-column layouts
until 1.7.0.
Legacy-only fields such as allowRepick, dropdowns, tooltipText, tooltipNumber, and
inlineMode are accepted for source compatibility but have no separate canonical behavior.
Migrate to direct props when updating a call site.
Color themes
<Datepicker v-model="dates1" primary-color="#3b82f6" secondary-color="#60a5fa" />
<Datepicker v-model="dates2" primary-color="#8b5cf6" secondary-color="#a78bfa" />
Advanced composition
Use Rangepicker directly when you need your own trigger element and open-state control:
<script setup lang="ts">
import { ref } from 'vue'
import { Rangepicker, useDatePicker } from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const triggerRef = ref<HTMLElement | null>(null)
const { isOpen, dateRange, toggle } = useDatePicker(triggerRef)
</script>
<template>
<div>
<button ref="triggerRef" type="button" @click="toggle">
{{ dateRange.startDate && dateRange.endDate ? `${dateRange.startDate} - ${dateRange.endDate}` : 'Select dates' }}
</button>
<Rangepicker v-model="dateRange" v-model:is-open="isOpen" :trigger-element="triggerRef" />
</div>
</template>
API reference
Datepicker props
The default export. Recommended entry point for both range and single-date selection.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue |
string |
- | Range: "DD MMM YYYY - DD MMM YYYY". Single: "DD MMM YYYY". |
options |
LegacyDatepickerOptions |
- | Deprecated; scheduled for removal in 1.7.0. |
singleMode |
boolean |
false |
Select one date instead of a range. |
variant |
'desktop' | 'mobile' | 'full' |
'desktop' |
Inline dropdown, mobile bottom sheet, or full-screen takeover. |
primaryColor / secondaryColor |
string |
- | HEX colors, e.g. #3b82f6. |
minDate / maxDate |
string | Date |
- | Selectable date bounds. |
initialDate |
string | Date |
current month | Initial visible month when no date is selected. |
minDays / maxDays |
number |
- | Nights bounds in range mode. maxDays: 0 = unlimited. |
numberOfMonths |
number |
2 |
Month panels shown side by side (range mode). |
disabledDates |
(string | Date | { date, label? })[] |
[] |
Blocked dates, optionally with a sold-out label. |
holidays |
HolidayInput[] |
[] |
Bare dates or { date, name, type? } objects — see "Holidays & the legend" below. |
holidayLegendLabels |
{ holiday?, promoday?, other? } |
- | Fallback legend label per category, used only for entries with no name. |
weekendDays |
WeekendDay[] |
['saturday','sunday'] |
Days styled as weekends. |
prices |
DayPrice[] |
- | Per-date nightly prices rendered in each cell. |
pricesLoading |
boolean |
false |
Show a loading skeleton in price slots. |
priceFormat |
'short' | 'currency' | 'raw' |
'short' |
Price label format. |
priceCurrency |
string |
'₱' |
Currency symbol for priceFormat: 'currency'. |
showPriceLegend |
boolean |
false |
Show a legend for the lowest-price color. |
priceCurrencyLabel |
string |
'IDR' |
Currency label in the price legend, e.g. 'IDR'. |
showPriceTooltip |
boolean |
true |
Include price in the hover tooltip. |
showOtherMonthDays |
boolean |
true |
Render adjacent-month days; false blanks those cells. |
format |
string |
'DD MMM YYYY' |
dayjs display/emit format. |
placeholder |
string |
mode-dependent | 'Select dates' (range) or 'Select a date' (single). |
showToday |
boolean |
true |
Highlight today's date. |
showTooltip |
boolean |
true |
Night-count tooltip on hover (range mode). |
showClearButton |
boolean |
true |
Show the ✕ clear button. |
autoApply |
boolean |
true |
Apply on selection complete, no Apply/Cancel buttons. |
close |
boolean |
- | Set true to close the picker programmatically. |
keepPositionOnScroll |
boolean |
true |
Recalculate popup position on page scroll (desktop). |
mobileTopPosition |
number | string |
undefined |
Unset anchors below the trigger; 'center' centers; a number/px string pins a fixed offset. |
borderRadius |
string |
'0.75rem' |
Calendar container border radius. |
dayBorderRadius |
string |
- | Day cell border radius (falls back to --rangepicker-day-radius). |
colorScheme |
'light' | 'dark' |
'light' |
Color scheme. |
fontFamily |
string |
- | Custom font family. |
id / name |
string |
- | Native id/name on the input element. |
readonly |
boolean |
true |
Prevent manual text entry; select via calendar only. |
class |
string |
- | CSS class on the inner input element. |
Rangepicker props
Most props match Datepicker above. Naming differs in a few places (this component predates
Datepicker): valueOfMonths/valueOfColumns instead of numberOfMonths, plus isOpen,
triggerElement, position, delimiter, and colorStyles for manual composition. See
types.ts for the full RangepickerProps interface.
Holidays & the legend
Each holidays entry is either a bare date (defaults to type: 'holiday', no name) or a
{ date, name, type? } object:
const holidays = [
{ date: '17-08', name: 'Indonesian Independence Day' }, // recurring — no year, shown every year
{ date: '27-05-2026', name: 'Eid al-Adha', type: 'holiday' }, // specific — 2026 only
{ date: '2026-09-18', name: 'Long-weekend promo rate', type: 'promoday' }, // blue
{ date: '2026-09-10', name: 'Loyalty member birthday', type: 'birthday' }, // gray ("Other")
]
datewith no year ('DD-MM') recurs every year the calendar renders; a full date (ISO,Date, or'DD-MM-YYYY') shows only in that one year — use this for lunar-calendar holidays whose Gregorian date shifts (Eid, Nyepi, Waisak, Isra Mi'raj).typehas three visual buckets:'holiday'(default, red day number + red legend date),'promoday'(blue), or anything else —'birthday', a custom string, or omitted — which is gray and labeled "Other".- Names are not shown in a tooltip. Passing
holidaysis the only thing needed to also get a legend below the calendar — it appears automatically and re-filters live as the user navigates prev/next. The legend renders as month sections with one row per entry: a category-colored date marker followed by the label. - There's no date-range field — a multi-day event is entered as several same-named dated
entries, one per day. The legend automatically merges same-name entries within a month into a
compact range (e.g.
"20, 23–24 Cuti Bersama Idulfitri") instead of repeating the name. holidayLegendLabelsoverrides the fallback label used only for entries with noname; named entries always show their own name.
AI-agent implementation contract
Use this deterministic mapping when generating holiday data:
| Input style | Use when | Example | Visibility behavior |
|---|---|---|---|
DD-MM |
Recurring annual holiday | 17-08 |
Appears every year (2026, 2027, ...). |
DD-MM-YYYY |
One-off/specific year holiday | 17-08-2026 |
Appears only in that exact year. |
YYYY-MM-DD (ISO) |
One-off/specific year holiday | 2026-08-17 |
Appears only in that exact year. |
Implementation rules for agents:
- Convert recurring holidays to
DD-MMto avoid duplicating entries each year. - Keep moving-date holidays (Eid/Nyepi/Waisak/Isra Mi'raj) as explicit year dates.
- Prefer stable short names so merged legend rows remain readable.
- Never generate both recurring and explicit duplicates for the same holiday/date unless an explicit yearly override is intentional.
Validation checklist:
- Navigate to next year and confirm
DD-MMentries still appear. - Confirm
DD-MM-YYYYand ISO entries disappear outside their year. - Verify legend updates as visible months change (
monthChangeevent).
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue |
{ startDate, endDate } (Rangepicker) / string (Datepicker) |
Date value changed. |
focusin |
- | Input focus event (Datepicker only). Useful for analytics or lazy data fetch. |
update:isOpen |
boolean |
Picker opened/closed (Rangepicker only). |
dateSelected |
Dayjs |
A date was clicked. |
rangeSelected |
start: Dayjs, end: Dayjs |
A range was completed. |
monthChange |
MonthChangePayload[] |
Prev/next navigation, with all visible months. |
Key types
interface DateRange {
startDate: string
endDate: string
}
interface RangepickerEmits {
'update:modelValue': [value: { startDate: string, endDate: string }]
'update:isOpen': [value: boolean]
'dateSelected': [date: Dayjs]
'rangeSelected': [start: Dayjs, end: Dayjs]
'monthChange': [months: MonthChangePayload[]]
}
type WeekendDay = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday'
Styling
The component ships Tailwind utilities prefixed with arch-, so it's safe alongside Vuetify,
Bootstrap, or your app's own Tailwind config. Three ways to theme it, from easiest to most
custom:
<!-- 1. Color props -->
<Datepicker primary-color="#3b82f6" secondary-color="#60a5fa" />
/* 2. CSS variables (global), RGB channel values */
:root {
--color-primary: 59 130 246;
--color-secondary: 148 163 184;
}
/* 3. Override a specific class */
.rangepicker-day-selected {
background-color: purple !important;
}
If styles don't apply, confirm you imported @archpublicwebsite/rangepicker/style.css.
Quick implementation checklist
- Import stylesheet once:
@archpublicwebsite/rangepicker/style.css. - Use
holidayswith the date-format contract above. - Set
weekendDaysexplicitly for local market calendars when needed. - Test both one-month and two-month modes (
numberOfMonths: 1 | 2). - Test desktop and mobile variants for footer/legend wrapping.
Browser support
Chrome/Edge, Firefox, and Safari (latest 2 versions), Mobile Safari (iOS 14+), and Chrome for Android.
Development
pnpm install
pnpm dev # demo app with live examples
pnpm build # build the package
pnpm type-check
Contributing
See the root README for contribution guidelines.
License
MIT © Archipelago Hotels
Related Packages
A Vue 3 datepicker with multi-calendar support and a self-contained theme (no Ta...
A lightweight, zero-dependency Persian (Jalali / Shamsi) date and range picker f...
⚠️**WARNING: vue-accessible-datepicker is at pre-alpha stage of development so t...
A simple Vue.js datepicker component. Supports disabling of dates, inline mode,...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.7.3 | ^3.5.22 | MIT | |
| 1.7.2 | ^3.5.22 | MIT | |
| 1.7.1 | ^3.5.22 | MIT | |
| 1.7.0 | ^3.5.22 | MIT | |
| 1.6.0 | ^3.5.22 | MIT | |
| 1.5.17 | ^3.5.22 | MIT | |
| 1.5.16 | ^3.5.22 | MIT | |
| 1.5.15 | ^3.5.22 | MIT | |
| 1.5.14 | ^3.5.22 | MIT | |
| 1.5.13 | ^3.5.22 | MIT | |
| 1.5.12 | ^3.5.22 | MIT | |
| 1.5.11 | ^3.5.22 | MIT | |
| 1.5.10 | ^3.5.22 | MIT | |
| 1.5.9 | ^3.5.22 | MIT | |
| 1.5.8 | ^3.5.22 | MIT | |
| 1.5.7 | ^3.5.22 | MIT | |
| 1.5.6 | ^3.5.22 | MIT | |
| 1.5.5 | ^3.5.22 | MIT | |
| 1.5.4 | ^3.5.22 | MIT | |
| 1.5.3 | ^3.5.22 | MIT | |
| 1.5.2 | ^3.5.22 | MIT | |
| 1.5.1 | ^3.5.22 | MIT | |
| 1.5.0 | ^3.5.22 | MIT | |
| 1.4.4 | ^3.5.22 | MIT | |
| 1.4.3 | ^3.5.22 | MIT | |
| 1.4.2 | ^3.5.22 | MIT | |
| 1.4.1 | 3.5.22 | MIT | |
| 1.2.27 | ^3.5.22 | MIT | |
| 1.2.26 | ^3.5.22 | MIT | |
| 1.2.24 | ^3.5.22 | MIT |
Showing the latest 30 of 63. See every release on npm