momentum-picker
v0.2.1
Published
A production-ready iOS-style wheel DateTime picker for the web. Zero dependencies, Vanilla TypeScript.
Maintainers
Readme
momentum-picker 🎡
A smooth, iOS-style wheel DateTime picker for the web.
Zero dependencies · Vanilla TypeScript · Touch + Mouse · Fully Accessible
Features
- 🎡 Smooth wheel columns — exact iOS feel with infinite scroll illusion
- 📅 DatePicker (Calendar) — modern, full-featured calendar for date selection
- ⚡ Momentum scrolling — natural inertia + snap-to-item (Wheel mode)
- 📅 Multiple modes —
date,time,datetime,range,multiple - 🖱️ Touch & Mouse — works on mobile and desktop
- 🌙 Light / Dark theme out of the box
- 🎨 16+ Premium Styles — Material, Brutalist, Brutalist, Retro, Neumorphism, etc.
- ♿ Accessible — ARIA roles, keyboard navigation, focus management
- 🎯 Vanilla TypeScript — Zero dependencies, framework-agnostic
Installation
npm install momentum-pickerQuick Start
🎡 Wheel Picker (iOS-style)
import MomentumPicker from 'momentum-picker';
import 'momentum-picker/style.css';
const wheel = new MomentumPicker({
container: '#app',
mode: 'datetime',
onConfirm: (date) => console.log('Confirmed:', date),
});
wheel.show();📅 Calendar Picker (Modern)
import { DatePicker } from 'momentum-picker';
const calendar = new DatePicker({
container: '#app',
mode: 'range', // 'single' | 'range' | 'multiple'
displayMode: 'inline', // 'inline' | 'popover' | 'modal'
showTimePicker: true,
onChange: (val) => console.log('Selection:', val),
});⚛️ React Support
We provide built-in React components that wrap the vanilla pickers and add controlled state, easy prop updates, and standard event handling.
import { useState } from 'react';
import { ReactMomentumPicker, ReactDatePicker } from 'momentum-picker';
import 'momentum-picker/style.css'; // Includes both wheel and calendar styles
export function MyComponent() {
const [date, setDate] = useState(new Date());
return (
<>
<ReactDatePicker
mode="single"
displayMode="popover"
value={date}
onChange={(val) => setDate(val as Date)}
/>
<ReactMomentumPicker
mode="datetime"
displayMode="modal"
value={date}
onChange={(val) => setDate(val as Date)}
/>
</>
);
}💚 Vue 3 Support
Similar to React, we provide native lightweight components tailored to Vue's reactive ecosystem using v-model.
<script setup>
import { ref } from 'vue';
import { VueMomentumPicker, VueDatePicker } from 'momentum-picker';
import 'momentum-picker/style.css'; // Includes all styles
const date = ref(new Date());
</script>
<template>
<VueDatePicker
mode="single"
displayMode="popover"
v-model:value="date"
/>
<VueMomentumPicker
mode="datetime"
displayMode="modal"
v-model:value="date"
/>
</template>API Reference
Constructor Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| container | string \| HTMLElement | required | Mount target (CSS selector or element) |
| mode | "date" \| "time" \| "datetime" | "datetime" | Picker mode |
| value | Date | new Date() | Initial selected value |
| minDate | Date | — | Minimum selectable date |
| maxDate | Date | — | Maximum selectable date |
| minuteStep | number | 1 | Minute increment (e.g. 5 → 0, 5, 10…) |
| format | string | — | Output format (YYYY, MM, DD, HH, mm) |
| locale | string | navigator.language | BCP 47 locale for month names |
| theme | "light" \| "dark" | "light" | Colour theme |
| primaryColor | string | "#007aff" | Accent color (any CSS colour) |
| itemHeight | number | 44 | Row height in px |
| visibleRows | number | 5 | Number of visible rows (odd recommended) |
| onChange | (date, formatted?) => void | — | Fires on every column change |
| onConfirm | (date, formatted?) => void | — | Fires on "Done" button |
| onCancel | () => void | — | Fires on "Cancel" or Escape |
Instance Methods
picker.show() // Show the picker
picker.hide() // Hide the picker
picker.toggle() // Toggle visibility
picker.getValue() // → Date (clone)
picker.getFormattedValue() // → string | null
picker.setValue(date: Date) // Programmatically set value
picker.setOptions(partial) // Update theme, primaryColor at runtime
picker.destroy() // Remove DOM + clean up listenersCSS Customisation
All visual properties are CSS custom properties. Override them on any ancestor element:
/* In your own CSS */
:root {
--mp-primary: #ff9500; /* Accent / confirm button color */
--mp-bg: #ffffff; /* Picker background */
--mp-text: #000000; /* Item text color */
--mp-item-height: 44px; /* Height of each wheel row */
--mp-visible-rows: 5; /* Visible rows (as number) */
--mp-font-family: 'Inter', sans-serif;
--mp-border-radius: 16px;
--mp-overlay: rgba(0,0,0,0.45);
--mp-selection-bg: rgba(118,118,128,0.12); /* Selection band fill */
}Dark mode (manual)
picker.setOptions({ theme: 'dark' });Or set data-mp-theme="dark" on the container.
Format Tokens
| Token | Description | Example |
|-------|-------------|---------|
| YYYY | 4-digit year | 2024 |
| MM | 2-digit month | 03 |
| DD | 2-digit day | 07 |
| HH | 2-digit hour (24h) | 14 |
| mm | 2-digit minute | 30 |
Example:
format: 'YYYY-MM-DD HH:mm' // → "2024-03-07 14:30"Keyboard Navigation
| Key | Action |
|-----|--------|
| ↑ / ↓ | Move focused column up/down |
| Tab | Move focus to next column |
| Home | Jump to first item |
| End | Jump to last item |
| Escape | Close picker (triggers onCancel) |
Package Structure
momentum-picker/
├── src/
│ ├── types.ts # All TypeScript interfaces
│ ├── utils.ts # Pure date/format utilities
│ ├── WheelColumn.ts # Single wheel column (momentum, snap, ARIA)
│ ├── MomentumPicker.ts # Orchestrator class
│ ├── styles.css # iOS-style CSS with CSS variables
│ └── index.ts # Public entry point
├── example/
│ └── index.html # Plain HTML demo (all modes + theme toggle)
├── dist/ # Built output (generated)
├── README.md
├── package.json
├── tsconfig.json
└── vite.config.tsDevelopment
git clone https://github.com/your-org/momentum-picker
cd momentum-picker
npm install
# Start dev server with the example page
npm run dev
# Build library → dist/
npm run build
# Type-check only
npm run typecheckPublishing to npm
Update version in
package.json(follow semver):npm version patch # 0.1.0 → 0.1.1 npm version minor # 0.1.0 → 0.2.0 npm version major # 0.1.0 → 1.0.0Build the package:
npm run buildDry-run to see what will be published:
npm pack --dry-runPublish:
npm login # if not already logged in npm publish # public package # or for scoped: npm publish --access publicTag the release in git:
git tag v0.1.0 git push origin v0.1.0
Browser Support
| Browser | Support | |---------|---------| | Chrome 80+ | ✅ | | Firefox 75+ | ✅ | | Safari 13.1+ | ✅ | | Edge 80+ | ✅ | | iOS Safari 13+ | ✅ | | Android Chrome | ✅ |
License
MIT © momentum-picker contributors
