Digital ACT-191 ONEAPP-9311 story: changes about PR notes
This commit is contained in:
parent
7a9910e830
commit
928db0f1fc
@ -78,11 +78,8 @@ open class Carousel: View {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
/// Aspect-ratio options for tilelet in the carousel. If 'none' is passed, the tilelet will take the height of the tallest item in the carousel.
|
||||
open var aspectRatio: Tilelet.AspectRatio = .none { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// Data used to render tilelets in the carousel.
|
||||
open var data: [Any] = [] { didSet { setNeedsUpdate() } }
|
||||
/// views used to render view in the carousel slots.
|
||||
open var views: [UIView] = [] { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// If provided, width of slots will be rendered based on this value. If omitted, default widths are rendered.
|
||||
open var width: Width? {
|
||||
@ -110,19 +107,11 @@ open class Carousel: View {
|
||||
}
|
||||
|
||||
/// Space between each tile. The default value will be 24px (6X) in tablet and 12px (3X) in mobile.
|
||||
open var gutter: Gutter {
|
||||
get { return _gutter }
|
||||
set {
|
||||
_gutter = newValue
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
open var gutter: Gutter = UIDevice.isIPad ? .twentyFourPX : .twelvePX { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// The amount of slides visible in the carousel container at one time. The default value will be 3UP in tablet and 1UP in mobile.
|
||||
open var layout: CarouselScrollbar.Layout {
|
||||
get { return _layout }
|
||||
set {
|
||||
_layout = newValue
|
||||
open var layout: CarouselScrollbar.Layout = UIDevice.isIPad ? .threeUP : .oneUP {
|
||||
didSet {
|
||||
carouselScrollBar.position = 0
|
||||
setNeedsUpdate()
|
||||
}
|
||||
@ -143,82 +132,29 @@ open class Carousel: View {
|
||||
}
|
||||
|
||||
/// Config object for pagination.
|
||||
open var pagination: CarouselPaginationModel {
|
||||
get { return _pagination }
|
||||
set {
|
||||
_pagination = newValue
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
open var pagination: CarouselPaginationModel = .init(kind: .lowContrast, floating: true) { didSet {setNeedsUpdate() } }
|
||||
|
||||
/// If provided, will determine the conditions to render the pagination arrows.
|
||||
open var paginationDisplay: PaginationDisplay {
|
||||
get { return _paginationDisplay }
|
||||
set {
|
||||
_paginationDisplay = newValue
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
open var paginationDisplay: PaginationDisplay = .none { didSet {setNeedsUpdate() } }
|
||||
|
||||
/// If provided, will apply margin to pagination arrows. Can be set to either positive or negative values.
|
||||
/// The default value will be 12px in tablet and 8px in mobile. These values are the default in order to avoid overlapping content within the carousel.
|
||||
open var paginationInset: CGFloat {
|
||||
get { return _paginationInset }
|
||||
set {
|
||||
_paginationInset = newValue
|
||||
updatePaginationInset()
|
||||
}
|
||||
}
|
||||
open var paginationInset: CGFloat = UIDevice.isIPad ? VDSLayout.space3X : VDSLayout.space2X { didSet { updatePaginationInset() } }
|
||||
|
||||
/// Options for user to configure the partially-visible tile in group. Setting peek to 'none' will display arrow navigation icons on mobile devices.
|
||||
open var peek: Peek {
|
||||
get { return _peek }
|
||||
set {
|
||||
_peek = newValue
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
open var peek: Peek = .standard { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// The initial visible slide's index in the carousel.
|
||||
open var selectedIndex: Int? { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// If provided, will set the alignment for slot content when the slots has different heights.
|
||||
open var slotAlignment: CarouselSlotAlignmentModel? {
|
||||
get { return _slotAlignment }
|
||||
set {
|
||||
if let newValue {
|
||||
_slotAlignment = newValue
|
||||
} else {
|
||||
_slotAlignment = nil
|
||||
}
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
open var slotAlignment: CarouselSlotAlignmentModel? = nil { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// Render item style. If provided, the slot gets the background, width, height, border-radius.
|
||||
open var renderItemStyle: CarouselRenderItemStyle? {
|
||||
get { return _renderItemStyle }
|
||||
set {
|
||||
if let newValue {
|
||||
_renderItemStyle = newValue
|
||||
} else {
|
||||
_renderItemStyle = nil
|
||||
}
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
open var renderItemStyle: CarouselRenderItemStyle? = nil { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// Render item. It passes a data array object and expects the styled component to apply in return.
|
||||
open var renderItem: CarouselSlotItemModel? {
|
||||
get { _renderItem }
|
||||
set {
|
||||
if let newValue {
|
||||
_renderItem = newValue
|
||||
} else {
|
||||
_renderItem = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// /// Render item. It passes a data array object and expects the styled component to apply in return.
|
||||
// open var renderItem: CarouselSlotItemModel? = nil { didSet { setNeedsUpdate() } }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
@ -278,18 +214,6 @@ open class Carousel: View {
|
||||
/// A publisher for when the carousel moves. Passes parameters (data).
|
||||
open var onScrollPublisher = PassthroughSubject<Array<Any>, Never>()
|
||||
private var onScrollCancellable: AnyCancellable?
|
||||
|
||||
internal var _layout: CarouselScrollbar.Layout = UIDevice.isIPad ? .threeUP : .oneUP
|
||||
internal var _pagination: CarouselPaginationModel = .init(kind: .lowContrast, floating: true)
|
||||
internal var _paginationDisplay: PaginationDisplay = .none
|
||||
internal var _paginationInset: CGFloat = UIDevice.isIPad ? VDSLayout.space3X : VDSLayout.space2X
|
||||
internal var _gutter: Gutter = UIDevice.isIPad ? .twentyFourPX : .twelvePX
|
||||
internal var _peek: Peek = .standard
|
||||
internal var _numberOfSlides: Int = 1
|
||||
internal var _slotAlignment: CarouselSlotAlignmentModel? = nil
|
||||
internal var _renderItemStyle: CarouselRenderItemStyle? = nil
|
||||
internal var _renderItem: CarouselSlotItemModel? = nil
|
||||
|
||||
private var _width: Width? = nil
|
||||
private var selectedGroupIndex: Int? = nil
|
||||
private var containerStackHeightConstraint: NSLayoutConstraint?
|
||||
@ -301,7 +225,7 @@ open class Carousel: View {
|
||||
// The scrollbar has top 5X space. So the expected top space is adjusted for tablet and mobile.
|
||||
let scrollbarTopSpace = UIDevice.isIPad ? VDSLayout.space3X : VDSLayout.space1X
|
||||
|
||||
var slotHeight = 100.0
|
||||
var slotHeight = 50.0
|
||||
var peekMinimum = 24.0
|
||||
var minimumSlotWidth = 0.0
|
||||
var carouselScrollbarMinWidth = 96.0
|
||||
@ -386,8 +310,8 @@ open class Carousel: View {
|
||||
}
|
||||
}
|
||||
|
||||
carouselScrollBar.numberOfSlides = data.count
|
||||
carouselScrollBar.layout = _layout
|
||||
carouselScrollBar.numberOfSlides = views.count
|
||||
carouselScrollBar.layout = layout
|
||||
if (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) {
|
||||
carouselScrollBar.position = 1
|
||||
}
|
||||
@ -417,7 +341,6 @@ open class Carousel: View {
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
shouldUpdateView = false
|
||||
aspectRatio = .none
|
||||
layout = UIDevice.isIPad ? .threeUP : .oneUP
|
||||
pagination = .init(kind: .lowContrast, floating: true)
|
||||
paginationDisplay = .none
|
||||
@ -473,7 +396,7 @@ open class Carousel: View {
|
||||
|
||||
// Show/Hide pagination buttons of Carousel based on First or Middle or Last
|
||||
private func showPaginationControls() {
|
||||
if carouselScrollBar.numberOfSlides == _layout.value {
|
||||
if carouselScrollBar.numberOfSlides == layout.value {
|
||||
previousButton.isHidden = true
|
||||
nextButton.isHidden = true
|
||||
} else {
|
||||
@ -482,6 +405,26 @@ open class Carousel: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func estimateHeightFor(item: CarouselSlotItemModel, with width: CGFloat) -> CGFloat {
|
||||
let itemWidth = width
|
||||
let maxSize = CGSize(width: itemWidth, height: CGFloat.greatestFiniteMagnitude)
|
||||
let estItemSize = item.component?.systemLayoutSizeFitting(maxSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel) ?? CGSize(width: itemWidth, height: item.defaultHeight)
|
||||
return estItemSize.height
|
||||
}
|
||||
|
||||
private func fetchCarouselHeight() {
|
||||
if views.count > 0 {
|
||||
var height = slotHeight
|
||||
for x in 0...views.count - 1 {
|
||||
// Add received component
|
||||
let item : CarouselSlotItemModel = .init(style: renderItemStyle, component: views[x])
|
||||
slotHeight = estimateHeightFor(item: item, with: minimumSlotWidth)
|
||||
height = slotHeight > height ? slotHeight : height
|
||||
}
|
||||
slotHeight = height
|
||||
}
|
||||
}
|
||||
|
||||
// Add carousel slots and load data if any
|
||||
private func addCarouselSlots() {
|
||||
getSlotWidth()
|
||||
@ -495,10 +438,12 @@ open class Carousel: View {
|
||||
subView.removeFromSuperview()
|
||||
}
|
||||
|
||||
fetchCarouselHeight()
|
||||
|
||||
// Add carousel items
|
||||
if data.count > 0 {
|
||||
if views.count > 0 {
|
||||
var xPos = 0.0
|
||||
for x in 0...data.count - 1 {
|
||||
for x in 0...views.count - 1 {
|
||||
|
||||
// Add Carousel Slot
|
||||
let carouselSlot = View().with {
|
||||
@ -507,8 +452,7 @@ open class Carousel: View {
|
||||
}
|
||||
scrollView.addSubview(carouselSlot)
|
||||
scrollView.delegate = self
|
||||
let size = ratioSize(for: minimumSlotWidth)
|
||||
slotHeight = size.height
|
||||
|
||||
carouselSlot
|
||||
.pinTop()
|
||||
.pinBottom()
|
||||
@ -518,24 +462,28 @@ open class Carousel: View {
|
||||
carouselSlot.layer.cornerRadius = 12.0
|
||||
xPos = xPos + minimumSlotWidth + gutter.value
|
||||
|
||||
// Add received component
|
||||
let item : CarouselSlotItemModel = .init(style: renderItemStyle, component: views[x])
|
||||
let contentViewHeight = estimateHeightFor(item: item, with: minimumSlotWidth)
|
||||
|
||||
// Add subview for content to Carousel Slot
|
||||
let contentView = View().with {
|
||||
$0.clipsToBounds = true
|
||||
$0.backgroundColor = UIColor(red: CGFloat(216) / 255.0, green: CGFloat(218) / 255.0, blue: CGFloat(218) / 255.0, alpha: 1)
|
||||
}
|
||||
carouselSlot.addSubview(contentView)
|
||||
|
||||
// Add received component
|
||||
let item : CarouselSlotItemModel = .init(style: renderItemStyle, component: data[x] as? UIView)
|
||||
if let component = item.component {
|
||||
if slotAlignment != nil {
|
||||
// If slotAlignment exist, should use expected height
|
||||
contentView.widthAnchor.constraint(equalToConstant: minimumSlotWidth).activate()
|
||||
contentView.heightAnchor.constraint(equalToConstant: contentViewHeight).activate()
|
||||
setSlotAlignment(contentView: contentView, parentView: carouselSlot)
|
||||
} else {
|
||||
// // If no slotAlignment, should use full slot
|
||||
contentView.pinToSuperView()
|
||||
}
|
||||
contentView.addSubview(component)
|
||||
component.pinToSuperView()
|
||||
contentView.layer.cornerRadius = component.layer.cornerRadius
|
||||
if var surfacedView = component as? Surfaceable {
|
||||
surfacedView.surface = surface
|
||||
}
|
||||
@ -590,7 +538,7 @@ open class Carousel: View {
|
||||
// Get the slot width relative to the peak
|
||||
private func getSlotWidth() {
|
||||
let actualWidth = containerView.frame.size.width
|
||||
let isScrollbarSuppressed = data.count > 0 && layout.value == data.count
|
||||
let isScrollbarSuppressed = views.count > 0 && layout.value == views.count
|
||||
let isPeekMinimumOnTablet = UIDevice.isIPad && peek == .minimum
|
||||
let isPeekNone: Bool = peek == .none
|
||||
minimumSlotWidth = isScrollbarSuppressed || isPeekMinimumOnTablet || isPeekNone ? actualWidth - ((CGFloat(layout.value)-1) * gutter.value): actualWidth - (CGFloat(layout.value) * gutter.value)
|
||||
@ -626,37 +574,6 @@ open class Carousel: View {
|
||||
updateScrollPosition(position: carouselScrollBar.position, callbackText:"pageControlClicks")
|
||||
}
|
||||
|
||||
// The size of slot depends on the selected aspect ratio
|
||||
private func ratioSize(for width: CGFloat) -> CGSize {
|
||||
var height: CGFloat = width
|
||||
|
||||
switch aspectRatio {
|
||||
case .ratio1x1:
|
||||
break;
|
||||
case .ratio3x4:
|
||||
height = (4 / 3) * width
|
||||
case .ratio4x3:
|
||||
height = (3 / 4) * width
|
||||
case .ratio2x3:
|
||||
height = (3 / 2) * width
|
||||
case .ratio3x2:
|
||||
height = (2 / 3) * width
|
||||
case .ratio9x16:
|
||||
height = (16 / 9) * width
|
||||
case .ratio16x9:
|
||||
height = (9 / 16) * width
|
||||
case .ratio1x2:
|
||||
height = (2 / 1) * width
|
||||
case .ratio2x1:
|
||||
height = (1 / 2) * width
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return CGSize(width: width, height: height)
|
||||
}
|
||||
|
||||
private func updatePaginationInset() {
|
||||
prevButtonLeadingConstraint?.isActive = false
|
||||
nextButtonTrailingConstraint?.isActive = false
|
||||
@ -688,7 +605,7 @@ open class Carousel: View {
|
||||
} else if position == totalPositions {
|
||||
xPos = scrollContentSizeWidth - containerView.frame.size.width
|
||||
} else {
|
||||
let isScrollbarSuppressed = data.count > 0 && layout.value == data.count
|
||||
let isScrollbarSuppressed = views.count > 0 && layout.value == views.count
|
||||
let isPeekMinimumOnTablet = UIDevice.isIPad && peek == .minimum
|
||||
if !isScrollbarSuppressed {
|
||||
let subpart = minimumSlotWidth + gutter.value
|
||||
@ -719,7 +636,7 @@ open class Carousel: View {
|
||||
|
||||
// Get the overall positions of the carousel scrollbar relative to the slides and selected layout
|
||||
private func totalPositions() -> Int {
|
||||
return Int (ceil (Double(carouselScrollBar.numberOfSlides) / Double(_layout.value)))
|
||||
return Int (ceil (Double(carouselScrollBar.numberOfSlides) / Double(layout.value)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@ public struct CarouselSlotItemModel {
|
||||
/// Style props if provided any
|
||||
public var style: CarouselRenderItemStyle?
|
||||
|
||||
public let defaultHeight: CGFloat = 50.0
|
||||
|
||||
/// Component to be show on Carousel slot
|
||||
public var component: UIView?
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user