@archpublicwebsite/rangepicker
v1.5.0
Published
Custom date range picker component for PBA Hotel Apps
Downloads
840
Maintainers
Readme
@archpublicwebsite/rangepicker
Custom, lightweight date range picker for Vue 3 with Tailwind CSS prefix support.
Update 1 Bulan Terakhir (Mei-Jun 2026)
Perubahan terbaru di package ini fokus pada workflow monorepo.
- Setup lint, TypeScript, dan editor sekarang lebih konsisten.
- Hook pre-commit dan security scan lebih stabil.
- Opsi validasi commit/push ketat tersedia lewat
REQUIRE_VERIFIED_ACCOUNT=1.
Tidak ada perubahan besar pada API publik Rangepicker/RangepickerInput dalam update ini.
Rekomendasi sebelum publish:
pnpm lint:check
pnpm typecheck
pnpm -C packages/rangepicker buildWhat this package includes
The package exports the picker entry points and the composable that powers the shared state flow:
RangepickerInputas the default exportRangepickerDatepickerInputuseRangepicker- type exports for strongly typed integrations
Features
- Vue 3 Composition API and TypeScript support
- Tailwind utility classes prefixed with
arch- - Dayjs integration for date handling
- Themeable via HEX color props
- Mobile responsive bottom-sheet behavior
- Smart positioning based on viewport space
- Selected-month restore behavior
- Optional scroll-follow alignment
- Keyboard and screen-reader support
- Nuxt 3 compatibility
Requirements
Consumer projects should install the package dependencies used by the picker:
pnpm add vue dayjs @vueuse/coreInstallation
npm install @archpublicwebsite/rangepicker
# or
pnpm add @archpublicwebsite/rangepicker
# or
yarn add @archpublicwebsite/rangepickerQuick Start
You must import both the component and the stylesheet:
<script setup lang="ts">
import { ref } from 'vue'
import RangepickerInput from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const dates = ref('')
</script>
<template>
<RangepickerInput v-model="dates" primary-color="#3b82f6" placeholder="Check in / Check out" />
</template>Public API
Components
RangepickerInputdefault exportRangepickerDatepickerInput
Composable
useRangepicker(triggerRef, options)returnsisOpen,dateRange, and open/close/toggle helpers
Types
DateRangeRangepickerPropsRangepickerInputPropsRangepickerEmitsDatepickerInputPropsDayPricePriceFormatCalendarDayCalendarMonthDisabledDateConfigDisabledDateInput
Usage Examples
Type-safe picker
<script setup lang="ts">
import { ref } from 'vue'
import RangepickerInput, { type DateRange, type RangepickerProps } from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const dates = ref<DateRange>({ startDate: '', endDate: '' })
const pickerOptions: Partial<RangepickerProps> = {
format: 'DD/MM/YYYY',
autoApply: true,
minDays: 2,
maxDays: 30,
showTooltip: true,
}
</script>
<template>
<RangepickerInput
v-model="dates"
v-bind="pickerOptions"
primary-color="#3b82f6"
placeholder="Check in / Check out"
/>
</template>Color customization
<script setup lang="ts">
import { ref } from 'vue'
import RangepickerInput from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const dates1 = ref('')
const dates2 = ref('')
</script>
<template>
<RangepickerInput
v-model="dates1"
primary-color="#3b82f6"
secondary-color="#60a5fa"
placeholder="Blue theme"
/>
<RangepickerInput
v-model="dates2"
primary-color="#8b5cf6"
secondary-color="#a78bfa"
placeholder="Purple theme"
/>
</template>Advanced composition
<script setup lang="ts">
import { ref } from 'vue'
import { Rangepicker, useRangepicker, type RangepickerProps } from '@archpublicwebsite/rangepicker'
import '@archpublicwebsite/rangepicker/style.css'
const triggerRef = ref<HTMLElement | null>(null)
const options: Partial<RangepickerProps> = {
valueOfMonths: 2,
format: 'DD MMM YYYY',
minDays: 1,
autoApply: true,
}
const { isOpen, dateRange, toggle } = useRangepicker(triggerRef, options)
</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>AI Implementation Guide
If you are modifying or extending this package, keep the structure aligned with the public API:
- Put picker UI changes in
src/Rangepicker.vue,src/RangepickerInput.vue, orsrc/DatepickerInput.vue. - Put shared state and orchestration in
src/index.tsor a composable only if it stays reusable. - Put type changes in
src/types.ts. - Keep style changes in
src/styles/and document when consumers must importstyle.css. - Keep the default export aligned with
RangepickerInput. - Re-run the package build after any behavior or API changes.
AI-friendly implementation notes
- Prefer named exports for additional public entry points.
- Keep color props and type exports documented when they are part of the public contract.
- Treat the CSS import as required for consumer usage examples.
- Validate with a package build before publish.
Verification
Ran: pnpm -C packages/rangepicker build
Result: rangepicker build completed successfully.Framework Compatibility
This package is designed to work with Vue 3 frameworks such as Nuxt 3, with no CSS conflicts thanks to the arch- prefix.
License
MIT v-bind="options" />
Props
| Prop | Type | Default | Description |
| ---------------- | ---------------------------------------------------------------------------- | ---------------- | ----------------------------------------------- |
| modelValue | { startDate?: string \| Date \| Dayjs, endDate?: string \| Date \| Dayjs } | {} | Selected date range |
| isOpen | boolean | false | Controls picker visibility |
| variant | 'desktop' \| 'mobile' | 'desktop' | Display variant |
| primaryColor | string | - | Primary color in HEX format (e.g., #3b82f6) |
| secondaryColor | string | - | Secondary color in HEX format (e.g., #60a5fa) |
| minDate | string \| Date \| Dayjs | - | Minimum selectable date |
| maxDate | string \| Date \| Dayjs | - | Maximum selectable date |
| minDays | number | - | Minimum number of days in range |
| maxDays | number | - | Maximum number of days in range |
| valueOfMonths | number | 2 | Number of months to display |
| valueOfColumns | number | 2 | Grid columns for months |
| disabledDates | (string \| Date)[] | [] | Array of disabled dates |
| holidays | (string \| Date)[] | [] | Array of holiday dates |
| format | string | 'YYYY-MM-DD' | Date format |
| delimiter | string | ' - ' | Delimiter between dates |
| placeholder | string | 'Select dates' | Placeholder text |
| label | string | - | Label for the picker |
| showTooltip | boolean | true | Show night count tooltip |
| autoApply | boolean | false | Auto-apply selection |
| position | 'auto' \| 'top' \| 'bottom' | 'auto' | Positioning strategy |
| triggerElement | HTMLElement \| null | - | Trigger element for positioning |
| keepPositionOnScroll | boolean | false | Recalculate popup position while scrolling (desktop) |
Events
| Event | Payload | Description |
| ------------------- | ---------------------------------------- | -------------------------------- |
| update:modelValue | { startDate: string, endDate: string } | Emitted when date range changes |
| update:isOpen | boolean | Emitted when picker opens/closes |
| dateSelected | Dayjs | Emitted when a date is clicked |
| rangeSelected | { start: Dayjs, end: Dayjs } | Emitted when range is complete |
TypeScript Support
This package is built with TypeScript and provides full type definitions. All types are automatically exported for your convenience.
Available Types
import type {
RangepickerProps, // Component props interface
RangepickerEmits, // Event emitter interface
DateRange, // Date range object type
CalendarDay, // Internal calendar day type
CalendarMonth, // Internal calendar month type
} from '@archpublicwebsite/rangepicker'Type Definitions
RangepickerProps
Complete props interface with JSDoc documentation. All props are optional with sensible defaults:
interface RangepickerProps {
modelValue?: { startDate?: string | Date | Dayjs; endDate?: string | Date | Dayjs }
isOpen?: boolean
variant?: 'desktop' | 'mobile'
minDate?: string | Date | Dayjs
maxDate?: string | Date | Dayjs
minDays?: number
maxDays?: number
close?: boolean
valueOfMonths?: number // default: 2
valueOfColumns?: number // default: 2
disabledDates?: (string | Date)[]
holidays?: (string | Date)[]
format?: string // default: 'YYYY-MM-DD'
delimiter?: string // default: ' - '
placeholder?: string
label?: string
showTooltip?: boolean // default: true
autoApply?: boolean // default: false
position?: 'auto' | 'top' | 'bottom'
triggerElement?: HTMLElement | null
keepPositionOnScroll?: boolean // default: false
colorStyles?: Record<string, string>
}Positioning Behavior Notes
- When the picker opens, the visible month is synced to the selected date month.
- If no date is selected, it opens on the current month.
- Set
keep-position-on-scrollto keep desktop popup aligned while page/container scrolls. RangepickerInputandDatepickerInputenablekeep-position-on-scrollby default.
DateRange
Type for the v-model binding:
interface DateRange {
startDate: string
endDate: string
}RangepickerEmits
Event emitter types for type-safe event handling:
interface RangepickerEmits {
'update:modelValue': [value: { startDate: string; endDate: string }]
'update:isOpen': [value: boolean]
"dateSelected": [date: Dayjs]
"rangeSelected": [start: Dayjs, end: Dayjs]
}Usage Examples
Type-Safe Component Props
import type { RangepickerProps } from '@archpublicwebsite/rangepicker'
// Define props with autocomplete support
const config: Partial<RangepickerProps> = {
format: 'DD/MM/YYYY',
minDays: 2,
maxDays: 30,
autoApply: true,
showTooltip: true,
}Type-Safe Event Handlers
import type { Dayjs } from 'dayjs'
function handleDateSelected(date: Dayjs) {
console.log('Selected:', date.format('YYYY-MM-DD'))
}
function handleRangeSelected(start: Dayjs, end: Dayjs) {
const nights = end.diff(start, 'day')
console.log(`Booking: ${nights} nights`)
}Type-Safe Refs
import { ref } from 'vue'
import type { DateRange } from '@archpublicwebsite/rangepicker'
const dateRange = ref<DateRange>({ startDate: '', endDate: '' })
const holidays = ref<string[]>(['2025-12-25', '2025-01-01'])
const disabledDates = ref<Date[]>([new Date('2025-12-24')])IDE Support
With the exported types, you'll get:
- ✅ Autocomplete - IntelliSense for all props and events
- ✅ Type Checking - Compile-time error detection
- ✅ Documentation - Hover tooltips with prop descriptions and default values
- ✅ Refactoring - Safe rename and refactor operations
- ✅ Error Prevention - Catch typos and incorrect prop usage before runtime
Development
# Install dependencies
pnpm install
# Start dev server with demo
pnpm dev
# Build package
pnpm build
# Type check
pnpm type-check
# Preview build
pnpm previewCSS Architecture
The component uses Tailwind CSS with arch- prefix to prevent conflicts with other frameworks:
Why the prefix?
- ✅ Zero conflicts with Vuetify, Bootstrap, Element Plus, etc.
- ✅ Safe to use alongside any CSS framework
- ✅ All utilities prefixed:
.arch-flex,.arch-text-sm,.arch-bg-white, etc. - ✅ Custom classes untouched:
.rangepicker-*classes remain unprefixed
Styling Options
- Color Props (Easiest):
<RangepickerInput primary-color="#3b82f6" secondary-color="#60a5fa" />- CSS Variables (Global):
:root {
--color-primary: 59 130 246; /* RGB format */
--color-secondary: 148 163 184;
}- Custom CSS Overrides:
/* Override component styles */
.rangepicker-day-selected {
background-color: purple !important;
}Troubleshooting
Styles not showing
Make sure you imported the CSS:
import '@archpublicwebsite/rangepicker/style.css'CSS conflicts with Vuetify
This should NOT happen thanks to the arch- prefix. If you see conflicts, please open an issue.
TypeScript errors
Ensure vue is installed as a dependency in your project.
Browser Support
- Chrome/Edge (latest 2 versions)
- Firefox (latest 2 versions)
- Safari (latest 2 versions)
- Mobile Safari (iOS 14+)
- Chrome for Android (latest)
Contributing
See the main repository README for contribution guidelines.
License
MIT © Archipelago Hotels
