Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2f5bd7d16 | |||
| b012aecb6b | |||
| 22b4ddd47e | |||
| 17a8231f20 | |||
| 1819113e97 | |||
| 208640e03e | |||
| f02439dc0c | |||
| 047415090a | |||
| 1e7c0534fc | |||
| 7f07cdff27 | |||
| 45f8dfcf19 |
@@ -0,0 +1,22 @@
|
||||
// swift-tools-version:5.1
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "PanModal",
|
||||
platforms: [.iOS(.v10)],
|
||||
products: [
|
||||
.library(
|
||||
name: "PanModal",
|
||||
targets: ["PanModal"]),
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
.target(
|
||||
name: "PanModal",
|
||||
dependencies: [],
|
||||
path: "PanModal")
|
||||
],
|
||||
swiftLanguageVersions: [.version("5.0")]
|
||||
)
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'PanModal'
|
||||
s.version = '1.2.5'
|
||||
s.version = '1.2.7'
|
||||
s.summary = 'PanModal is an elegant and highly customizable presentation API for constructing bottom sheet modals on iOS.'
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -36,3 +37,4 @@ struct PanModalAnimator {
|
||||
completion: completion)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -168,3 +169,4 @@ extension PanModalPresentationAnimator: UIViewControllerAnimatedTransitioning {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ open class PanModalPresentationController: UIPresentationController {
|
||||
}
|
||||
view.didTap = { [weak self] _ in
|
||||
if self?.presentable?.allowsTapToDismiss == true {
|
||||
self?.dismissPresentedViewController()
|
||||
self?.presentedViewController.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
return view
|
||||
@@ -191,7 +192,14 @@ open class PanModalPresentationController: UIPresentationController {
|
||||
})
|
||||
}
|
||||
|
||||
override public func presentationTransitionDidEnd(_ completed: Bool) {
|
||||
if completed { return }
|
||||
|
||||
backgroundView.removeFromSuperview()
|
||||
}
|
||||
|
||||
override public func dismissalTransitionWillBegin() {
|
||||
presentable?.panModalWillDismiss()
|
||||
|
||||
guard let coordinator = presentedViewController.transitionCoordinator else {
|
||||
backgroundView.dimState = .off
|
||||
@@ -209,10 +217,10 @@ open class PanModalPresentationController: UIPresentationController {
|
||||
})
|
||||
}
|
||||
|
||||
override public func presentationTransitionDidEnd(_ completed: Bool) {
|
||||
if completed { return }
|
||||
|
||||
backgroundView.removeFromSuperview()
|
||||
override public func dismissalTransitionDidEnd(_ completed: Bool) {
|
||||
if !completed { return }
|
||||
|
||||
presentable?.panModalDidDismiss()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +318,7 @@ private extension PanModalPresentationController {
|
||||
var isPresentedViewAnchored: Bool {
|
||||
if !isPresentedViewAnimating
|
||||
&& extendsPanScrolling
|
||||
&& presentedView.frame.minY <= anchoredYPosition {
|
||||
&& presentedView.frame.minY.rounded() <= anchoredYPosition.rounded() {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -366,7 +374,8 @@ private extension PanModalPresentationController {
|
||||
if ![shortFormYPosition, longFormYPosition].contains(panFrame.origin.y) {
|
||||
// if the container is already in the correct position, no need to adjust positioning
|
||||
// (rotations & size changes cause positioning to be out of sync)
|
||||
adjust(toYPosition: panFrame.origin.y - panFrame.height + frame.height)
|
||||
let yPosition = panFrame.origin.y - panFrame.height + frame.height
|
||||
presentedView.frame.origin.y = max(yPosition, anchoredYPosition)
|
||||
}
|
||||
panContainerView.frame.origin.x = frame.origin.x
|
||||
presentedViewController.view.frame = CGRect(origin: .zero, size: adjustedSize)
|
||||
@@ -514,7 +523,7 @@ private extension PanModalPresentationController {
|
||||
transition(to: .shortForm)
|
||||
|
||||
} else {
|
||||
dismissPresentedViewController()
|
||||
presentedViewController.dismiss(animated: true)
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -532,7 +541,7 @@ private extension PanModalPresentationController {
|
||||
transition(to: .shortForm)
|
||||
|
||||
} else {
|
||||
dismissPresentedViewController()
|
||||
presentedViewController.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -671,16 +680,6 @@ private extension PanModalPresentationController {
|
||||
else { return number }
|
||||
return nearestVal
|
||||
}
|
||||
|
||||
/**
|
||||
Dismiss presented view
|
||||
*/
|
||||
func dismissPresentedViewController() {
|
||||
presentable?.panModalWillDismiss()
|
||||
presentedViewController.dismiss(animated: true) { [weak self] in
|
||||
self?.presentable?.panModalDidDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UIScrollView Observer
|
||||
@@ -890,3 +889,4 @@ private extension UIScrollView {
|
||||
return isDragging && !isDecelerating || isTracking
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -77,3 +78,4 @@ extension PanModalPresentationDelegate: UIAdaptivePresentationControllerDelegate
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -40,3 +41,4 @@ public enum PanModalHeight: Equatable {
|
||||
*/
|
||||
case intrinsicHeight
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -124,3 +125,4 @@ public extension PanModalPresentable where Self: UIViewController {
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -26,7 +27,11 @@ extension PanModalPresentable where Self: UIViewController {
|
||||
Gives us the safe area inset from the top.
|
||||
*/
|
||||
var topLayoutOffset: CGFloat {
|
||||
return UIApplication.shared.keyWindow?.rootViewController?.topLayoutGuide.length ?? 0
|
||||
|
||||
guard let rootVC = rootViewController
|
||||
else { return 0}
|
||||
|
||||
if #available(iOS 11.0, *) { return rootVC.view.safeAreaInsets.top } else { return rootVC.topLayoutGuide.length }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,7 +39,11 @@ extension PanModalPresentable where Self: UIViewController {
|
||||
Gives us the safe area inset from the bottom.
|
||||
*/
|
||||
var bottomLayoutOffset: CGFloat {
|
||||
return UIApplication.shared.keyWindow?.rootViewController?.bottomLayoutGuide.length ?? 0
|
||||
|
||||
guard let rootVC = rootViewController
|
||||
else { return 0}
|
||||
|
||||
if #available(iOS 11.0, *) { return rootVC.view.safeAreaInsets.bottom } else { return rootVC.bottomLayoutGuide.length }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,4 +108,13 @@ extension PanModalPresentable where Self: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private var rootViewController: UIViewController? {
|
||||
|
||||
guard let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as? UIApplication
|
||||
else { return nil }
|
||||
|
||||
return application.keyWindow?.rootViewController
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -59,3 +60,4 @@ public extension PanModalPresentable where Self: UIViewController {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2017 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -233,3 +234,4 @@ public protocol PanModalPresentable: AnyObject {
|
||||
*/
|
||||
func panModalDidDismiss()
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -28,6 +29,10 @@ protocol PanModalPresenter: AnyObject {
|
||||
/**
|
||||
Presents a view controller that conforms to the PanModalPresentable protocol
|
||||
*/
|
||||
func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType, sourceView: UIView?, sourceRect: CGRect)
|
||||
func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType,
|
||||
sourceView: UIView?,
|
||||
sourceRect: CGRect,
|
||||
completion: (() -> Void)?)
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2019 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -34,10 +35,14 @@ extension UIViewController: PanModalPresenter {
|
||||
- viewControllerToPresent: The view controller to be presented
|
||||
- sourceView: The view containing the anchor rectangle for the popover.
|
||||
- sourceRect: The rectangle in the specified view in which to anchor the popover.
|
||||
- completion: The block to execute after the presentation finishes. You may specify nil for this parameter.
|
||||
|
||||
- Note: sourceView & sourceRect are only required for presentation on an iPad.
|
||||
*/
|
||||
public func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType, sourceView: UIView? = nil, sourceRect: CGRect = .zero) {
|
||||
public func presentPanModal(_ viewControllerToPresent: PanModalPresentable.LayoutType,
|
||||
sourceView: UIView? = nil,
|
||||
sourceRect: CGRect = .zero,
|
||||
completion: (() -> Void)? = nil) {
|
||||
|
||||
/**
|
||||
Here, we deliberately do not check for size classes. More info in `PanModalPresentationDelegate`
|
||||
@@ -54,7 +59,8 @@ extension UIViewController: PanModalPresenter {
|
||||
viewControllerToPresent.transitioningDelegate = PanModalPresentationDelegate.default
|
||||
}
|
||||
|
||||
present(viewControllerToPresent, animated: true, completion: nil)
|
||||
present(viewControllerToPresent, animated: true, completion: completion)
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2017 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -72,3 +73,4 @@ public class DimmedView: UIView {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
/**
|
||||
@@ -40,3 +41,4 @@ extension UIView {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -54,6 +54,14 @@ pod 'PanModal'
|
||||
github "slackhq/PanModal"
|
||||
```
|
||||
|
||||
* <a href="https://swift.org/package-manager/" target="_blank">Swift Package Manager</a>:
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/slackhq/PanModal.git", .exact("1.2.6")),
|
||||
],
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
PanModal was designed to be used effortlessly. Simply call `presentPanModal` in the same way you would expect to present a `UIViewController`
|
||||
@@ -139,7 +147,7 @@ We will only be fixing critical bugs, thus, for any non-critical issues or featu
|
||||
|
||||
## Authors
|
||||
|
||||
[Stephen Sowole](https://github.com/tun57) • [Tosin Afolabi](https://github.com/tosinaf)
|
||||
[Stephen Sowole](https://github.com/ste57) • [Tosin Afolabi](https://github.com/tosinaf)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user