Skip to content

elber-code/ex-date-picker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@elberpg/ex-date-picker

Composable date and time pickers for React Native / Expo.
Drum-scroll columns — no native dependencies, no @elberpg/ex-modal required.

npm version license platform

Spanish docs: README_ES.md


Preview

Default — Date Default — Time
Default date picker Default time picker

Fully themeable via global style objects — no props required.

Dark ☕ — Date Dark ☕ — Time Square ⬛ — Date Square ⬛ — Time
Dark date picker Dark time picker Square date picker Square time picker

Installation

npm install @elberpg/ex-date-picker

Concept — composable pattern

Each picker and modal are independent components. You compose them:

<DatePickerModal visible={open} onClose={onClose} onConfirm={() => onConfirm(draft)}>
  <DatePicker value={draft} onChange={setDraft} />
</DatePickerModal>

This gives full style control over each part independently.


DatePicker

Scroll columns for day, month, and year. Use standalone or inside any modal.

import { DatePicker } from '@elberpg/ex-date-picker';

<DatePicker
  value={date}
  onChange={setDate}
  locale="en-US"
/>

Props

Prop Type Default Description
value Date | DatePickerValue today Current value
onChange (date: Date) => void Called on every scroll change
locale string 'en' Locale for month names
minYear number current − 100 Minimum year
maxYear number current + 10 Maximum year
itemHeight number from theme Row height in px
selectedColor string from theme Color of the selected item
unselectedColor string from theme Color of unselected items
style ViewStyle Container style

TimePicker

Scroll columns for hour and minute. Supports 12-hour (AM/PM) mode.

import { TimePicker } from '@elberpg/ex-date-picker';

<TimePicker
  value={time}
  onChange={setTime}
  use12h={false}
/>

Props

Prop Type Default Description
value TimeValue | Date now Current value
onChange (time: TimeValue) => void Called on every scroll change
use12h boolean false 12-hour mode with AM/PM column
itemHeight number from theme Row height in px
selectedColor string from theme Color of the selected item
unselectedColor string from theme Color of unselected items
style ViewStyle Container style

TimeValue

interface TimeValue {
  hours: number;    // 0–23 (or 1–12 in 12h mode)
  minutes: number;  // 0–59
}

DatePickerModal — native RN Modal

Bottom-sheet using React Native's Modal component. Renders on top of everything including toasts.

import { DatePicker, DatePickerModal } from '@elberpg/ex-date-picker';

const [open, setOpen]   = useState(false);
const [date, setDate]   = useState(new Date());
const [draft, setDraft] = useState(new Date());

// Open: sync draft with current value
<Pressable onPress={() => { setDraft(date); setOpen(true); }}>
  <Text>{date.toLocaleDateString()}</Text>
</Pressable>

<DatePickerModal
  visible={open}
  onClose={() => setOpen(false)}
  onConfirm={() => { setDate(draft); setOpen(false); }}
  title="Select date"
>
  <DatePicker value={draft} onChange={setDraft} locale="en-US" />
</DatePickerModal>

DatePickerModalOverlay — style-based overlay

Same API as DatePickerModal but uses position: absolute instead of RN's Modal.
Avoids conflicts with toasts, sheets, and other overlays. Must be placed at root level.

import { DatePicker, DatePickerModalOverlay } from '@elberpg/ex-date-picker';

<DatePickerModalOverlay
  visible={open}
  onClose={() => setOpen(false)}
  onConfirm={() => { setDate(draft); setOpen(false); }}
  title="Select date"
>
  <DatePicker value={draft} onChange={setDraft} />
</DatePickerModalOverlay>

TimePickerModal / TimePickerModalOverlay

Same API as the date variants. Just swap DatePicker for TimePicker as children.

import { TimePicker, TimePickerModal } from '@elberpg/ex-date-picker';

<TimePickerModal
  visible={open}
  onClose={() => setOpen(false)}
  onConfirm={() => { setTime(draft); setOpen(false); }}
  title="Select time"
  clearable
  onClear={() => { setTime(undefined); setOpen(false); }}
>
  <TimePicker value={draft} onChange={setDraft} use12h />
