import { compileToFunctions } from 'vue-template-compiler'
import VDatePickerDateTable from '@/components/VDatePicker/VDatePickerDateTable'
import { test } from '@/test'

test('VDatePickerDateTable.js', ({ mount }) => {
  it('should render component and match snapshot', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03'
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component with events (array) and match snapshot', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03',
        events: ['2005-05-03'],
        eventColor: 'red'
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component with events (function) and match snapshot', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03',
        events: date => date === '2005-05-03',
        eventColor: 'red'
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component with events colored by object and match snapshot', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03',
        events: ['2005-05-03', '2005-05-04'],
        eventColor: {'2005-05-03': 'red', '2005-05-04': 'blue lighten-1'}
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component with events colored by function and match snapshot', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03',
        events: ['2005-05-03', '2005-05-04'],
        eventColor: date => ({'2005-05-03': 'red'}[date])
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should match snapshot with first day of week', function () {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03',
        firstDayOfWeek: 2
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should watch tableDate value and run transition', async () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03'
      }
    })

    wrapper.setProps({
      tableDate: '2005-06'
    })
    await wrapper.vm.$nextTick()
    expect(wrapper.find('table')[0].element.className).toBe('tab-transition-enter tab-transition-enter-active')
  })

  it('should watch tableDate value and run reverse transition', async () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03'
      }
    })

    wrapper.setProps({
      tableDate: '2005-04'
    })
    await wrapper.vm.$nextTick()
    expect(wrapper.find('table')[0].element.className).toBe('tab-reverse-transition-enter tab-reverse-transition-enter-active')
  })

  it('should emit event when date button is clicked', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03'
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)

    wrapper.find('tbody button')[0].trigger('click')
    expect(input).toBeCalledWith('2005-05-01')
  })

  it('should not emit event when disabled month button is clicked', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        current: '2005-07',
        value: '2005-11-03',
        allowedDates: () => false
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)

    wrapper.find('tbody button')[0].trigger('click')
    expect(input).not.toBeCalled()
  })

  it('should emit tableDate event when scrolled and scrollable', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05',
        scrollable: true
      }
    })

    const tableDate = jest.fn()
    wrapper.vm.$on('tableDate', tableDate)

    wrapper.trigger('wheel')
    expect(tableDate).toBeCalledWith('2005-06')
  })

  it('should not emit tableDate event when scrolled and not scrollable', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05'
      }
    })

    const tableDate = jest.fn()
    wrapper.vm.$on('tableDate', tableDate)

    wrapper.trigger('wheel')
    expect(tableDate).not.toBeCalled()
  })

  // TODO
  it.skip('should emit tableDate event when swiped', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05'
      }
    })

    const tableDate = jest.fn()
    wrapper.vm.$on('tableDate', tableDate)

    wrapper.trigger('touchstart')
    wrapper.trigger('touchend')
    expect(tableDate).toBeCalledWith('2005-06')
  })

  it('should change tableDate when touch is called', () => {
    const wrapper = mount(VDatePickerDateTable, {
      propsData: {
        tableDate: '2005-05'
      }
    })

    const tableDate = jest.fn()
    wrapper.vm.$on('tableDate', tableDate)

    wrapper.vm.touch(1)
    expect(tableDate).toBeCalledWith('2005-06')
    wrapper.vm.touch(-1)
    expect(tableDate).toBeCalledWith('2005-04')
  })
})


}
},
onMouseDown (e) {
e.preventDefault()
this.isDragging = true
this.onDragMove(e)
},
onMouseUp () {

keep keep keep keep add keep keep keep keep

this.valueOnMouseDown = null
this.valueOnMouseUp = null

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VRadioGroup.vue should be in error when v-radio-group is 1`] = `

            <input aria-checked="false"
                   role="radio"
                   type="radio"
                   tabindex="0"
            >

              radio_button_unchecked

`;

exports[`VRadioGroup.vue should be in error when v-radio-group is 2`] = `

            <input aria-checked="false"
                   role="radio"
                   type="radio"
                   tabindex="0"
            >

              radio_button_unchecked

`;

exports[`VRadioGroup.vue should render role on radio group 1`] = `

`;


this.isAllowed(this.inputValue) && this.$emit('change', this.inputValue)

if (!this.isDragging && e.type !== 'click') return

keep keep keep keep keep replace keep keep keep keep keep

if (this.valueOnMouseUp !== null && this.isAllowed(this.valueOnMouseUp)) {

import VTimePickerClock from '@/components/VTimePicker/VTimePickerClock'
import { test, touch } from '@/test'

test('VTimePickerClock.js', ({ mount }) => {
  it('should render component', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        allowedValues: n => n % 2,
        max: 59,
        min: 0,
        size: 280,
        step: 5,
        value: 10
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component with double prop', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        allowedValues: n => n % 2,
        double: true,
        max: 59,
        min: 0,
        size: 280,
        step: 5,
        value: 10
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should emit input event on wheel if scrollable', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        max: 59,
        min: 3,
        value: 59,
        scrollable: true
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)
    wrapper.trigger('wheel')
    expect(input).toBeCalledWith(3)
  })

  it('should emit input event on wheel if scrollable and has allowedValues', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        max: 10,
        min: 1,
        value: 6,
        scrollable: true,
        allowedValues: val => !(val % 3)
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)
    wrapper.trigger('wheel')
    expect(input).toBeCalledWith(9)
  })

  it('should not emit input event on wheel if not scrollable', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        max: 59,
        min: 3,
        value: 59,
        scrollable: false
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)
    wrapper.trigger('wheel')
    expect(input).not.toBeCalled()
  })

  it('should emit change event on mouseup/touchend', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        value: 59,
        min: 0,
        max: 60
      }
    })

    const change = jest.fn()
    wrapper.vm.$on('change', change)

    wrapper.trigger('mouseup')
    expect(change).toBeCalledWith(59)

    wrapper.setProps({ value: 55 })
    wrapper.trigger('touchend')
    expect(change).toBeCalledWith(55)
  })

  it('should emit change event on mouseleave', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        value: 59,
        min: 0,
        max: 60
      }
    })

    const change = jest.fn()
    wrapper.vm.$on('change', change)

    wrapper.trigger('mouseleave')
    expect(change).not.toBeCalled()

    wrapper.vm.isDragging = true
    wrapper.trigger('mouseleave')
    expect(change).toBeCalledWith(59)
  })

  it('should calculate angle', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        value: 59,
        min: 0,
        max: 60
      }
    })

    const center = { x: 1, y: 1 }
    const angle = p => Math.round(wrapper.vm.angle(center, p))
    expect(angle({ x: 2, y: 1 })).toBe(90)
    expect(angle({ x: 2, y: 2 })).toBe(45)
    expect(angle({ x: 0, y: 2 })).toBe(315)
    expect(angle({ x: 0, y: 0 })).toBe(225)
    expect(angle({ x: 2, y: 0 })).toBe(135)
  })

  it('should change with touch move', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        min: 0,
        max: 7,
        value: 0,
        size: 300,
        double: true
      }
    })

    wrapper.vm.$refs.clock.getBoundingClientRect = () => {
      return {
        width: 300,
        height: 300,
        top: 0,
        left: 0,
        right: 300,
        bottom: 300,
        x: 0,
        y: 0
      }
    }

    const input = jest.fn()
    const finger = touch(wrapper).start(0, 0)
    wrapper.vm.$on('input', input)

    finger.move(300, 150)
    expect(input).toBeCalledWith(1)
    finger.move(150, 300)
    expect(input).toBeCalledWith(2)
    finger.move(150, 200)
    expect(input).toBeCalledWith(6)

    // edge case
    finger.move(120, 0)
    expect(input).toBeCalledWith(0)
    finger.move(135, 90)
    expect(input).toBeCalledWith(7)
  })
})


const padStart = (string, targetLength, padString) => {
  targetLength = targetLength >> 0
  string = String(string)
  padString = String(padString)
  if (string.length > targetLength) {
    return String(string)
  }

  targetLength = targetLength - string.length
  if (targetLength > padString.length) {
    padString += padString.repeat(targetLength / padString.length)
  }
  return padString.slice(0, targetLength) + String(string)
}

export default (n, length = 2) => padStart(n, length, '0')


'use strict'

module.exports = {
  'no-render-string-reference': {
    create: require('./eslint-rules/no-render-string-reference')
  }
}


function searchChildren (children) {
  const results = []
  for (let index = 0; index < children.length; index++) {
    const child = children[index]
    if (child.isActive && child.isDependent) {
      results.push(child)
    } else {
      results.push(...searchChildren(child.$children))
    }
  }

  return results
}

export default {
  name: 'dependent',

  data () {
    return {
      closeDependents: true,
      isDependent: true
    }
  },

  methods: {
    getOpenDependents () {
      if (this.closeDependents) return searchChildren(this.$children)

      return []
    },
    getOpenDependentElements () {
      const result = []
      const openDependents = this.getOpenDependents()

      for (let index = 0; index < openDependents.length; index++) {
        result.push(...openDependents[index].getClickableDependentElements())
      }

      return result
    },
    getClickableDependentElements () {
      const result = [this.$el]
      if (this.$refs.content) result.push(this.$refs.content)
      result.push(...this.getOpenDependentElements())

      return result
    }
  },

  watch: {
    isActive (val) {
      if (val) return

      const openDependents = this.getOpenDependents()
      for (let index = 0; index < openDependents.length; index++) {
        openDependents[index].isActive = false
      }
    }
  }
}


this.min + (insideClick ? this.roundCount : 0)

// Necessary to fix edge case when selecting left part of max value

if (handAngle >= (360 - this.degreesPerUnit / 2)) {


@import '../bootstrap'
@import '../theme'

v-date-picker-header($material)

  .v-date-picker-header__value:not(.v-date-picker-header__value--disabled)
    strong:not(:hover)
      color: $material.text.primary !important

  .v-date-picker-header__value--disabled strong
    color: $material.text.disabled

theme(v-date-picker-header, "v-date-picker-header")

.v-date-picker-header
  padding: 4px 16px

  align-items: center
  display: flex
  justify-content: space-between
  position: relative

  .v-btn
    margin: 0
    z-index: auto

  .v-icon
    cursor: pointer
    user-select: none

.v-date-picker-header__value
  flex: 1
  text-align: center
  position: relative
  overflow: hidden

  strong
    cursor: pointer
    transition: $primary-transition
    display: block
    width: 100%


import { test } from '@/test'
import VParallax from '@/components/VParallax'

test('VParallax.js', ({ mount }) => {
  it('should render', async () => {
    const wrapper = mount(VParallax, {
      attachToDocument: true
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should use alt tag when supplied', async () => {
    const wrapper = mount(VParallax, {
      attachToDocument: true,
      propsData: {
        alt: 'name'
      }
    })

    const img = wrapper.find('img')[0]
    expect(img.getAttribute('alt')).toBe('name')
    expect(wrapper.html()).toMatchSnapshot()
  })
})


import Vue from 'vue'
import { test } from '@/test'
import VTimePicker from '@/components/VTimePicker'
import VMenu from '@/components/VMenu'

test('VTimePicker.js', ({ mount }) => {
  it('should accept a value', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '09:12:34'
      }
    })

    await wrapper.vm.$nextTick()
    expect(wrapper.vm.selectingHour).toBe(true)
    expect(wrapper.vm.inputHour).toBe(9)
    expect(wrapper.vm.inputMinute).toBe(12)
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render landscape component', async () => {
    var wrapper = mount(VTimePicker, {
      propsData: {
        value: '09:12:34',
        landscape: true
      }
    })

    await wrapper.vm.$nextTick()
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component without a title', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '09:12:34',
        noTitle: true
      }
    })

    expect(wrapper.find('.v-picker__title')).toHaveLength(0)
  })

  it('should accept a date object for a value', async () => {
    const now = new Date('2017-01-01 12:00 AM')
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: now
      }
    })

    await wrapper.vm.$nextTick()
    expect(wrapper.vm.inputHour).toBe(0)
    expect(wrapper.vm.inputMinute).toBe(0)
    expect(wrapper.vm.period).toBe('am')
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should change am/pm when updated from model', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '9:00am'
      }
    })

    await wrapper.vm.$nextTick()
    wrapper.setProps({ value: '9:00pm' })

    expect(wrapper.vm.period).toBe('pm')
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should set picker to pm when given Date after noon', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: new Date('2017-01-01 12:00 PM')
      }
    })

    expect(wrapper.vm.period).toBe('pm')
  })

  it('should set picker to pm when given string with PM in it', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '1:00 PM'
      }
    })

    expect(wrapper.vm.period).toBe('pm')
  })

  it('should set picker to pm when given string with pm in it', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '1:00 pm'
      }
    })

    expect(wrapper.vm.period).toBe('pm')
  })

  it('should set picker to am when given Date before noon', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: new Date('2017-01-01 1:00 AM')
      }
    })

    expect(wrapper.vm.period).toBe('am')
  })

  it('should render colored time picker', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '09:00:00',
        color: 'primary',
        headerColor: 'orange darken-1'
      }
    })

    await wrapper.vm.$nextTick()
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render dark time picker', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        dark: true
      }
    })

    await wrapper.vm.$nextTick()
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render colored time picker', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '09:00:00',
        color: 'orange darken-1'
      }
    })

    await wrapper.vm.$nextTick()
    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should set input hour when setting hour in 12hr mode', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '01:23pm',
        format: 'ampm'
      }
    })

    const clock = wrapper.vm.$refs.clock

    clock.$emit('input', 7)
    expect(wrapper.vm.inputHour).toBe(19)

    wrapper.setProps({ format: '24hr' })
    clock.$emit('input', 8)
    expect(wrapper.vm.inputHour).toBe(8)

    wrapper.vm.selectingHour = false
    clock.$emit('input', 33)
    expect(wrapper.vm.inputHour).toBe(8)
    expect(wrapper.vm.inputMinute).toBe(33)
  })

  it('should set properly input time', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        format: '24hr'
      }
    })

    wrapper.vm.setInputData(new Date('2001-01-01 17:35'))
    expect(wrapper.vm.inputHour).toBe(17)
    expect(wrapper.vm.inputMinute).toBe(35)

    wrapper.vm.setInputData(null)
    expect(wrapper.vm.inputHour).toBe(null)
    expect(wrapper.vm.inputMinute).toBe(null)

    wrapper.vm.setInputData('12:34am')
    expect(wrapper.vm.inputHour).toBe(0)
    expect(wrapper.vm.inputMinute).toBe(34)

    wrapper.vm.setInputData('7:34am')
    expect(wrapper.vm.inputHour).toBe(7)

    wrapper.vm.setInputData('12:34pm')
    expect(wrapper.vm.inputHour).toBe(12)

    wrapper.vm.setInputData('7:34pm')
    expect(wrapper.vm.inputHour).toBe(19)
  })

  it('should update hour when changing period', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '15:34'
      }
    })

    wrapper.vm.setPeriod('am')
    await wrapper.vm.$nextTick()
    expect(wrapper.vm.inputHour).toBe(3)
    wrapper.vm.setPeriod('pm')
    await wrapper.vm.$nextTick()
    expect(wrapper.vm.inputHour).toBe(15)
  })

  it('should change selectingHour when hour/minute is selected', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '01:23pm',
        format: 'ampm'
      }
    })

    const clock = wrapper.vm.$refs.clock

    clock.$emit('change')
    expect(wrapper.vm.selectingHour).toBe(false)
    clock.$emit('change')
    expect(wrapper.vm.selectingHour).toBe(false)
  })

  it('should change selectingHour when clicked in title', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '01:23pm',
        format: 'ampm'
      }
    })

    const title = wrapper.vm.$refs.title

    expect(wrapper.vm.selectingHour).toBe(true)
    title.$emit('update:selectingHour', false)
    expect(wrapper.vm.selectingHour).toBe(false)
    title.$emit('update:selectingHour', true)
    expect(wrapper.vm.selectingHour).toBe(true)
  })

  it('should change period when clicked in title', () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '01:23pm',
        format: 'ampm'
      }
    })

    const title = wrapper.vm.$refs.title

    expect(wrapper.vm.period).toBe('pm')
    title.$emit('update:period', 'am')
    expect(wrapper.vm.period).toBe('am')
    title.$emit('update:period', 'pm')
    expect(wrapper.vm.period).toBe('pm')
  })

  it('should match snapshot with slot', async () => {
    const vm = new Vue()
    const slot = props => vm.$createElement('div', { class: 'scoped-slot' })
    const component = Vue.component('test', {
      render (h) {
        return h(VTimePicker, {
          props: {
            value: '10:12'
          },
          scopedSlots: {
            default: slot
          }
        })
      }
    })

    const wrapper = mount(component)
    expect(wrapper.find('.v-picker__actions .scoped-slot')).toHaveLength(1)
  })

  it('should calculate allowed minute/hour callback', async () => {
    const wrapper = mount(VTimePicker, {
      propsData: {
        value: '10:00',
        allowedMinutes: value => value % 5 === 0,
        allowedHours: value => value !== 11,
        min: '9:31',
        max: '12:30'
      }
    })

    expect(wrapper.vm.isAllowedHourCb(8)).toBe(false)
    expect(wrapper.vm.isAllowedHourCb(9)).toBe(true)
    expect(wrapper.vm.isAllowedHourCb(10)).toBe(true)
    expect(wrapper.vm.isAllowedHourCb(11)).toBe(false)
    expect(wrapper.vm.isAllowedHourCb(12)).toBe(true)
    expect(wrapper.vm.isAllowedHourCb(13)).toBe(false)

    wrapper.vm.inputHour = 8
    expect(wrapper.vm.isAllowedMinuteCb(30)).toBe(false)

    wrapper.vm.inputHour = 9
    expect(wrapper.vm.isAllowedMinuteCb(30)).toBe(false)
    expect(wrapper.vm.isAllowedMinuteCb(31)).toBe(false)
    expect(wrapper.vm.isAllowedMinuteCb(35)).toBe(true)

    wrapper.vm.inputHour = 10
    expect(wrapper.vm.isAllowedMinuteCb(30)).toBe(true)
    expect(wrapper.vm.isAllowedMinuteCb(31)).toBe(false)
    expect(wrapper.vm.isAllowedMinuteCb(35)).toBe(true)

    wrapper.vm.inputHour = 11
    expect(wrapper.vm.isAllowedMinuteCb(30)).toBe(false)
    expect(wrapper.vm.isAllowedMinuteCb(31)).toBe(false)
    expect(wrapper.vm.isAllowedMinuteCb(35)).toBe(false)

    wrapper.vm.inputHour = 12
    expect(wrapper.vm.isAllowedMinuteCb(30)).toBe(true)
    expect(wrapper.vm.isAllowedMinuteCb(31)).toBe(false)
    expect(wrapper.vm.isAllowedMinuteCb(35)).toBe(false)
  })
})


newValue = insideClick ? this.max : this.min

import '../../stylus/components/_time-picker-clock.styl'

// Mixins
import Colorable from '../../mixins/colorable'
import Themeable from '../../mixins/themeable'

export default {
  name: 'v-time-picker-clock',

  mixins: [
    Colorable,
    Themeable
  ],

  data () {
    return {
      defaultColor: 'accent',
      inputValue: this.value,
      isDragging: false
    }
  },

  props: {
    allowedValues: Function,
    double: Boolean,
    format: {
      type: Function,
      default: val => val
    },
    max: {
      type: Number,
      required: true
    },
    min: {
      type: Number,
      required: true
    },
    scrollable: Boolean,
    rotate: {
      type: Number,
      default: 0
    },
    size: {
      type: [Number, String],
      default: 270
    },
    step: {
      type: Number,
      default: 1
    },
    value: Number
  },

  computed: {
    count () {
      return this.max - this.min + 1
    },
    innerRadius () {
      return this.radius - Math.max(this.radius * 0.4, 48)
    },
    outerRadius () {
      return this.radius - 4
    },
    roundCount () {
      return this.double ? (this.count / 2) : this.count
    },
    degreesPerUnit () {
      return 360 / this.roundCount
    },
    degrees () {
      return this.degreesPerUnit * Math.PI / 180
    },
    radius () {
      return this.size / 2
    },
    displayedValue () {
      return this.value == null ? this.min : this.value
    }
  },

  watch: {
    value (value) {
      this.inputValue = value
    }
  },

  methods: {
    wheel (e) {
      e.preventDefault()

      const delta = Math.sign(e.wheelDelta || 1)
      let value = this.displayedValue
      do {
        value = value + delta
        value = (value - this.min + this.count) % this.count + this.min
      } while (!this.isAllowed(value) && value !== this.displayedValue)

      if (value !== this.displayedValue) {
        this.update(value)
      }
    },
    handScale (value) {
      return this.double && (value - this.min >= this.roundCount) ? (this.innerRadius / this.radius) : (this.outerRadius / this.radius)
    },
    isAllowed (value) {
      return !this.allowedValues || this.allowedValues(value)
    },
    genValues () {
      const children = []

      for (let value = this.min; value <= this.max; value = value + this.step) {
        const classes = {
          active: value === this.displayedValue,
          disabled: !this.isAllowed(value)
        }

        children.push(this.$createElement('span', {
          'class': this.addBackgroundColorClassChecks(classes, value === this.value ? this.computedColor : null),
          style: this.getTransform(value),
          domProps: { innerHTML: `<span>${this.format(value)}</span>` }
        }))
      }

      return children
    },
    genHand () {
      const scale = `scaleY(${this.handScale(this.displayedValue)})`
      const angle = this.rotate + this.degreesPerUnit * (this.displayedValue - this.min)

      return this.$createElement('div', {
        staticClass: 'v-time-picker-clock__hand',
        'class': this.value == null ? {} : this.addBackgroundColorClassChecks(),
        style: {
          transform: `rotate(${angle}deg) ${scale}`
        }
      })
    },
    getTransform (i) {
      const { x, y } = this.getPosition(i)
      return { transform: `translate(${x}px, ${y}px)` }
    },
    getPosition (value) {
      const radius = (this.radius - 24) * this.handScale(value)
      const rotateRadians = this.rotate * Math.PI / 180
      return {
        x: Math.round(Math.sin((value - this.min) * this.degrees + rotateRadians) * radius),
        y: Math.round(-Math.cos((value - this.min) * this.degrees + rotateRadians) * radius)
      }
    },
    onMouseDown (e) {
      e.preventDefault()

      this.isDragging = true
      this.onDragMove(e)
    },
    onMouseUp () {
      this.isDragging = false
      this.isAllowed(this.inputValue) && this.$emit('change', this.inputValue)
    },
    onDragMove (e) {
      e.preventDefault()
      if (!this.isDragging && e.type !== 'click') return

      const { width, top, left } = this.$refs.clock.getBoundingClientRect()
      const { clientX, clientY } = 'touches' in e ? e.touches[0] : e
      const center = { x: width / 2, y: -width / 2 }
      const coords = { x: clientX - left, y: top - clientY }
      const handAngle = Math.round(this.angle(center, coords) - this.rotate + 360) % 360
      const insideClick = this.double && this.euclidean(center, coords) < (this.outerRadius + this.innerRadius) / 2 - 16
      const value = Math.round(handAngle / this.degreesPerUnit) +
        this.min + (insideClick ? this.roundCount : 0)

      // Necessary to fix edge case when selecting left part of max value
      if (handAngle >= (360 - this.degreesPerUnit / 2)) {
        this.update(insideClick ? this.max : this.min)
      } else {
        this.update(value)
      }
    },
    update (value) {
      if (this.inputValue !== value && this.isAllowed(value)) {
        this.inputValue = value
        this.$emit('input', value)
      }
    },
    euclidean (p0, p1) {
      const dx = p1.x - p0.x
      const dy = p1.y - p0.y

      return Math.sqrt(dx * dx + dy * dy)
    },
    angle (center, p1) {
      const value = 2 * Math.atan2(p1.y - center.y - this.euclidean(center, p1), p1.x - center.x)
      return Math.abs(value * 180 / Math.PI)
    }
  },

  render () {
    const data = {
      staticClass: 'v-time-picker-clock',
      class: {
        'v-time-picker-clock--indeterminate': this.value == null,
        ...this.themeClasses
      },
      on: {
        mousedown: this.onMouseDown,
        mouseup: this.onMouseUp,
        mouseleave: () => (this.isDragging && this.onMouseUp()),
        touchstart: this.onMouseDown,
        touchend: this.onMouseUp,
        mousemove: this.onDragMove,
        touchmove: this.onDragMove
      },
      style: {
        height: `${this.size}px`,
        width: `${this.size}px`
      },
      ref: 'clock'
    }

    this.scrollable && (data.on.wheel = this.wheel)

    return this.$createElement('div', data, [
      this.genHand(),
      this.genValues()
    ])
  }
}


// Components
import VJumbotron from '../VJumbotron'

// Mixins
import { inject as RegistrableInject } from '../../mixins/registrable'

export default {
  name: 'v-carousel-item',

  mixins: [RegistrableInject('carousel', 'v-carousel-item', 'v-carousel')],

  inheritAttrs: false,

  data () {
    return {
      active: false,
      reverse: false
    }
  },

  props: {
    transition: {
      type: String,
      default: 'tab-transition'
    },
    reverseTransition: {
      type: String,
      default: 'tab-reverse-transition'
    }
  },

  computed: {
    computedTransition () {
      return this.reverse ? this.reverseTransition : this.transition
    }
  },

  methods: {
    open (id, reverse) {
      this.active = this._uid === id
      this.reverse = reverse
    }
  },

  mounted () {
    this.carousel.register(this._uid, this.open)
  },

  beforeDestroy () {
    this.carousel.unregister(this._uid, this.open)
  },

  render (h) {
    const item = h(VJumbotron, {
      props: {
        ...this.$attrs,
        height: '100%'
      },
      on: this.$listeners,
      directives: [{
        name: 'show',
        value: this.active
      }]
    }, this.$slots.default)

    return h('transition', { props: { name: this.computedTransition } }, [item])
  }
}


// Styles
import '../../stylus/components/_forms.styl'

import { provide as RegistrableProvide } from '../../mixins/registrable'

export default {
  name: 'v-form',

  inheritAttrs: false,

  mixins: [RegistrableProvide('form')],

  data () {
    return {
      inputs: [],
      errorBag: {}
    }
  },

  props: {
    value: Boolean,
    lazyValidation: Boolean
  },

  watch: {
    errorBag: {
      handler () {
        const errors = Object.values(this.errorBag).includes(true)
        this.$emit('input', !errors)
      },
      deep: true,
      immediate: true
    }
  },

  methods: {
    watchInput (input) {
      const watcher = input => {
        return input.$watch('hasError', val => {
          this.$set(this.errorBag, input._uid, val)
        }, { immediate: true })
      }

      const watchers = {
        valid: undefined,
        shouldValidate: undefined
      }

      if (this.lazyValidation) {
        // Only start watching inputs if we need to
        watchers.shouldValidate = input.$watch('shouldValidate', val => {
          if (!val) return

          // Only watch if we're not already doing it
          if (this.errorBag.hasOwnProperty(input._uid)) return

          watchers.valid = watcher(input)
        })
      } else {
        watchers.valid = watcher(input)
      }

      return watchers
    },
    validate () {
      const errors = this.inputs.filter(input => !input.validate(true)).length
      return !errors
    },
    reset () {
      for (let i = this.inputs.length; i--;) {
        this.inputs[i].reset()
      }
      if (this.lazyValidation) {
        // Account for timeout in validatable
        setTimeout(() => {
          this.errorBag = {}
        }, 0)
      }
    },
    register (input) {
      const unwatch = this.watchInput(input)
      this.inputs.push({
        uid: input._uid,
        validate: input.validate,
        reset: input.reset,
        unwatch
      })
    },
    unregister (input) {
      const found = this.inputs.find(i => i.uid === input._uid)

      if (!found) return

      found.unwatch.valid && found.unwatch.valid()
      found.unwatch.shouldValidate && found.unwatch.shouldValidate()
      this.inputs = this.inputs.filter(i => i.uid !== found.uid)
      this.$delete(this.errorBag, found.uid)
    }
  },

  render (h) {
    return h('form', {
      staticClass: 'v-form',
      attrs: Object.assign({
        novalidate: true
      }, this.$attrs),
      on: {
        submit: e => this.$emit('submit', e)
      }
    }, this.$slots.default)
  }
}


// Components
import VInput from '../components/VInput'

// Mixins
import Rippleable from './rippleable'
import Comparable from './comparable'

// Utils
import { keyCodes } from '../util/helpers'

export default {
  name: 'selectable',

  extends: VInput,

  mixins: [Rippleable, Comparable],

  model: {
    prop: 'inputValue',
    event: 'change'
  },

  data: vm => ({
    lazyValue: vm.inputValue
  }),

  props: {
    color: {
      type: String,
      default: 'accent'
    },
    id: String,
    inputValue: null,
    falseValue: null,
    trueValue: null,
    multiple: {
      type: Boolean,
      default: null
    },
    label: String,
    toggleKeys: {
      type: Array,
      default: () => [keyCodes.enter, keyCodes.space]
    }
  },

  computed: {
    classesSelectable () {
      return this.addTextColorClassChecks(
        {},
        this.isDirty ? this.color : this.validationState
      )
    },
    isMultiple () {
      return this.multiple === true || (this.multiple === null && Array.isArray(this.internalValue))
    },
    isActive () {
      const value = this.value
      const input = this.internalValue

      if (this.isMultiple) {
        if (!Array.isArray(input)) return false

        return input.some(item => this.valueComparator(item, value))
      }

      if (this.trueValue === undefined || this.falseValue === undefined) {
        return value
          ? this.valueComparator(value, input)
          : Boolean(input)
      }

      return this.valueComparator(input, this.trueValue)
    },
    isDirty () {
      return this.isActive
    }
  },

  watch: {
    inputValue (val) {
      this.internalValue = val
    }
  },

  methods: {
    genLabel () {
      if (!this.hasLabel) return null

      const label = VInput.methods.genLabel.call(this)

      label.data.on = { click: this.onChange }

      return label
    },
    genInput (type, attrs) {
      return this.$createElement('input', {
        attrs: Object.assign({}, {
          'aria-label': this.label,
          'aria-checked': this.isActive.toString(),
          id: this.id,
          role: type,
          type,
          value: this.inputValue
        }, attrs),
        on: {
          blur: this.onBlur,
          change: this.onChange,
          focus: this.onFocus,
          keydown: this.onKeydown
        }
      })
    },
    onBlur () {
      this.isFocused = false
    },
    onChange () {
      if (this.isDisabled) return

      const value = this.value
      let input = this.internalValue

      if (this.isMultiple) {
        if (!Array.isArray(input)) {
          input = []
        }

        const length = input.length

        input = input.filter(item => !this.valueComparator(item, value))

        if (input.length === length) {
          input.push(value)
        }
      } else if (this.trueValue !== undefined && this.falseValue !== undefined) {
        input = this.valueComparator(input, this.trueValue) ? this.falseValue : this.trueValue
      } else if (value) {
        input = this.valueComparator(input, value) ? null : value
      } else {
        input = !input
      }

      this.validate(true, input)
      this.lazyValue = input
      this.$emit('change', input)
    },
    onFocus () {
      this.isFocused = true
    },
    onKeydown (e) {
      // Overwrite default behavior to only allow
      // the specified keyCodes
      if (this.toggleKeys.indexOf(e.keyCode) > -1) {
        e.preventDefault()

        this.onChange()
      }
    }
  }
}


} else {
this.update(value)
}
},
update (value) {


import VMessages from './VMessages'

/* istanbul ignore next */
VMessages.install = function install (Vue) {
  Vue.component(VMessages.name, VMessages)
}

export { VMessages }
export default VMessages


import Vue from 'vue'

export default Vue.extend({
  name: 'themeable',

  props: {
    dark: Boolean,
    light: Boolean
  },

  computed: {
    themeClasses (): any {
      return {
        'theme--light': this.light,
        'theme--dark': this.dark
      }
    }
  }
})


import VProgressCircular from './VProgressCircular'

/* istanbul ignore next */
VProgressCircular.install = function install (Vue) {
  Vue.component(VProgressCircular.name, VProgressCircular)
}

export { VProgressCircular }
export default VProgressCircular


if (this.inputValue !== value && this.isAllowed(value)) {


// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VDatePickerHeader.js should render component and match snapshot 1`] = `

  <button type="button"
          class="v-btn v-btn--icon"
  >

        chevron_left

  </button>

      November 2005

  <button type="button"
          class="v-btn v-btn--icon"
  >

        chevron_right

  </button>

`;

exports[`VDatePickerHeader.js should render component with default slot and match snapshot 1`] = `

  <button type="button"
          class="v-btn v-btn--icon"
  >

        chevron_left

  </button>

        foo

  <button type="button"
          class="v-btn v-btn--icon"
  >

        chevron_right

  </button>

`;


import VDatePicker from './VDatePicker'
import VDatePickerTitle from './VDatePickerTitle'
import VDatePickerHeader from './VDatePickerHeader'
import VDatePickerDateTable from './VDatePickerDateTable'
import VDatePickerMonthTable from './VDatePickerMonthTable'
import VDatePickerYears from './VDatePickerYears'

export {
  VDatePicker,
  VDatePickerTitle,
  VDatePickerHeader,
  VDatePickerDateTable,
  VDatePickerMonthTable,
  VDatePickerYears
}

/* istanbul ignore next */
VDatePicker.install = function install (Vue) {
  Vue.component(VDatePicker.name, VDatePicker)
  Vue.component(VDatePickerTitle.name, VDatePickerTitle)
  Vue.component(VDatePickerHeader.name, VDatePickerHeader)
  Vue.component(VDatePickerDateTable.name, VDatePickerDateTable)
  Vue.component(VDatePickerMonthTable.name, VDatePickerMonthTable)
  Vue.component(VDatePickerYears.name, VDatePickerYears)
}

export default VDatePicker


import Vue from 'vue'
import { test } from '@/test'
import Ripple from '@/directives/ripple'

test('VRipple', ({ mount }) => {
  it('Ripple with no value should render element with ripple enabled', () => {
    const testComponent = Vue.component('test', {
      directives: {
        Ripple
      },
      render (h){
        const data = {
          directives: [{
            name: 'ripple'
          }]
        }
        return h('div', data)
      }
    })

    const wrapper = mount(testComponent)

    const div = wrapper.find('div')[0]
    expect(div.element._ripple.enabled).toBe(true)
  })

  it('Ripple should update element property reactively', () => {
    const testComponent = Vue.component('test', {
      directives: {
        Ripple
      },
      props: {
        ripple: Boolean,
        default: false
      },
      render (h){
        const data = {
          directives: [{
            name: 'ripple',
            value: this.ripple
          }]
        }
        return h('div', data)
      }
    })

    const wrapper = mount(testComponent, {
      propsData: {
        ripple: true
      }
    })

    const div = wrapper.find('div')[0]
    expect(div.element._ripple.enabled).toBe(true)

    wrapper.setProps({ ripple: false })
    expect(div.element._ripple.enabled).toBe(false)

    wrapper.setProps({ ripple: true })
    expect(div.element._ripple.enabled).toBe(true)
  })
})


})
const change = jest.fn()
wrapper.vm.$on('change', change)
wrapper.trigger('mouseup')


