diff --git a/Example/Source/MainView.swift b/Example/Source/MainView.swift index b5417cb..419b917 100644 --- a/Example/Source/MainView.swift +++ b/Example/Source/MainView.swift @@ -55,58 +55,42 @@ struct MainView: View { .navigationTitle("SwiftUI presentation") .frame(maxWidth: .infinity, maxHeight: .infinity) .sheet(isPresented: $showRangeCalendar) { - self.rangeCalendarView() - } - .sheet(isPresented: $showSingleCalendar) { - self.singleCalendarView() - } - } - - private func rangeCalendarView() -> some View { - let config: FastisConfig = .default - var fastisView = FastisView(mode: .range, config: config) - fastisView.title = "Choose range" - fastisView.initialValue = self.currentValue as? FastisRange - fastisView.minimumDate = Calendar.current.date(byAdding: .month, value: -2, to: Date()) - fastisView.maximumDate = Calendar.current.date(byAdding: .month, value: 3, to: Date()) - fastisView.allowToChooseNilDate = true - fastisView.allowDateRangeChanges = false - fastisView.shortcuts = [.lastWeek, .lastMonth] - fastisView.selectMonthOnHeaderTap = true - - fastisView.dismissHandler = { action in - switch action { - case .done(let newValue): - self.currentValue = newValue - case .cancel: - print("any actions") + FastisView(mode: .range) { action in + switch action { + case .done(let newValue): + self.currentValue = newValue + case .cancel: + print("any actions") + } } + .title("Choose range") + .initialValue(self.currentValue as? FastisRange) + .minimumDate(Calendar.current.date(byAdding: .month, value: -2, to: Date())) + .maximumDate(Calendar.current.date(byAdding: .month, value: 3, to: Date())) + .allowToChooseNilDate(true) + .allowDateRangeChanges(false) + .shortcuts([.lastWeek, .lastMonth]) + .selectMonthOnHeaderTap(true) + .ignoresSafeArea() } - return fastisView.ignoresSafeArea() - } - - private func singleCalendarView() -> some View { - let config: FastisConfig = .default - var fastisView = FastisView(mode: .single, config: config) - fastisView.title = "Choose date" - fastisView.initialValue = self.currentValue as? Date - fastisView.minimumDate = Calendar.current.date(byAdding: .month, value: -2, to: Date()) - fastisView.maximumDate = Date() - fastisView.allowToChooseNilDate = true - fastisView.allowDateRangeChanges = false - fastisView.shortcuts = [.yesterday, .today, .tomorrow] - fastisView.closeOnSelectionImmediately = true - - fastisView.dismissHandler = { action in - switch action { - case .done(let newValue): - self.currentValue = newValue - case .cancel: - print("any actions") + .sheet(isPresented: $showSingleCalendar) { + FastisView(mode: .single) { action in + switch action { + case .done(let newValue): + self.currentValue = newValue + case .cancel: + print("any actions") + } } + .title("Choose date") + .initialValue(self.currentValue as? Date) + .minimumDate(Calendar.current.date(byAdding: .month, value: -2, to: Date())) + .maximumDate(Date()) + .allowToChooseNilDate(true) + .allowDateRangeChanges(false) + .shortcuts([.yesterday, .today, .tomorrow]) + .closeOnSelectionImmediately(true) + .ignoresSafeArea() } - return fastisView.ignoresSafeArea() } - } - diff --git a/Sources/Views/FastisView.swift b/Sources/Views/FastisView.swift index e172819..532139c 100644 --- a/Sources/Views/FastisView.swift +++ b/Sources/Views/FastisView.swift @@ -12,76 +12,128 @@ import SwiftUI View of Fastis framework. Use it to create and present dade picker Usage example: - ```swift - let fastisView = FastisView(mode: .range) - fastisView.title = "Choose range" - fastisView.maximumDate = Date() - fastisView.allowToChooseNilDate = true - fastisView.shortcuts = [.today, .lastWeek] - fastisView.dismissHandler = { [weak self] action in - switch action { - case .done(let newValue): - ... - case .cancel: - ... - } + ```swiftUI + FastisView(mode: .range) { action in + switch action { + case .done(let newValue): + ... + case .cancel: + ... + } } + .title = "Choose range" + .maximumDate = Date() + .allowToChooseNilDate = true + .shortcuts = [.today, .lastWeek] ``` **Single and range modes** If you want to get a single date you have to use `Date` type: - ```swift - let fastisView = FastisView(mode: .single) - fastisView.initialValue = Date() - fastisView.closeOnSelectionImmediately = true - fastisView.dismissHandler = { [weak self] action in - switch action { - case .done(let resultDate): - print(resultDate) // resultDate is Date - case .cancel: - ... - } - } + ```swiftUI +FastisView(mode: .single) { action in + switch action { + case .done(let resultDate): + print(resultDate) // resultDate is Date + case .cancel: + ... + } +} +.initialValue = Date() +.closeOnSelectionImmediately = true ``` If you want to get a date range you have to use `FastisRange` type: - ```swift - let fastisView = FastisView(mode: .range) - fastisView.initialValue = FastisRange(from: Date(), to: Date()) // or .from(Date(), to: Date()) - fastisView.dismissHandler = { [weak self] action in - switch action { - case .done(let resultRange): - print(resultRange) // resultRange is FastisRange - case .cancel: - ... - } + ```swiftUI +FastisView(mode: .range) { action in + switch action { + case .done(let resultRange): + print(resultRange) // resultRange is FastisRange + case .cancel: + ... + } } +.initialValue = FastisRange(from: Date(), to: Date()) // or .from(Date(), to: Date()) ``` */ public struct FastisView: UIViewControllerRepresentable { + private var privateSelectMonthOnHeaderTap = false + private var privateCloseOnSelectionImmediately = false + private let config: FastisConfig + + /** + And title controller + */ public var title: String? = nil + + /** + And initial value which will be selected by default + */ public var initialValue: Value? = nil + + /** + Minimal selection date. Dates less then current will be marked as unavailable + */ public var minimumDate: Date? = nil + + /** + Maximum selection date. Dates greater then current will be marked as unavailable + */ public var maximumDate: Date? = nil + + /** + Allow to choose `nil` date + + When `allowToChooseNilDate` is `true`: + * "Done" button will be always enabled + * You will be able to reset selection by you tapping on selected date again + */ public var allowToChooseNilDate: Bool = false + + /** + Allow date range changes + + Set this variable to `false` if you want to disable date range changes. + Next tap after selecting range will start new range selection. + */ public var allowDateRangeChanges: Bool = true - public var shortcuts: [FastisShortcut] = [] - public var dismissHandler: ((FastisController.DismissAction) -> Void)? = nil - private var privateSelectMonthOnHeaderTap = false - private var privateCloseOnSelectionImmediately = false + /** + Shortcuts array - private let config: FastisConfig + You can use prepared shortcuts depending on the current mode. + + - For `.single` mode: `.today`, `.tomorrow`, `.yesterday` + - For `.range` mode: `.today`, `.lastWeek`, `.lastMonth` + + Or you can create your own shortcuts: + + ``` + var customShortcut = FastisShortcut(name: "Today") { + let now = Date() + return FastisRange(from: now.startOfDay(), to: now.endOfDay()) + } + ``` + */ + public var shortcuts: [FastisShortcut] = [] + + /** + The block to execute after the dismissal finishes, return two variable .done(FastisValue?) and .cancel + */ + public var dismissHandler: ((FastisController.DismissAction) -> Void)? = nil /// Initiate FastisView /// - Parameter config: Configuration parameters - init(config: FastisConfig = .default) { + public init( + config: FastisConfig = .default, + dismissHandler: ((FastisController.DismissAction) -> Void)? = nil + ) { self.config = config + self.dismissHandler = dismissHandler } public func makeUIViewController(context: Context) -> UINavigationController { @@ -117,8 +169,12 @@ public extension FastisView where Value == FastisRange { /// - Parameters: /// - mode: Choose `.range` or `.single` mode /// - config: Custom configuration parameters. Default value is equal to `FastisConfig.default` - init(mode: FastisModeRange, config: FastisConfig = .default) { - self.init(config: config) + init( + mode: FastisModeRange, + config: FastisConfig = .default, + dismissHandler: ((FastisController.DismissAction) -> Void)? = nil + ) { + self.init(config: config, dismissHandler: dismissHandler) } /** @@ -140,8 +196,12 @@ public extension FastisView where Value == Date { /// - Parameters: /// - mode: Choose .range or .single mode /// - config: Custom configuration parameters. Default value is equal to `FastisConfig.default` - init(mode: FastisModeSingle, config: FastisConfig = .default) { - self.init(config: config) + init( + mode: FastisModeSingle, + config: FastisConfig = .default, + dismissHandler: ((FastisController.DismissAction) -> Void)? = nil + ) { + self.init(config: config, dismissHandler: dismissHandler) } /** @@ -159,3 +219,74 @@ public extension FastisView where Value == Date { } } +public extension FastisView { + + /// Modifier for property 'title' + func title(_ value: String?) -> FastisView { + var view = self + view.title = value + return view + } + + /// Modifier for property 'initialValue' + func initialValue(_ value: Value?) -> FastisView { + var view = self + view.initialValue = value + return view + } + + /// Modifier for property 'minimumDate' + func minimumDate(_ value: Date?) -> FastisView { + var view = self + view.minimumDate = value + return view + } + + /// Modifier for property 'maximumDate' + func maximumDate(_ value: Date?) -> FastisView { + var view = self + view.maximumDate = value + return view + } + + /// Modifier for property 'allowToChooseNilDate' + func allowToChooseNilDate(_ value: Bool) -> FastisView { + var view = self + view.allowToChooseNilDate = value + return view + } + + /// Modifier for property 'allowDateRangeChanges' + func allowDateRangeChanges(_ value: Bool) -> FastisView { + var view = self + view.allowDateRangeChanges = value + return view + } + + /// Modifier for property 'shortcuts' + func shortcuts(_ value: [FastisShortcut]) -> FastisView { + var view = self + view.shortcuts = value + return view + } +} + +public extension FastisView where Value == FastisRange { + + /// Modifier for property 'selectMonthOnHeaderTap' + func selectMonthOnHeaderTap(_ value: Bool) -> FastisView { + var view = self + view.selectMonthOnHeaderTap = value + return view + } +} + +public extension FastisView where Value == Date { + + /// Modifier for property 'closeOnSelectionImmediately' + func closeOnSelectionImmediately(_ value: Bool) -> FastisView { + var view = self + view.closeOnSelectionImmediately = value + return view + } +}