</TimePickerModal>

Modal props — PickerModalProps

Shared by DatePickerModal, DatePickerModalOverlay, TimePickerModal, TimePickerModalOverlay.

Prop Type Default Description
visible boolean Shows or hides the modal
onClose () => void Called when the backdrop or Cancel is tapped
onConfirm () => void Called when Confirm is tapped
children ReactNode The picker to render inside
title string Modal title
confirmLabel string 'Confirm' Confirm button text
cancelLabel string 'Cancel' Cancel button text
clearable boolean false Show a Clear button
clearLabel string 'Clear' Clear button text
onClear () => void Called when Clear is tapped
btnConfirm ({ onPress }) => ReactNode Replace the Confirm button
btnCancel ({ onPress }) => ReactNode Replace the Cancel button
btnClear ({ onPress }) => ReactNode Replace the Clear button

Global styles

There are two separate style objects — one for the picker, one for the modal shell.

ExDatePicker.styles — picker (scroll columns)

import { ExDatePicker } from '@elberpg/ex-date-picker';

ExDatePicker.styles.selectedColor   = '#0a84ff';
ExDatePicker.styles.unselectedColor = '#8e8e93';
ExDatePicker.styles.itemHeight      = 52;
ExDatePicker.styles.fontFamily      = 'Georgia';
ExDatePicker.styles.lineColor       = '#3a3a3c';
ExDatePicker.styles.columnLabel     = { fontSize: 11, color: '#888', textTransform: 'uppercase' };
Field Type Description
selectedColor string Color of the selected scroll item
unselectedColor string Color of unselected scroll items
itemHeight number Height of each scroll row in px
fontFamily string Font family for scroll item text
lineColor string Color of the two selection indicator lines
columnLabel TextStyle Column labels (DAY · MONTH · YEAR / HOUR · MIN)

ExDatePickerModal.styles — modal shell

import { ExDatePickerModal } from '@elberpg/ex-date-picker';

ExDatePickerModal.styles.card = {
  backgroundColor: '#1c1c1e',
  borderTopLeftRadius: 28,
  borderTopRightRadius: 28,
};
ExDatePickerModal.styles.title          = { fontSize: 17, fontWeight: '700', color: '#fff' };
ExDatePickerModal.styles.btnConfirm     = { backgroundColor: '#0a84ff' };
ExDatePickerModal.styles.btnConfirmText = { fontSize: 15, fontWeight: '600', color: '#fff' };
ExDatePickerModal.styles.backdropColor  = 'rgba(0,0,0,0.65)';
Field Type Description
card ViewStyle Main card (background, border radius, padding)
pill ViewStyle Drag pill at the top
title TextStyle Modal title (fontSize, color, fontFamily…)
headerBorder ViewStyle Separator below the title
btnConfirm ViewStyle Confirm button container
btnCancel ViewStyle Cancel button container
btnClear ViewStyle Clear button container
btnConfirmText TextStyle Confirm button text
btnCancelText TextStyle Cancel button text
btnClearText TextStyle Clear button text
backdropColor string Backdrop color + opacity (rgba(…))

Custom button example

<DatePickerModal
  btnConfirm={({ onPress }) => (
    <Pressable onPress={onPress} style={{ backgroundColor: '#0a84ff', borderRadius: 12, flex: 1, height: 48, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ color: '#fff', fontWeight: '700' }}>Done</Text>
    </Pressable>
  )}
>
  <DatePicker value={draft} onChange={setDraft} />
</DatePickerModal>

Important rule

Place modals outside any ScrollView.

// ✅ Correct
return (
  <>
    <SafeAreaView>
      <ScrollView>...</ScrollView>
    </SafeAreaView>
    <DatePickerModal visible={open} onClose={onClose} onConfirm={onConfirm}>
      <DatePicker value={draft} onChange={setDraft} />
    </DatePickerModal>
  </>
);

// ❌ Wrong — the modal scrolls with the content
return (
  <ScrollView>
    <DatePickerModal visible={open} .../>
  </ScrollView>
);

About

Composable scroll-based date & time picker with modal shells for React Native / Expo

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors