Skip to content

A Persian (Jalali/Shamsi) Date Picker built with Jetpack Compose Multiplatform 🎉 This library provides beautiful Material 3 styled dialogs and pickers for selecting single dates and date ranges in the Persian calendar. Developed following Material Design Components guidelines.

License

Notifications You must be signed in to change notification settings

faridsolgi/Persian-Date-picker-kotlin-multiplatform

Repository files navigation

📅 Persian Date Picker – Kotlin Multiplatform

A Persian (Jalali/Shamsi) Date Picker built with Jetpack Compose Multiplatform 🎉 This library provides beautiful Material 3 styled dialogs and pickers for selecting single dates and date ranges in the Persian calendar. Developed following Material Design Components guidelines.


✨ Features

License: MIT Kotlin Android iOS JVM WASM

  • 📌 Persian (Jalali) calendar
  • 🖼️ Material 3 design components
  • 📱 Works on Android,iOS, Desktop, and WASM Compose Multiplatform targets
  • 🎛️ Supports both date picker and date range picker
  • 🔄 Fully customizable colors, shapes, and typography
  • ⚡ Easy-to-use APIs

🚀 Installation

The library is published to Maven Central.

The library is compatible with the Kotlin Standard Library not lower than 2.1.20.

If you target Android devices running below API 26, you need to use Android Gradle plugin 4.0 or newer and enable core library desugaring.

⚠️ Note: This library depends on the latest version of kotlinx-datetime and PersianDateTime, so make sure to always use the most recent release.

implementation("io.github.faridsolgi:persian-date-picker:<latest-version>")
implementation("io.github.faridsolgi:persianDateTime:<latest-version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:<latest-version>")

👉 Replace <latest-version> with the latest release versions from GitHub or Maven Central.


📸 Screen Recordings


📖 Usage Examples

🔹 1. Simple Persian Date Picker Dialog

val state = rememberPersianDatePickerState()
var showDialog by remember { mutableStateOf(false) }

if (showDialog) {
    PersianDatePickerDialog(
        onDismissRequest = { showDialog = false },
        confirmButton = {
            TextButton(onClick = {
                println("Selected date: ${state.selectedDate}")
                showDialog = false
            }) {
                Text("تایید")
            }
        }
    ) {
        PersianDatePicker(state = state)
    }
}

Button(onClick = { showDialog = true }) {
    Text("انتخاب تاریخ")
}

🔹 2. Persian Date Range Picker Dialog

val rangeState = rememberPersianDateRangePickerState()
var showDialog by remember { mutableStateOf(false) }

if (showDialog) {
    PersianDatePickerDialog(
        onDismissRequest = { showDialog = false },
        confirmButton = {
            TextButton(onClick = {
                println("Start: ${rangeState.selectedStartDate}")
                println("End: ${rangeState.selectedEndDate}")
                showDialog = false
            }) {
                Text("تایید")
            }
        }
    ) {
        PersianDateRangePicker(state = rangeState)
    }
}

Button(onClick = { showDialog = true }) {
    Text("انتخاب بازه تاریخ")
}

🔹 3. Date Picker Popup

val state = rememberPersianDatePickerState()
var expanded by remember { mutableStateOf(false) }

PersianDatePickerPopup(
    expanded = expanded,
    onDismissRequest = { expanded = false },
    anchor = {
        Button(onClick = { expanded = true }) {
            Text("انتخاب تاریخ")
        }
    }
) {
    PersianDatePicker(state = state)
}

🔹 4. Range Picker Popup

val rangeState = rememberPersianDateRangePickerState()
var expanded by remember { mutableStateOf(false) }

PersianDatePickerPopup(
    expanded = expanded,
    onDismissRequest = { expanded = false },
    anchor = {
        Button(onClick = { expanded = true }) {
            Text("انتخاب بازه تاریخ")
        }
    }
) {
    PersianDateRangePicker(state = rangeState)
}

🔹 5. Customizing Title & Headline

val state = rememberPersianDatePickerState()

PersianDatePickerDialog(
    onDismissRequest = {},
    confirmButton = { TextButton(onClick = {}) { Text("تایید") } }
) {
    PersianDatePicker(
        state = state,
        title = {
            Text(
                text = "📅 انتخاب تاریخ",
                style = MaterialTheme.typography.headlineMedium,
                modifier = Modifier.padding(16.dp)
            )
        },
        headline = {
            Text(
                text = state.selectedDate?.toString() ?: "هیچ تاریخی انتخاب نشده",
                style = MaterialTheme.typography.bodyLarge,
                modifier = Modifier.padding(16.dp)
            )
        }
    )
}

