Skip to content

srabbijan/kmpdatetimepicker

Repository files navigation

KMP DateTime Picker Library

A highly customizable and feature-rich date and time picker library for Kotlin Multiplatform Compose applications. This library provides beautiful, Material Design 3 compliant date and time selection components with extensive customization options.

Features

  • 🎨 Fully Customizable: Colors, shapes, typography, dimensions, and locale
  • 🌙 Multiple Themes: Light, Dark, Material3, and Cupertino themes
  • 📅 Multiple Formats: Various date and time formats support
  • 🔧 Easy Configuration: Builder pattern for easy setup
  • Validation: Built-in validation helpers
  • 🎯 State Management: Convenient state management with rememberDateTimePickerState
  • 📱 KMP Ready: Works on Android, iOS, Desktop, and Web
  • 🎪 Multiple Components: Date picker, time picker, and combined date-time picker

Installation

Add the library to your commonMain dependencies:

dependencies {
    implementation("io.github.srabbijan:kmpdatetimepicker:1.0.0")
    implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
}

##Preview https://youtube.com/shorts/GVtyaTCNjf8?feature=share

Quick Start

Basic Usage

@Composable
fun MyScreen() {
    val dateTimeState = rememberDateTimePickerState()
    
    Column {
        // Date Input Field
        DateInputField(
            label = "Select Date",
            selectedDate = dateTimeState.selectedDate,
            onDateClick = { dateTimeState.showDatePicker() }
        )
        
        // Date Picker Dialog
        DateTimePicker(
            label = "Select Date",
            isVisible = dateTimeState.isDatePickerVisible,
            onDateSelected = dateTimeState::onDateSelected,
            onDismiss = dateTimeState::hideDatePicker
        )
    }
}

Customization

@Composable
fun CustomizedDatePicker() {
    val customConfig = dateTimePickerConfig {
        colors {
            copy(
                primary = Color(0xFF6200EE),
                background = Color.White,
                border = Color(0xFFE0E0E0)
            )
        }
        shapes {
            copy(
                container = RoundedCornerShape(12.dp),
                dialog = RoundedCornerShape(20.dp)
            )
        }
        locale {
            copy(
                selectDate = "Choose Date",
                dateFormat = DateFormat.YYYY_MM_DD,
                timeFormat = TimeFormat.TWENTY_FOUR_HOUR
            )
        }
    }
    
    DateInputField(
        label = "Custom Date Picker",
        selectedDate = selectedDate,
        config = customConfig,
        onDateClick = { /* show picker */ }
    )
}

Components

1. DateTimePicker

A standalone date picker dialog.

DateTimePicker(
    label = "Select Date",
    isVisible = isVisible,
    initialDate = LocalDate.now(),
    minDate = LocalDate.now().minusDays(30),
    maxDate = LocalDate.now().plusDays(30),
    config = config,
    onDateSelected = { date -> /* handle date */ },
    onDismiss = { /* handle dismiss */ }
)

2. DateTimeTimePicker

A standalone time picker dialog.

DateTimeTimePicker(
    label = "Select Time",
    isVisible = isVisible,
    initialTime = LocalTime.now(),
    config = config,
    onTimeSelected = { time -> /* handle time */ },
    onDismiss = { /* handle dismiss */ }
)

3. DateTimeFullPicker

A combined date and time picker with tabs.

DateTimeFullPicker(
    label = "Select Date & Time",
    isVisible = isVisible,
    initialDateTime = LocalDateTime.now(),
    config = config,
    onDateTimeSelected = { dateTime -> /* handle datetime */ },
    onDismiss = { /* handle dismiss */ }
)

4. Input Fields

DateInputField

DateInputField(
    label = "Date",
    selectedDate = selectedDate,
    config = config,
    enabled = true,
    isError = false,
    errorMessage = null,
    leadingIcon = { /* custom icon */ },
    trailingIcon = { /* custom icon */ },
    onDateClick = { /* show picker */ }
)

TimeInputField

TimeInputField(
    label = "Time",
    selectedTime = selectedTime,
    config = config,
    enabled = true,
    isError = false,
    errorMessage = null,
    leadingIcon = { /* custom icon */ },
    trailingIcon = { /* custom icon */ },
    onTimeClick = { /* show picker */ }
)

DateTimeInputField

DateTimeInputField(
    label = "Date & Time",
    selectedDateTime = selectedDateTime,
    config = config,
    enabled = true,
    isError = false,
    errorMessage = null,
    leadingIcon = { /* custom icon */ },
    trailingIcon = { /* custom icon */ },
    onDateTimeClick = { /* show picker */ }
)

Configuration

DateTimePickerConfig

The main configuration class that controls the appearance and behavior of all components.

data class DateTimePickerConfig(
    val colors: DateTimePickerColors,
    val shapes: DateTimePickerShapes,
    val typography: DateTimePickerTypography,
    val dimensions: DateTimePickerDimensions,
    val locale: DateTimePickerLocale
)

Colors

data class DateTimePickerColors(
    val primary: Color,
    val background: Color,
    val surface: Color,
    val onPrimary: Color,
    val onBackground: Color,
    val onSurface: Color,
    val border: Color,
    val error: Color,
    val placeholder: Color,
    val label: Color,
    val selectedDay: Color,
    val todayBorder: Color
)

Shapes

data class DateTimePickerShapes(
    val container: Shape,
    val dialog: Shape,
    val button: Shape
)

Typography

data class DateTimePickerTypography(
    val title: TextStyle,
    val label: TextStyle,
    val body: TextStyle,
    val button: TextStyle,
    val error: TextStyle
)

Dimensions

