diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3d3d0dd..35ea5c19f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Changed +- `ListLayout` and its associated types are now public, allowing you to make custom layouts. Note that these APIs are still experimental and subject to change. + ### Misc # Past Releases diff --git a/ListableUI/Sources/Layout/ListLayout/LayoutDescription.swift b/ListableUI/Sources/Layout/ListLayout/LayoutDescription.swift index 497ef03fc..17ba9388f 100644 --- a/ListableUI/Sources/Layout/ListLayout/LayoutDescription.swift +++ b/ListableUI/Sources/Layout/ListLayout/LayoutDescription.swift @@ -53,10 +53,10 @@ public struct LayoutDescription } -public extension ListLayout +extension ListLayout { /// Creates a new layout description for a list layout, with the provided optional layout configuration. - static func describe( + public static func describe( appearance : @escaping (inout Self.LayoutAppearance) -> () = { _ in } ) -> LayoutDescription { @@ -70,15 +70,15 @@ public extension ListLayout extension LayoutDescription { - struct Configuration : AnyLayoutDescriptionConfiguration + public struct Configuration : AnyLayoutDescriptionConfiguration { - let layoutType : LayoutType.Type + public let layoutType : LayoutType.Type - let configure : (inout LayoutType.LayoutAppearance) -> () + public let configure : (inout LayoutType.LayoutAppearance) -> () // MARK: AnyLayoutDescriptionConfiguration - func createEmptyLayout( + public func createEmptyLayout( appearance : Appearance, behavior: Behavior ) -> AnyListLayout diff --git a/ListableUI/Sources/Layout/ListLayout/ListLayout.swift b/ListableUI/Sources/Layout/ListLayout/ListLayout.swift index d781dd354..d9451da61 100644 --- a/ListableUI/Sources/Layout/ListLayout/ListLayout.swift +++ b/ListableUI/Sources/Layout/ListLayout/ListLayout.swift @@ -33,7 +33,7 @@ public struct ListLayoutLayoutContext { public var environment : ListEnvironment - init( + public init( viewBounds : CGRect, safeAreaInsets : UIEdgeInsets, environment : ListEnvironment @@ -54,13 +54,13 @@ public struct ListLayoutLayoutContext { } } -public extension ListLayout +extension ListLayout { - var direction: LayoutDirection { + public var direction: LayoutDirection { self.layoutAppearance.direction } - var stickySectionHeaders: Bool { + public var stickySectionHeaders: Bool { self.layoutAppearance.stickySectionHeaders } } @@ -109,9 +109,9 @@ public protocol AnyListLayout : AnyObject } -public extension AnyListLayout +extension AnyListLayout { - func setZIndexes() + public func setZIndexes() { self.content.header.zIndex = 5 @@ -129,7 +129,7 @@ public extension AnyListLayout self.content.overscrollFooter.zIndex = 0 } - func adjust( + public func adjust( layoutAttributesForReorderingItem attributes : inout ListContentLayoutAttributes, originalAttributes : ListContentLayoutAttributes, at indexPath: IndexPath, @@ -140,9 +140,9 @@ public extension AnyListLayout } -public extension AnyListLayout +extension AnyListLayout { - func visibleContentFrame(for collectionView : UICollectionView) -> CGRect + public func visibleContentFrame(for collectionView : UICollectionView) -> CGRect { CGRect( x: collectionView.contentOffset.x + collectionView.safeAreaInsets.left, @@ -154,9 +154,9 @@ public extension AnyListLayout } -public extension AnyListLayout +extension AnyListLayout { - func positionStickySectionHeadersIfNeeded(in collectionView : UICollectionView) + public func positionStickySectionHeadersIfNeeded(in collectionView : UICollectionView) { guard self.stickySectionHeaders else { return @@ -183,7 +183,7 @@ public extension AnyListLayout } } - func updateOverscrollFooterPosition(in collectionView : UICollectionView) + public func updateOverscrollFooterPosition(in collectionView : UICollectionView) { guard self.direction == .vertical else { // Currently only supported for vertical layouts. @@ -205,7 +205,7 @@ public extension AnyListLayout } } - func adjustPositionsForLayoutUnderflow(in collectionView : UICollectionView) + public func adjustPositionsForLayoutUnderflow(in collectionView : UICollectionView) { guard self.direction == .vertical else { // Currently only supported for vertical layouts. diff --git a/ListableUI/Sources/Layout/ListLayout/ListLayoutAttributes.swift b/ListableUI/Sources/Layout/ListLayout/ListLayoutAttributes.swift index 2e5eb19a2..a254ad57d 100644 --- a/ListableUI/Sources/Layout/ListLayout/ListLayoutAttributes.swift +++ b/ListableUI/Sources/Layout/ListLayout/ListLayoutAttributes.swift @@ -9,7 +9,7 @@ import Foundation import UIKit -public struct ListLayoutAttributes : Equatable { +struct ListLayoutAttributes : Equatable { var contentSize : CGSize diff --git a/ListableUI/Sources/Layout/ListLayout/ListLayoutContent.swift b/ListableUI/Sources/Layout/ListLayout/ListLayoutContent.swift index 5fc975317..98e49912b 100644 --- a/ListableUI/Sources/Layout/ListLayout/ListLayoutContent.swift +++ b/ListableUI/Sources/Layout/ListLayout/ListLayoutContent.swift @@ -11,17 +11,17 @@ import UIKit public final class ListLayoutContent { - var contentSize : CGSize + public var contentSize : CGSize - let containerHeader : SupplementaryItemInfo - let header : SupplementaryItemInfo - let footer : SupplementaryItemInfo + public let containerHeader : SupplementaryItemInfo + public let header : SupplementaryItemInfo + public let footer : SupplementaryItemInfo - let overscrollFooter : SupplementaryItemInfo + public let overscrollFooter : SupplementaryItemInfo - let sections : [SectionInfo] + public let sections : [SectionInfo] - var all : [ListLayoutContentItem] { + public var all : [ListLayoutContentItem] { var all : [ListLayoutContentItem] = [] if header.isPopulated { @@ -248,7 +248,7 @@ public final class ListLayoutContent } -protocol ListLayoutContentItem : AnyObject +public protocol ListLayoutContentItem : AnyObject { var size : CGSize { get set } var x : CGFloat { get set } @@ -258,18 +258,18 @@ protocol ListLayoutContentItem : AnyObject } -public extension ListLayoutContent +extension ListLayoutContent { - final class SectionInfo + public final class SectionInfo { let state : PresentationState.SectionState - let header : SupplementaryItemInfo - let footer : SupplementaryItemInfo + public let header : SupplementaryItemInfo + public let footer : SupplementaryItemInfo - var items : [ItemInfo] + public internal(set) var items : [ItemInfo] - var layouts : SectionLayouts { + public var layouts : SectionLayouts { self.state.model.layouts } @@ -325,7 +325,7 @@ public extension ListLayoutContent } } - final class SupplementaryItemInfo : ListLayoutContentItem + public final class SupplementaryItemInfo : ListLayoutContentItem { static func empty(_ kind : SupplementaryKind) -> SupplementaryItemInfo { @@ -339,32 +339,33 @@ public extension ListLayoutContent let state : AnyPresentationHeaderFooterState? let kind : SupplementaryKind - let measurer : (Sizing.MeasureInfo) -> CGSize + public let measurer : (Sizing.MeasureInfo) -> CGSize - let isPopulated : Bool + public let isPopulated : Bool - var size : CGSize = .zero + public var size : CGSize = .zero - var x : CGFloat = .zero + public var x : CGFloat = .zero var pinnedX : CGFloat? = nil - var y : CGFloat = .zero + public var y : CGFloat = .zero var pinnedY : CGFloat? = nil - var zIndex : Int = 0 + public var zIndex : Int = 0 - var layouts : HeaderFooterLayouts { + public var layouts : HeaderFooterLayouts { + // TODO: Why the ?? here self.state?.anyModel.layouts ?? .init() } - var defaultFrame : CGRect { + public var defaultFrame : CGRect { CGRect( origin: CGPoint(x: self.x, y: self.y), size: self.size ) } - var visibleFrame : CGRect { + public var visibleFrame : CGRect { CGRect( origin: CGPoint( x: self.pinnedX ?? self.x, @@ -398,25 +399,25 @@ public extension ListLayoutContent } - final class ItemInfo : ListLayoutContentItem + public final class ItemInfo : ListLayoutContentItem { let state : AnyPresentationItemState var indexPath : IndexPath let insertAndRemoveAnimations : ItemInsertAndRemoveAnimations - let measurer : (Sizing.MeasureInfo) -> CGSize + public let measurer : (Sizing.MeasureInfo) -> CGSize - var position : ItemPosition = .single + public var position : ItemPosition = .single - var size : CGSize = .zero + public var size : CGSize = .zero - var x : CGFloat = .zero - var y : CGFloat = .zero + public var x : CGFloat = .zero + public var y : CGFloat = .zero - var zIndex : Int = 0 + public var zIndex : Int = 0 - var layouts : ItemLayouts { + public var layouts : ItemLayouts { self.state.anyModel.layouts } diff --git a/ListableUI/Sources/Sizing.swift b/ListableUI/Sources/Sizing.swift index 79c1222c7..531d78aeb 100644 --- a/ListableUI/Sources/Sizing.swift +++ b/ListableUI/Sources/Sizing.swift @@ -134,11 +134,11 @@ extension Sizing { public struct MeasureInfo { - var sizeConstraint : CGSize - var defaultSize : CGSize - var direction : LayoutDirection + public var sizeConstraint : CGSize + public var defaultSize : CGSize + public var direction : LayoutDirection - init( + public init( sizeConstraint: CGSize, defaultSize: CGSize, direction: LayoutDirection @@ -332,8 +332,13 @@ public enum CustomWidth : Equatable public struct Position : Equatable { - var origin : CGFloat - var width : CGFloat + public var origin : CGFloat + public var width : CGFloat + + public init(origin: CGFloat, width: CGFloat) { + self.origin = origin + self.width = width + } } }