},
genDefaultSlot () {
return this.$slots.default
},
genIcon (type, cb) {
cb = cb || this[`${type}IconCb`]
const data = {

// Styles
import '../../stylus/components/_text-fields.styl'
import '../../stylus/components/_select.styl'

// Components
import VChip from '../VChip'
import VMenu from '../VMenu'
import VSelectList from './VSelectList'

// Extensions
import VTextField from '../VTextField/VTextField'

// Mixins
import Comparable from '../../mixins/comparable'
import Dependent from '../../mixins/dependent'
import Filterable from '../../mixins/filterable'
import Menuable from '../../mixins/menuable'

// Directives
import ClickOutside from '../../directives/click-outside'

// Helpers
import { getPropertyFromItem, keyCodes } from '../../util/helpers'

export default {
  name: 'v-select',

  extends: VTextField,

  directives: {
    ClickOutside
  },

  mixins: [
    Comparable,
    Dependent,
    Filterable
  ],

  data: vm => ({
    attrsInput: { role: 'combobox' },
    cachedItems: vm.cacheItems ? vm.items : [],
    isMenuActive: false,
    // As long as a value is defined, show it
    // Otherwise, check if multiple
    // to determine which default to provide
    lazyValue: vm.value != null
      ? vm.value
      : vm.multiple ? [] : undefined,
    selectedIndex: -1,
    selectedItems: []
  }),

  props: {
    ...VMenu.props, // TODO: remove some, just for testing,
    ...Menuable.props,
    appendIcon: {
      type: String,
      default: 'arrow_drop_down'
    },
    appendIconCb: Function,
    attach: Boolean,
    auto: Boolean,
    browserAutocomplete: {
      type: String,
      default: 'on'
    },
    cacheItems: Boolean,
    chips: Boolean,
    clearable: Boolean,
    contentClass: String,
    deletableChips: Boolean,
    dense: Boolean,
    editable: Boolean,
    hideSelected: Boolean,
    items: {
      type: Array,
      default: () => []
    },
    itemAvatar: {
      type: [String, Array, Function],
      default: 'avatar'
    },
    itemDisabled: {
      type: [String, Array, Function],
      default: 'disabled'
    },
    itemText: {
      type: [String, Array, Function],
      default: 'text'
    },
    itemValue: {
      type: [String, Array, Function],
      default: 'value'
    },
    maxHeight: {
      type: [Number, String],
      default: 300
    },
    minWidth: {
      type: [Boolean, Number, String],
      default: 0
    },
    multiple: Boolean,
    multiLine: Boolean,
    openOnClear: Boolean,
    overflow: Boolean,
    returnObject: Boolean,
    searchInput: {
      default: null
    },
    segmented: Boolean,
    smallChips: Boolean,
    singleLine: Boolean
  },

  computed: {
    classes () {
      return Object.assign({}, VTextField.computed.classes.call(this), {
        'v-select': true,
        'v-select--chips': this.chips,
        'v-select--is-menu-active': this.isMenuActive
      })
    },
    computedItems () {
      return this.filterDuplicates(this.cachedItems.concat(this.items))
    },
    directives () {
      return [{
        name: 'click-outside',
        // TODO: Check into this firing when it shouldn't
        value: e => {
          if (this.isMenuActive) {
            this.onKeyDown(e)
          }

          this.isMenuActive = false
          this.isFocused = false
          this.selectedIndex = -1
        },
        args: {
          closeConditional: e => {
            return !this.$refs.menu.$refs.content.contains(e.target) &&
              !this.$el.contains(e.target) &&
              e.target !== this.$el
          }
        }
      }]
    },
    dynamicHeight () {
      return 'auto'
    },
    hasSlot () {
      return Boolean(this.chips || this.$slots.item)
    },
    isDirty () {
      return this.selectedItems.length > 0
    },
    isDisabled () {
      return this.disabled || this.readonly
    },
    isMulti () {
      return this.multiple
    }
  },

  watch: {
    internalValue: 'setSelectedItems',
    items (val) {
      if (this.cacheItems) {
        this.cachedItems = this.filterDuplicates(this.cachedItems.concat(val))
      }

      this.setSelectedItems()
    }
  },

  created () {
    this.setSelectedItems()
  },

  methods: {
    clearableCallback () {
      this.internalValue = this.isMulti ? [] : null
      this.$emit('change', this.internalValue)
      this.$nextTick(() => this.$refs.input.focus())

      if (this.openOnClear) this.isMenuActive = true
    },
    filterDuplicates (arr) {
      const uniqueValues = new Map()
      for (let index = 0; index < arr.length; ++index) {
        const item = arr[index]
        const val = this.getValue(item)

        // TODO: comparator
        !uniqueValues.has(val) && uniqueValues.set(val, item)
      }
      return Array.from(uniqueValues.values())
    },
    findExistingIndex (item) {
      const itemValue = this.getValue(item)

      return (this.internalValue || []).findIndex(i => this.valueComparator(this.getValue(i), itemValue))
    },
    genChipSelection (item, index) {
      const isDisabled = this.disabled || this.readonly
      const click = e => {
        if (isDisabled) return

        e.stopPropagation()
        this.selectedIndex = index
        this.onFocus()
      }

      return this.$createElement(VChip, {
        staticClass: 'chip--select-multi',
        props: {
          close: this.deletableChips && !isDisabled,
          dark: this.dark,
          disabled: isDisabled,
          selected: index === this.selectedIndex,
          small: this.smallChips
        },
        on: {
          click: click,
          focus: click,
          input: () => {
            if (this.isMulti) this.selectItem(item)
            else this.internalValue = null

            // If all items have been deleted,
            // open `v-menu`
            if (this.selectedItems.length === 0) {
              this.isMenuActive = true
            }

            this.selectedIndex = -1
          }
        },
        key: this.getValue(item)
      }, this.getText(item))
    },
    genClearIcon () {
      if (!this.clearable ||
        !this.isDirty
      ) return null

      return this.genSlot('append', 'inner', [
        this.genIcon('clear', this.clearIconCb || this.clearableCallback)
      ])
    },
    genCommaSelection (item, index, last) {
      // Item may be an object
      // TODO: Remove JSON.stringify
      const key = JSON.stringify(this.getValue(item))

      return this.$createElement('div', {
        staticClass: 'v-select__selection v-select__selection--comma',
        'class': index === this.selectedIndex
          ? this.addTextColorClassChecks()
          : null,
        key
      }, `${this.getText(item)}${last ? '' : ', '}`)
    },
    genDefaultSlot () {
      const selections = this.genSelections()
      const input = this.genInput()

      // If the return is an empty array
      // push the input
      if (Array.isArray(selections)) {
        selections.push(input)
      // Otherwise push it into children
      } else {
        selections.children = selections.children || []
        selections.children.push(input)
      }

      const activator = this.genSelectSlot([
        this.genLabel(),
        this.prefix ? this.genAffix('prefix') : null,
        selections,
        this.suffix ? this.genAffix('suffix') : null,
        this.genClearIcon(),
        this.genSlot('append', 'inner', [this.genIcon('append')]),
        this.genProgress()
      ])

      return [this.genMenu(activator)]
    },
    genInput () {
      const input = VTextField.methods.genInput.call(this)

      input.data.domProps.value = null

      return input
    },
    genList () {
      return this.$createElement(VSelectList, {
        props: {
          action: this.isMulti && !this.isHidingSelected,
          color: this.color,
          dark: this.dark,
          dense: this.dense,
          items: this.items,
          light: this.light,
          noDataText: this.noDataText,
          selectedItems: this.selectedItems,
          itemAvatar: this.itemAvatar,
          itemDisabled: this.itemDisabled,
          itemValue: this.itemValue,
          itemText: this.itemText
        },
        on: {
          select: this.selectItem
        },
        scopedSlots: {
          item: this.$scopedSlots.item
        }
      }, [
        this.$slots['no-data'] ? this.$createElement('div', {
          slot: 'no-data'
        }, this.$slots['no-data']) : null
      ])
    },
    genMenu (activator) {
      const props = {
        contentClass: this.contentClass
      }
      const inheritedProps = Object.keys(VMenu.props).concat(Object.keys(Menuable.props))
      const nudgeMenu = !this.isSolo && !this.box

      // Later this might be filtered
      for (let prop of inheritedProps) {
        props[prop] = this[prop]
      }

      // These styles encompass the prepend
      // and append icons. Change activator
      // to the entire component
      if (this.isSolo) {
        props.activator = this.$el
      } else {
        props.activator = this.$refs['input-slot']
      }

      props.closeOnClick = false
      props.closeOnContentClick = false
      props.openOnClick = false
      props.value = this.isMenuActive
      props.offsetY = this.offsetY || nudgeMenu
      props.nudgeBottom = nudgeMenu ? 2 : 0 // convert to int

      return this.$createElement(VMenu, {
        props,
        on: {
          input: val => {
            this.isMenuActive = val
            this.isFocused = val
          }
        },
        ref: 'menu'
      }, [activator, this.genList()])
    },
    genSelections () {
      if (this.hideSelected) return []

      let length = this.selectedItems.length
      const children = new Array(length)

      let genSelection
      if (this.$scopedSlots.selection) {
        genSelection = this.genSlotSelection
      } else if (this.chips) {
        genSelection = this.genChipSelection
      } else {
        genSelection = this.genCommaSelection
      }

      while (length--) {
        children[length] = genSelection(
          this.selectedItems[length],
          length,
          length === children.length - 1
        )
      }

      return this.$createElement('div', {
        staticClass: 'v-select__selections'
      }, children)
    },
    genSelectSlot (children) {
      return this.$createElement('div', {
        staticClass: 'v-select__slot',
        directives: this.directives,
        slot: 'activator'
      }, children)
    },
    genSlotSelection (item, index) {
      return this.$scopedSlots.selection({
        parent: this,
        item,
        index,
        selected: index === this.selectedIndex,
        disabled: this.disabled || this.readonly
      })
    },
    getMenuIndex () {
      return this.$refs.menu ? this.$refs.menu.listIndex : -1
    },
    getText (item) {
      return getPropertyFromItem(item, this.itemText, item)
    },
    getValue (item) {
      return getPropertyFromItem(item, this.itemValue, item)
    },
    onBlur (e) {
      this.$emit('blur', e)
    },
    onClick () {
      if (this.isDisabled) return

      this.onFocus()
      this.isMenuActive = true
    },
    // Detect tab and call original onBlur method
    onKeyDown (e) {
      if (e.keyCode === keyCodes.tab) {
        VTextField.methods.onBlur.call(this, e)
      } else if ([
        keyCodes.enter,
        keyCodes.space,
        keyCodes.up,
        keyCodes.down
      ].includes(e.keyCode)) {
        this.isMenuActive = true
      }
    },
    onMouseUp (e) {
      if (this.isSolo || this.hasOutline) {
        this.isMenuActive = true
      }

      VTextField.methods.onMouseUp.call(this, e)
    },
    selectItem (item) {
      if (!this.isMulti) {
        this.internalValue = this.returnObject ? item : this.getValue(item)
        this.isMenuActive = false
      } else {
        const internalValue = (this.internalValue || []).slice()
        const i = this.findExistingIndex(item, internalValue)

        i !== -1 ? internalValue.splice(i, 1) : internalValue.push(item)
        this.internalValue = internalValue.map(i => {
          return this.returnObject ? i : this.getValue(i)
        })
      }

      this.$emit('change', this.internalValue)

      this.$nextTick(() => {
        this.$refs.menu &&
          this.$refs.menu.updateDimensions()
      })
    },
    setMenuIndex (index) {
      this.$refs.menu && (this.$refs.menu.listIndex = index)
    },
    setSelectedItems () {
      const fn = !this.isMulti
        ? i => this.valueComparator(
          this.getValue(i),
          this.getValue(this.internalValue)
        )
        : i => this.findExistingIndex(i, this.internalValue) > -1

      this.selectedItems = this.computedItems.filter(fn)
    }
  }
}


import Vue from 'vue'
import { test } from '@/test'
import VSelectList from '@/components/VSelect/VSelectList'
import {
  VListTile,
  VListTileTitle,
  VListTileContent
} from '@/components/VList'

test('VSelect', ({ mount, compileToFunctions }) => {
  const app = document.createElement('div')
  app.setAttribute('data-app', true)
  document.body.appendChild(app)

  it('should generate a divider', () => {
    const wrapper = mount(VSelectList)

    const divider = wrapper.vm.genDivider({
      inset: true
    })

    expect(divider.data.props.inset).toBe(true)
  })

  it('should generate a header', () => {
    const wrapper = mount(VSelectList)

    const divider = wrapper.vm.genHeader({
      light: true,
      header: 'foobar'
    })

    expect(divider.data.props.light).toBe(true)

    // Check that header exists
    expect(divider.children.length).toBe(1)
    expect(divider.children[0].text).toBe('foobar')
  })

  it('should use no-data slot', () => {
    const wrapper = mount(VSelectList, {
      slots: {
        'no-data': [{
          render: h => h('div', 'foo')
        }]
      }
    })
    expect(wrapper.vm.$slots['no-data'].length).toBe(1)
  })

  it('should generate children', () => {
    const wrapper = mount(VSelectList, {
      propsData: {
        items: [
          { header: true },
          { divider: true },
          'foo'
        ]
      }
    })

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

  it('should return defined item value', () => {
    const wrapper = mount(VSelectList, {
      propsData: {
        itemValue: 'foo'
      }
    })

    const getValue = wrapper.vm.getValue

    expect(getValue({ fizz: 'buzz' })).toEqual({ fizz: 'buzz' })

    wrapper.setProps({ itemValue: 'fizz' })

    expect(getValue({ fizz: 'buzz' })).toEqual('buzz')
  })
})


@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%


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

exports[`VAvatar.vue should have an v-avatar class 1`] = `

<div class="v-avatar"
     style="height: 48px; width: 48px;"
>
</div>

`;


keep keep keep keep keep replace keep keep keep


import { provide as RegistrableProvide } from './registrable'
import { consoleWarn } from '../util/console'

export default {
  name: 'button-group',

  mixins: [RegistrableProvide('buttonGroup')],

  data () {
    return {
      buttons: [],
      listeners: [],
      isDestroying: false
    }
  },

  watch: {
    buttons: 'update'
  },

  methods: {
    getValue (i) {
      if (this.buttons[i].value != null) {
        return this.buttons[i].value
      }

      // Fix for testing, this should always be false in the browser
      if (this.buttons[i].$el.value != null && this.buttons[i].$el.value !== '') {
        return this.buttons[i].$el.value
      }

      return i
    },
    update () {
      const selected = []

      for (let i = 0; i < this.buttons.length; i++) {
        const elm = this.buttons[i].$el
        const button = this.buttons[i]

        elm.removeAttribute('data-only-child')

        if (this.isSelected(i)) {
          !button.to && (button.isActive = true)
          selected.push(i)
        } else {
          !button.to && (button.isActive = false)
        }
      }

      if (selected.length === 1) {
        this.buttons[selected[0]].$el.setAttribute('data-only-child', true)
      }

      this.ensureMandatoryInvariant(selected.length > 0)
    },
    register (button) {
      const index = this.buttons.length
      this.buttons.push(button)
      this.listeners.push(this.updateValue.bind(this, index))
      button.$on('click', this.listeners[index])
    },
    unregister (buttonToUnregister) {
      // Basic cleanup if we're destroying
      if (this.isDestroying) {
        const index = this.buttons.indexOf(buttonToUnregister)
        if (index !== -1) {
          buttonToUnregister.$off('click', this.listeners[index])
        }
        return
      }

      this.redoRegistrations(buttonToUnregister)
    },
    redoRegistrations (buttonToUnregister) {
      let selectedCount = 0

      const buttons = []
      for (let index = 0; index < this.buttons.length; ++index) {
        const button = this.buttons[index]
        if (button !== buttonToUnregister) {
          buttons.push(button)
          selectedCount += Boolean(this.isSelected(index))
        }

        button.$off('click', this.listeners[index])
      }

      this.buttons = []
      this.listeners = []

      for (let index = 0; index < buttons.length; ++index) {
        this.register(buttons[index])
      }

      this.ensureMandatoryInvariant(selectedCount > 0)
      this.updateAllValues && this.updateAllValues()
    },
    ensureMandatoryInvariant (hasSelectedAlready) {
      // Preserve the mandatory invariant by selecting the first tracked button, if needed

      if (!this.mandatory || hasSelectedAlready) return

      if (!this.listeners.length) {
        consoleWarn('There must be at least one v-btn child if the mandatory property is true.', this)
        return
      }

      this.listeners[0]()
    }
  },

  mounted () {
    this.update()
  },

  beforeDestroy () {
    this.isDestroying = true
  }
}


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

exports[`VBreadcrumbs.js should have breadcrumbs classes 1`] = `

`;

exports[`VBreadcrumbs.js should inject slot to children 1`] = `

    /

    /

    /

`;

exports[`VBreadcrumbs.js should not create dividers for non-items 1`] = `

    /

`;

exports[`VBreadcrumbs.js should use a custom divider slot 1`] = `

    /divider/

`;

exports[`VBreadcrumbs.js should use custom justify props 1`] = `

`;

exports[`VBreadcrumbs.js should use custom justify props 2`] = `

`;


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

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

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

          chevron_left

    </button>

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

          chevron_right

    </button>

`;

exports[`VCarousel.js should render component with custom duration between image cycles and match snapshot 1`] = `

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

          chevron_left

    </button>

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

          chevron_right

    </button>

`;

exports[`VCarousel.js should render component with custom icon and match snapshot 1`] = `

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

          chevron_left

    </button>

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

          chevron_right

    </button>

    <button type="button"
            class="v-btn v-btn--icon v-btn--small theme--dark v-carousel__controls__item v-carousel__controls__item--active"
    >

          stop

    </button>
    <button type="button"
            class="v-btn v-btn--icon v-btn--small theme--dark v-carousel__controls__item"
    >

          stop

    </button>
    <button type="button"
            class="v-btn v-btn--icon v-btn--small theme--dark v-carousel__controls__item"
    >

          stop

    </button>

`;

exports[`VCarousel.js should render component with custom next icon and match snapshot 1`] = `

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

          chevron_left

    </button>

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

          stop

    </button>

`;

exports[`VCarousel.js should render component with custom prev icon and match snapshot 1`] = `

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

          stop

    </button>

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

          chevron_right

    </button>

`;

exports[`VCarousel.js should render component with image cycling off and match snapshot 1`] = `

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

          chevron_left

    </button>

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

          chevron_right

    </button>

`;

exports[`VCarousel.js should render component with selected active item 1`] = `

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

          chevron_left

    </button>

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

          chevron_right

    </button>

    <button type="button"
            class="v-btn v-btn--icon v-btn--small theme--dark v-carousel__controls__item"
    >

          fiber_manual_record

    </button>
    <button type="button"
            class="v-btn v-btn--icon v-btn--small theme--dark v-carousel__controls__item v-carousel__controls__item--active"
    >

          fiber_manual_record

    </button>
    <button type="button"
            class="v-btn v-btn--icon v-btn--small theme--dark v-carousel__controls__item"
    >

          fiber_manual_record

    </button>

`;

exports[`VCarousel.js should render component without delimiters 1`] = `

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

          chevron_left

    </button>

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

          chevron_right

    </button>

`;

exports[`VCarousel.js should render component without next icon and match snapshot 1`] = `

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

          chevron_left

    </button>

`;

exports[`VCarousel.js should render component without prev icon and match snapshot 1`] = `

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

          chevron_right

    </button>

`;


}, [
this.$createElement(
VIcon,
data,
this[`${type}Icon`]
)
])
},
genInputSlot () {

keep keep keep keep replace keep keep keep keep


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

test('VDatePicker/util/pad.js', ({ mount }) => {
  it('should pad 1-digit numbers', () => {
    expect(pad(0)).toBe('00')
    expect(pad('3', 3)).toBe('003')
  })

  it('should pad 2-digit numbers', () => {
    expect(pad(40)).toBe('40')
    expect(pad('98')).toBe('98')
  })

  it('should not pad 3-digit numbers', () => {
    expect(pad(400)).toBe('400')
    expect(pad('998')).toBe('998')
  })
})


import { test } from '@/test'
import VTextarea from '@/components/VTextarea'
import Vue from 'vue'

const tabClick = 'Injection "tabClick" not found'
const tabsWarning = '[Vuetify] The v-tab component must be used inside a v-tabs'
const stub = {
  name: 'router-link',

  props: {
    to: [String, Object]
  },

  render (h) {
    return h('a', {
      domProps: { href: this.to }
    })
  }
}

test('VTextarea.vue', ({ mount }) => {
  it('should have no resize handle', async () => {
    const wrapper = mount(VTextarea)

    expect(wrapper.vm.noResizeHandle).toBe(false)

    wrapper.setProps({ noResize: true })

    expect(wrapper.vm.noResizeHandle).toBe(true)

    wrapper.setProps({ noResize: false, autoGrow: true })

    expect(wrapper.vm.noResizeHandle).toBe(true)

    wrapper.setProps({ autoGrow: false })

    expect(wrapper.vm.noResizeHandle).toBe(false)
  })

  it('should watch lazy value', async () => {
    const wrapper = mount(VTextarea)

    const calculateInputHeight = jest.fn()
    wrapper.setMethods({ calculateInputHeight })

    wrapper.vm.lazyValue = 'foo'

    expect(calculateInputHeight).not.toBeCalled()

    wrapper.setProps({ autoGrow: true })

    wrapper.vm.lazyValue = 'bar'

    // wait for watcher
    await wrapper.vm.$nextTick()

    expect(calculateInputHeight).toBeCalled()
  })

  it('should calculate height on mounted', async () => {
    const calculateInputHeight = jest.fn()

    const wrapper = mount(VTextarea, {
      attachToDocument: true,
      propsData: {
        autoGrow: true
      },
      methods: { calculateInputHeight }
    })

    expect(calculateInputHeight).toBeCalled()
  })

  it('should calculate input height', async () => {
    const wrapper = mount(VTextarea, {
      propsData: {
        autoGrow: true
      }
    })

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.inputHeight).toBe(120)

    wrapper.setData({ inputHeight: 200 })

    expect(wrapper.vm.inputHeight).toBe(200)

    wrapper.vm.calculateInputHeight()

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.inputHeight).toBe(120)

    wrapper.vm.calculateInputHeight()

    await wrapper.vm.$nextTick()

    delete wrapper.vm.$refs.input
    wrapper.vm.calculateInputHeight()

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.inputHeight).toBe(120)
  })

  it('should stop propagation', async () => {
    const wrapper = mount(VTextarea)

    const stopPropagation = jest.fn()
    const onKeyDown = {
      keyCode: 13,
      stopPropagation
   }
    wrapper.vm.onKeyDown(onKeyDown)

    expect(stopPropagation).not.toBeCalled()

    wrapper.setData({ isFocused: true })

    wrapper.vm.onKeyDown(onKeyDown)

    expect(stopPropagation).toBeCalled()
  })

  it.skip('should render no-resize the same if already auto-grow', () => {
    const wrappers = [
      { autoGrow:true, multiLine: true },
      { autoGrow:true, textarea: true }
    ].map(propsData => mount(VTextField,{propsData}))

    wrappers.forEach(async wrapper => {
      await wrapper.vm.$nextTick()
      const html1 = wrapper.html()

      wrapper.setProps({ noResize: true })
      // will still pass without this, do not remove
      await wrapper.vm.$nextTick()
      const html2 = wrapper.html()

      expect(html2).toBe(html1)
    })
  })
})


@import '../bootstrap'

.v-alert
  border-radius: $alert-border-radius
  border-width: $alert-border-width
  border-style: solid
  color: #fff
  display: flex
  font-size: $alert-font-size
  margin: $alert-margin
  padding: $alert-padding
  position: relative
  transition: $primary-transition

  .v-alert__icon.v-icon,
  &__dismissible .v-icon
    align-self: center
    color: $alert-icon-color
    font-size: $alert-icon-font-size
  &--outline .v-icon
    color: inherit !important

  &__icon
    margin-right: $alert-padding

  &__dismissible
    align-self: flex-start
    color: inherit
    margin-left: $alert-padding
    margin-right: 0
    text-decoration: none
    transition: $primary-transition
    user-select: none

    &:hover
      opacity: .8

  &--no-icon
    .v-alert__icon
      display: none

  > div
    align-self: center
    flex: 1 1

  @media screen and (max-width: $grid-breakpoints.sm)
    &__icon
      display: none

// Double .v-alert is intended - it increases css specificity
// to properly set the border color where alert has set color
// with modifier (for example "red lighten-2")
.v-alert.v-alert
  border-color: $material-light.dividers !important
  &--outline
    border: $alert-outline-border-width $alert-outline-border-style currentColor !important


keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep

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

// Components
import VIcon from '../VIcon'
import VMessages from '../VMessages'

// Mixins
import Loadable from '../../mixins/loadable'
import Themeable from '../../mixins/themeable'
import Validatable from '../../mixins/validatable'

// Utilities
import {
  convertToUnit,
  kebabCase
} from '../../util/helpers'

export default {
  name: 'v-input',

  mixins: [
    Loadable,
    Themeable,
    Validatable
  ],

  data: vm => ({
    lazyValue: vm.value,
    isFocused: false
  }),

  props: {
    appendIcon: String,
    appendIconCb: Function,
    disabled: Boolean,
    height: [Number, String],
    hideDetails: Boolean,
    hint: String,
    persistentHint: Boolean,
    prependIcon: String,
    prependIconCb: Function,
    readonly: Boolean,
    tabindex: { default: 0 },
    value: { required: false }
  },

  computed: {
    classesInput () {
      return {
        ...this.classes,
        'v-input--has-state': this.hasState,
        'v-input--hide-details': this.hideDetails,
        'v-input--is-label-active': this.isLabelActive,
        'v-input--is-dirty': this.isDirty,
        'v-input--is-disabled': this.disabled,
        'v-input--is-focused': this.isFocused,
        'v-input--is-loading': this.loading !== false,
        ...this.addTextColorClassChecks({}, this.validationState),
        ...this.themeClasses
      }
    },
    directivesInput () {
      return []
    },
    hasHint () {
      return !this.hasMessages &&
        this.hint &&
        (this.persistentHint || this.isFocused)
    },
    // Proxy for `lazyValue`
    // This allows an input
    // to function without
    // a provided model
    internalValue: {
      get () {
        return this.lazyValue
      },
      set (val) {
        this.lazyValue = val
        this.$emit('input', val)
      }
    },
    isDirty () {
      return !!this.lazyValue
    },
    isLabelActive () {
      return this.isDirty
    }
  },

  watch: {
    value (val) {
      this.lazyValue = val
    }
  },

  methods: {
    genContent () {
      return this.$createElement('div', {
        staticClass: 'v-input__control'
      }, [
        this.genInputSlot(),
        this.genMessages()
      ])
    },
    genDefaultSlot () {
      return this.$slots.default
    },
    genIcon (type, cb) {
      cb = cb || this[`${type}IconCb`]

      const data = {
        props: {
          color: this.validationState,
          disabled: this.disabled
        },
        on: !cb
          ? null
          : {
            click: e => {
              e.preventDefault()
              e.stopPropagation()

              cb(e)
            }
          }
      }

      return this.$createElement('div', {
        staticClass: `v-input__icon v-input__icon--${kebabCase(type)}`
      }, [
        this.$createElement(
          VIcon,
          data,
          this[`${type}Icon`]
        )
      ])
    },
    genInputSlot () {
      return this.$createElement('div', {
        staticClass: 'v-input__slot',
        'class': this.addTextColorClassChecks(
          {},
          this.hasState ? this.validationState : this.color
        ),
        style: { height: convertToUnit(this.height) },
        directives: this.directivesInput,
        on: { click: this.onClick },
        ref: 'input-slot'
      }, this.genDefaultSlot())
    },
    genMessages () {
      if (this.hideDetails) return null

      const messages = this.hasHint
        ? [this.hint]
        : this.validations

      return this.$createElement(VMessages, {
        props: {
          color: this.hasHint ? '' : this.validationState,
          value: (this.hasMessages || this.hasHint) ? messages : []
        }
      })
    },
    genSlot (ref, location, slot) {
      if (!slot.length) return null

      return this.$createElement('div', {
        staticClass: `v-input__${ref}-${location}`
      }, slot)
    },
    genPrependSlot () {
      const slot = []

      // Backwards compat
      // TODO: Deprecate prepend-icon slot 2.0
      if (this.$slots['prepend-icon']) {
        slot.push(this.$slots['prepend-icon'])
      } else if (this.$slots['prepend']) {
        slot.push(this.$slots['prepend'])
      } else if (this.prependIcon) {
        slot.push(this.genIcon('prepend'))
      }

      return this.genSlot('prepend', 'outer', slot)
    },
    genAppendSlot () {
      const slot = []

      // Append icon for text field was really
      // an appended inner icon, v-text-field
      // will overwrite this method in order to obtain
      // backwards compat
      if (this.$slots['append']) {
        slot.push(this.$slots['append'])
      } else if (this.$slots['append-icon']) {
        slot.push(this.$slots['append-icon'])
      } else if (this.appendIcon) {
        slot.push(this.genIcon('append'))
      }

      return this.genSlot('append', 'outer', slot)
    },
    onClick (e) {
      this.$emit('click', e)
    },
    onMouseDown (e) {
      this.$emit('mousedown', e)
    },
    onMouseUp (e) {
      this.$emit('mouseup', e)
    }
  },

  render (h) {
    return h('div', {
      staticClass: 'v-input',
      attrs: this.attrsInput,
      'class': this.classesInput,
      on: {
        mousedown: this.onMouseDown,
        mouseup: this.onMouseUp
      }
    }, [
      this.genPrependSlot(),
      this.genContent(),
      this.genAppendSlot()
    ])
  }
}


/**
 * Tabs props
 *
 * @mixin
 */
export default {
  props: {
    alignWithTitle: Boolean,
    centered: Boolean,
    fixedTabs: Boolean,
    grow: Boolean,
    height: {
      type: [Number, String],
      default: undefined,
      validator: v => !isNaN(parseInt(v))
    },
    hideSlider: Boolean,
    iconsAndText: Boolean,
    mobileBreakPoint: {
      type: [Number, String],
      default: 1264,
      validator: v => !isNaN(parseInt(v))
    },
    nextIcon: {
      type: String,
      default: '$vuetify.icons.next'
    },
    prevIcon: {
      type: String,
      default: '$vuetify.icons.prev'
    },
    right: Boolean,
    showArrows: Boolean,
    sliderColor: {
      type: String,
      default: 'accent'
    },
    value: [Number, String]
  }
}


@require './_theme'

// ============================================================
// Vuetify variables
// ============================================================

$color-pack := true

// Grid
// ============================================================
$grid-breakpoints := {
  xs: 0
  sm: 600px
  md: 960px
  lg: (1280px - 16px) // Desktop gets a 16dp reduction
  xl: (1920px - 16px) // https://material.io/guidelines/layout/responsive-ui.html#responsive-ui-breakpoints
}

$grid-gutter = 8px
$grid-columns := 12
$grid-gutters := {
  xs: ($grid-gutter / 4)
  sm: ($grid-gutter / 2)
  md: $grid-gutter
  lg: ($grid-gutter * 2)
  xl: ($grid-gutter * 3)
}

$container-max-widths := {
  md: $grid-breakpoints.md
  lg: $grid-breakpoints.lg
  xl: $grid-breakpoints.xl
}

// Display
// ============================================================
$display-breakpoints := {
  xs-only: "only screen and (max-width: %s)" % ($grid-breakpoints.sm - 1)
  sm-only: "only screen and (min-width: %s) and (max-width: %s)" % ($grid-breakpoints.sm ($grid-breakpoints.md  - 1))
  sm-and-down: "only screen and (max-width: %s)" % ($grid-breakpoints.md - 1)
  sm-and-up: "only screen and (min-width: %s)" % $grid-breakpoints.sm
  md-only: "only screen and (min-width: %s) and (max-width: %s)" % ($grid-breakpoints.md ($grid-breakpoints.lg  - 1))
  md-and-down: "only screen and (max-width: %s )" % ($grid-breakpoints.lg - 1)
  md-and-up: "only screen and (min-width: %s)" % $grid-breakpoints.md
  lg-only: "only screen and (min-width: %s) and (max-width: %s)" % ($grid-breakpoints.lg ($grid-breakpoints.xl - 1))
  lg-and-down: "only screen and (max-width: (%s - 1))" % $grid-breakpoints.xl
  lg-and-up: "only screen and (min-width: %s)" % $grid-breakpoints.lg
  xl-only: "only screen and (min-width: %s)" % $grid-breakpoints.xl
}

// Spacing
// ============================================================
$spacer := 16px
$spacer-x := $spacer
$spacer-y := $spacer
$spacers := {
  zero: {
    x: 0,
    y: 0
  },
  one: {
    x: ($spacer-x * .25),
    y: ($spacer-y * .25)
  },
  two: {
    x: ($spacer-x * .5),
    y: ($spacer-y * .5)
  },
  three: {
    x: $spacer-x,
    y: $spacer-y
  },
  four: {
    x: ($spacer-x * 1.5),
    y: ($spacer-y * 1.5)
  },
  five: {
    x: ($spacer-x * 3),
    y: ($spacer-y * 3)
  }
}

$font-weights := {
  thin: 100,
  light: 300,
  regular: 400,
  medium: 500,
  bold: 700,
  black: 900
}

// Headings
// ============================================================
$heading-font-family := $body-font-family
$headings := {
  h1: { size: 112px, weight: 300, line-height: 1, letter-spacing: -.04em, font-family: $heading-font-family },
  h2: { size: 56px, weight: 400, line-height: 1.35, letter-spacing: -.02em, font-family: $heading-font-family },
  h3: { size: 45px, weight: 400, line-height: 48px, letter-spacing: normal, font-family: $heading-font-family },
  h4: { size: 34px, weight: 400, line-height: 40px, letter-spacing: normal, font-family: $heading-font-family },
  h5: { size: 24px, weight: 400, line-height: 32px, letter-spacing: normal, font-family: $heading-font-family },
  h6: { size: 20px, weight: 500, line-height: 1, letter-spacing: .02em, font-family: $heading-font-family },
  subheading: { size: 16px, weight: 400 },
  body-2: { size: 14px, weight: 500 },
  body-1: { size: 14px, weight: 400 },
  caption: { size: 12px, weight: 400 },
  button: { size: 14px, weight: 500 }
}

// Transitions
$transition := {
  fast-out-slow-in: cubic-bezier(0.4, 0.0, 0.2, 1),
  linear-out-slow-in: cubic-bezier(0.0, 0.0, 0.2, 1),
  fast-out-linear-in: cubic-bezier(0.4, 0.0, 1, 1),
  ease-in-out: cubic-bezier(0.4, 0.0, 0.6, 1),
  fast-in-fast-out: cubic-bezier(.25,.8,.25,1),
  swing: cubic-bezier(.25,.8,.50,1)
}

$primary-transition := 0.3s $transition.swing
$secondary-transition := 0.2s $transition.ease-in-out

// Components
// ============================================================

// Alerts
$alert-color := inherit
$alert-border-radius := 0
$alert-border-width := 4px 0 0 0
$alert-font-size := $font-size-root
$alert-icon-color := rgba($material-light.fg-color, .3)
$alert-icon-font-size := 24px
$alert-padding := 16px
$alert-margin := $spacers.one.y auto
$alert-outline-border-width := 1px
$alert-outline-border-style := solid

// Badges
$badge-border-radius := 50%
$badge-color := $material-dark.fg-color
$badge-font-family := $body-font-family
$badge-font-size := 14px
$badge-height := 22px
$badge-top := 0
$badge-right := 0
$badge-width := 22px

// Breadcrumbs
$breadcrumbs-flex := 0 1 auto
$breadcrumbs-padding := 18px 12px
$breadcrumbs-even-child-padding := 0 12px
$breadcrumbs-item-font-size := 14px
$breadcrumbs-item-large-font-size := 16px
$breadcrumbs-margin := 0
$breadcrumbs-padding := 0 14px

/** Buttons */

// Base
$button-border-radius := 2px
$button-color := $material-light.fg-color
$button-background-color := #999999
$button-height := 36px
$button-font-size := 14px
$button-font-weight := 500
$button-margin-y := 6px
$button-margin-x := 8px
$button-margin := $button-margin-y $button-margin-x
$button-min-width := 88px
$button-small-padding := 0 8px
$button-padding := 0 16px
$button-large-padding := 0 32px
$button-text-transform := uppercase

$button-small-height := 28px
$button-small-font-size := 13px

$button-large-height := 44px
$button-large-font-size := 15px

$button-floating-width := 56px
$button-floating-icon-height := 24px
$button-floating-icon-width := 24px
$button-floating-small-width := 40px
$button-floating-large-width := 72px
$button-floating-small-icon-width := 18px
$button-floating-large-icon-width := 30px

// Card
$card-border-radius := 2px

// Chip
$chip-border-radius := 28px
$chip-close-margin := 0 2px 0 8px
$chip-font-size := 13px
$chip-label-border-radius := $card-border-radius
$chip-icon-font-size := 20px
$chip-padding := 0 12px
$chip-removeable-padding := 0 4px 0 12px
$chip-outline-background := transparent !important
$chip-outline-color := $grey.base
$chip-height := 32px
$chip-margin := 4px
$chip-small-height := 26px
$chip-small-font-size := 20px
$chip-icon-offset := 12px
$chip-icon-negative-offset := -8px

// Collapsible
$expansion-panel-collapse-height := 48px
$collapsible-transition-height := 0.23s

// Footer
$footer-height := 36px

/** Lists */
//  list fonts and weights */
$list-tile-font-size := $headings.subheading.size // 16px - the mdc scss uses subheading to configure like this
$list-tile-font-weight := $headings.subheading.weight // 400

$list-action-text-font-size := 12px // this is for the stacked actions
$list-action-text-font-color := $grey.base

$list-sub-title-font-size := ($list-tile-font-size - 2px) // 14px

$subheader-height-font-size := ($list-tile-font-size - 2px) // 14px
$subheader-font-weight := $font-weights.medium // 500

//   list spacing*/
$list-left-padding := 16px
$list-right-padding := 16px
$list-top-padding := 8px
$list-bottom-padding := 8px

$list-item-right-margin := 56px
$list-item-left-padding := 72px
$list-item-avatar-triple-margin-top := -18px
$list-item-single-height := 48px
$list-item-double-height := 72px
$list-item-triple-height := 88px
$list-item-avatar-single-height := 56px

$subheader-inset-margin := $list-item-right-margin

//   list dense overrides */
$list-item-dense-font-size := ($list-tile-font-size - 3px) //13px
$subheader-dense-font-size := $list-item-dense-font-size
$list-item-dense-icon-font-size := 22px
$list-item-dense-avatar-triple-margin-top := -14px
$list-item-dense-top-padding := $list-top-padding / 2
$list-item-dense-single-height := $list-item-single-height - 8px //40px
$list-item-dense-double-height := $list-item-double-height - 12px //60px
$list-item-dense-triple-height := $list-item-triple-height - 12px //76px

$list-item-dense-avatar-single-height := $list-item-single-height //48px the dense concept was to take avatars to a normal single item height
$list-item-dense-avatar-height := 38px

$list-dense-subheader-height := $list-item-dense-single-height
$list-dense-subheader-group-height := $list-dense-subheader-height //the subheader under a group menu

/** Pickers */
$time-picker-number-font-size := 16px
$time-picker-indicator-size := 40px

// Toolbar
$toolbar-height := 56px
$toolbar-item-padding := 0 16px
$toolbar-padding-y := 0
$toolbar-padding-x := 16px

// Progress Circular
$progress-circular-rotate-animation := progress-circular-rotate 1.4s linear infinite
$progress-circular-rotate-dash := progress-circular-dash 1.4s ease-in-out infinite
$process-circular-intermediate-svg-transition := all .2s ease-in-out
$progress-circular-underlay-stroke := rgba($material-light.fg-color, 0.1)
$progress-circular-overlay-transition := all .6s ease-in-out

// Navigation drawer
$navigation-drawer-item-font-size := 14px
$navigation-drawer-item-font-weight := $font-weights.medium
$navigation-drawer-group-item-font-weight := $font-weights.regular

/** Snackbar */
$snackbar-color := #fff
$snackbar-background-color := #323232
$snackbar-corner-offset := 24px

// Tab
$tab-text-transform := uppercase

/* Text Input */
$input-group-padding := 18px 0 0
$input-font-size := 16px
$input-height := 30px
$input-group-text-field-label-top := 18px

// Directives
// ============================================================

// Ripple animation
$ripple-animation-transition := .4s $transition.linear-out-slow-in
$ripple-animation-visible-opacity := .15


module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint',
    ecmaVersion: 2017,
    sourceType: 'module'
  },
  extends: [
    'standard'
  ],
  env: {
    browser: true
  },
  globals: {
    'expect': true,
    'describe': true,
    'it': true,
    'jest': true,
    'process': true
  },
  plugins: [
    'eslint-plugin-local-rules'
  ],
  rules: {
    // allow paren-less arrow functions
    'arrow-parens': [2, 'as-needed'],
    'local-rules/no-render-string-reference': 2,
    // set maximum line characters
    'max-len': [2, 140, 4, {
      'ignoreUrls': true,
      'ignoreTemplateLiterals': true,
      'ignoreStrings': true
    }],
    'max-statements': [2, 24],
    'no-console': 'off',
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
    'no-return-assign': 0,
    'prefer-promise-reject-errors': 0,
    'no-unused-vars': ['error', {
      vars: 'all',
      args: 'after-used',
      ignoreRestSiblings: false
    }],
    'no-empty': 'error',
    'object-curly-spacing': ['error', 'always'],
    'space-before-function-paren': [
      'error',
      {
        anonymous: 'always',
        named: 'always',
        asyncArrow: 'always'
      }
    ]
  }
}


},
onBlur (e) {
this.$emit('blur', e)
},
onClick () {
if (this.isDisabled) return
this.onFocus()


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

exports[`VDatePicker.js should match snapshot with allowed dates as array 1`] = `

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

          Jan

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Feb

      </button>

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

          Mar

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Apr

      </button>

      <button type="button"
              class="v-btn v-btn--active v-btn--depressed accent"
      >

          May

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Jun

      </button>

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

          Jul

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Aug

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Sep

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Oct

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Nov

      </button>

      <button type="button"
              class="v-btn v-btn--flat v-btn--disabled"
              disabled
      >

          Dec

      </button>

`;

exports[`VDatePicker.js should match snapshot with colored picker 1`] = `

        2005

          November

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

              chevron_left

        </button>

            2005

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

              chevron_right

        </button>

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

                    Jan

                </button>

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

                    Feb

                </button>

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

                    Mar

                </button>

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

                    Apr

                </button>

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

                    May

                </button>

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

                    Jun

                </button>

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

                    Jul

                </button>

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

                    Aug

                </button>

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

                    Sep

                </button>

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

                    Oct

                </button>

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

                    Nov

                </button>

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

                    Dec

                </button>

`;

exports[`VDatePicker.js should match snapshot with colored picker 2`] = `

        2005

          November

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

              chevron_left

        </button>

            2005

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

              chevron_right

        </button>

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

                    Jan

                </button>

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

                    Feb

                </button>

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

                    Mar

                </button>

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

                    Apr

                </button>

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

                    May

                </button>

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

                    Jun

                </button>

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

                    Jul

                </button>

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

                    Aug

                </button>

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

                    Sep

                </button>

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

                    Oct

                </button>

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

                    Nov

                </button>

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

                    Dec

                </button>

`;

exports[`VDatePicker.js should match snapshot with month formatting functions 1`] = `

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

          (01)

      </button>

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

          (02)

      </button>

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

          (03)

      </button>

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

          (04)

      </button>

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

          (05)

      </button>

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

          (06)

      </button>

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

          (07)

      </button>

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

          (08)

      </button>

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

          (09)

      </button>

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

          (10)

      </button>

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

          (11)

      </button>

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

          (12)

      </button>

`;

exports[`VDatePicker.js should match snapshot with pick-month prop 1`] = `

        2013

          May

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

              chevron_left

        </button>

            2013

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

              chevron_right

        </button>

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

                    Jan

                </button>

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

                    Feb

                </button>

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

                    Mar

                </button>

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

                    Apr

                </button>

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

                    May

                </button>

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

                    Jun

                </button>

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

                    Jul

                </button>

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

                    Aug

                </button>

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

                    Sep

                </button>

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

                    Oct

                </button>

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

                    Nov

                </button>

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

                    Dec

                </button>

`;


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

/* Theme */
v-slider($material)
  .v-slider__track,
  .v-slider__track-fill
    background: $material.slider.inactive

  .v-slider__track__container
    &:after
      border: 1px solid $material.text.primary

  .v-slider__ticks
    border: 1px solid $material.text.primary
    color: $material.text.secondary

  &:not(.v-input--is-dirty)
    .v-slider__thumb-label
      background: $material.slider.inactive

    .v-slider__thumb
      border: 3px solid $material.slider.inactive

    &.v-input--slider--is-active
      .v-slider__thumb
        border: 3px solid $material.slider.active

    .v-slider__ticks:first-child
      border-color: transparent

  &.v-input--is-disabled
    .v-slider__thumb
      border: 3px solid $material.slider.disabled

  &.v-input--is-disabled.v-input--is-dirty
    .v-slider__thumb
      background: $material.slider.disabled
      border: 0px solid transparent

  &.v-input--slider--is-active
    .v-slider__track
      background: $material.slider.active

v-slider-rtl()
  .v-label
    margin-left: 16px
    margin-right: 0

theme(v-slider, "v-input--slider")
rtl(v-slider-rtl, "v-input--slider")

/** Input Group */
.v-input--slider
  &:not(.v-input--slider--thumb-label)
    margin-top: 0

  &.v-input--is-focused
    .v-slider__thumb-container--is-active:not(.v-slider__thumb-container--show-label)
      &:before
        opacity: .2
        transform: scale(1)

    .v-slider__track
      transition: none

    &.v-input--slider--ticks
      .v-slider
        &__track__container:after,
        .v-slider__tick
          opacity: 1

  &.v-input--slider--ticks
    .v-slider__ticks.v-slider__ticks--always-show
      opacity: 1

    &-labels
      .v-input__slot
        margin-bottom: 16px

  &.v-input--is-disabled
    .v-slider__thumb
      transform: translateY(-50%) scale(.45)

  .v-input__slot > *:first-child:not(:only-child)
    margin-right: 16px

  // to line up control with icons
  .v-input__control
    padding-top: 2px

/** Slider */
.v-slider
  cursor: default
  display: flex
  align-items: center
  position: relative
  height: 32px
  flex: 1
  outline: none
  user-select: none

  input
    cursor: default
    opacity: 0
    padding: 0
    width: 100%

/** Thumb/Track/Ticks */
.v-slider
  &__track__container
    height: 2px
    left: 0
    overflow: hidden
    pointer-events: none
    position: absolute
    top: 50%
    transform: translateY(-50%)
    width: 100%

    &:after
      content: ''
      position: absolute
      right: 0
      top: 0
      height: 2px
      transition: .3s $transition.swing
      width: 2px
      opacity: 0

  &__track,
  &__thumb,
  &__ticks
    position: absolute
    top: 0

  &__track
    height: 2px
    left: 0
    transition: .3s $transition.swing
    transform-origin: right
    overflow: hidden
    width: 100%

    &-fill
      position: absolute
      left: 0
      height: 2px
      transform-origin: left
      width: 100%
      transition: .3s $transition.swing

  &__ticks-container
    position: absolute
    left: 0
    height: 2px
    width: 100%
    top: 50%
    transform: translate(0, -50%)

  &__ticks
    opacity: 0
    transition: .3s $transition.swing

    > span
      position: absolute
      top: 8px
      transform: translateX(-50%)
      white-space: nowrap
      user-select: none

    &:first-child > span
      transform: translateX(0)

    &:last-child > span
      transform: translateX(-100%)

  &__thumb-container
    position: absolute
    top: 50%
    transition: .3s $transition.swing

    &:before
      content: ''
      color: inherit
      border-radius: 50%
      background: currentColor
      height: 32px
      left: -16px
      opacity: 0
      overflow: hidden
      pointer-events: none
      position: absolute
      top: -16px
      transform: scale(0.2)
      transition: $ripple-animation-transition
      width: 32px
      will-change: transform, opacity

  &__thumb
    width: 24px
    height: 24px
    left: -12px
    top: 50%
    border-radius: 50%
    background: transparent
    transition: .3s $transition.swing
    transform: translateY(-50%) scale(.6)
    user-select: none

/** Thumb Label */
.v-slider
  &--is-active
    .v-slider__thumb-container--is-active
      .v-slider__thumb
        transform: translateY(-50%) scale(1)

      &.v-slider__thumb-container--show-label
        .v-slider__thumb
          transform: translateY(-50%) scale(0)

  &__thumb-label__container
    position: absolute
    left: 0
    top: 0
    transition: .3s $transition.fast-in-fast-out

  &__thumb-label
    display: flex
    align-items: center
    justify-content: center
    font-size: 12px
    color: #fff
    width: 32px
    height: 32px
    border-radius: 50% 50% 0
    position: absolute
    left: 0
    bottom: 100%
    // Needed for IE11 which does not
    // process translateY(calc(-20% - 12px))
    // or translate(-50%, calc(-20% - 12px))
    transform: translateY(-20%) translateY(-12px) translateX(-50%) rotate(45deg)
    user-select: none
    transition: .3s $transition.fast-in-fast-out

    > *
      transform: rotate(-45deg)

  &__track,
  &__track-fill
    position: absolute


margin-left: -4px // to line up the chips

keep keep keep replace replace keep keep keep keep keep

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

test('VAutocomplete - tags', ({ mount, compileToFunctions }) => {
  const app = document.createElement('div')
  app.setAttribute('data-app', true)
  document.body.appendChild(app)
  const backspace = new Event('keydown')
  backspace.keyCode = 8

  function createTagsAutocomplete (propsData) {
    const change = jest.fn()
    const wrapper = mount(VAutocomplete, {
      attachToDocument: true,
      propsData: Object.assign({
        tags: true,
        value: []
      }, propsData)
    })

    wrapper.vm.$on('input', change)
    return { wrapper, change }
  }

  it('should create new values when tagging', async () => {
    const { wrapper, change } = createTagsAutocomplete()

    const input = wrapper.first('input')

    input.trigger('focus')
    input.element.value = 'foo'
    input.trigger('input')
    input.trigger('keydown.enter')

    expect(change).toHaveBeenCalledWith(['foo'])
  })

  it('should change selectedIndex with keyboard', async () => {
    const { wrapper } = createTagsAutocomplete({
      value: ['foo', 'bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')
    await wrapper.vm.$nextTick()

    for (const index of [1, 0, -1]) {
      input.trigger('keydown.left')
      await wrapper.vm.$nextTick()
      expect(wrapper.vm.selectedIndex).toBe(index)
    }

  })

  it('should delete a tagged item when selected and backspace/delete is pressed', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      value: ['foo', 'bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')
    input.trigger('keydown.left')
    expect(wrapper.vm.selectedIndex).toBe(1)

    input.trigger('keydown.delete')
    await wrapper.vm.$nextTick()
    expect(change).toHaveBeenCalledWith(['foo'])
    expect(wrapper.vm.selectedIndex).toBe(0)

    input.element.dispatchEvent(backspace) // Avoriaz doesn't wrap keydown.backspace
    await wrapper.vm.$nextTick()
    expect(change).toHaveBeenCalledWith([])
    expect(wrapper.vm.selectedIndex).toBe(-1)

  })

  it('should add a tag on tab using the first suggestion', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      items: ['bar']
    })

    const input = wrapper.first('input')
    const menu = wrapper.first('.v-menu')

    input.trigger('focus')
    await wrapper.vm.$nextTick()

    input.element.value = 'b'
    input.trigger('input')
    menu.trigger('keydown.down')
    input.trigger('keydown.tab')

    expect(change).toBeCalledWith(['bar'])
    expect(wrapper.vm.getMenuIndex()).toBe(0)
  })

  it('should add a tag on tab using the current searchValue', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      items: ['bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')

    wrapper.setProps({ searchInput: 'ba' })
    input.trigger('keydown.tab')
    await wrapper.vm.$nextTick()
    expect(change).toBeCalledWith(['ba'])

    wrapper.setProps({ searchInput: 'it' })
    input.trigger('keydown.tab')
    await wrapper.vm.$nextTick()
    expect(change).toBeCalledWith(['ba', 'it'])
  })

  it('should add a tag on enter using the current searchValue', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      items: ['bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')
    await wrapper.vm.$nextTick()

    input.element.value = 'ba'
    input.trigger('input')
    await wrapper.vm.$nextTick()
    input.trigger('keydown.enter')
    await wrapper.vm.$nextTick()

    expect(change).toBeCalledWith(['ba'])
  })

  it('should add a tag on left arrow and select the previous tag', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      value: ['foo'],
      items: ['foo', 'bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')
    input.element.value = 'b'
    input.trigger('input')
    input.trigger('keydown.left')

    expect(change).toBeCalledWith(['foo', 'b'])
    expect(wrapper.vm.selectedIndex).toBe(0)
  })

  it('should remove a duplicate tag and add it to the end', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      value: ['foo', 'bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')
    await wrapper.vm.$nextTick()

    input.element.value = 'foo'
    input.trigger('input')
    input.trigger('keydown.tab')
    await wrapper.vm.$nextTick()

    expect(change).toBeCalledWith(['bar', 'foo'])
  })

  it('should add tag with valid search value on blur', async () => {
    const { wrapper, change } = createTagsAutocomplete()

    const input = wrapper.first('input')

    input.trigger('focus')
    input.element.value = 'bar'
    input.trigger('input')
    input.trigger('keydown.tab')

    expect(change).toBeCalledWith(['bar'])
  })

  it('should be able to add a tag from user input after deleting a tag with delete', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      multiple: true,
      value: ['foo', 'bar']
    })

    let input = wrapper.first('input')

    input.trigger('focus')
    input.trigger('keydown.left')
    expect(wrapper.vm.selectedIndex).toBe(1)
    input.trigger('keydown.delete')
    expect(change).toHaveBeenCalledWith(['foo'])
    expect(wrapper.vm.selectedIndex).toBe(0)

    // Must be reset for input to update
    wrapper.vm.selectedIndex = -1
    await wrapper.vm.$nextTick()

    input.element.value = 'baz'
    input.trigger('input')
    input.trigger('keydown.enter')

    expect(change).toBeCalledWith(['foo', 'baz'])
    expect(wrapper.vm.selectedIndex).toBe(-1)

  })

  it('should be able to add a tag from user input after clicking a deletable chip', async () => {
    const { wrapper, change } = createTagsAutocomplete({
      chips: true,
      clearable: true,
      deletableChips: true,
      value: ['foo', 'bar']
    })

    const input = wrapper.first('input')
    const chip = wrapper.find('.v-chip')[1]
    const close = chip.first('.v-chip__close')

    input.trigger('focus')
    chip.trigger('click')
    close.trigger('click')
    expect(change).toHaveBeenCalledWith(['foo'])
    expect(wrapper.vm.selectedIndex).toBe(-1)

    input.element.value = 'baz'
    input.trigger('input')
    expect(wrapper.vm.internalSearch).toBe('baz')
    input.trigger('keydown.enter')

    expect(change).toBeCalledWith(['foo', 'baz'])
    expect(wrapper.vm.selectedIndex).toBe(-1)
  })

  it('should not change search when selecting an index', () => {
    const { wrapper } = createTagsAutocomplete({
      chips: true,
      multiple: true,
      value: ['foo', 'bar']
    })

    const input = wrapper.first('input')

    input.trigger('focus')
    expect(wrapper.vm.selectedIndex).toBe(-1)

    input.trigger('keydown.left')
    expect(wrapper.vm.selectedIndex).toBe(1)

    expect(wrapper.vm.internalSearch).toBe(null)
    input.element.value = 'fizz'
    input.trigger('input')

    input.trigger('keydown.right')
    expect(wrapper.vm.selectedIndex).toBe(-1)

    input.element.value = 'fizz'
    input.trigger('input')
    expect(wrapper.vm.internalSearch).toBe('fizz')
  })
})


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

exports[`VToolbar.vue should render an extended toolbar 1`] = `

`;

exports[`VToolbar.vue should render an extended toolbar with specific height 1`] = `

`;


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

// 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 || !this.falseValue) {
        return value
          ? this.valueComparator(value, input)
          : Boolean(input)
      }

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

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

  methods: {
    genLabel () {
      return this.$createElement(VLabel, {
        on: { click: this.onChange },
        attrs: {
          for: this.id
        },
        props: {
          color: 'error',
          focused: this.hasState
        }
      }, this.$slots.label || this.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.disabled) 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 || this.falseValue) {
        // If has a true or false value set
        input = this.valueComparator(this.trueValue, value) ? this.falseValue : this.trueValue
      } else if (value) {
        // If has a value set
        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()
      }
    }
  }
}


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

// Mixins
import Picker from '../../mixins/picker'

// Utils
import { pad, createNativeLocaleFormatter } from './util'
import isDateAllowed from './util/isDateAllowed'

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

  mixins: [Picker],

  data () {
    const now = new Date()
    return {
      activePicker: this.type.toUpperCase(),
      defaultColor: 'accent',
      inputDay: null,
      inputMonth: null,
      inputYear: null,
      isReversing: false,
      now,
      // tableDate is a string in 'YYYY' / 'YYYY-M' format (leading zero for month is not required)
      tableDate: (() => {
        if (this.pickerDate) {
          return this.pickerDate
        }

        const date = this.value || `${now.getFullYear()}-${now.getMonth() + 1}`
        const type = this.type === 'date' ? 'month' : 'year'
        return this.sanitizeDateString(date, type)
      })()
    }
  },

  props: {
    allowedDates: Function,
    // Function formatting the day in date picker table
    dayFormat: {
      type: Function,
      default: null
    },
    events: {
      type: [Array, Object, Function],
      default: () => null
    },
    eventColor: {
      type: [String, Function, Object],
      default: 'warning'
    },
    firstDayOfWeek: {
      type: [String, Number],
      default: 0
    },
    // Function formatting the tableDate in the day/month table header
    headerDateFormat: {
      type: Function,
      default: null
    },
    locale: {
      type: String,
      default: 'en-us'
    },
    max: String,
    min: String,
    // Function formatting month in the months table
    monthFormat: {
      type: Function,
      default: null
    },
    nextIcon: {
      type: String,
      default: '$vuetify.icons.next'
    },
    pickerDate: String,
    prevIcon: {
      type: String,
      default: '$vuetify.icons.prev'
    },
    reactive: Boolean,
    readonly: Boolean,
    scrollable: Boolean,
    showCurrent: {
      type: [Boolean, String],
      default: true
    },
    // Function formatting currently selected date in the picker title
    titleDateFormat: {
      type: Function,
      default: null
    },
    type: {
      type: String,
      default: 'date',
      validator: type => ['date', 'month'].includes(type) // TODO: year
    },
    value: String,
    // Function formatting the year in table header and pickup title
    yearFormat: {
      type: Function,
      default: null
    },
    yearIcon: String
  },

  computed: {
    current () {
      if (this.showCurrent === true) {
        return this.sanitizeDateString(`${this.now.getFullYear()}-${this.now.getMonth() + 1}-${this.now.getDate()}`, this.type)
      }

      return this.showCurrent || null
    },
    inputDate () {
      return this.type === 'date'
        ? `${this.inputYear}-${pad(this.inputMonth + 1)}-${pad(this.inputDay)}`
        : `${this.inputYear}-${pad(this.inputMonth + 1)}`
    },
    tableMonth () {
      return (this.pickerDate || this.tableDate).split('-')[1] - 1
    },
    tableYear () {
      return (this.pickerDate || this.tableDate).split('-')[0] * 1
    },
    minMonth () {
      return this.min ? this.sanitizeDateString(this.min, 'month') : null
    },
    maxMonth () {
      return this.max ? this.sanitizeDateString(this.max, 'month') : null
    },
    minYear () {
      return this.min ? this.sanitizeDateString(this.min, 'year') : null
    },
    maxYear () {
      return this.max ? this.sanitizeDateString(this.max, 'year') : null
    },
    formatters () {
      return {
        year: this.yearFormat || createNativeLocaleFormatter(this.locale, { year: 'numeric', timeZone: 'UTC' }, { length: 4 }),
        titleDate: this.titleDateFormat || this.defaultTitleDateFormatter
      }
    },
    defaultTitleDateFormatter () {
      const titleFormats = {
        year: { year: 'numeric', timeZone: 'UTC' },
        month: { month: 'long', timeZone: 'UTC' },
        date: { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC' }
      }

      const titleDateFormatter = createNativeLocaleFormatter(this.locale, titleFormats[this.type], {
        start: 0,
        length: { date: 10, month: 7, year: 4 }[this.type]
      })

      const landscapeFormatter = date => titleDateFormatter(date)
        .replace(/([^\d\s])([\d])/g, (match, nonDigit, digit) => `${nonDigit} ${digit}`)
        .replace(', ', ',<br>')

      return this.landscape ? landscapeFormatter : titleDateFormatter
    }
  },

  watch: {
    tableDate (val, prev) {
      // Make a ISO 8601 strings from val and prev for comparision, otherwise it will incorrectly
      // compare for example '2000-9' and '2000-10'
      const sanitizeType = this.type === 'month' ? 'year' : 'month'
      this.isReversing = this.sanitizeDateString(val, sanitizeType) < this.sanitizeDateString(prev, sanitizeType)
      this.$emit('update:pickerDate', val)
    },
    pickerDate (val) {
      if (val) {
        this.tableDate = val
      } else if (this.value && this.type === 'date') {
        this.tableDate = this.sanitizeDateString(this.value, 'month')
      } else if (this.value && this.type === 'month') {
        this.tableDate = this.sanitizeDateString(this.value, 'year')
      }
    },
    value () {
      this.setInputDate()
      if (this.value && !this.pickerDate) {
        this.tableDate = this.sanitizeDateString(this.inputDate, this.type === 'month' ? 'year' : 'month')
      }
    },
    type (type) {
      this.activePicker = type.toUpperCase()

      if (this.value) {
        const date = this.sanitizeDateString(this.value, type)
        this.$emit('input', this.isDateAllowed(date) ? date : null)
      }
    }
  },

  methods: {
    isDateAllowed (value) {
      return isDateAllowed(value, this.min, this.max, this.allowedDates)
    },
    yearClick (value) {
      this.inputYear = value
      if (this.type === 'month') {
        this.tableDate = `${value}`
      } else {
        this.tableDate = `${value}-${pad(this.tableMonth + 1)}`
      }
      this.activePicker = 'MONTH'
      this.reactive && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate)
    },
    monthClick (value) {
      this.inputYear = parseInt(value.split('-')[0], 10)
      this.inputMonth = parseInt(value.split('-')[1], 10) - 1
      if (this.type === 'date') {
        this.tableDate = value
        this.activePicker = 'DATE'
        this.reactive && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate)
      } else {
        this.$emit('input', this.inputDate)
        this.$emit('change', this.inputDate)
      }
    },
    dateClick (value) {
      this.inputYear = parseInt(value.split('-')[0], 10)
      this.inputMonth = parseInt(value.split('-')[1], 10) - 1
      this.inputDay = parseInt(value.split('-')[2], 10)
      this.$emit('input', this.inputDate)
      this.$emit('change', this.inputDate)
    },
    genPickerTitle () {
      return this.$createElement(VDatePickerTitle, {
        props: {
          date: this.value ? this.formatters.titleDate(this.value) : '',
          selectingYear: this.activePicker === 'YEAR',
          year: this.formatters.year(`${this.inputYear}`),
          yearIcon: this.yearIcon,
          value: this.value
        },
        slot: 'title',
        style: this.readonly ? {
          'pointer-events': 'none'
        } : undefined,
        on: {
          'update:selectingYear': value => this.activePicker = value ? 'YEAR' : this.type.toUpperCase()
        }
      })
    },
    genTableHeader () {
      return this.$createElement(VDatePickerHeader, {
        props: {
          nextIcon: this.nextIcon,
          color: this.color,
          disabled: this.readonly,
          format: this.headerDateFormat,
          locale: this.locale,
          min: this.activePicker === 'DATE' ? this.minMonth : this.minYear,
          max: this.activePicker === 'DATE' ? this.maxMonth : this.maxYear,
          prevIcon: this.prevIcon,
          value: this.activePicker === 'DATE' ? `${this.tableYear}-${pad(this.tableMonth + 1)}` : `${this.tableYear}`
        },
        on: {
          toggle: () => this.activePicker = (this.activePicker === 'DATE' ? 'MONTH' : 'YEAR'),
          input: value => this.tableDate = value
        }
      })
    },
    genDateTable () {
      return this.$createElement(VDatePickerDateTable, {
        props: {
          allowedDates: this.allowedDates,
          color: this.color,
          current: this.current,
          disabled: this.readonly,
          events: this.events,
          eventColor: this.eventColor,
          firstDayOfWeek: this.firstDayOfWeek,
          format: this.dayFormat,
          locale: this.locale,
          min: this.min,
          max: this.max,
          tableDate: `${this.tableYear}-${pad(this.tableMonth + 1)}`,
          scrollable: this.scrollable,
          value: this.value
        },
        ref: 'table',
        on: {
          input: this.dateClick,
          tableDate: value => this.tableDate = value
        }
      })
    },
    genMonthTable () {
      return this.$createElement(VDatePickerMonthTable, {
        props: {
          allowedDates: this.type === 'month' ? this.allowedDates : null,
          color: this.color,
          current: this.current ? this.sanitizeDateString(this.current, 'month') : null,
          disabled: this.readonly,
          format: this.monthFormat,
          locale: this.locale,
          min: this.minMonth,
          max: this.maxMonth,
          scrollable: this.scrollable,
          value: (!this.value || this.type === 'month') ? this.value : this.value.substr(0, 7),
          tableDate: `${this.tableYear}`
        },
        ref: 'table',
        on: {
          input: this.monthClick,
          tableDate: value => this.tableDate = value
        }
      })
    },
    genYears () {
      return this.$createElement(VDatePickerYears, {
        props: {
          color: this.color,
          format: this.yearFormat,
          locale: this.locale,
          min: this.minYear,
          max: this.maxYear,
          value: `${this.tableYear}`
        },
        on: {
          input: this.yearClick
        }
      })
    },
    genPickerBody () {
      const children = this.activePicker === 'YEAR' ? [
        this.genYears()
      ] : [
        this.genTableHeader(),
        this.activePicker === 'DATE' ? this.genDateTable() : this.genMonthTable()
      ]

      return this.$createElement('div', {
        key: this.activePicker,
        style: this.readonly ? {
          'pointer-events': 'none'
        } : undefined
      }, children)
    },
    // Adds leading zero to month/day if necessary, returns 'YYYY' if type = 'year',
    // 'YYYY-MM' if 'month' and 'YYYY-MM-DD' if 'date'
    sanitizeDateString (dateString, type) {
      const [year, month = 1, date = 1] = dateString.split('-')
      return `${year}-${pad(month)}-${pad(date)}`.substr(0, { date: 10, month: 7, year: 4 }[type])
    },
    setInputDate () {
      if (this.value) {
        const array = this.value.split('-')
        this.inputYear = parseInt(array[0], 10)
        this.inputMonth = parseInt(array[1], 10) - 1
        if (this.type === 'date') {
          this.inputDay = parseInt(array[2], 10)
        }
      } else {
        this.inputYear = this.inputYear || this.now.getFullYear()
        this.inputMonth = this.inputMonth == null ? this.inputMonth : this.now.getMonth()
        this.inputDay = this.inputDay || this.now.getDate()
      }
    }
  },

  created () {
    if (this.pickerDate !== this.tableDate) {
      this.$emit('update:pickerDate', this.tableDate)
    }
    this.setInputDate()
  },

  render () {
    return this.genPicker('v-picker--date')
  }
}


export default {
  name: 'transitionable',

  props: {
    mode: String,
    origin: String,
    transition: String
  }
}


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

test('VListTileAvatar.js', ({ mount, functionalContext }) => {
  it('should render component and match snapshot', () => {
    const wrapper = mount(VListTileAvatar, functionalContext())

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


<!--
MAKE SURE TO READ THE CONTRIBUTING GUIDE BEFORE CREATING A PR
https://github.com/vuetifyjs/vuetify/blob/master/.github/CONTRIBUTING.md
-->

<!--- Provide a general summary of your changes in the Title above -->

## Description
<!--- Describe your changes in detail -->

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->

## How Has This Been Tested?
<!--- Please describe how you tested your changes. -->
<!--- Have you created new tests or updated existing ones? -->
<!--- e.g. unit | visually | e2e | none -->

## Markup:
<!--- Paste markup that showcases your contribution --->
<!--- You can use ```vue to style the code -->

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Improvement/refactoring (non-breaking change that doesn't add any feature but make things better)

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] The PR title is no longer than 64 characters.
- [ ] The PR is submitted to the correct branch (`master` for bug fixes, `dev` for new features and breaking changes).
- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have created a PR in the [documentation](https://github.com/vuetifyjs/vuetifyjs.com) with the necessary changes.


constructor: ->
@model = Meteor.users
# FIND ONE
findOneById: (_id, options) ->
return @findOne _id, options

@tryEnsureIndex { 'roles': 1 }, { sparse: 1 }

# Deny Account.createUser in client and set Meteor.loginTokenExpires
accountsConfig = { forbidClientAccountCreation: true, loginExpirationInDays: RocketChat.settings.get 'Accounts_LoginExpiration' }
Accounts.config accountsConfig

RocketChat.settings.get 'Accounts_AllowedDomainsList', (_id, value) ->
	domainWhiteList = _.map value.split(','), (domain) -> domain.trim()
	restrictCreationByEmailDomain = if domainWhiteList.length == 1 then domainWhiteList[0] else (email) ->
		ret = false
		for domain in domainWhiteList
			if email.match('@' + RegExp.escape(domain) + '$')
				ret = true
				break;

		return ret
	delete Accounts._options['restrictCreationByEmailDomain']

	if not _.isEmpty value
		Accounts.config({ restrictCreationByEmailDomain: restrictCreationByEmailDomain });

Accounts.emailTemplates.siteName = RocketChat.settings.get 'Site_Name';
Accounts.emailTemplates.from = "#{RocketChat.settings.get 'Site_Name'} <#{RocketChat.settings.get 'From_Email'}>";

verifyEmailText = Accounts.emailTemplates.verifyEmail.text
Accounts.emailTemplates.verifyEmail.text = (user, url) ->
	url = url.replace Meteor.absoluteUrl(), Meteor.absoluteUrl() + 'login/'
	verifyEmailText user, url

resetPasswordText = Accounts.emailTemplates.resetPassword.text
Accounts.emailTemplates.resetPassword.text = (user, url) ->
	url = url.replace /\/#\//, '/'
	resetPasswordText user, url

if RocketChat.settings.get 'Accounts_Enrollment_Email'
	Accounts.emailTemplates.enrollAccount.text = (user, url) ->
		text = RocketChat.settings.get 'Accounts_Enrollment_Email'

		text = text.replace /\[name\]/g, user.name or ''
		text = text.replace /\[fname\]/g, _.strLeft(user.name, ' ') or  ''
		text = text.replace /\[lname\]/g, _.strRightBack(user.name, ' ') or  ''
		text = text.replace /\[email\]/g, user.emails?[0]?.address or ''

		return text

Accounts.onCreateUser (options, user) ->
	# console.log 'onCreateUser ->',JSON.stringify arguments, null, '  '
	# console.log 'options ->',JSON.stringify options, null, '  '
	# console.log 'user ->',JSON.stringify user, null, '  '

	RocketChat.callbacks.run 'beforeCreateUser', options, user

	user.status = 'offline'
	user.active = not RocketChat.settings.get 'Accounts_ManuallyApproveNewUsers'

	if not user?.name? or user.name is ''
		if options.profile?.name?
			user.name = options.profile?.name

	if user.services?
		for serviceName, service of user.services
			if not user?.name? or user.name is ''
				if service.name?
					user.name = service.name
				else if service.username?
					user.name = service.username

			if not user.emails? and service.email?
				user.emails = [
					address: service.email
					verified: true
				]

	return user

# Wrap insertUserDoc to allow executing code after Accounts.insertUserDoc is run
Accounts.insertUserDoc = _.wrap Accounts.insertUserDoc, (insertUserDoc, options, user) ->
	roles = []
	if Match.test(user.globalRoles, [String]) and user.globalRoles.length > 0
		roles = roles.concat user.globalRoles

	delete user.globalRoles

	_id = insertUserDoc.call(Accounts, options, user)

	if roles.length is 0
		# when inserting first user give them admin privileges otherwise make a regular user
		firstUser = RocketChat.models.Users.findOne({ _id: { $ne: 'rocket.cat' }}, { sort: { createdAt: 1 }})
		if firstUser?._id is _id
			roles.push 'admin'
		else
			roles.push 'user'

	RocketChat.authz.addUserRoles(_id, roles)

	RocketChat.callbacks.run 'afterCreateUser', options, user
	return _id

Accounts.validateLoginAttempt (login) ->
	login = RocketChat.callbacks.run 'beforeValidateLogin', login

	if login.allowed isnt true
		return login.allowed

	if !!login.user?.active isnt true
		throw new Meteor.Error 'inactive-user', TAPi18n.__ 'User_is_not_activated'
		return false

	# If user is admin, no need to check if e-mail is verified
	if 'admin' not in login.user?.roles and login.type is 'password' and RocketChat.settings.get('Accounts_EmailVerification') is true
		validEmail = login.user.emails.filter (email) ->
			return email.verified is true

		if validEmail.length is 0
			throw new Meteor.Error 'no-valid-email'
			return false

	RocketChat.models.Users.updateLastLoginById login.user._id

	Meteor.defer ->
		RocketChat.callbacks.run 'afterValidateLogin', login

	return true

Accounts.validateNewUser (user) ->
	if RocketChat.settings.get('Accounts_Registration_AuthenticationServices_Enabled') is false and RocketChat.settings.get('LDAP_Enable') is false and not user.services?.password?
		throw new Meteor.Error 'registration-disabled-authentication-services', 'User registration is disabled for authentication services'
	return true


(The MIT License)

Copyright (c) 2013 Arunoda Susiripala <arunoda.susiripala@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


لا توجد رسائل مميزة


# when inserting first user give them admin privileges otherwise make a regular user

firstUser = RocketChat.models.Users.findOne({ _id: { $ne: 'rocket.cat' }}, { sort: { createdAt: 1 }})

keep keep keep replace replace replace replace keep

hasAdmin = RocketChat.models.Users.findOne({ roles: 'admin' }, {fields: {_id: 1}})


//! moment.js locale configuration
//! locale : finnish (fi)
//! author : Tarmo Aidantausta : https://github.com/bleadof

(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) :
   typeof define === 'function' && define.amd ? define(['moment'], factory) :
   factory(global.moment)
}(this, function (moment) { 'use strict';

    var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
        numbersFuture = [
            'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
            numbersPast[7], numbersPast[8], numbersPast[9]
        ];
    function translate(number, withoutSuffix, key, isFuture) {
        var result = '';
        switch (key) {
        case 's':
            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
        case 'm':
            return isFuture ? 'minuutin' : 'minuutti';
        case 'mm':
            result = isFuture ? 'minuutin' : 'minuuttia';
            break;
        case 'h':
            return isFuture ? 'tunnin' : 'tunti';
        case 'hh':
            result = isFuture ? 'tunnin' : 'tuntia';
            break;
        case 'd':
            return isFuture ? 'päivän' : 'päivä';
        case 'dd':
            result = isFuture ? 'päivän' : 'päivää';
            break;
        case 'M':
            return isFuture ? 'kuukauden' : 'kuukausi';
        case 'MM':
            result = isFuture ? 'kuukauden' : 'kuukautta';
            break;
        case 'y':
            return isFuture ? 'vuoden' : 'vuosi';
        case 'yy':
            result = isFuture ? 'vuoden' : 'vuotta';
            break;
        }
        result = verbalNumber(number, isFuture) + ' ' + result;
        return result;
    }
    function verbalNumber(number, isFuture) {
        return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
    }

    var fi = moment.defineLocale('fi', {
        months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
        monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
        weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
        weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
        weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
        longDateFormat : {
            LT : 'HH.mm',
            LTS : 'HH.mm.ss',
            L : 'DD.MM.YYYY',
            LL : 'Do MMMM[ta] YYYY',
            LLL : 'Do MMMM[ta] YYYY, [klo] LT',
            LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] LT',
            l : 'D.M.YYYY',
            ll : 'Do MMM YYYY',
            lll : 'Do MMM YYYY, [klo] LT',
            llll : 'ddd, Do MMM YYYY, [klo] LT'
        },
        calendar : {
            sameDay : '[tänään] [klo] LT',
            nextDay : '[huomenna] [klo] LT',
            nextWeek : 'dddd [klo] LT',
            lastDay : '[eilen] [klo] LT',
            lastWeek : '[viime] dddd[na] [klo] LT',
            sameElse : 'L'
        },
        relativeTime : {
            future : '%s päästä',
            past : '%s sitten',
            s : translate,
            m : translate,
            mm : translate,
            h : translate,
            hh : translate,
            d : translate,
            dd : translate,
            M : translate,
            MM : translate,
            y : translate,
            yy : translate
        },
        ordinalParse: /\d{1,2}\./,
        ordinal : '%d.',
        week : {
            dow : 1, // Monday is the first day of the week.
            doy : 4  // The week that contains Jan 4th is the first week of the year.
        }
    });

    return fi;

}));