@import '../bootstrap'
@import '../theme'

/* Themes */
v-icon($material)
  color: $material.icons.active

  &.v-icon--disabled
    color: $material.icons.inactive !important

theme(v-icon, "v-icon")

.v-icon
  align-items: center
  display: inline-flex
  font-feature-settings: 'liga'
  font-size: 24px
  justify-content: center
  line-height: 1
  transition: $primary-transition
  vertical-align: middle

  &--link
    cursor: pointer

  &.v-icon--large
    font-size: 2.5rem

  &.v-icon--medium
    font-size: 2rem

  &.v-icon--x-large
    font-size: 3rem

  &.v-icon--disabled
    pointer-events: none


import monthChange from '@/components/VDatePicker/util/monthChange'
import { test } from '@/test'

test('VDatePicker/util/monthChange.js', ({ mount }) => {
  it('should change month', () => {
    expect(monthChange('2000-01', -1)).toBe('1999-12')
    expect(monthChange('2000-01', +1)).toBe('2000-02')
    expect(monthChange('2000-12', -1)).toBe('2000-11')
    expect(monthChange('2000-12', +1)).toBe('2001-01')
  })
})


@import '../bootstrap'

.v-speed-dial
  position: relative

  &--absolute
    position: absolute

  &--fixed
    position: fixed

  &--fixed,
  &--absolute
    z-index: 4

    & > .v-btn--floating
      margin: 0

  &--top
    &:not(.v-speed-dial--absolute)
      top: $grid-gutters.lg

    &.v-speed-dial--absolute
      top: 50%
      transform: translateY(-50%)

  &--bottom
    &:not(.v-speed-dial--absolute)
      bottom: $grid-gutters.lg

    &.v-speed-dial--absolute
      bottom: 50%
      transform: translateY(50%)

  &--left
    left: $grid-gutters.lg

  &--right
    right: $grid-gutters.lg

  &--direction
    &-left,
    &-right
      .v-speed-dial__list
        height: 100%
        top: 0

    &-top,
    &-bottom
      .v-speed-dial__list
        left: 0
        width: 100%

    &-top
      .v-speed-dial__list
        flex-direction: column-reverse
        bottom: 100%

    &-right
      .v-speed-dial__list
        flex-direction: row
        left: 100%

    &-bottom
      .v-speed-dial__list
        flex-direction: column
        top: 100%

    &-left
      .v-speed-dial__list
        flex-direction: row-reverse
        right: 100%

/** Elements */
.v-speed-dial__list
  align-items: center
  display: flex
  justify-content: center
  position: absolute

  .v-btn
    for n in (1..7)
      &:nth-child({n})
        transition-delay: "%ss" % (n * .05)


import VTimePickerClock from '@/components/VTimePicker/VTimePickerClock'
import { test, touch } from '@/test'

test('VTimePickerClock.js', ({ mount }) => {
  it('should render component', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        allowedValues: n => n % 2,
        max: 59,
        min: 0,
        size: 280,
        step: 5,
        value: 10
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render component with double prop', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        allowedValues: n => n % 2,
        double: true,
        max: 59,
        min: 0,
        size: 280,
        step: 5,
        value: 10
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should emit input event on wheel if scrollable', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        max: 59,
        min: 3,
        value: 59,
        scrollable: true
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)
    wrapper.trigger('wheel')
    expect(input).toBeCalledWith(3)
  })

  it('should emit input event on wheel if scrollable and has allowedValues', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        max: 10,
        min: 1,
        value: 6,
        scrollable: true,
        allowedValues: val => !(val % 3)
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)
    wrapper.trigger('wheel')
    expect(input).toBeCalledWith(9)
  })

  it('should not emit input event on wheel if not scrollable', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        max: 59,
        min: 3,
        value: 59,
        scrollable: false
      }
    })

    const input = jest.fn()
    wrapper.vm.$on('input', input)
    wrapper.trigger('wheel')
    expect(input).not.toBeCalled()
  })

  it('should emit change event on mouseup/touchend', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        value: 59,
        min: 0,
        max: 60
      }
    })

    const change = jest.fn()
    wrapper.vm.$on('change', change)

    wrapper.trigger('mouseup')
    expect(change).toBeCalledWith(59)

    wrapper.setProps({ value: 55 })
    wrapper.trigger('touchend')
    expect(change).toBeCalledWith(55)
  })

  it('should emit change event on mouseleave', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        value: 59,
        min: 0,
        max: 60
      }
    })

    const change = jest.fn()
    wrapper.vm.$on('change', change)

    wrapper.trigger('mouseleave')
    expect(change).not.toBeCalled()

    wrapper.vm.isDragging = true
    wrapper.trigger('mouseleave')
    expect(change).toBeCalledWith(59)
  })

  it('should calculate angle', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        value: 59,
        min: 0,
        max: 60
      }
    })

    const center = { x: 1, y: 1 }
    const angle = p => Math.round(wrapper.vm.angle(center, p))
    expect(angle({ x: 2, y: 1 })).toBe(90)
    expect(angle({ x: 2, y: 2 })).toBe(45)
    expect(angle({ x: 0, y: 2 })).toBe(315)
    expect(angle({ x: 0, y: 0 })).toBe(225)
    expect(angle({ x: 2, y: 0 })).toBe(135)
  })

  it('should change with touch move', () => {
    const wrapper = mount(VTimePickerClock, {
      propsData: {
        min: 0,
        max: 7,
        value: 0,
        size: 300,
        double: true
      }
    })

    wrapper.vm.$refs.clock.getBoundingClientRect = () => {
      return {
        width: 300,
        height: 300,
        top: 0,
        left: 0,
        right: 300,
        bottom: 300,
        x: 0,
        y: 0
      }
    }

    const input = jest.fn()
    const finger = touch(wrapper).start(0, 0)
    wrapper.vm.$on('input', input)

    finger.move(300, 150)
    expect(input).toBeCalledWith(1)
    finger.move(150, 300)
    expect(input).toBeCalledWith(2)
    finger.move(150, 200)
    expect(input).toBeCalledWith(6)

    // edge case
    finger.move(120, 0)
    expect(input).toBeCalledWith(0)
    finger.move(135, 90)
    expect(input).toBeCalledWith(7)
  })
})


const semver = require('semver')

const version = process.argv[2]

if (!semver.valid(version)) {
  console.error(`Error: '${version}' is not a valid NPM version string`)
  process.exit(9)
}

const prerelease = semver.prerelease(version)

if (prerelease == null) {
  console.log('latest')
} else {
  console.log('next')
}


import '../../stylus/components/_date-picker-header.styl'

// Components
import VBtn from '../VBtn'
import VIcon from '../VIcon'

// Mixins
import Colorable from '../../mixins/colorable'
import Themeable from '../../mixins/themeable'

// Utils
import { createNativeLocaleFormatter, monthChange } from './util'

export default {
  name: 'v-date-picker-header',

  mixins: [
    Colorable,
    Themeable
  ],

  data () {
    return {
      isReversing: false,
      defaultColor: 'accent'
    }
  },

  props: {
    disabled: Boolean,
    format: {
      type: Function,
      default: null
    },
    locale: {
      type: String,
      default: 'en-us'
    },
    min: String,
    max: String,
    nextIcon: {
      type: String,
      default: '$vuetify.icons.next'
    },
    prevIcon: {
      type: String,
      default: '$vuetify.icons.prev'
    },
    value: {
      type: [Number, String],
      required: true
    }
  },

  computed: {
    formatter () {
      if (this.format) {
        return this.format
      } else if (String(this.value).split('-')[1]) {
        return createNativeLocaleFormatter(this.locale, { month: 'long', year: 'numeric', timeZone: 'UTC' }, { length: 7 })
      } else {
        return createNativeLocaleFormatter(this.locale, { year: 'numeric', timeZone: 'UTC' }, { length: 4 })
      }
    }
  },

  watch: {
    value (newVal, oldVal) {
      this.isReversing = newVal < oldVal
    }
  },

  methods: {
    genBtn (change) {
      const disabled = this.disabled ||
        (change < 0 && this.min && this.calculateChange(change) < this.min) ||
        (change > 0 && this.max && this.calculateChange(change) > this.max)

      return this.$createElement(VBtn, {
        props: {
          dark: this.dark,
          disabled,
          icon: true,
          light: this.light
        },
        nativeOn: {
          click: e => {
            e.stopPropagation()
            this.$emit('input', this.calculateChange(change))
          }
        }
      }, [
        this.$createElement(VIcon, change < 0 ? this.prevIcon : this.nextIcon)
      ])
    },
    calculateChange (sign) {
      const [year, month] = String(this.value).split('-').map(v => 1 * v)

      if (month == null) {
        return `${year + sign}`
      } else {
        return monthChange(String(this.value), sign)
      }
    },
    genHeader () {
      const header = this.$createElement('strong', {
        'class': this.disabled ? undefined : this.addTextColorClassChecks(),
        key: String(this.value),
        on: {
          click: () => this.$emit('toggle')
        }
      }, [this.$slots.default || this.formatter(String(this.value))])

      const transition = this.$createElement('transition', {
        props: {
          name: this.isReversing ? 'tab-reverse-transition' : 'tab-transition'
        }
      }, [header])

      return this.$createElement('div', {
        staticClass: 'v-date-picker-header__value',
        class: {
          'v-date-picker-header__value--disabled': this.disabled
        }
      }, [transition])
    }
  },

  render () {
    return this.$createElement('div', {
      staticClass: 'v-date-picker-header',
      class: {
        ...this.themeClasses
      }
    }, [
      this.genBtn(-1),
      this.genHeader(),
      this.genBtn(+1)
    ])
  }
}


export default {
  name: 'tab-focusable',

  data () {
    return {
      tabFocused: false
    }
  }
}


import '../../stylus/components/_time-picker-clock.styl'