data class DateTimePickerDimensions(
    val dialogWidth: Float,
    val dialogPadding: Dp,
    val fieldHeight: Dp,
    val spacing: Dp,
    val iconSize: Dp,
    val borderWidth: Dp
)

Locale

data class DateTimePickerLocale(
    val selectDate: String,
    val selectTime: String,
    val selectDateTime: String,
    val cancel: String,
    val select: String,
    val dateTab: String,
    val timeTab: String,
    val datePlaceholder: String,
    val timePlaceholder: String,
    val dateTimePlaceholder: String,
    val dateFormat: DateFormat,
    val timeFormat: TimeFormat
)

Predefined Themes

The library comes with several predefined themes:

// Default theme
DateTimePickerThemes.Default

// Dark theme
DateTimePickerThemes.Dark

// Material 3 theme
DateTimePickerThemes.Material3

// Cupertino (iOS-style) theme
DateTimePickerThemes.Cupertino

Using Predefined Themes

DateInputField(
    label = "Select Date",
    selectedDate = selectedDate,
    config = DateTimePickerThemes.Dark,
    onDateClick = { /* show picker */ }
)

State Management

Use rememberDateTimePickerState for convenient state management:

@Composable
fun MyScreen() {
    val dateTimeState = rememberDateTimePickerState(
        initialDate = LocalDate.now(),
        initialTime = LocalTime.now(),
        initialDateTime = LocalDateTime.now()
    )
    
    // Access state
    val selectedDate = dateTimeState.selectedDate
    val selectedTime = dateTimeState.selectedTime
    val selectedDateTime = dateTimeState.selectedDateTime
    
    // Control visibility
    dateTimeState.showDatePicker()
    dateTimeState.hideDatePicker()
    
    // Handle selections
    dateTimeState.onDateSelected(LocalDate.now())
    dateTimeState.onTimeSelected(LocalTime.now())
    dateTimeState.onDateTimeSelected(LocalDateTime.now())
    
    // Reset state
    dateTimeState.reset()
}

Validation

The library includes built-in validation helpers:

// Validate date
val dateValidation = DateTimeValidator.validateDate(
    date = selectedDate,
    minDate = LocalDate.now().minusDays(30),
    maxDate = LocalDate.now().plusDays(30),
    isRequired = true
)

if (!dateValidation.isValid) {
    // Show error message
    println(dateValidation.errorMessage)
}

// Validate time
val timeValidation = DateTimeValidator.validateTime(
    time = selectedTime,
    minTime = LocalTime(9, 0),
    maxTime = LocalTime(17, 0),
    isRequired = true
)

// Validate datetime
val dateTimeValidation = DateTimeValidator.validateDateTime(
    dateTime = selectedDateTime,
    minDateTime = LocalDateTime.now(),
    maxDateTime = LocalDateTime.now().plusDays(7),
    isRequired = true
)

Utility Functions

DateTimePickerUtils

// Get current date/time
val currentDate = DateTimePickerUtils.getCurrentDate()
val currentTime = DateTimePickerUtils.getCurrentTime()
val currentDateTime = DateTimePickerUtils.getCurrentDateTime()

// Parse date/time strings
val parsedDate = DateTimePickerUtils.parseDate("25/12/2023", DateFormat.DD_MM_YYYY)
val parsedTime = DateTimePickerUtils.parseTime("14:30", TimeFormat.TWENTY_FOUR_HOUR)

// Validate date range
val isInRange = DateTimePickerUtils.isDateInRange(
    date = selectedDate,
    minDate = minDate,
    maxDate = maxDate
)

Extension Functions

// Format dates
val formattedDate = localDate.toDisplayString(DateFormat.YYYY_MM_DD)
val apiFormat = localDate.toAPIFormat()

// Format times
val formattedTime = localTime.toDisplayString(TimeFormat.TWENTY_FOUR_HOUR)

// Format datetime
val formattedDateTime = localDateTime.toDisplayString(
    DateFormat.DD_MM_YYYY,
    TimeFormat.TWELVE_HOUR
)

Advanced Examples

Custom Validation with Error Display

@Composable
fun ValidatedDateInput() {
    var selectedDate by remember { mutableStateOf<LocalDate?>(null) }
    var isError by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf<String?>(null) }
    
    val validation = DateTimeValidator.validateDate(
        date = selectedDate,
        minDate = LocalDate.now(),
        isRequired = true
    )
    
    LaunchedEffect(selectedDate) {
        isError = !validation.isValid
        errorMessage = validation.errorMessage
    }
    
    DateInputField(
        label = "Select Future Date",
        selectedDate = selectedDate,
        isError = isError,
        errorMessage = errorMessage,
        onDateClick = { /* show picker */ }
    )
}

Multi-Language Support

val arabicConfig = dateTimePickerConfig {
    locale {
        copy(
            selectDate = "اختر التاريخ",
            selectTime = "اختر الوقت",
            cancel = "إلغاء",
            select = "اختيار",
            dateFormat = DateFormat.DD_MM_YYYY
        )
    }
}

Custom Icons

DateInputField(
    label = "Date",
    selectedDate = selectedDate,
    trailingIcon = {
        Icon(
            painter = painterResource(Res.drawable.custom_calendar),
            contentDescription = "Calendar",
            tint = MaterialTheme.colorScheme.primary
        )
    },
    onDateClick = { /* show picker */ }
)

Requirements

  • Kotlin Multiplatform 1.9.0+
  • Compose Multiplatform 1.5.0+
  • kotlinx-datetime 0.4.0+

License


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For support, please open an issue on GitHub or contact us at srabbijan@gmail.com.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors