diff --git a/README.MD b/README.MD index 4c31fac..55ea3ae 100644 --- a/README.MD +++ b/README.MD @@ -17,6 +17,15 @@ Web sample: +# Platforms: + +| Platform | Supported | +|-----------|-----------| +| Android | ✅ | +| iOS | ✅ | +| Web(Wasm) | ✅ | +| Desktop | ✅ | + # How to use: 1. Import library from Maven Central repository: @@ -71,6 +80,18 @@ HorizontalCalendarView { monthOffset -> 4. You can style months name, day view or week label as you prefer, just pass them as composables to lib and it is done! +5. You can also use WeekView: + +``` +val today = LocalDate(1995, monthNumber = 7, dayOfMonth = 4) +WeekView( + date = today, + minDate = LocalDate(1990, monthNumber = 1, dayOfMonth = 1), + maxDate = LocalDate(2050, monthNumber = 12, dayOfMonth = 31), +) +``` + +![weekview.png](readme%2Fweekview.png) # Sample project: diff --git a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarDay.kt b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarDay.kt index 56c96ba..98a424e 100644 --- a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarDay.kt +++ b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarDay.kt @@ -29,8 +29,8 @@ fun CalendarDay( interactionSource: MutableInteractionSource = MutableInteractionSource(), onClick: () -> Unit = {}, modifier: Modifier = Modifier, - isForPreviousMonth: Boolean, - isForNextMonth: Boolean, + isForPreviousMonth: Boolean = false, + isForNextMonth: Boolean = false, secondRowText: String = "", ) { OutlinedButton( diff --git a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarView.kt b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarView.kt index 3fd2531..1df074d 100644 --- a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarView.kt +++ b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/CalendarView.kt @@ -29,8 +29,18 @@ fun CalendarView( verticalArrangement: Arrangement.Vertical = Arrangement.SpaceEvenly, showPreviousMonthDays: Boolean = true, showNextMonthDays: Boolean = true, - showMonthLabel: Boolean = true, - day: @Composable (date: LocalDate, isToday: Boolean, isForPreviousMonth: Boolean, isForNextMonth: Boolean) -> Unit = { dayNumber, isToday, isForPreviousMonth, isForNextMonth -> + showHeader: Boolean = true, + isToday: (LocalDate) -> Boolean = { + val today = + Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).toLocalDate() + today == it + }, + day: @Composable ( + date: LocalDate, + isToday: Boolean, + isForPreviousMonth: Boolean, + isForNextMonth: Boolean + ) -> Unit = { dayNumber, isToday, isForPreviousMonth, isForNextMonth -> CalendarDay( dayNumber, isToday = isToday, @@ -38,8 +48,8 @@ fun CalendarView( isForNextMonth = isForNextMonth ) }, - monthLabel: @Composable (month: Month, year: Int) -> Unit = { month, year -> - MonthLabel(month, year) + header: @Composable (month: Month, year: Int) -> Unit = { month, year -> + MonthHeader(month, year) }, dayOfWeekLabel: @Composable (dayOfWeek: DayOfWeek) -> Unit = { dayOfWeek -> val day = when (dayOfWeek) { @@ -63,8 +73,8 @@ fun CalendarView( if (showNextMonthDays) calculateVisibleDaysOfNextMonth(date) else 0 val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).toLocalDate() - if (showMonthLabel) { - monthLabel(date.month, date.year) + if (showHeader) { + header(date.month, date.year) } LazyVerticalGrid( @@ -102,7 +112,7 @@ fun CalendarView( } else { day( newDate, - newDate == today, + isToday(newDate), previousMonthDay, nextMonthDay ) diff --git a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/MonthLabel.kt b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/MonthHeader.kt similarity index 95% rename from calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/MonthLabel.kt rename to calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/MonthHeader.kt index 7e6fbaa..35d253c 100644 --- a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/MonthLabel.kt +++ b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/MonthHeader.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.unit.sp import kotlinx.datetime.Month @Composable -fun MonthLabel(month: Month, year: Int) { +fun MonthHeader(month: Month, year: Int) { val months = listOf( "January", "February", diff --git a/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/WeekView.kt b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/WeekView.kt new file mode 100644 index 0000000..fe9da71 --- /dev/null +++ b/calendar/src/commonMain/kotlin/io/wojciechosak/calendar/view/WeekView.kt @@ -0,0 +1,89 @@ +package io.wojciechosak.calendar.view + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import io.wojciechosak.calendar.utils.copy +import io.wojciechosak.calendar.utils.monthLength +import io.wojciechosak.calendar.utils.toLocalDate +import kotlinx.datetime.Clock +import kotlinx.datetime.DateTimeUnit +import kotlinx.datetime.DayOfWeek +import kotlinx.datetime.LocalDate +import kotlinx.datetime.TimeZone +import kotlinx.datetime.daysUntil +import kotlinx.datetime.plus +import kotlinx.datetime.toLocalDateTime + +@Composable +fun WeekView( + date: LocalDate = Clock.System.now() + .toLocalDateTime(TimeZone.currentSystemDefault()) + .toLocalDate(), + minDate: LocalDate = date.copy(day = 1), + maxDate: LocalDate = date.copy(day = monthLength(date.month, date.year)), + minimumDaysVisible: Int = 7, + isToday: (LocalDate) -> Boolean = { + val today = + Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).toLocalDate() + today == it + }, + day: @Composable (date: LocalDate, isToday: Boolean) -> Unit = { date, isToday -> + weekDay(date, isToday) { + CalendarDay( + date, + isToday = isToday, + modifier = Modifier.width(58.dp), + ) + } + }, +) { + require(date in minDate..maxDate) { + throw IllegalArgumentException("Provided date should be in range of minDate and maxDate.") + } + LazyRow( + state = rememberLazyListState( + initialFirstVisibleItemIndex = (minDate.daysUntil(date) - 3).coerceAtLeast(0), + initialFirstVisibleItemScrollOffset = 0 + ) + ) { + items((minDate.daysUntil(maxDate) + 1).coerceAtLeast(minimumDaysVisible.coerceAtLeast(1))) { index -> + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val newDate = minDate.plus(index, DateTimeUnit.DAY) + day(newDate, isToday(newDate)) + } + } + } +} + +@Composable +private fun weekDay( + newDate: LocalDate, + isToday: Boolean, + function: @Composable () -> Unit, +) { + val weekDay = when (newDate.dayOfWeek) { + DayOfWeek.MONDAY -> "Mon" + DayOfWeek.TUESDAY -> "Tue" + DayOfWeek.WEDNESDAY -> "Wed" + DayOfWeek.THURSDAY -> "Thu" + DayOfWeek.FRIDAY -> "Fri" + DayOfWeek.SATURDAY -> "Sat" + DayOfWeek.SUNDAY -> "Sun" + else -> "" + } + Text(weekDay, fontSize = 12.sp, textAlign = TextAlign.Center) + function() +} \ No newline at end of file diff --git a/readme/weekview.png b/readme/weekview.png new file mode 100644 index 0000000..5c3b28c Binary files /dev/null and b/readme/weekview.png differ diff --git a/sample/composeApp/src/commonMain/kotlin/io/wojciechosak/calendar/calendar/App.kt b/sample/composeApp/src/commonMain/kotlin/io/wojciechosak/calendar/calendar/App.kt index c6e8651..2b192cf 100644 --- a/sample/composeApp/src/commonMain/kotlin/io/wojciechosak/calendar/calendar/App.kt +++ b/sample/composeApp/src/commonMain/kotlin/io/wojciechosak/calendar/calendar/App.kt @@ -28,6 +28,7 @@ import androidx.compose.ui.unit.sp import io.wojciechosak.calendar.view.CalendarDay import io.wojciechosak.calendar.view.CalendarView import io.wojciechosak.calendar.view.HorizontalCalendarView +import io.wojciechosak.calendar.view.WeekView import kotlinx.datetime.Clock import kotlinx.datetime.DateTimeUnit import kotlinx.datetime.LocalDate @@ -40,6 +41,13 @@ import kotlin.random.Random internal fun App() { Column(modifier = Modifier.width(400.dp)) { + val today = LocalDate(1995, monthNumber = 7, dayOfMonth = 4) + WeekView( + date = today, + minDate = LocalDate(1990, monthNumber = 1, dayOfMonth = 1), + maxDate = LocalDate(2050, monthNumber = 12, dayOfMonth = 31), + ) + Spacer(Modifier.height(20.dp)) HorizontalCalendarView { monthOffset -> @@ -77,7 +85,7 @@ internal fun App() { showWeekdays = false, showPreviousMonthDays = false, showNextMonthDays = false, - showMonthLabel = false + showHeader = false ) } }