🔹 6. Custom Year Range & Initial Date

val state = rememberPersianDatePickerState(
    initialSelectedDate = PersianDateTime.now(),
    yearRange = 1300..1500 // Restrict to a custom range
)

PersianDatePickerDialog(
    onDismissRequest = {},
    confirmButton = { TextButton(onClick = {}) { Text("تایید") } }
) {
    PersianDatePicker(state = state)
}

🔹 7. Range Picker with Custom Headline

val rangeState = rememberPersianDateRangePickerState()

PersianDatePickerDialog(
    onDismissRequest = {},
    confirmButton = { TextButton(onClick = {}) { Text("تایید") } }
) {
    PersianDateRangePicker(
        state = rangeState,
        headline = {
            Column(modifier = Modifier.padding(16.dp)) {
                val start = rangeState.selectedStartDate?.toLocalDate()
                val end = rangeState.selectedEndDate?.toLocalDate()
                if (start != null && end != null) {
                    val days = start.daysUntil(end)
                    Text("📆 شروع: $start")
                    Text("📆 پایان: $end")
                    Text("⏳ فاصله: $days روز")
                } else {
                    Text("هیچ بازه‌ای انتخاب نشده")
                }
            }
        }
    )
}

🔹 Custom Persian Date Picker with State Parameters

You can fully customize the Persian Date Picker using rememberPersianDatePickerState by specifying initial dates, year range, selectable dates, and display mode.

@Composable
@ExperimentalMaterial3Api
fun CustomPersianDatePickerExample() {
    // Custom initial selected date (12 Mehr 1404)
    val initialDate = PersianDateTime(1404, 7, 12)
    
    // Custom year range
    val customYearRange = 1400..1450
    
   

    // Create a custom state
    val state = rememberPersianDatePickerState(
        initialSelectedDate = initialDate,
        initialDisplayedDate = initialDate,
        yearRange = customYearRange,
        initialDisplayMode = DisplayMode.Companion.Picker
    )

    var showDialog by remember { mutableStateOf(false) }

    // Button to open the dialog
    Button(onClick = { showDialog = true }) {
        Text("انتخاب تاریخ")
    }

    if (showDialog) {
        PersianDatePickerDialog(
            onDismissRequest = { showDialog = false },
            confirmButton = {
                TextButton(onClick = {
                    println("Selected date: ${state.selectedDate}")
                    showDialog = false
                }) {
                    Text("تایید")
                }
            }
        ) {
            PersianDatePicker(
                state = state,
                title = {
                    Text(
                        "📅 انتخاب تاریخ سفارشی",
                        style = MaterialTheme.typography.headlineMedium,
                        modifier = Modifier.padding(16.dp)
                    )
                },
                headline = {
                    Text(
                        text = state.selectedDate?.toString() ?: "هیچ تاریخی انتخاب نشده",
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.padding(16.dp)
                    )
                }
            )
        }
    }
}

🔹 8. Custom Colors

By default, the colors of the PersianDatePicker depend on your Material app theme. You can customize the colors using the PersianDatePickerDefaults.colors function.

Example:

val state = rememberPersianDatePickerState()

PersianDatePickerDialog(
    onDismissRequest = {},
    confirmButton = { TextButton(onClick = {}) { Text("تایید") } }
) {
    PersianDatePicker(
        state = state,
        colors = PersianDatePickerDefaults.colors(
            containerColor = Color.Unspecified,
            titleColor = Color.Unspecified,
            confirmButtonColor = Color.Unspecified,
            dismissButtonColor = Color.Unspecified,
            selectedDayColor = Color.Unspecified,
            onSelectedDayColor = Color.Unspecified,
            notSelectedDayColor = Color.Unspecified,
            todayColor = Color.Unspecified,
            weekdaysColor = Color.Unspecified
        )
    )
}

🎨 Customization

You can customize:

  • 🟦 ColorsPersianDatePickerDefaults.colors()
  • 🔷 ShapePersianDatePickerDefaults.Shape
  • 📐 Year Range → pass yearRange to rememberPersianDatePickerState() or rememberPersianDateRangePickerState()
  • 🪟 Dialog PropertiesDialogProperties
  • 🎭 Headlines & Titles → Provide your own Composables

🤝 Contributing

Contributions are welcome! Feel free to open issues or submit pull requests to improve functionality, fix bugs, or add new features.


📜 License

This project is licensed under the MIT License.

About

A Persian (Jalali/Shamsi) Date Picker built with Jetpack Compose Multiplatform 🎉 This library provides beautiful Material 3 styled dialogs and pickers for selecting single dates and date ranges in the Persian calendar. Developed following Material Design Components guidelines.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages