Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pagination for Variable Width Slides #146

Merged
merged 2 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions demo/components/demos/responsive/variable-width-with-arrows.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<ssr-carousel :slides-per-page="null" show-arrows show-dots>
<slide :index="1" :style="{ width: '65%', height: '30vw' }"></slide>
<slide :index="2" :style="{ width: '50%', height: '30vw' }"></slide>
<slide :index="3" :style="{ width: '30%', height: '30vw' }"></slide>
<slide :index="4" :style="{ width: '65%', height: '30vw' }"></slide>
<slide :index="5" :style="{ width: '30%', height: '30vw' }"></slide>
<slide :index="6" :style="{ width: '50%', height: '30vw' }"></slide>
<slide :index="7" :style="{ width: '50%', height: '30vw' }"></slide>
<slide :index="8" :style="{ width: '65%', height: '30vw' }"></slide>
<slide :index="9" :style="{ width: '30%', height: '30vw' }"></slide>
</ssr-carousel>
</template>
23 changes: 22 additions & 1 deletion demo/content/responsive.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ While it's not the primary use case of this package, you if you set `slidesPerPa

- If there are not enough slides to fill the viewport, slides will be left aligned rather than center aligned.
- This hasn't been tested with responsive props or looping. Peeking doesn't make sense for this use case but care hasn't been taken to disabling it.
- Pagination controls aren't supported yet, this is purely drag only.
- Pagination controls are in beta
- Pagination is done on a per slide basis
- Looping still has not been implemented
- Slides are left aligned

<demos-responsive-variable-width></demos-responsive-variable-width>

Expand All @@ -82,6 +85,24 @@ While it's not the primary use case of this package, you if you set `slidesPerPa
</ssr-carousel>
```

Carousel with variable width and arrows:

<demos-responsive-variable-width-with-arrows></demos-responsive-variable-width-with-arrows>

```vue
<ssr-carousel data-cy="variable-width" :slides-per-page="null">
<slide :index="1" :style="{ width: '65%', height: '30vw' }"></slide>
<slide :index="2" :style="{ width: '50%', height: '30vw' }"></slide>
<slide :index="3" :style="{ width: '30%', height: '30vw' }"></slide>
<slide :index="4" :style="{ width: '65%', height: '30vw' }"></slide>
<slide :index="5" :style="{ width: '30%', height: '30vw' }"></slide>
<slide :index="6" :style="{ width: '50%', height: '30vw' }"></slide>
<slide :index="7" :style="{ width: '50%', height: '30vw' }"></slide>
<slide :index="8" :style="{ width: '65%', height: '30vw' }"></slide>
<slide :index="9" :style="{ width: '30%', height: '30vw' }"></slide>
</ssr-carousel>
```

Here's an example where there aren't enough slides to exceed the carouel width:

<demos-responsive-variable-width-disabled></demos-responsive-variable-width-disabled>
Expand Down
9 changes: 8 additions & 1 deletion src/concerns/dimensions.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export default
@carouselWidth = @$el.getBoundingClientRect().width + @gutterWidth
@viewportWidth = window.innerWidth
@capturePeekingMeasurements()
@captureTrackWidth() if @isVariableWidth
@captureCarouselDims() if @isVariableWidth

# Make the width style that gives a slide it's width given
# slidesPerPage. Reduce this width by the gutter if present
Expand Down Expand Up @@ -114,3 +114,10 @@ export default
(#{@autoUnit(peekLeft)} + #{@autoUnit(peekRight)}) / #{slidesPerPage} -
(#{@autoUnit(gutter)} * #{slidesPerPage - 1}) / #{slidesPerPage}
)"


# Get the target X scroll position of a given slide
targetXOfIdx: (idx) ->
if @isVariableWidth
then @measuredSlidesWidths[idx].targetXScroll
else @pageWidth / @currentSlidesPerPage
14 changes: 13 additions & 1 deletion src/concerns/dragging.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ export default
fractionalIndex: ->
return 0 unless @trackWidth

if @isVariableWidth then return @fractionalIndexFromMeasurements

# Work in positive numbers
x = @currentX * -1

Expand Down Expand Up @@ -104,6 +106,16 @@ export default
# Return the final value by adding all the passed index values
return pageProgressPercent + setIndex * @pages + pageIndex

fractionalIndexFromMeasurements: ->
# Work in positive numbers
x = @currentX * -1

slideIdx = @measuredSlidesWidths.findIndex((measuredSlide) => measuredSlide.targetXScroll > x) - 1

percentage = (x - @measuredSlidesWidths[slideIdx].targetXScroll) / @measuredSlidesWidths[slideIdx].width

return slideIdx + percentage

# Determine if the user is dragging vertically
isVerticalDrag: ->
return unless @dragDirectionRatio
Expand Down Expand Up @@ -141,7 +153,7 @@ export default
else @gotoEnd()

# If rendering variable width slides, don't come to a rest at an index
else if @isVariableWidth then @tweenToStop()
else if @isVariableWidth then @goto @dragIndex

# If user was vertically dragging, reset the index
else if @isVerticalDrag then @goto @index
Expand Down
9 changes: 6 additions & 3 deletions src/concerns/pagination.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export default

# The current number of pages
pages: -> switch
# When variable width, pages is slide count
when @isVariableWidth then @slidesCount

# When looping and paginating per slide, make a dot per slide
when @paginateBySlide and @shouldLoop then @slidesCount
Expand Down Expand Up @@ -146,9 +148,10 @@ export default
getXForIndex: (index) ->

# Figure out the new x position
x = if @paginateBySlide
then index * @slideWidth * -1
else index * @pageWidth * -1
x = switch
when @isVariableWidth then @targetXOfIdx(@applyIndexBoundaries(index)) * -1
when @paginateBySlide then index * @slideWidth * -1
else index * @pageWidth * -1

# Apply adjustments to x value and persist
x += @makeIncompletePageOffset index
Expand Down
22 changes: 21 additions & 1 deletion src/concerns/variable-width.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,36 @@ Functionality related to supporting variable width slides
###
export default

data: -> measuredTrackWidth: 0
data: ->
measuredTrackWidth: 0
measuredSlidesWidths: []

computed:

# Is the carousel in variable width mode
isVariableWidth: -> @slidesPerPage == null

methods:
# Capture all dimensions of carousel
captureCarouselDims: ->
@captureTrackWidth()
@captureSlideWidths()

# Measure the width of the track
captureTrackWidth: ->
return unless @$refs.track
@measuredTrackWidth = @$refs.track.$el.scrollWidth

# Capture slide dims and place them into an array of data
captureSlideWidths: ->
return unless @$refs.track
@measuredSlidesWidths = @$refs?.track?.$children.reduce((acc, child, idx, arr) =>
return [
...acc
{
width: child.$el.clientWidth
targetXScroll: (acc[idx - 1]?.targetXScroll || 0) + (acc[idx - 1]?.width || 0) + @gutter * (idx > 0)
}
]
, [] )

Loading