// Mixins
import Colorable from '../../mixins/colorable'
import Themeable from '../../mixins/themeable'

export default {
  name: 'v-time-picker-clock',

  mixins: [
    Colorable,
    Themeable
  ],

  data () {
    return {
      defaultColor: 'accent',
      inputValue: this.value,
      isDragging: false
    }
  },

  props: {
    allowedValues: Function,
    double: Boolean,
    format: {
      type: Function,
      default: val => val
    },
    max: {
      type: Number,
      required: true
    },
    min: {
      type: Number,
      required: true
    },
    scrollable: Boolean,
    rotate: {
      type: Number,
      default: 0
    },
    size: {
      type: [Number, String],
      default: 270
    },
    step: {
      type: Number,
      default: 1
    },
    value: Number
  },

  computed: {
    count () {
      return this.max - this.min + 1
    },
    innerRadius () {
      return this.radius - Math.max(this.radius * 0.4, 48)
    },
    outerRadius () {
      return this.radius - 4
    },
    roundCount () {
      return this.double ? (this.count / 2) : this.count
    },
    degreesPerUnit () {
      return 360 / this.roundCount
    },
    degrees () {
      return this.degreesPerUnit * Math.PI / 180
    },
    radius () {
      return this.size / 2
    },
    displayedValue () {
      return this.value == null ? this.min : this.value
    }
  },

  watch: {
    value (value) {
      this.inputValue = value
    }
  },

  methods: {
    wheel (e) {
      e.preventDefault()

      const delta = Math.sign(e.wheelDelta || 1)
      let value = this.displayedValue
      do {
        value = value + delta
        value = (value - this.min + this.count) % this.count + this.min
      } while (!this.isAllowed(value) && value !== this.displayedValue)

      if (value !== this.displayedValue) {
        this.update(value)
      }
    },
    handScale (value) {
      return this.double && (value - this.min >= this.roundCount) ? (this.innerRadius / this.radius) : (this.outerRadius / this.radius)
    },
    isAllowed (value) {
      return !this.allowedValues || this.allowedValues(value)
    },
    genValues () {
      const children = []

      for (let value = this.min; value <= this.max; value = value + this.step) {
        const classes = {
          active: value === this.displayedValue,
          disabled: !this.isAllowed(value)
        }

        children.push(this.$createElement('span', {
          'class': this.addBackgroundColorClassChecks(classes, value === this.value ? this.computedColor : null),
          style: this.getTransform(value),
          domProps: { innerHTML: `<span>${this.format(value)}</span>` }
        }))
      }

      return children
    },
    genHand () {
      const scale = `scaleY(${this.handScale(this.displayedValue)})`
      const angle = this.rotate + this.degreesPerUnit * (this.displayedValue - this.min)

      return this.$createElement('div', {
        staticClass: 'v-time-picker-clock__hand',
        'class': this.value == null ? {} : this.addBackgroundColorClassChecks(),
        style: {
          transform: `rotate(${angle}deg) ${scale}`
        }
      })
    },
    getTransform (i) {
      const { x, y } = this.getPosition(i)
      return { transform: `translate(${x}px, ${y}px)` }
    },
    getPosition (value) {
      const radius = (this.radius - 24) * this.handScale(value)
      const rotateRadians = this.rotate * Math.PI / 180
      return {
        x: Math.round(Math.sin((value - this.min) * this.degrees + rotateRadians) * radius),
        y: Math.round(-Math.cos((value - this.min) * this.degrees + rotateRadians) * radius)
      }
    },
    onMouseDown (e) {
      e.preventDefault()

      this.isDragging = true
      this.onDragMove(e)
    },
    onMouseUp () {
      this.isDragging = false
      this.isAllowed(this.inputValue) && this.$emit('change', this.inputValue)
    },
    onDragMove (e) {
      e.preventDefault()
      if (!this.isDragging && e.type !== 'click') return

      const { width, top, left } = this.$refs.clock.getBoundingClientRect()
      const { clientX, clientY } = 'touches' in e ? e.touches[0] : e
      const center = { x: width / 2, y: -width / 2 }
      const coords = { x: clientX - left, y: top - clientY }
      const handAngle = Math.round(this.angle(center, coords) - this.rotate + 360) % 360
      const insideClick = this.double && this.euclidean(center, coords) < (this.outerRadius + this.innerRadius) / 2 - 16
      const value = Math.round(handAngle / this.degreesPerUnit) +
        this.min + (insideClick ? this.roundCount : 0)

      // Necessary to fix edge case when selecting left part of max value
      if (handAngle >= (360 - this.degreesPerUnit / 2)) {
        this.update(insideClick ? this.max : this.min)
      } else {
        this.update(value)
      }
    },
    update (value) {
      if (this.inputValue !== value && this.isAllowed(value)) {
        this.inputValue = value
        this.$emit('input', value)
      }
    },
    euclidean (p0, p1) {
      const dx = p1.x - p0.x
      const dy = p1.y - p0.y

      return Math.sqrt(dx * dx + dy * dy)
    },
    angle (center, p1) {
      const value = 2 * Math.atan2(p1.y - center.y - this.euclidean(center, p1), p1.x - center.x)
      return Math.abs(value * 180 / Math.PI)
    }
  },

  render () {
    const data = {
      staticClass: 'v-time-picker-clock',
      class: {
        'v-time-picker-clock--indeterminate': this.value == null,
        ...this.themeClasses
      },
      on: {
        mousedown: this.onMouseDown,
        mouseup: this.onMouseUp,
        mouseleave: () => (this.isDragging && this.onMouseUp()),
        touchstart: this.onMouseDown,
        touchend: this.onMouseUp,
        mousemove: this.onDragMove,
        touchmove: this.onDragMove
      },
      style: {
        height: `${this.size}px`,
        width: `${this.size}px`
      },
      ref: 'clock'
    }

    this.scrollable && (data.on.wheel = this.wheel)

    return this.$createElement('div', data, [
      this.genHand(),
      this.genValues()
    ])
  }
}


import '../../stylus/components/_grid.styl'

import Grid from './grid'

export default Grid('layout')


@require './settings/*'
@require './generic/*'
@require './elements/*'
@require './tools/*'
@require './trumps/*'


@import '../bootstrap'
@import '../theme'

v-radio($material)
  &--is-disabled
    label
      color: $material.text.disabled

    .v-icon
      // needed for helper override
      color: $material.buttons.disabled !important

theme(v-radio, "v-radio")

.v-radio
  align-items: center
  display: flex
  height: auto
  margin-right: 16px
  outline: none

  &--is-disabled
    pointer-events: none


@import '../bootstrap'
@import '../theme'

v-small-dialog($material)
  &__content
    background: $material.cards

  &__actions
    background: $material.cards

  a
    color: rgba($material.fg-color, $material.primary-text-percent)

theme(v-small-dialog, "v-small-dialog")

.v-small-dialog
  display: block
  width: 100%
  height: 100%

  &__content
    padding: 0 24px

  &__actions
    text-align: right

  a
    display: flex
    align-items: center

    height: 100%
    text-decoration: none

    > *
      width: 100%

  .v-menu__activator
    height: 100%


import { test } from '@/test'
import { maskText, unmaskText, isMaskDelimiter } from '@/util/mask'

test('mask.js', ({ mount }) => {
  // Mask
  it('should add delimiter', () => {
    expect(maskText('5', '(#')).toBe('(5')
  })

  it('should add delimiter if explicity typed', () => {
    expect(maskText('(', '(#')).toBe('(')
  })

  it('should add delimiters and masks', () => {
    expect(maskText('4567', '(###) #')).toBe('(456) 7')
    expect(maskText('444444444', '#### - #### - #### - ####')).toBe('4444 - 4444 - 4')
    expect(maskText('A314444', 'A## - ####')).toBe('A31 - 4444')
  })

  it('should fill mask blanks', () => {
    expect(maskText('55', '## - ##')).toBe('55 - ')
  })

  it('should not fill mask blanks if told not to', () => {
    expect(maskText('55', '## - ##', true)).toBe('55')
  })

  it('should not fill if no value is provided', () => {
    expect(maskText('', '## - ##')).toBe('')
  })

  it('should only allow exact input if dontFillMaskBlanks is true', () => {
    expect(maskText('4567', '(###) #', true)).toBe('')
    expect(maskText('(456)', '(###) #', true)).toBe('(456)')
  })

  it('should convert alphanumeric to the proper case', () => {
    expect(maskText('aa', 'Aa')).toBe('Aa')
    expect(maskText('AA', 'aa')).toBe('aa')
    expect(maskText('A1', 'Aa')).toBe('A')
    expect(maskText('12abAB', 'NnNnNn')).toBe('12AbAb')
  })

  it('should not fill if wrong value is provided even if it is correct later in mask', () => {
    expect(maskText('a', '#a')).toBe('')
  })

  /* Not sure how to implement this
  it('should not fill in delimiter value if it does not match', () => {
    expect(maskText('a', '(')).toBe('')
  })
  */

  it('should fill last characters if they are all delimiters', () => {
    expect(maskText('1', '#)')).toBe('1)')
    expect(maskText('123', '(###)!!')).toBe('(123)!!')
  })

  it('should mask numbers', () => {
    expect(maskText(1234, '##.##')).toBe('12.34')
  })

  it('should return empty string if no input is given', () => {
    expect(maskText(null, '#')).toBe('')
  })

  it('should accept masked parameter if array', () => {
    expect(maskText('12', ['#', '-', '#'])).toBe('1-2')
  })

  // Unmasks
  it('should remove delimiter', () => {
    expect(unmaskText('(5')).toBe('5')
  })

  it('should return proper text length', () => {
    expect(unmaskText('1111')).toBe('1111')
  })

  it('should remove delimiters and masks', () => {
    expect(unmaskText('(123)4')).toBe('1234')
    expect(unmaskText('(456) 7)')).toBe('4567')
    expect(unmaskText('4444 - 4444 - 4')).toBe('444444444')
    expect(unmaskText('A31 - 4444')).toBe('A314444')
  })

  it('should include all possible matching values', () => {
    expect(unmaskText('555')).toBe('555')
  })

  it('should return null if no input is given', () => {
    expect(unmaskText(null)).toBe(null)
  })

  // isMaskDelimiter
  it('should identify mask delimiters', () => {
    expect(isMaskDelimiter('a')).toBe(false)
    expect(isMaskDelimiter('-')).toBe(true)
  })
})


@import '../bootstrap'

.v-date-picker-title
  display: flex
  justify-content: space-between
  flex-direction: column
  flex-wrap: wrap
  line-height: 1

.v-date-picker-title__year
    align-items: center
    display: inline-flex
    font-size: 14px
    font-weight: 500
    margin-bottom: 8px

.v-date-picker-title__date
    font-size: 34px
    text-align: left
    font-weight: 500
    position: relative
    overflow: hidden

    > div
      position: relative


import VList from '@/components/VList'
import { test } from '@/test'

