Skip to content

Commit

Permalink
Suffix Day and Month with Components
Browse files Browse the repository at this point in the history
  • Loading branch information
bryankeller committed Dec 19, 2023
1 parent 66dd26d commit 950a0e9
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 48 deletions.
14 changes: 7 additions & 7 deletions Sources/Public/CalendarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,22 @@ public final class CalendarView: UIView {
/// A closure (that is retained) that is invoked whenever a day is selected. It is the responsibility of your feature code to decide what to
/// do with each day. For example, you might store the most recent day in a selected day property, then read that property in your
/// `dayItemProvider` closure to add specific "selected" styling to a particular day view.
public var daySelectionHandler: ((Day) -> Void)?
public var daySelectionHandler: ((DayComponents) -> Void)?

/// A closure (that is retained) that is invoked inside `scrollViewDidScroll(_:)`
public var didScroll: ((_ visibleDayRange: DayRange, _ isUserDragging: Bool) -> Void)?
public var didScroll: ((_ visibleDayRange: DayComponentsRange, _ isUserDragging: Bool) -> Void)?

/// A closure (that is retained) that is invoked inside `scrollViewDidEndDragging(_: willDecelerate:)`.
public var didEndDragging: ((_ visibleDayRange: DayRange, _ willDecelerate: Bool) -> Void)?
public var didEndDragging: ((_ visibleDayRange: DayComponentsRange, _ willDecelerate: Bool) -> Void)?

/// A closure (that is retained) that is invoked inside `scrollViewDidEndDecelerating(_:)`.
public var didEndDecelerating: ((_ visibleDayRange: DayRange) -> Void)?
public var didEndDecelerating: ((_ visibleDayRange: DayComponentsRange) -> Void)?

/// A closure (that is retained) that is invoked during a multiple-selection-drag-gesture. Multiple selection is initiated with a long press,
/// followed by a drag / pan. As the gesture crosses over more days in the calendar, this handler will be invoked with each new day. It
/// is the responsibility of your feature code to decide what to do with this stream of days. For example, you might convert them to
/// `Date` instances and use them as input to the `dayRangeItemProvider`.
public var multiDaySelectionDragHandler: ((Day, UIGestureRecognizer.State) -> Void)? {
public var multiDaySelectionDragHandler: ((DayComponents, UIGestureRecognizer.State) -> Void)? {
didSet {
configureMultiDaySelectionPanGestureRecognizer()
}
Expand All @@ -94,12 +94,12 @@ public final class CalendarView: UIView {
}

/// The range of months that are partially of fully visible.
public var visibleMonthRange: MonthRange? {
public var visibleMonthRange: MonthComponentsRange? {
visibleItemsDetails?.visibleMonthRange
}

/// The range of days that are partially or fully visible.
public var visibleDayRange: DayRange? {
public var visibleDayRange: DayComponentsRange? {
visibleItemsDetails?.visibleDayRange
}

Expand Down
8 changes: 4 additions & 4 deletions Sources/Public/CalendarViewContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public final class CalendarViewContent {
/// - month: The `Month` for which to provide a month header item.
/// - Returns: A mutated `CalendarViewContent` instance with a new month header item provider.
public func monthHeaderItemProvider(
_ monthHeaderItemProvider: @escaping (_ month: Month) -> AnyCalendarItemModel?)
_ monthHeaderItemProvider: @escaping (_ month: MonthComponents) -> AnyCalendarItemModel?)
-> CalendarViewContent
{
self.monthHeaderItemProvider = { [defaultMonthHeaderItemProvider] month in
Expand Down Expand Up @@ -217,7 +217,7 @@ public final class CalendarViewContent {
/// - Returns: A mutated `CalendarViewContent` instance with a new day-of-week item provider.
public func dayOfWeekItemProvider(
_ dayOfWeekItemProvider: @escaping (
_ month: Month?,
_ month: MonthComponents?,
_ weekdayIndex: Int)
-> AnyCalendarItemModel?)
-> CalendarViewContent
Expand Down Expand Up @@ -250,7 +250,7 @@ public final class CalendarViewContent {
/// - day: The `Day` for which to provide a day item.
/// - Returns: A mutated `CalendarViewContent` instance with a new day item provider.
public func dayItemProvider(
_ dayItemProvider: @escaping (_ day: Day) -> AnyCalendarItemModel?)
_ dayItemProvider: @escaping (_ day: DayComponents) -> AnyCalendarItemModel?)
-> CalendarViewContent
{
self.dayItemProvider = { [defaultDayItemProvider] day in
Expand Down Expand Up @@ -279,7 +279,7 @@ public final class CalendarViewContent {
/// - day: The `Day` for which to provide a day background item.
/// - Returns: A mutated `CalendarViewContent` instance with a new day background item provider.
public func dayBackgroundItemProvider(
_ dayBackgroundItemProvider: @escaping (_ day: Day) -> AnyCalendarItemModel?)
_ dayBackgroundItemProvider: @escaping (_ day: DayComponents) -> AnyCalendarItemModel?)
-> CalendarViewContent
{
self.dayBackgroundItemProvider = dayBackgroundItemProvider
Expand Down
30 changes: 15 additions & 15 deletions Sources/Public/CalendarViewRepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ extension CalendarViewRepresentable {
/// - month: The `Month` for which to provide a month header item.
/// - Returns: A new `CalendarViewRepresentable` with a new month header item provider.
public func monthHeaderItemProvider(
_ monthHeaderItemProvider: @escaping (_ month: Month) -> AnyCalendarItemModel?)
_ monthHeaderItemProvider: @escaping (_ month: MonthComponents) -> AnyCalendarItemModel?)
-> Self
{
var view = self
Expand All @@ -350,7 +350,7 @@ extension CalendarViewRepresentable {
/// - month: The `Month` for which to provide a month header view.
/// - Returns: A new `CalendarViewRepresentable` with custom month header views configured.
public func monthHeaders(
@ViewBuilder _ content: @escaping (_ month: Month) -> some View)
@ViewBuilder _ content: @escaping (_ month: MonthComponents) -> some View)
-> CalendarViewRepresentable
{
monthHeaderItemProvider { month in
Expand All @@ -377,7 +377,7 @@ extension CalendarViewRepresentable {
/// - Returns: A new `CalendarViewRepresentable` with a new day-of-week item provider.
public func dayOfWeekItemProvider(
_ dayOfWeekItemProvider: @escaping (
_ month: Month?,
_ month: MonthComponents?,
_ weekdayIndex: Int)
-> AnyCalendarItemModel?)
-> Self
Expand All @@ -401,7 +401,7 @@ extension CalendarViewRepresentable {
/// - weekdayIndex: The weekday index for which to provide a day-of-week header view.
/// - Returns: A new `CalendarViewRepresentable` with custom day-of-week header views configured.
public func dayOfWeekHeaders(
_ content: @escaping (_ month: Month?, _ weekdayIndex: Int) -> some View)
_ content: @escaping (_ month: MonthComponents?, _ weekdayIndex: Int) -> some View)
-> Self
{
dayOfWeekItemProvider { month, weekdayIndex in
Expand All @@ -425,7 +425,7 @@ extension CalendarViewRepresentable {
/// - day: The `Day` for which to provide a day item.
/// - Returns: A new `CalendarViewRepresentable` with a new day item provider.
public func dayItemProvider(
_ dayItemProvider: @escaping (_ day: Day) -> AnyCalendarItemModel?)
_ dayItemProvider: @escaping (_ day: DayComponents) -> AnyCalendarItemModel?)
-> Self
{
var view = self
Expand All @@ -445,7 +445,7 @@ extension CalendarViewRepresentable {
/// - day: The `Day` for which to provide a day view.
/// - Returns: A new `CalendarViewRepresentable` with custom day views configured.
public func days(
@ViewBuilder _ content: @escaping (_ day: Day) -> some View)
@ViewBuilder _ content: @escaping (_ day: DayComponents) -> some View)
-> Self
{
dayItemProvider { day in
Expand All @@ -468,7 +468,7 @@ extension CalendarViewRepresentable {
/// - day: The `Day` for which to provide a day background item.
/// - Returns: A new `CalendarViewRepresentable` with a new day background item provider.
public func dayBackgroundItemProvider(
_ dayBackgroundItemProvider: @escaping (_ day: Day) -> AnyCalendarItemModel?)
_ dayBackgroundItemProvider: @escaping (_ day: DayComponents) -> AnyCalendarItemModel?)
-> Self
{
var view = self
Expand All @@ -488,7 +488,7 @@ extension CalendarViewRepresentable {
/// - day: The `Day` for which to provide a day background view.
/// - Returns: A new `CalendarViewRepresentable` with day background views configured.
public func dayBackgrounds(
@ViewBuilder _ content: @escaping (_ day: Day) -> some View)
@ViewBuilder _ content: @escaping (_ day: DayComponents) -> some View)
-> Self
{
dayBackgroundItemProvider { day in
Expand Down Expand Up @@ -685,7 +685,7 @@ extension CalendarViewRepresentable {
///
/// - Parameters:
/// - daySelectionHandler: A closure (that is retained) that is invoked whenever a day is selected.
public func onDaySelection(_ daySelectionHandler: @escaping (Day) -> Void) -> Self {
public func onDaySelection(_ daySelectionHandler: @escaping (DayComponents) -> Void) -> Self {
var view = self
view.daySelectionHandler = daySelectionHandler
return view
Expand All @@ -704,9 +704,9 @@ extension CalendarViewRepresentable {
/// - changed: A closure (that is retained) that is invoked when the multiple-day-selection drag gesture intersects a new day.
/// - ended: A closure (that is retained) that is invoked when the multiple-day-selection drag gesture ends.
public func onMultipleDaySelectionDrag(
began: @escaping (Day) -> Void,
changed: @escaping (Day) -> Void,
ended: @escaping (Day) -> Void)
began: @escaping (DayComponents) -> Void,
changed: @escaping (DayComponents) -> Void,
ended: @escaping (DayComponents) -> Void)
-> Self
{
var view = self
Expand All @@ -726,7 +726,7 @@ extension CalendarViewRepresentable {
}

public func onScroll(
_ scrollHandler: @escaping (_ visibleDayRange: DayRange, _ isUserDragging: Bool) -> Void)
_ scrollHandler: @escaping (_ visibleDayRange: DayComponentsRange, _ isUserDragging: Bool) -> Void)
-> Self
{
var view = self
Expand All @@ -735,7 +735,7 @@ extension CalendarViewRepresentable {
}

public func onDragEnd(
_ dragEndHandler: @escaping (_ visibleDayRange: DayRange, _ willDecelerate: Bool) -> Void)
_ dragEndHandler: @escaping (_ visibleDayRange: DayComponentsRange, _ willDecelerate: Bool) -> Void)
-> Self
{
var view = self
Expand All @@ -744,7 +744,7 @@ extension CalendarViewRepresentable {
}

public func onDeceleratingEnd(
_ deceleratingEndHandler: @escaping (_ visibleDayRange: DayRange) -> Void)
_ deceleratingEndHandler: @escaping (_ visibleDayRange: DayComponentsRange) -> Void)
-> Self
{
var view = self
Expand Down
21 changes: 13 additions & 8 deletions Sources/Public/Day.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,25 @@ import Foundation

// MARK: - Day

/// Represents the components of a day (with a corresponding year and month) in a particular calendar. All days are assumed to have
/// been instantiated with the same `Calendar`, which is enforced throughout the implementation.
public struct Day: Hashable {
typealias Day = DayComponents

// MARK: - DayComponents

/// Represents the components of a day. This type is created internally, then vended to you via the public API. All `DayComponents`
/// instances that are vended to you are created using the `Calendar` instance that you provide when initializing your
/// `CalendarView`.
public struct DayComponents: Hashable {

// MARK: Lifecycle

init(month: Month, day: Int) {
init(month: MonthComponents, day: Int) {
self.month = month
self.day = day
}

// MARK: Public

public let month: Month
public let month: MonthComponents
public let day: Int

public var components: DateComponents {
Expand All @@ -41,7 +46,7 @@ public struct Day: Hashable {

// MARK: CustomStringConvertible

extension Day: CustomStringConvertible {
extension DayComponents: CustomStringConvertible {

public var description: String {
let yearDescription = String(format: "%04d", month.year)
Expand All @@ -54,9 +59,9 @@ extension Day: CustomStringConvertible {

// MARK: Comparable

extension Day: Comparable {
extension DayComponents: Comparable {

public static func < (lhs: Day, rhs: Day) -> Bool {
public static func < (lhs: DayComponents, rhs: DayComponents) -> Bool {
guard lhs.month == rhs.month else { return lhs.month < rhs.month }
return lhs.day < rhs.day
}
Expand Down
10 changes: 7 additions & 3 deletions Sources/Public/DayRange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@

import Foundation

// MARK: - DayRange
// MARK: DayRange

public typealias DayRange = ClosedRange<Day>
typealias DayRange = DayComponentsRange

extension DayRange {
// MARK: - DayComponentsRange

public typealias DayComponentsRange = ClosedRange<DayComponents>

extension DayComponentsRange {

/// Instantiates a `DayRange` that encapsulates the `dateRange` in the `calendar` as closely as possible. For example,
/// a date range of [2020-05-20T23:59:59, 2021-01-01T00:00:00] will result in a day range of [2020-05-20, 2021-01-01].
Expand Down
4 changes: 2 additions & 2 deletions Sources/Public/DayRangeLayoutContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import CoreGraphics
/// of those frames. This can be used in a custom day range view to draw the day range in the correct location.
public struct DayRangeLayoutContext: Hashable {
/// The day range that this layout context describes.
public let dayRange: DayRange
public let dayRange: DayComponentsRange

/// An ordered list of tuples containing day and day frame pairs.
///
/// Each frame represents the frame of an individual day in the day range in the coordinate system of
/// `boundingUnionRectOfDayFrames`. If a day range extends beyond the `visibleDateRange`, this array will only
/// contain the day-frame pairs for the visible portion of the day range.
public let daysAndFrames: [(day: Day, frame: CGRect)]
public let daysAndFrames: [(day: DayComponents, frame: CGRect)]

/// A rectangle that perfectly contains all day frames in `daysAndFrames`. In other words, it is the union of all day frames in
/// `daysAndFrames`.
Expand Down
17 changes: 11 additions & 6 deletions Sources/Public/Month.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ import Foundation

// MARK: - Month

/// Represents the components of a month (with a corresponding year) in a particular calendar. All months are assumed to have been
/// instantiated with the same `Calendar`, which is enforced throughout the implementation.
public struct Month: Hashable {
typealias Month = MonthComponents

// MARK: - MonthComponents

/// Represents the components of a month. This type is created internally, then vended to you via the public API. All
/// `MonthComponents` instances that are vended to you are created using the `Calendar` instance that you provide when
/// initializing your `CalendarView`.
public struct MonthComponents: Hashable {

// MARK: Lifecycle

Expand Down Expand Up @@ -50,7 +55,7 @@ public struct Month: Hashable {

// MARK: CustomStringConvertible

extension Month: CustomStringConvertible {
extension MonthComponents: CustomStringConvertible {

public var description: String {
"\(String(format: "%04d", year))-\(String(format: "%02d", month))"
Expand All @@ -60,9 +65,9 @@ extension Month: CustomStringConvertible {

// MARK: Comparable

extension Month: Comparable {
extension MonthComponents: Comparable {

public static func < (lhs: Month, rhs: Month) -> Bool {
public static func < (lhs: MonthComponents, rhs: MonthComponents) -> Bool {
guard lhs.era == rhs.era else { return lhs.era < rhs.era }

let lhsCorrectedYear = lhs.isInGregorianCalendar && lhs.era == 0 ? -lhs.year : lhs.year
Expand Down
4 changes: 2 additions & 2 deletions Sources/Public/MonthLayoutContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import CoreGraphics
public struct MonthLayoutContext: Hashable {

/// The month that this layout context describes.
public let month: Month
public let month: MonthComponents

/// The frame of the month header in the coordinate system of `bounds`.
public let monthHeaderFrame: CGRect
Expand All @@ -36,7 +36,7 @@ public struct MonthLayoutContext: Hashable {
/// An ordered list of tuples containing day and day frame pairs.
///
/// Each frame represents the frame of an individual day in the month in the coordinate system of `bounds`.
public let daysAndFrames: [(day: Day, frame: CGRect)]
public let daysAndFrames: [(day: DayComponents, frame: CGRect)]

/// The bounds into which a background can be drawn without getting clipped. Additionally, all other frames in this type are in the
/// coordinate system of this.
Expand Down
6 changes: 5 additions & 1 deletion Sources/Public/MonthRange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import Foundation

// MARK: - MonthRange

public typealias MonthRange = ClosedRange<Month>
typealias MonthRange = MonthComponentsRange

// MARK: - MonthComponentsRange

public typealias MonthComponentsRange = ClosedRange<MonthComponents>

extension MonthRange {

Expand Down

0 comments on commit 950a0e9

Please sign in to comment.