<template lang="pug">
.vertical-timeline
.date(
v-for="(pair, index) in AdjacentPairs" ,
v-bind:style="{ 'grid-row': index+1 + ' / span 1', 'grid-column': '1 / span 1'}"
)
slot(name="date", :from="pair[0]", :to="pair[1]")
.item(
v-for="(item, index) in items"
v-bind:style="{ 'grid-row': gridRow(item)}"
)
slot(name="item", :item="item")
.row(
v-for="(n, index) in AdjacentPairs.length"
v-bind:style="{ 'grid-row': index+1 + ' / span 1', 'grid-column': '1 / auto'}"
)
</template>
<script lang="coffee">
import Moment from 'moment'
import { extendMoment } from 'moment-range'
moment = extendMoment(Moment)
export default
props:
startStr:
type: String
require: false
default: null
endStr:
type: String
require: false
default: null
format:
type: String
require: false
default: 'YYYY-MM-DD'
unit:
type: String
require: true
validator: (val) ->
['years', 'quarters', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds'].includes(val)
step:
type: Number
require: false
default: 1
items:
type: Array
require: true
computed:
startStrOfItems: -> _.minBy(@items, (item) => item.startStr).startStr
endStrOfItems: -> _.maxBy(@items, (item) => item.endStr).endStr
start: ->
s = if @startStr? then @startStr else @startStrOfItems
moment(s, @format)
end: ->
e = if @endStr? then @endStr else @endStrOfItems
moment(e, @format)
range: ->
moment.range(@start, @end)
rangeByUnit: -> Array.from(@range.by(@unit, { step: @step }))
AdjacentPairs: ->
_.map @rangeByUnit, (a) =>
[_.cloneDeep(a).startOf(@unit), _.cloneDeep(a).add(@step - 1, @unit).endOf(@unit)]
methods:
gridRowIndex: (dateStr) ->
result = null
target = moment(dateStr, @format)
_.forEach @AdjacentPairs, (pair, index) =>
range = moment.range(pair[0], pair[1])
if range.contains(target, { exclusive: false })
result = index
false
result
gridRow: (item) ->
"#{@gridRowIndex(item.startStr) + 1} / #{@gridRowIndex(item.endStr) + 2}"
</script>
<style lang="stylus" scoped>
.vertical-timeline
position: relative
display: grid
grid-template-columns: auto
grid-auto-columns: 1fr
> .date
z-index: base-z-index + 1
> .item
z-index: base-z-index + 1
> .row
position: absolute
top: 0
bottom: 0
left: 0
right: 0
z-index: base-z-index
</style>