// TODO: Test actual behaviour instead of classes
test('VList.js', ({ mount }) => {
  it('should render component and match snapshot', () => {
    const wrapper = mount(VList)

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render a dense component and match snapshot', () => {
    const wrapper = mount(VList, {
      propsData: {
        dense: true
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render a subheader component and match snapshot', () => {
    const wrapper = mount(VList, {
      propsData: {
        subheader: true
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render a threeLine component and match snapshot', () => {
    const wrapper = mount(VList, {
      propsData: {
        threeLine: true
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })

  it('should render a twoLine component and match snapshot', () => {
    const wrapper = mount(VList, {
      propsData: {
        twoLine: true
      }
    })

    expect(wrapper.html()).toMatchSnapshot()
  })
})


@import '../bootstrap'
@import '../components/_ripples'
@import '../theme'

button($material)
  color: $material.text.primary

  &.v-btn--disabled
    color: $material.buttons.disabled !important

    .v-icon,
    .v-btn__loading
      color: $material.buttons.disabled !important

    &:not(.v-btn--icon):not(.v-btn--flat)
      background-color: $material.buttons.focused !important

  &:not(.v-btn--icon):not(.v-btn--flat)
    background-color: $material.app-bar

theme(button, "v-btn")

/** Base Spec */
.v-btn
  align-items: center
  border-radius: $button-border-radius
  display: inline-flex
  height: $button-height
  flex: 0 1 auto
  font-size: $button-font-size
  font-weight: $button-font-weight
  justify-content: center
  margin: $button-margin
  min-width: $button-min-width
  outline: 0
  text-transform: $button-text-transform
  text-decoration: none
  transition: $primary-transition, color 1ms
  position: relative
  vertical-align: middle
  user-select: none

/** Psuedo */
.v-btn
  &:before
    border-radius: inherit
    color: inherit
    content: ''
    position: absolute
    left: 0
    top: 0
    height: 100%
    opacity: .12
    transition: $primary-transition
    width: 100%

/** Content */
.v-btn
  padding: $button-padding

  &--active,
  &:hover,
  &:focus
    position: relative

    &:before
      background-color: currentColor

  &__content
    align-items: center
    border-radius: inherit
    color: inherit
    display: flex
    height: inherit
    flex: 1 0 auto
    justify-content: center
    margin: 0 auto
    // Fixes bug where IE11 moves
    // button content when clicked
    // https://stackoverflow.com/questions/10305658/prevent-button-from-shifting-during-click-in-ie
    position: relative
    transition: $primary-transition
    white-space: nowrap
    width: inherit

/** Sizes */
.v-btn
  &--small
    font-size: $button-small-font-size
    height: $button-small-height
    padding: $button-small-padding

  &--large
    font-size: $button-large-font-size
    height: $button-large-height
    padding: $button-large-padding

/** Icons */
.v-btn .v-btn__content .v-icon
  color: inherit

/** Types */
.v-btn
  &--flat
    background-color: transparent !important
    box-shadow: none !important

  &:not(.v-btn--depressed)
    will-change: box-shadow
    elevation(2)

    &:active
      elevation(8)

  &--icon
    background: transparent
    box-shadow: none !important
    border-radius: 50%
    justify-content: center
    min-width: 0
    width: $button-height

    &.v-btn--small
      width: $button-small-height

    &.v-btn--large
      width: $button-large-height

    &:before
      border-radius: 50%

  &--floating
    border-radius: 50%
    min-width: 0
    height: $button-floating-width
    width: $button-floating-width
    padding: 0

    &.v-btn--fixed,
    &.v-btn--absolute
      z-index: 4

    &:not(.v-btn--depressed)
      elevation(6)

      &:active
        elevation(12)

    .v-btn__content
      flex: 1 1 auto
      margin: 0

    &:after
      border-radius: 50%

    .v-btn__content
      :not(:only-child)
        transition: $primary-transition

        &:first-child
          opacity: 1

        &:last-child
          opacity: 0
          transform: rotate(-45deg)

        &:last-child,
        &:first-child
          // https://stackoverflow.com/questions/14729492/css3-transform-rotate-causing-1px-shift-in-chrome
          -webkit-backface-visibility: hidden
          position: absolute
          left: 0
          top: 0

    &.v-btn--active
      .v-btn__content
        :not(:only-child)
          &:first-child
            opacity: 0
            transform: rotate(45deg)

          &:last-child
            opacity: 1
            transform: rotate(0)

    .v-icon
      height: inherit
      width: inherit

    &.v-btn--small
      height: $button-floating-small-width
      width: $button-floating-small-width

      .v-icon
        font-size: $button-floating-small-icon-width

    &.v-btn--large
      height: $button-floating-large-width
      width: $button-floating-large-width

      .v-icon
        font-size: $button-floating-large-icon-width

  &--reverse
    .v-btn__content
      flex-direction: row-reverse

    &.v-btn--column
      .v-btn__content
        flex-direction: column-reverse

  &--fixed, &--absolute
    margin: 0

  // Position must have prepended .v-btn
  // to account for tooltip
  // TODO: Remove this once tooltips are
  // converted to elements
  &.v-btn--absolute
    position: absolute

  &.v-btn--fixed
    position: fixed

  &--top
    &:not(.v-btn--absolute)
      top: $grid-gutters.lg

    &.v-btn--absolute
      top: -($button-floating-width / 2)

      &.v-btn--small
        top: -($button-floating-small-width / 2)

      &.v-btn--large
        top: -($button-floating-large-width / 2)

  &--bottom
    &:not(.v-btn--absolute)
      bottom: $grid-gutters.lg

    &.v-btn--absolute
      bottom: -($button-floating-width / 2)

      &.v-btn--small
        bottom: -($button-floating-small-width / 2)

      &.v-btn--large
        bottom: -($button-floating-large-width / 2)

  &--left
    left: $grid-gutters.lg

  &--right
    right: $grid-gutters.lg

/** Disabled */
.v-btn
  &.v-btn--disabled
    box-shadow: none !important
    pointer-events: none

  &:not(.v-btn--disabled)
    .v-btn__content .v-icon
      transition: none

.v-btn--icon
  padding: 0

/** Loader */
.v-btn
  &--loader
    pointer-events: none

    .v-btn__content
      opacity: 0

  &__loading
    align-items: center
    display: flex
    height: 100%
    justify-content: center
    left: 0
    position: absolute
    top: 0
    width: 100%

    .v-icon
      &--left
        margin-right: 1rem
        line-height: inherit

      &--right
        margin-left: 1rem
        line-height: inherit

/** Custom Buttons */
.v-btn
  &.v-btn--outline
    border: 1px solid currentColor
    background: transparent !important
    box-shadow: none

    &:hover
      box-shadow: none

  &--block
    display: flex
    flex: 1
    margin: $button-margin-y 0
    width: 100%

  &--round
    border-radius: 28px

    &:after
      border-radius: 28px

/** Button w/ directional Icon */
.v-btn
  .v-icon
    &--right
      margin-left: 16px

    &--left
      margin-right: 16px

/** Themes */
.v-btn
  &.primary,
  &.secondary,
  &.accent,
  &.success,
  &.error,
  &.warning,
  &.info
    color: $material-dark.text.primary


/**
 * Menu activator
 *
 * @mixin
 *
 * Handles the click and hover activation
 * Supports slotted and detached activators
 */
export default {
  methods: {
    activatorClickHandler (e) {
      if (this.disabled) return
      if (this.openOnClick && !this.isActive) {
        this.getActivator().focus()
        this.isActive = true
        this.absoluteX = e.clientX
        this.absoluteY = e.clientY
      } else if (this.closeOnClick && this.isActive) {
        this.getActivator().blur()
        this.isActive = false
      }
    },
    mouseEnterHandler () {
      this.runDelay('open', () => {
        if (this.hasJustFocused) return

        this.hasJustFocused = true
        this.isActive = true
      })
    },
    mouseLeaveHandler (e) {
      // Prevent accidental re-activation
      this.runDelay('close', () => {
        if (this.$refs.content.contains(e.relatedTarget)) return

        requestAnimationFrame(() => {
          this.isActive = false
          this.callDeactivate()
        })
      })
    },
    addActivatorEvents (activator = null) {
      if (!activator) return
      activator.addEventListener('click', this.activatorClickHandler)
    },
    removeActivatorEvents (activator = null) {
      if (!activator) return
      activator.removeEventListener('click', this.activatorClickHandler)
    }
  }
}


&--disabled
pointer-events: none
&--dense
&--is-component
height: $icon-size-dense

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VIcon for component icon should render an svg icon 1`] = `

  <svg xmlns="http://www.w3.org/2000/svg"
       viewbox="0 0 24 24"
       role="img"
       aria-hidden="true"
       class="v-icon__svg"
  >
    <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z">
    </path>
  </svg>

`;

exports[`VIcon for component icon should render an svg icon 2`] = `

  <svg xmlns="http://www.w3.org/2000/svg"
       viewbox="0 0 24 24"
       role="img"
       aria-hidden="true"
       class="v-icon__svg"
       style="font-size: 36px; height: 36px; width: 36px;"
  >
    <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z">
    </path>
  </svg>

`;

exports[`VIcon for component icon should render component 1`] = `

    test icon

`;

exports[`VIcon for component icon should set font size from helper prop 1`] = `

    test icon

`;

exports[`VIcon for component icon should set font size from helper prop 2`] = `

    test icon

`;

exports[`VIcon for component icon should set font size from helper prop 3`] = `

    test icon

`;

exports[`VIcon for component icon should set font size from helper prop 4`] = `

    test icon

`;

exports[`VIcon set font size from helper prop 1`] = `

  add

`;

exports[`VIcon set font size from helper prop 2`] = `

  add

`;

exports[`VIcon set font size from helper prop 3`] = `

  add

`;

exports[`VIcon set font size from helper prop 4`] = `

  add

`;


<template>
  <v-file-input
    label="File input"
    outlined
    dense
  ></v-file-input>
</template>


import { factory as PositionableFactory } from '../positionable'
import { TargetProp } from 'vuetify/types/services/application'

// Util
import mixins from '../../util/mixins'

export default function applicationable (value: TargetProp, events: string[] = []) {
  /* @vue/component */
  return mixins(PositionableFactory(['absolute', 'fixed'])).extend({
    name: 'applicationable',

    props: {
      app: Boolean,
    },

    computed: {
      applicationProperty (): TargetProp {
        return value
      },
    },

    watch: {
      // If previous value was app
      // reset the provided prop
      app (x: boolean, prev: boolean) {
        prev
          ? this.removeApplication(true)
          : this.callUpdate()
      },
      applicationProperty (newVal, oldVal) {
        this.$vuetify.application.unregister(this._uid, oldVal)
      },
    },

    activated () {
      this.callUpdate()
    },

    created () {
      for (let i = 0, length = events.length; i < length; i++) {
        this.$watch(events[i], this.callUpdate)
      }
      this.callUpdate()
    },

    mounted () {
      this.callUpdate()
    },

    deactivated () {
      this.removeApplication()
    },

    destroyed () {
      this.removeApplication()
    },

    methods: {
      callUpdate () {
        if (!this.app) return

        this.$vuetify.application.register(
          this._uid,
          this.applicationProperty,
          this.updateApplication()
        )
      },
      removeApplication (force = false) {
        if (!force && !this.app) return

        this.$vuetify.application.unregister(
          this._uid,
          this.applicationProperty
        )
      },
      updateApplication: () => 0,
    },
  })
}


export default {
  badge: 'Jelvény',
  close: 'Bezárás',
  dataIterator: {
    noResultsText: 'Nincs egyező találat',
    loadingText: 'Betöltés...',
  },
  dataTable: {
    itemsPerPageText: 'Elem oldalanként:',
    ariaLabel: {
      sortDescending: 'Csökkenő sorrendbe rendezve.',
      sortAscending: 'Növekvő sorrendbe rendezve.',
      sortNone: 'Rendezetlen.',
      activateNone: 'Rendezés törlése.',
      activateDescending: 'Aktiváld a csökkenő rendezésért.',
      activateAscending: 'Aktiváld a növekvő rendezésért.',
    },
    sortBy: 'Rendezés',
  },
  dataFooter: {
    itemsPerPageText: 'Elem oldalanként:',
    itemsPerPageAll: 'Mind',
    nextPage: 'Következő oldal',
    prevPage: 'Előző oldal',
    firstPage: 'Első oldal',
    lastPage: 'Utolsó oldal',
    pageText: '{0}-{1} / {2}',
  },
  datePicker: {
    itemsSelected: '{0} kiválasztva',
    nextMonthAriaLabel: 'Következő hónap',
    nextYearAriaLabel: 'Következő év',
    prevMonthAriaLabel: 'Előző hónap',
    prevYearAriaLabel: 'Előző év',
  },
  noDataText: 'Nincs elérhető adat',
  carousel: {
    prev: 'Előző',
    next: 'Következő',
    ariaLabel: {
      delimiter: 'Dia {0}/{1}',
    },
  },
  calendar: {
    moreEvents: '{0} további',
  },
  fileInput: {
    counter: '{0} fájl',
    counterSize: '{0} fájl ({1} összesen)',
  },
  timePicker: {
    am: 'de',
    pm: 'du',
  },
  pagination: {
    ariaLabel: {
      wrapper: 'Oldal navigáció',
      next: 'Következő oldal',
      previous: 'Előző oldal',
      page: 'Menj a(z) {0}. oldalra',
      currentPage: 'Aktuális oldal: {0}',
    },
  },
}


height: $icon-size-dense
&__svg
height: $icon-size
width: $icon-size
fill: currentColor

&__component
height: $icon-size
width: $icon-size


<template>
  <v-card
    class="mx-auto"
    max-width="400"
  >
    <v-card-title>

        Toothbrush

      <v-spacer></v-spacer>
      $4.99
    </v-card-title>

    <v-card-text>
      Our company takes pride in making handmade brushes.
      Our toothbrushes are available in 4 different bristel types, from extra soft to hard.
    </v-card-text>

    <v-divider class="mx-4"></v-divider>

    <v-card-text>
      Select type

      <v-chip-group
        v-model="selection"
        active-class="deep-purple--text text--accent-4"
        mandatory
      >
        <v-chip>Extra Soft</v-chip>
        <v-chip>Soft</v-chip>
        <v-chip>Medium</v-chip>
        <v-chip>Hard</v-chip>
      </v-chip-group>
    </v-card-text>

    <v-card-actions>
      <v-btn
        block
        class="white--text"
        color="deep-purple accent-4"
      >
        Add to Cart
      </v-btn>
    </v-card-actions>
  </v-card>
</template>


@import '../../styles/styles.sass';

$avatar-margin-x: 16px !default;
$list-border-radius: 0 !default;
$list-elevation: 0 !default;
$list-dense-subheader-font-size: 0.75rem !default;
$list-dense-subheader-height: 40px !default;
// TODO: Resolve naming conflicts for
// shaped style propagation to items
$list-shaped-border-radius: 0 !default;

$list-item-avatar-margin-y: 8px !default;
$list-item-avatar-horizontal-margin-x: -16px !default;

$list-item-icon-margin-y: 16px !default;

$list-item-min-height: 48px !default;
$list-item-two-line-min-height: 64px !default;
$list-item-three-line-min-height: 88px !default;

$list-item-title-font-size: map-deep-get($headings, 'subtitle-1', 'size') !default;
$list-item-subtitle-font-size: map-deep-get($headings, 'subtitle-2', 'size') !default;

$list-item-dense-title-font-size: 0.8125rem !default;
$list-item-dense-title-font-weight: 500 !default;
$list-padding: 8px 0 !default;
$list-dense-subheading-padding: 0 8px !default;
$list-nav-border-radius: $border-radius-root !default;
$list-nav-rounded-item-margin-bottom: 8px !default;
$list-nav-rounded-item-dense-margin-bottom: 4px !default;
$list-nav-padding-left: 8px !default;
$list-nav-padding-right: 8px !default;
$list-nav-item-padding: 0 8px !default;
$list-shaped-padding: 8px !default;
$list-subheader-padding-top: 0 !default;
$list-group-header-icon-min-width: 48px !default;
$list-group-sub-group-child-margin: 16px !default;
$list-group-sub-group-header-margin: 32px !default;
$list-group-items-item-padding: 40px !default;
$list-group-no-action-item-padding: 72px !default;
$list-dense-subheader-padding: 0 8px !default;
$list-nav-rounded-dense-item-margin-bottom: 4px !default;
$list-group-no-action-sub-group-item-padding: 88px !default;
$list-group-dense-sub-group-header-padding: 24px !default;
$list-group-nav-no-action-item-padding: 64px !default;
$list-group-sub-group-item-padding: 80px !default;
$list-item-padding: 0 16px !default;
$list-item-action-margin: 12px 0 !default;
$list-item-action-text-font-size: map-deep-get($headings, 'caption', 'size') !default;
$list-item-avatar-horizontal-margin: 8px !default;
$list-item-content-padding: 12px 0 !default;
$list-item-content-children-margin-bottom: 2px !default;
$list-item-icon-margin: 16px 0 !default;
$list-item-child-last-type-margin: 16px !default;
$list-item-child-min-width: 24px !default;
$list-item-title-subtitle-line-height: 1.2 !default;
$list-item-avatar-first-child-margin: 16px !default;
$list-item-action-icon-margin: 32px !default;
$list-dense-icon-height: 24px !default;
$list-dense-icon-margin: 8px !default;
$list-dense-min-height: 40px !default;
$list-item-dense-title-line-height: 1rem !default;
$list-item-dense-two-line-min-height: 60px !default;
$list-item-dense-three-line-min-height: 76px !default;
$list-dense-content-padding: 8px 0 !default;
$list-item-two-line-icon-margin-bottom: 32px !default;
$list-item-three-line-avatar-action-margin: 16px !default;


import Vue, { VNode, PropType } from 'vue'
import { getObjectValueByPath } from '../../util/helpers'
import { DataTableHeader } from 'vuetify/types'

export default Vue.extend({
  name: 'row',

  functional: true,

  props: {
    headers: Array as PropType<DataTableHeader[]>,
    hideDefaultHeader: Boolean,
    item: Object,
    rtl: Boolean,
  },

  render (h, { props, slots, data }): VNode {
    const computedSlots = slots()

    const columns: VNode[] = props.headers.map((header: DataTableHeader) => {
      const classes = {
        'v-data-table__mobile-row': true,
      }

      const children = []
      const value = getObjectValueByPath(props.item, header.value)

      const slotName = header.value
      const scopedSlot = data.scopedSlots && data.scopedSlots[slotName]
      const regularSlot = computedSlots[slotName]

      if (scopedSlot) {
        children.push(scopedSlot({ item: props.item, header, value }))
      } else if (regularSlot) {
        children.push(regularSlot)
      } else {
        children.push(value == null ? value : String(value))
      }

      const mobileRowChildren = [
        h('div', {
          staticClass: 'v-data-table__mobile-row__cell',
        }, children),
      ]

      if (header.value !== 'dataTableSelect' && !props.hideDefaultHeader) {
        mobileRowChildren.unshift(
          h('div', {
            staticClass: 'v-data-table__mobile-row__header',
          }, [header.text])
        )
      }

      return h('td', { class: classes }, mobileRowChildren)
    })

    return h('tr', { ...data, staticClass: 'v-data-table__mobile-table-row' }, columns)
  },
})


): VNode {
const data: VNodeData = {
class: {
'v-icon__svg': true,
},
}
const size = this.getSize()
if (size) {

keep keep keep replace keep keep keep keep keep

// Imports
@import './_variables.scss'

// Theme
+theme(v-icon) using ($material)
  color: map-deep-get($material, 'icons', 'active')

  &:focus::after
    opacity: map-deep-get($material, 'states', 'focus')

  &.v-icon.v-icon--disabled
    color: map-deep-get($material, 'icons', 'inactive') !important

// Increased specificity to overwrite
// iconfont css interference
.v-icon.v-icon
  align-items: center
  display: inline-flex
  font-feature-settings: 'liga'
  font-size: $icon-size
  justify-content: center
  letter-spacing: normal
  line-height: 1
  position: relative
  text-indent: 0
  transition: $primary-transition, visibility 0s
  vertical-align: middle
  user-select: none

  &::after
    background-color: currentColor
    border-radius: 50%
    content: ''
    display: inline-block
    height: 100%
    left: 0
    opacity: 0
    pointer-events: none
    position: absolute
    top: 0
    transform: scale(1.3)
    width: 100%
    transition: opacity 0.2s map-get($transition, 'ease-in-out')

  &--dense
    font-size: $icon-size-dense

.v-icon
  &--right
    margin-left: map-get($grid-gutters, 'md')
  &--left
    margin-right: map-get($grid-gutters, 'md')

  &.v-icon.v-icon--link
    cursor: pointer
    outline: none

  &--disabled
    pointer-events: none

  &--dense
    &--is-component
      height: $icon-size-dense

  &__svg
    height: $icon-size
    width: $icon-size
    fill: currentColor


module.exports = {
  'v-item-group': {
    events: [
      {
        name: 'change',
        value: 'any[] | any',
      },
    ],
  },
}


module.exports = {
  'v-theme-provider': {},
}


module.exports = {
  'v-list-item-title': {
    slots: [
      {
        name: 'default',
        props: undefined,
      },
    ],
  },
}


exports[`VIcon for component icon should render component 1`] = `

<div class="test-component v-icon__svg theme--light">

<div class="test-component v-icon__component theme--light">


const semver = require('semver')
const shell = require('shelljs')
const inquirer = require('inquirer')
const version = require('../lerna.json').version

function exec (command) {
  const result = shell.exec(command, { silent: true })
  if (result.code) {
    shell.echo('')
    console.error(result.stdout.trim())
    shell.exit(1)
  }
  return result.stdout.trim()
}

const branch = exec('git symbolic-ref --short HEAD')
const tag = semver.prerelease(version) == null ? 'latest' : branch

shell.echo(`Releasing ${version} on ${branch}`)
shell.echo(`Tag: ${tag}`)
inquirer.prompt({
  type: 'confirm',
  name: 'yes',
  message: 'Are you sure?',
  default: true,
}).then(({ yes }) => yes || shell.exit(1))


<template>
  <v-app>
    <v-main>
      <playground></playground>
    </v-main>
  </v-app>
</template>

<script>
  import Playground from './Playground'

  export default {
    components: {
      Playground,
    },
  }
</script>


// https://davestewart.github.io/vuex-pathify/#/setup/config

import pathify from 'vuex-pathify'

// options
pathify.options.mapping = 'simple'
pathify.options.strict = true

export default pathify


style="font-size: 16px; height: 16px; width: 16px;"

<div class="test-component v-icon__svg theme--light"

<div class="test-component v-icon__component theme--light"


---
meta:
  title: List component
  description: The list component is a continuous group of text, images and icons that may contain primary or supplemental actions.
  keywords: lists, vuetify list component, vue list component
related:
  - /components/item-groups/
  - /components/list-item-groups/
  - /components/subheaders/
---

# Lists

The `v-list` component is used to display information. It can contain an avatar, content, actions, subheaders and much more. Lists present content in a way that makes it easy to identify a specific item in a collection. They provide a consistent styling for organizing groups of text and images.

<entry-ad />

## Usage

Lists come in three main variations. **single-line** (default), **two-line** and **three-line**. The line declaration specifies the minimum height of the item and can also be controlled from `v-list` with the same prop.

<example file="v-list/usage" />

## API

- [v-list](/api/v-list)
- [v-list-item](/api/v-list-item)
- [v-list-item-action](/api/v-list-item-action)
- [v-list-item-action-text](/api/v-list-item-action-text)
- [v-list-item-avatar](/api/v-list-item-avatar)
- [v-list-item-content](/api/v-list-item-content)
- [v-list-item-group](/api/v-list-group)
- [v-list-item-icon](/api/v-list-item-icon)
- [v-list-item-subtitle](/api/v-list-item-subtitle)
- [v-list-item-title](/api/v-list-item-title)

<!-- ## Sub-components

### v-list-item

v-list-item description

### v-list-item-action

v-list-item-action description

### v-list-item-action-text

v-list-item-action-text description

### v-list-item-avatar

v-list-item-avatar description

### v-list-item-content

v-list-item-content description

### v-list-item-subtitle

v-list-item-subtitle description

### v-list-item-title

v-list-item-title description -->

## Caveats

<alert type="info">

  If you are looking for stateful list items, please check out [v-list-item-group](/components/list-item-groups).

</alert>

## Examples

### Props

#### Dense

`v-list` can be lowered with **dense** property.

<example file="v-list/prop-dense" />

#### Disabled

You cannot interact with disabled `v-list`.

<example file="v-list/prop-disabled" />

#### Flat

Items don't change when selected in `v-list` with **flat** property.

<example file="v-list/prop-flat" />

#### Nav

Lists can receive an alternative **nav** styling that reduces the width `v-list-item` takes up as well as adding a border radius.

<example file="v-list/prop-nav" />

#### Rounded

You can make `v-list` items rounded.

<example file="v-list/prop-rounded" />

#### Shaped

Shaped lists have rounded borders on one side of the `v-list-item`.

<example file="v-list/prop-shaped" />

#### Sub group

Using the `v-list-group` component you can create up to **2** levels in depth using the **sub-group** prop.

<example file="v-list/prop-sub-group" />

#### Three line

For three line lists, the subtitle will clamp vertically at 2 lines and then ellipsis. This feature uses [line-clamp](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp) and is not supported in all browsers.

<example file="v-list/prop-three-line" />

#### Two lines and subheader

Lists can contain subheaders, dividers, and can contain 1 or more lines. The subtitle will overflow with ellipsis if it extends past one line.

<example file="v-list/prop-two-line-and-subheader" />

### Slots

#### Expansion Lists

A list can contain a group of items which will display on click utilizing `v-item-group`'s `activator` slot. Expansion lists are also used within the **[v-navigation-drawer](/components/navigation-drawers)** component.

<example file="v-list/slot-expansion-lists" />

### Misc

#### Action and item groups

A **three-line** list with actions. Utilizing **[v-list-item-group](/components/list-item-groups)**, easily connect actions to your tiles.

<example file="v-list/misc-action-and-item-groups" />

#### Action stack

A list can contain a stack within an action. This is useful when you need to display meta text next to your action item.

<example file="v-list/misc-action-stack" />

#### Card list

A list can be combined with a card.

<example file="v-list/misc-card-list" />

#### Simple avatar list

A simple list utilizing `v-list-item-icon`, `v-list-item-title` and `v-list-item-avatar`.

<example file="v-list/misc-simple-avatar-list" />

#### Single line list

Here we combine **v-list-item-avatar** and **v-list-item-icon** in a single-line list.

<example file="v-list/misc-single-line-list" />

#### Subheadings and dividers

Lists can contain multiple subheaders and dividers.

<example file="v-list/misc-subheadings-and-dividers" />

<backmatter />


import Vue, { WatchHandler } from 'vue'

/**
 * This mixin provides `attrs$` and `listeners$` to work around
 * vue bug https://github.com/vuejs/vue/issues/10115
 */

function makeWatcher (property: string): ThisType<Vue> & WatchHandler<any> {
  return function (this: Vue, val, oldVal) {
    for (const attr in oldVal) {
      if (!Object.prototype.hasOwnProperty.call(val, attr)) {
        this.$delete(this.$data[property], attr)
      }
    }
    for (const attr in val) {
      this.$set(this.$data[property], attr, val[attr])
    }
  }
}

export default Vue.extend({
  data: () => ({
    attrs$: {} as Dictionary<string>,
    listeners$: {} as Dictionary<Function | Function[]>,
  }),

  created () {
    // Work around unwanted re-renders: https://github.com/vuejs/vue/issues/10115
    // Make sure to use `attrs$` instead of `$attrs` (confusing right?)
    this.$watch('$attrs', makeWatcher('attrs$'), { immediate: true })
    this.$watch('$listeners', makeWatcher('listeners$'), { immediate: true })
  },
})


Designates if menu should close on outside-activator click

Designates if menu should close when its content is clicked

Milliseconds to wait before closing component. Only works with the **open-on-hover** prop

Detaches the menu content inside of the component as opposed to the document.

Offset the menu on the x-axis. Works in conjunction with direction left/right

Offset the menu on the y-axis. Works in conjunction with direction top/bottom

Milliseconds to wait before opening component. Only works with the **open-on-hover** prop

Designates whether menu should open on activator click

Designates whether menu should open on activator hover

Sets the transition origin on the element. You can find more information on the MDN documentation [for transition origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin).

The value that is updated when the menu is closed - must be primitive. Dot notation is supported

Sets the component transition. Can be one of the [built in transitions](/styles/transitions) or one your own.


exports[`VIcon for component icon should set font size from helper prop 2`] = `

keep keep keep keep keep replace keep keep keep


<template>
  <v-card
    class="mx-auto"
    max-width="400"
  >
    <v-card
      dark
      flat
    >
      <v-btn
        absolute
        bottom
        color="pink"
        right
        fab
      >
        <v-icon>mdi-plus</v-icon>
      </v-btn>
      <v-card-title class="pa-2 purple lighten-3">
        <v-btn icon>
          <v-icon>mdi-menu</v-icon>
        </v-btn>

          Timeline

        <v-avatar>
          <v-img src="https://avataaars.io/?avatarStyle=Circle&topType=LongHairStraight&accessoriesType=Blank&hairColor=BrownDark&facialHairType=Blank&clotheType=BlazerShirt&eyeType=Default&eyebrowType=Default&mouthType=Default&skinColor=Light"></v-img>
        </v-avatar>
      </v-card-title>
      <v-img
        src="https://cdn.vuetifyjs.com/images/cards/forest.jpg"
        gradient="to top, rgba(0,0,0,.44), rgba(0,0,0,.44)"
      >
        <v-container class="fill-height">
          <v-row align="center">
            8
            <v-row justify="end">

                Monday

                February 2015

            </v-row>
          </v-row>
        </v-container>
      </v-img>
    </v-card>
    <v-card-text class="py-0">
      <v-timeline
        align-top
        dense
      >
        <v-timeline-item
          color="pink"
          small
        >
          <v-row class="pt-1">
            <v-col cols="3">
              5pm
            </v-col>
            <v-col>
              New Icon

                Mobile App

            </v-col>
          </v-row>
        </v-timeline-item>

        <v-timeline-item
          color="teal lighten-3"
          small
        >
          <v-row class="pt-1">
            <v-col cols="3">
              3-4pm
            </v-col>
            <v-col>
              Design Stand Up

                Hangouts

              <v-avatar>
                <v-img
                  src="https://avataaars.io/?avatarStyle=Circle&topType=LongHairFrida&accessoriesType=Kurt&hairColor=Red&facialHairType=BeardLight&facialHairColor=BrownDark&clotheType=GraphicShirt&clotheColor=Gray01&graphicType=Skull&eyeType=Wink&eyebrowType=RaisedExcitedNatural&mouthType=Disbelief&skinColor=Brown"
                ></v-img>
              </v-avatar>
              <v-avatar>
                <v-img
                  src="https://avataaars.io/?avatarStyle=Circle&topType=ShortHairFrizzle&accessoriesType=Prescription02&hairColor=Black&facialHairType=MoustacheMagnum&facialHairColor=BrownDark&clotheType=BlazerSweater&clotheColor=Black&eyeType=Default&eyebrowType=FlatNatural&mouthType=Default&skinColor=Tanned"
                ></v-img>
              </v-avatar>
              <v-avatar>
                <v-img
                  src="https://avataaars.io/?avatarStyle=Circle&topType=LongHairMiaWallace&accessoriesType=Sunglasses&hairColor=BlondeGolden&facialHairType=Blank&clotheType=BlazerSweater&eyeType=Surprised&eyebrowType=RaisedExcited&mouthType=Smile&skinColor=Pale"
                ></v-img>
              </v-avatar>
            </v-col>
          </v-row>
        </v-timeline-item>

        <v-timeline-item
          color="pink"
          small
        >
          <v-row class="pt-1">
            <v-col cols="3">
              12pm
            </v-col>
            <v-col>
              Lunch break
            </v-col>
          </v-row>
        </v-timeline-item>

        <v-timeline-item
          color="teal lighten-3"
          small
        >
          <v-row class="pt-1">
            <v-col cols="3">
              9-11am
            </v-col>
            <v-col>
              Finish Home Screen

                Web App

            </v-col>
          </v-row>
        </v-timeline-item>
      </v-timeline>
    </v-card-text>
  </v-card>
</template>


Removes the icon rotation animation when expanding a panel

Hide the expand icon in the content header

Applies the [v-ripple](/directives/ripple) directive.


Designates that the avatar is on the left side of a component. This is hooked into by components such as [v-chip](/components/chips) and [v-btn](/components/buttons).

Designates that the avatar is on the right side of a component. This is hooked into by components such as [v-chip](/components/chips) and [v-btn](/components/buttons).


style="font-size: 36px; height: 36px; width: 36px;"


import VTabs from './VTabs'
import VTab from './VTab'
import VTabsItems from './VTabsItems'
import VTabItem from './VTabItem'
import VTabsSlider from './VTabsSlider'

export { VTabs, VTab, VTabItem, VTabsItems, VTabsSlider }

export default {
  $_vuetify_subcomponents: {
    VTabs,
    VTab,
    VTabsItems,
    VTabItem,
    VTabsSlider,
  },
}


<template>
  <div class="text-center">
    <v-menu>
      <template v-slot:activator="{ on, attrs }">
        <v-btn
          v-bind="attrs"
          v-on="on"
        >
          Click me
        </v-btn>
      </template>

      <v-list>
        <v-list-item @click="onClick">
          <v-list-item-title>Option 1</v-list-item-title>
        </v-list-item>

        <v-list-item disabled>
          <v-list-item-title>Option 2</v-list-item-title>
        </v-list-item>

        <v-list-item @click="onClick">
          <v-list-item-title>Option 3</v-list-item-title>
        </v-list-item>
      </v-list>
    </v-menu>
  </div>
</template>

<script>
  export default {
    methods: {
      onClick () {
        // Perform an action
      },
    },
  }
</script>