Skip to content

Commit

Permalink
implement variable width pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
sjstark committed Apr 29, 2024
1 parent 472768c commit 554bde8
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 7 deletions.
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 data-cy="variable-width" :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)
}
]
, [] )

0 comments on commit 554bde8

Please sign in to comment.