diff --git a/.travis.yml b/.travis.yml index e7da06aa1ed..aa6adfd56fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -79,23 +79,14 @@ jobs: - stage: publish-docs-live name: 'Publish docs - live' before_script: yarn global add now - script: - - node scripts/set-now-alias.js vuetifyjs.com - - now --team=vuetifyjs --token=$NOW_TOKEN --npm - - now alias --team=vuetifyjs --token=$NOW_TOKEN + script: node scripts/deploy-and-alias.js vuetifyjs.com - stage: publish-docs-dev name: 'Publish docs - dev' before_script: yarn global add now - script: - - node scripts/set-now-alias.js dev.vuetifyjs.com - - now --team=vuetifyjs --token=$NOW_TOKEN --npm - - now alias --team=vuetifyjs --token=$NOW_TOKEN + script: node scripts/deploy-and-alias.js dev.vuetifyjs.com - stage: publish-docs-next name: 'Publish docs - next' before_script: yarn global add now - script: - - node scripts/set-now-alias.js next.vuetifyjs.com - - now --team=vuetifyjs --token=$NOW_TOKEN --npm - - now alias --team=vuetifyjs --token=$NOW_TOKEN + script: node scripts/deploy-and-alias.js next.vuetifyjs.com diff --git a/now.json b/now.json index a57a23e3a1a..22268a78912 100644 --- a/now.json +++ b/now.json @@ -4,5 +4,6 @@ "github": { "autoAlias": false, "silent": true - } + }, + "version": 1 } diff --git a/packages/api-generator/src/map.js b/packages/api-generator/src/map.js index 8daee9e46f3..592b5a74b8b 100755 --- a/packages/api-generator/src/map.js +++ b/packages/api-generator/src/map.js @@ -206,6 +206,10 @@ const textEvents = [ const inputSlots = ['append', 'prepend', 'default'] +const textFieldSlots = [...inputSlots, 'append-outer', 'prepend-inner', 'label'] + +const selectSlots = [...textFieldSlots, 'append-item', 'prepend-item'] + const VSelect = { props: [ { @@ -221,7 +225,7 @@ const VSelect = { default: '{"closeOnClick":false, "closeOnContentClick":false, "openOnClick":false, "maxHeight":300}' } ], - slots: inputSlots.concat(['no-data', 'label', 'progress']), + slots: selectSlots.concat(['no-data', 'progress']), scopedSlots: [ { name: 'selection', @@ -930,6 +934,9 @@ module.exports = { 'v-input': { events: [ ...inputEvents + ], + slots: [ + ...inputSlots ] }, 'v-layout': { @@ -1160,7 +1167,9 @@ module.exports = { ...inputEvents, ...textEvents ].concat(validatableEvents), - slots: ['label'] + slots: [ + ...textFieldSlots + ] }, 'v-time-picker': { events: [ diff --git a/packages/docs/src/components/core/Drawer.vue b/packages/docs/src/components/core/Drawer.vue index 532dad27d22..43c8466e5b4 100644 --- a/packages/docs/src/components/core/Drawer.vue +++ b/packages/docs/src/components/core/Drawer.vue @@ -142,7 +142,10 @@ ) this.inputValue = false }, inputValue (val) { - if (!val) this.docSearch.autocomplete.autocomplete.close() + if (!val) { + this.docSearch.autocomplete.autocomplete.close() + this.docSearch.autocomplete.autocomplete.setVal('') + } }, isSearching (val) { this.$refs.toolbar.isScrolling = !val @@ -155,6 +158,7 @@ search (val) { if (!val) { this.docSearch.autocomplete.autocomplete.close() + this.docSearch.autocomplete.autocomplete.setVal('') } } }, @@ -172,6 +176,7 @@ destroyed () { this.docSearch.autocomplete.autocomplete.close() + this.docSearch.autocomplete.autocomplete.setVal('') }, methods: { diff --git a/packages/docs/src/components/doc/Locales.vue b/packages/docs/src/components/doc/Locales.vue new file mode 100755 index 00000000000..21435da0fc8 --- /dev/null +++ b/packages/docs/src/components/doc/Locales.vue @@ -0,0 +1,34 @@ + + + diff --git a/packages/docs/src/data/pages/framework/Internationalization.json b/packages/docs/src/data/pages/framework/Internationalization.json index 14481eaf25d..09f4d4bad0d 100644 --- a/packages/docs/src/data/pages/framework/Internationalization.json +++ b/packages/docs/src/data/pages/framework/Internationalization.json @@ -26,6 +26,9 @@ "type": "text", "lang": "availableLocalesText" }, + { + "type": "locales" + }, { "type": "markup", "value": "js_vuetify_custom_locale" diff --git a/packages/docs/src/examples/cards/usage.vue b/packages/docs/src/examples/cards/usage.vue index 8efdc728e5b..b4841aecca0 100644 --- a/packages/docs/src/examples/cards/usage.vue +++ b/packages/docs/src/examples/cards/usage.vue @@ -10,7 +10,7 @@

Kangaroo Valley Safari

-
Located two hours south of Sydney in the
Southern Highlands of New South Wales, ...
+
{{ card_text }}
diff --git a/packages/docs/src/examples/text-fields/iconSlots.vue b/packages/docs/src/examples/text-fields/iconSlots.vue index 5199ace21fc..04dc087199b 100644 --- a/packages/docs/src/examples/text-fields/iconSlots.vue +++ b/packages/docs/src/examples/text-fields/iconSlots.vue @@ -18,7 +18,10 @@ I'm a tooltip - + ` autocomplete attribute", "clearIcon": "Applied when using **clearable** and the input is dirty", - "clearIconCb": "Callback for clear icon when clicked", "counter": "Creates counter for input length; if no number is specified, it defaults to 25. Does not apply any validation.", "flat": "Mixins.Soloable.props.flat", "fullWidth": "Desginates input type as full-width", @@ -107,7 +105,6 @@ "placeholder": "Sets the input’s placeholder text", "prefix": "Displays prefix text", "prependInnerIcon": "Prepends an icon inside the component, uses the same syntax as `v-icon`", - "prependInnerIconCb": "Callback for prepended icon when clicked", "reverse": "Reverses the input orientation", "rows": "Controls the number of rows in a textarea", "rowHeight": "Designate a custom _row-height_. Used for determining input height when using **multi-line** or **textarea** props", @@ -118,6 +115,12 @@ "toggleKeys": "Array of key codes that will toggle the input (if it supports toggling)", "type": "Sets input type" }, + "slots": { + "append": "Components.Inputs.slots.append", + "append-outer": "Appends an item inside input content", + "prepend": "Components.Inputs.slots.prepend", + "prepend-inner": "Prepends an item inside input content" + }, "events": { "change": "Components.Inputs.events.change", "click:append": "Components.Inputs.events['click:append']", diff --git a/packages/docs/src/lang/ru-RU/components/Treeview.json b/packages/docs/src/lang/ru-RU/components/Treeview.json new file mode 100644 index 00000000000..aa1a94b56c0 --- /dev/null +++ b/packages/docs/src/lang/ru-RU/components/Treeview.json @@ -0,0 +1,65 @@ +{ + "header": "# Treeview", + "headerText": "Компонент `v-treeview` полезен для отображения большого количества вложенных данных.", + "examples": { + "usage": { + "desc": "Основной пример" + }, + "fileExplorer": { + "header": "### Scoped slots", + "desc": "Используя scoped slots мы можем создать интуитивно понятный файловый менеджер. Кроме слота `prepend`, есть также один для `label`, и `append` слот." + }, + "directory": { + "header": "### Асинхронные элементы", + "desc": "Вы можете динамически загружать дочерние данные, предоставляя _Promise_ callback для `load-children` prop. Этот callback будет выполнен при первой попытке пользователя расширить элемент у которого есть свойство children, которое является пустым массивом." + }, + "hotspots": { + "header": "### Пользовательские иконки выбора", + "desc": "Настройте **on**, **off** и **indeterminate** иконки для вашего выбираемого дерева. Комбинируйте с другими продвинутыми возможностями, такими как элементы, загруженные через API." + }, + "humanResources": { + "header": "### Поиск директории", + "desc": "Легко фильтруйте ваш treeview используя **search** prop. Вы можете легко применить свою собственную функцию фильтрации (если вам нужна чувствительная к регистру или fuzzy фильтрация) установив **filter** prop. Это работает аналогично как [v-autocomplete](/components/autocompletes) компонент." + } + }, + "props": { + "v-treeview": { + "activatable": "Позволяет пользователю пометить узел как активный, нажав на него", + "active": "Синхронизируемая prop, позволяющая контролировать, какие узлы активны. Массив состоит из `item-key` каждого активного элемента.", + "activeClass": "Класс применяющийся к узлу, когда тот активен", + "customFilter": "Пользовательский фильтр поиска", + "expandIcon": "Иконка, используемая для обозначения возможности открытия узла", + "hoverable": "Применяет класс наведения при наведении мыши на узлы", + "filter": "Пользовательская функция фильтрации элементов. По умолчанию используется поиск без учета регистра по label элемента.", + "indeterminateIcon": "Значок, используемый, когда узел находится в неопределенном состоянии", + "itemChildren": "Свойство у предоставленных `items` которое содержит детей каждого элемента", + "itemKey": "Свойство для поставляемых `items`, используемое для отслеживания состояния узла. Значение этого свойства должно быть уникальным среди всех элементов.", + "itemText": "Свойство для поставляемых `items`, содержащее текст метки", + "items": "Массив элементов, используемых для построения дерева", + "loadChildren": "Функция, используемая при динамической загрузке детей. Если этот prop установлен, то функция будет работать если развернуть элемент, имеющий свойство `item-children`, которое является пустым массивом. Поддерживает возврат Promise.", + "loadingIcon": "Иконка, используемая, когда узел находится в состоянии загрузки", + "multipleActive": "Когда `true`, позволяет пользователю иметь несколько активных узлов одновременно", + "offIcon": "Иконка используется, когда узел не выбран", + "onIcon": "Иконка, используемая при выборе конечного узла или когда полностью выбран узел ветви", + "open": "Синхронизируемая prop которая позволяет контролировать, какие узлы открыты. Массив состоит из `item-key` каждого открытого элемента.", + "openAll": "Когда `true` приведет к открытию всех узлов всех ветвей при mounted компонента", + "openOnClick": "Когда `true` заставит узлы открываться щелчком в любом месте на нем, а не открываться только нажатием на значок расширения. При использовании этого prop с `activatable` вы не сможете пометить узлы с дочерними элементами как активные.", + "returnObject": "Когда `true`, заставит v-model, `active.sync` и `open.sync` возвращать весь объект, а не только ключ", + "search": "Модель поиска для фильтрации результатов", + "selectable": "Будет отображать флажок рядом с каждым узлом, позволяя им быть выбранными", + "selectedColor": "Цвет флажка выбора", + "transition": "Применяет переход, когда узлы открываются и закрываются", + "value": "Позволяет контролировать, какие узлы выбраны. Массив состоит из `item-key` каждого выбранного элемента. Используется с `@input` событием чтобы разрешить `v-model` биндинг." + } + }, + "scopedSlots": { + "v-treeview": { + "append": "Добавляет контент после label", + "label": "Контент для label", + "prepend": "Добавляет контент перед label" + } + }, + "functions": { + "updateAll": "Открывает или закрывает все узлы" + } +} diff --git a/packages/docs/src/util/helpers.js b/packages/docs/src/util/helpers.js index 57ff04e12a6..19c43eeef3e 100644 --- a/packages/docs/src/util/helpers.js +++ b/packages/docs/src/util/helpers.js @@ -31,6 +31,7 @@ export function getComponent (type) { case 'tree': return 'doc-tree' case 'up-next': return 'doc-up-next' case 'usage': return 'doc-usage' + case 'locales': return 'doc-locales' default: return type } } diff --git a/packages/vuetify/src/components/VCarousel/VCarousel.ts b/packages/vuetify/src/components/VCarousel/VCarousel.ts index fd61caa4d28..b9850e0ae4c 100644 --- a/packages/vuetify/src/components/VCarousel/VCarousel.ts +++ b/packages/vuetify/src/components/VCarousel/VCarousel.ts @@ -59,7 +59,7 @@ export default VWindow.extend({ data () { return { - changedByControls: false, + changedByDelimiters: false, internalHeight: this.height, slideTimeout: undefined as number | undefined } @@ -122,7 +122,15 @@ export default VWindow.extend({ props: { icon: true }, - on: { click: fn } + attrs: { + 'aria-label': this.$vuetify.lang.t(`$vuetify.carousel.${direction}`) + }, + on: { + click: () => { + this.changedByDelimiters = true + fn() + } + } }, [ this.$createElement(VIcon, { props: { 'size': '46px' } @@ -180,7 +188,6 @@ export default VWindow.extend({ }, on: { change: (val: any) => { - this.changedByControls = true this.internalValue = val } } @@ -199,11 +206,12 @@ export default VWindow.extend({ this.slideTimeout = window.setTimeout(this.next, +this.interval > 0 ? +this.interval : 6000) }, updateReverse (val: number, oldVal: number) { - if (this.changedByControls) { - this.changedByControls = false - - VWindow.options.methods.updateReverse.call(this, val, oldVal) + if (this.changedByDelimiters) { + this.changedByDelimiters = false + return } + + VWindow.options.methods.updateReverse.call(this, val, oldVal) } }, diff --git a/packages/vuetify/src/components/VIcon/VIcon.ts b/packages/vuetify/src/components/VIcon/VIcon.ts index 7171c72bce6..bb3e0db2a1e 100644 --- a/packages/vuetify/src/components/VIcon/VIcon.ts +++ b/packages/vuetify/src/components/VIcon/VIcon.ts @@ -130,6 +130,8 @@ const VIcon = mixins( const component = icon.component data.props = icon.props + data.nativeOn = data.on + return h(component, data) } }, diff --git a/packages/vuetify/src/components/VIcon/__tests__/VIcon.spec.ts b/packages/vuetify/src/components/VIcon/__tests__/VIcon.spec.ts index 8323e61e3f9..653123a825c 100644 --- a/packages/vuetify/src/components/VIcon/__tests__/VIcon.spec.ts +++ b/packages/vuetify/src/components/VIcon/__tests__/VIcon.spec.ts @@ -266,6 +266,15 @@ describe('VIcon', () => { expect(wrapper.element.classList).toContain('v-icon--right') }) + it('should be a link', () => { + const clickHandler = jest.fn() + const wrapper = mountFunction({ on: { click: clickHandler } }, '$vuetify.icons.testIcon') + wrapper.trigger('click') + + expect(wrapper.element.classList).toContain('v-icon--link') + expect(clickHandler).toHaveBeenCalled() + }) + it('should trim name', () => { const wrapper = mountFunction({}, ' add ') diff --git a/packages/vuetify/src/components/VMenu/VMenu.js b/packages/vuetify/src/components/VMenu/VMenu.js index c3ede49ceb4..9248c82b72d 100644 --- a/packages/vuetify/src/components/VMenu/VMenu.js +++ b/packages/vuetify/src/components/VMenu/VMenu.js @@ -96,7 +96,7 @@ export default Vue.extend({ computed: { calculatedLeft () { - const menuWidth = Math.max(this.dimensions.content.width, this.dimensions.activator.width) + const menuWidth = Math.max(this.dimensions.content.width, parseFloat(this.calculatedMinWidth)) if (!this.auto) return this.calcLeft(menuWidth) @@ -117,10 +117,11 @@ export default Vue.extend({ : `${this.minWidth}px` } - const minWidth = ( + const minWidth = Math.min( this.dimensions.activator.width + this.nudgeWidth + - (this.auto ? 16 : 0) + (this.auto ? 16 : 0), + Math.max(this.pageWidth - 24, 0) ) const calculatedMaxWidth = isNaN(parseInt(this.calculatedMaxWidth)) diff --git a/packages/vuetify/src/components/VSpeedDial/VSpeedDial.js b/packages/vuetify/src/components/VSpeedDial/VSpeedDial.js index 11df455dc78..b819439ca0a 100644 --- a/packages/vuetify/src/components/VSpeedDial/VSpeedDial.js +++ b/packages/vuetify/src/components/VSpeedDial/VSpeedDial.js @@ -63,10 +63,20 @@ export default { } if (this.isActive) { + let btnCount = 0 children = (this.$slots.default || []).map((b, i) => { - b.key = i - - return b + if (b.tag && b.componentOptions.Ctor.options.name === 'v-btn') { + btnCount++ + return h('div', { + style: { + transitionDelay: btnCount * 0.05 + 's' + }, + key: i + }, [b]) + } else { + b.key = i + return b + } }) } diff --git a/packages/vuetify/src/locale/af.ts b/packages/vuetify/src/locale/af.ts index c9681404f4f..96f0f45b0bf 100644 --- a/packages/vuetify/src/locale/af.ts +++ b/packages/vuetify/src/locale/af.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Rye per bladsy:' }, - noDataText: 'Geen data is beskikbaar nie' + noDataText: 'Geen data is beskikbaar nie', + carousel: { + prev: 'Vorige visuele', + next: 'Volgende visuele' + } } diff --git a/packages/vuetify/src/locale/ar.ts b/packages/vuetify/src/locale/ar.ts index d709522c015..48ebd802fb0 100644 --- a/packages/vuetify/src/locale/ar.ts +++ b/packages/vuetify/src/locale/ar.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'الصفوف لكل صفحة:' }, - noDataText: 'لا توجد بيانات متاحة' + noDataText: 'لا توجد بيانات متاحة', + carousel: { + prev: 'الصورة السابقة', + next: 'البصري التالي' + } } diff --git a/packages/vuetify/src/locale/ca.ts b/packages/vuetify/src/locale/ca.ts index a688cb2b26c..e4034e98d9c 100644 --- a/packages/vuetify/src/locale/ca.ts +++ b/packages/vuetify/src/locale/ca.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Files per pàgina:' }, - noDataText: 'Sense dades' + noDataText: 'Sense dades', + carousel: { + prev: 'Visualització prèvia', + next: 'Següent visual' + } } diff --git a/packages/vuetify/src/locale/de.ts b/packages/vuetify/src/locale/de.ts index 2a77a10c2f3..d489e85b002 100644 --- a/packages/vuetify/src/locale/de.ts +++ b/packages/vuetify/src/locale/de.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Zeilen pro Seite:' }, - noDataText: 'Keine Daten vorhanden' + noDataText: 'Keine Daten vorhanden', + carousel: { + prev: 'Vorheriges visuelles', + next: 'Nächstes Bild' + } } diff --git a/packages/vuetify/src/locale/el.ts b/packages/vuetify/src/locale/el.ts index 9d57a63ffc9..1ed281727d9 100755 --- a/packages/vuetify/src/locale/el.ts +++ b/packages/vuetify/src/locale/el.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Γραμμές ανά σελίδα:' }, - noDataText: 'Χωρίς δεδομένα' + noDataText: 'Χωρίς δεδομένα', + carousel: { + prev: 'הקודם חזותי', + next: 'הבא חזותי' + } } diff --git a/packages/vuetify/src/locale/en.ts b/packages/vuetify/src/locale/en.ts index d2f90b46173..a0a3d48566c 100644 --- a/packages/vuetify/src/locale/en.ts +++ b/packages/vuetify/src/locale/en.ts @@ -11,5 +11,9 @@ export default { dataTable: { rowsPerPageText: 'Rows per page:' }, - noDataText: 'No data available' + noDataText: 'No data available', + carousel: { + prev: 'Previous visual', + next: 'Next visual' + } } diff --git a/packages/vuetify/src/locale/es.ts b/packages/vuetify/src/locale/es.ts index b64ffb43c9d..ad353dc668a 100644 --- a/packages/vuetify/src/locale/es.ts +++ b/packages/vuetify/src/locale/es.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Filas por página:' }, - noDataText: 'Ningún dato disponible' + noDataText: 'Ningún dato disponible', + carousel: { + prev: 'Visual previo', + next: 'Siguiente visual' + } } diff --git a/packages/vuetify/src/locale/et.ts b/packages/vuetify/src/locale/et.ts index ffe044fb807..cd2fa20e16f 100644 --- a/packages/vuetify/src/locale/et.ts +++ b/packages/vuetify/src/locale/et.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Ridu leheküljel:' }, - noDataText: 'Andmed puuduvad' + noDataText: 'Andmed puuduvad', + carousel: { + prev: 'Eelmine visuaalne', + next: 'Järgmine visuaalne' + } } diff --git a/packages/vuetify/src/locale/fa.ts b/packages/vuetify/src/locale/fa.ts index d8c856afda6..add91077dd5 100644 --- a/packages/vuetify/src/locale/fa.ts +++ b/packages/vuetify/src/locale/fa.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'ردیف در صفحه:' }, - noDataText: 'اطلاعاتی یافت نشد' + noDataText: 'اطلاعاتی یافت نشد', + carousel: { + prev: 'تصویر قبلی', + next: 'بعدی بصری' + } } diff --git a/packages/vuetify/src/locale/fr.ts b/packages/vuetify/src/locale/fr.ts index 9898a21cb3a..d7c19e18975 100644 --- a/packages/vuetify/src/locale/fr.ts +++ b/packages/vuetify/src/locale/fr.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Lignes par page:' }, - noDataText: 'Aucune donnée disponible' + noDataText: 'Aucune donnée disponible', + carousel: { + prev: 'Visuel précédent', + next: 'Visuel suivant' + } } diff --git a/packages/vuetify/src/locale/gr.ts b/packages/vuetify/src/locale/gr.ts index 9d57a63ffc9..e2f969db704 100644 --- a/packages/vuetify/src/locale/gr.ts +++ b/packages/vuetify/src/locale/gr.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Γραμμές ανά σελίδα:' }, - noDataText: 'Χωρίς δεδομένα' + noDataText: 'Χωρίς δεδομένα', + carousel: { + prev: 'Προηγούμενη οπτική', + next: 'Επόμενη οπτική' + } } diff --git a/packages/vuetify/src/locale/hr.ts b/packages/vuetify/src/locale/hr.ts index 3b30fc7a93c..dcbaa85fbb1 100644 --- a/packages/vuetify/src/locale/hr.ts +++ b/packages/vuetify/src/locale/hr.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Redova po stranici:' }, - noDataText: 'Nema dostupnih podataka' + noDataText: 'Nema dostupnih podataka', + carousel: { + prev: 'Prethodna slika', + next: 'Sljedeća vizuala' + } } diff --git a/packages/vuetify/src/locale/hu.ts b/packages/vuetify/src/locale/hu.ts index 6864033d458..94fbba02ea0 100644 --- a/packages/vuetify/src/locale/hu.ts +++ b/packages/vuetify/src/locale/hu.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Elem oldalanként:' }, - noDataText: 'Nincs elérhető adat' + noDataText: 'Nincs elérhető adat', + carousel: { + prev: 'Korábbi vizuális', + next: 'Következő vizuális' + } } diff --git a/packages/vuetify/src/locale/id.ts b/packages/vuetify/src/locale/id.ts index bf15531b15d..63bf051bd84 100644 --- a/packages/vuetify/src/locale/id.ts +++ b/packages/vuetify/src/locale/id.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Baris setiap halaman:' }, - noDataText: 'Tidak ada data tersedia' + noDataText: 'Tidak ada data tersedia', + carousel: { + prev: 'Visual sebelumnya', + next: 'Visual selanjutnya' + } } diff --git a/packages/vuetify/src/locale/it.ts b/packages/vuetify/src/locale/it.ts index 6ea03334fad..fef8c8ab9a2 100644 --- a/packages/vuetify/src/locale/it.ts +++ b/packages/vuetify/src/locale/it.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Righe per pagina:' }, - noDataText: 'Nessun elemento disponibile' + noDataText: 'Nessun elemento disponibile', + carousel: { + prev: 'Precedente visivo', + next: 'Next visual' + } } diff --git a/packages/vuetify/src/locale/ja.ts b/packages/vuetify/src/locale/ja.ts index b4baab56525..b0a6e0bb981 100644 --- a/packages/vuetify/src/locale/ja.ts +++ b/packages/vuetify/src/locale/ja.ts @@ -1,14 +1,18 @@ -export default { - dataIterator: { - rowsPerPageText: '1ページあたりの件数:', - rowsPerPageAll: 'すべて', - pageText: '{0}-{1} 件目 / {2}件', - noResultsText: '検索結果が見つかりません。', - nextPage: '次のページ', - prevPage: '前のページ' - }, - dataTable: { - rowsPerPageText: '1ページあたりの行数:' - }, - noDataText: 'データはありません。' -} +export default { + dataIterator: { + rowsPerPageText: '1ページあたりの件数:', + rowsPerPageAll: 'すべて', + pageText: '{0}-{1} 件目 / {2}件', + noResultsText: '検索結果が見つかりません。', + nextPage: '次のページ', + prevPage: '前のページ' + }, + dataTable: { + rowsPerPageText: '1ページあたりの行数:' + }, + noDataText: 'データはありません。', + carousel: { + prev: '前のビジュアル', + next: '次のビジュアル' + } +} diff --git a/packages/vuetify/src/locale/nl.ts b/packages/vuetify/src/locale/nl.ts index 61b099f423b..f4a51442273 100644 --- a/packages/vuetify/src/locale/nl.ts +++ b/packages/vuetify/src/locale/nl.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Rijen per pagina:' }, - noDataText: 'Geen gegevens beschikbaar' + noDataText: 'Geen gegevens beschikbaar', + carousel: { + prev: 'Vorige visual', + next: 'Volgende visueel' + } } diff --git a/packages/vuetify/src/locale/pl.ts b/packages/vuetify/src/locale/pl.ts index d683e130dd7..91581c4f97d 100644 --- a/packages/vuetify/src/locale/pl.ts +++ b/packages/vuetify/src/locale/pl.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Wierszy na stronie:' }, - noDataText: 'Brak danych' + noDataText: 'Brak danych', + carousel: { + prev: 'Poprzedni obraz', + next: 'Następny obraz' + } } diff --git a/packages/vuetify/src/locale/pt.ts b/packages/vuetify/src/locale/pt.ts index cfaecfd1812..0c09a085e85 100644 --- a/packages/vuetify/src/locale/pt.ts +++ b/packages/vuetify/src/locale/pt.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Linhas por página:' }, - noDataText: 'Não há dados disponíveis' + noDataText: 'Não há dados disponíveis', + carousel: { + prev: 'Visual anterior', + next: 'Próximo visual' + } } diff --git a/packages/vuetify/src/locale/ro.ts b/packages/vuetify/src/locale/ro.ts index 5e379dcdf33..19799b824e7 100644 --- a/packages/vuetify/src/locale/ro.ts +++ b/packages/vuetify/src/locale/ro.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Rânduri pe pagină:' }, - noDataText: 'Nu există date disponibile' + noDataText: 'Nu există date disponibile', + carousel: { + prev: 'Anterior vizual', + next: 'Următorul vizual' + } } diff --git a/packages/vuetify/src/locale/ru.ts b/packages/vuetify/src/locale/ru.ts index a87f59bf7ef..1df92f0b026 100644 --- a/packages/vuetify/src/locale/ru.ts +++ b/packages/vuetify/src/locale/ru.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Строк на странице:' }, - noDataText: 'Отсутствуют данные' + noDataText: 'Отсутствуют данные', + carousel: { + prev: 'Предыдущий визуальный', + next: 'Следующий визуальный' + } } diff --git a/packages/vuetify/src/locale/sl.ts b/packages/vuetify/src/locale/sl.ts index d3a39ecdc7d..b48af6254cc 100644 --- a/packages/vuetify/src/locale/sl.ts +++ b/packages/vuetify/src/locale/sl.ts @@ -1,14 +1,18 @@ -export default { - dataIterator: { - rowsPerPageText: 'Predmetov na stran:', - rowsPerPageAll: 'Vse', - pageText: '{0}-{1} od {2}', - noResultsText: 'Ni iskanega zapisa', - nextPage: 'Naslednja stran', - prevPage: 'Prejšnja stran' - }, - dataTable: { - rowsPerPageText: 'Vrstic na stran:' - }, - noDataText: 'Ni podatkov' -} +export default { + dataIterator: { + rowsPerPageText: 'Predmetov na stran:', + rowsPerPageAll: 'Vse', + pageText: '{0}-{1} od {2}', + noResultsText: 'Ni iskanega zapisa', + nextPage: 'Naslednja stran', + prevPage: 'Prejšnja stran' + }, + dataTable: { + rowsPerPageText: 'Vrstic na stran:' + }, + noDataText: 'Ni podatkov', + carousel: { + prev: 'Prejšnji vizualni prikaz', + next: 'Naslednja vizuala' + } +} diff --git a/packages/vuetify/src/locale/sr-Cyrl.ts b/packages/vuetify/src/locale/sr-Cyrl.ts index c634db10db4..b416d8b75ea 100644 --- a/packages/vuetify/src/locale/sr-Cyrl.ts +++ b/packages/vuetify/src/locale/sr-Cyrl.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Редова по страници:' }, - noDataText: 'Нема доступних података' + noDataText: 'Нема доступних података', + carousel: { + prev: 'Превиоус висуал', + next: 'Нект висуал' + } } diff --git a/packages/vuetify/src/locale/th.ts b/packages/vuetify/src/locale/th.ts index fa295721cde..b1614a17f11 100644 --- a/packages/vuetify/src/locale/th.ts +++ b/packages/vuetify/src/locale/th.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'แถวต่อหน้า:' }, - noDataText: 'ไม่มีข้อมูล' + noDataText: 'ไม่มีข้อมูล', + carousel: { + prev: 'ภาพก่อนหน้า', + next: 'ภาพต่อไป' + } } diff --git a/packages/vuetify/src/locale/tr.ts b/packages/vuetify/src/locale/tr.ts index 328f7f0922a..f3f80b26191 100644 --- a/packages/vuetify/src/locale/tr.ts +++ b/packages/vuetify/src/locale/tr.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Sayfa başına satır:' }, - noDataText: 'Uygun veri yok' + noDataText: 'Uygun veri yok', + carousel: { + prev: 'Önceki görsel', + next: 'Sonraki görsel' + } } diff --git a/packages/vuetify/src/locale/uk.ts b/packages/vuetify/src/locale/uk.ts index 00b2c0677c0..8cf606037a6 100644 --- a/packages/vuetify/src/locale/uk.ts +++ b/packages/vuetify/src/locale/uk.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: 'Рядків на сторінці:' }, - noDataText: 'Немає даних для відображення' + noDataText: 'Немає даних для відображення', + carousel: { + prev: 'Попередній візуальний', + next: 'Наступний візуальнийa' + } } diff --git a/packages/vuetify/src/locale/zh-Hans.ts b/packages/vuetify/src/locale/zh-Hans.ts index 09b243c0f8d..aff431c7c88 100644 --- a/packages/vuetify/src/locale/zh-Hans.ts +++ b/packages/vuetify/src/locale/zh-Hans.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: '每页行数:' }, - noDataText: '无可用数据' + noDataText: '无可用数据', + carousel: { + prev: '以前的视觉', + next: '下一个视觉' + } } diff --git a/packages/vuetify/src/locale/zh-Hant.ts b/packages/vuetify/src/locale/zh-Hant.ts index 1625fce5c9b..9a7d5209906 100644 --- a/packages/vuetify/src/locale/zh-Hant.ts +++ b/packages/vuetify/src/locale/zh-Hant.ts @@ -10,5 +10,9 @@ export default { dataTable: { rowsPerPageText: '每頁行數:' }, - noDataText: '無可用數據' + noDataText: '無可用數據', + carousel: { + prev: '以前的視覺', + next: '下一個視覺' + } } diff --git a/packages/vuetify/src/mixins/menuable.js b/packages/vuetify/src/mixins/menuable.js index 9495e4905ba..7710867b940 100644 --- a/packages/vuetify/src/mixins/menuable.js +++ b/packages/vuetify/src/mixins/menuable.js @@ -98,6 +98,7 @@ export default Vue.extend({ absoluteY: 0, dimensions: Object.assign({}, dimensions), isContentActive: false, + pageWidth: 0, pageYOffset: 0, stackClass: 'v-menu__content--active', stackMinZIndex: 6 @@ -190,7 +191,7 @@ export default Vue.extend({ }px` }, calcXOverflow (left, menuWidth) { - const xOverflow = left + menuWidth - this.getInnerWidth() + 12 + const xOverflow = left + menuWidth - this.pageWidth + 12 if ((!this.left || this.right) && xOverflow > 0) { left = Math.max(left - xOverflow, 0) @@ -286,11 +287,6 @@ export default Vue.extend({ return window.innerHeight || document.documentElement.clientHeight }, - getInnerWidth () { - if (!this.hasWindow) return 0 - - return document.documentElement.clientWidth - }, getOffsetLeft () { if (!this.hasWindow) return 0 @@ -352,6 +348,7 @@ export default Vue.extend({ updateDimensions () { this.checkForWindow() this.checkForPageYOffset() + this.pageWidth = document.documentElement.clientWidth const dimensions = {} diff --git a/packages/vuetify/src/stylus/components/_buttons.styl b/packages/vuetify/src/stylus/components/_buttons.styl new file mode 100644 index 00000000000..84d04a9f2d5 --- /dev/null +++ b/packages/vuetify/src/stylus/components/_buttons.styl @@ -0,0 +1,332 @@ +@import '../bootstrap' +@import '../components/_ripples' +@import '../theme' + +button($material) + color: $material.text.primary + + &.v-btn--disabled + color: $material.buttons.disabled !important + + .v-icon, + .v-btn__loading + color: $material.buttons.disabled !important + + &:not(.v-btn--icon):not(.v-btn--flat):not(.v-btn--outline) + background-color: $material.buttons.focused !important + + &:not(.v-btn--icon):not(.v-btn--flat) + background-color: $material.app-bar + +theme(button, "v-btn") + +/** Base Spec */ +.v-btn + align-items: center + border-radius: $button-border-radius + display: inline-flex + height: $button-height + flex: 0 0 auto + font-size: $button-font-size + font-weight: $button-font-weight + justify-content: center + margin: $button-margin + min-width: $button-min-width + outline: 0 + text-transform: $button-text-transform + text-decoration: none + transition: $primary-transition, color 1ms + position: relative + vertical-align: middle + user-select: none + + +/** Psuedo */ +.v-btn + &:before + border-radius: inherit + color: inherit + content: '' + position: absolute + left: 0 + top: 0 + height: 100% + opacity: .12 + transition: $primary-transition + width: 100% + +/** Content */ +.v-btn + padding: $button-padding + + &--active, + &:hover, + &:focus + position: relative + + &:before + background-color: currentColor + + &:hover::before + @media (hover: none) + background-color: transparent + + &__content + align-items: center + border-radius: inherit + color: inherit + display: flex + flex: 1 0 auto + justify-content: center + margin: 0 auto + // Fixes bug where IE11 moves + // button content when clicked + // https://stackoverflow.com/questions/10305658/prevent-button-from-shifting-during-click-in-ie + position: relative + transition: $primary-transition + white-space: nowrap + width: inherit + +/** Sizes */ +.v-btn + &--small + font-size: $button-small-font-size + height: $button-small-height + padding: $button-small-padding + + &--large + font-size: $button-large-font-size + height: $button-large-height + padding: $button-large-padding + +/** Icons */ +.v-btn .v-btn__content .v-icon + color: inherit + +/** Types */ +.v-btn + &:not(.v-btn--depressed):not(.v-btn--flat) + will-change: box-shadow + elevation(2) + + &:active + elevation(8) + + &--icon + background: transparent + box-shadow: none !important + border-radius: 50% + justify-content: center + min-width: 0 + width: $button-height + + &.v-btn--small + width: $button-small-height + + &.v-btn--large + width: $button-large-height + + &:before + border-radius: 50% + + &--floating + border-radius: 50% + min-width: 0 + height: $button-floating-width + width: $button-floating-width + padding: 0 + + &.v-btn--fixed, + &.v-btn--absolute + z-index: 4 + + &:not(.v-btn--depressed):not(.v-btn--flat) + elevation(6) + + &:active + elevation(12) + + .v-btn__content + flex: 1 1 auto + margin: 0 + height: 100% + + &:after + border-radius: 50% + + .v-btn__content + :not(:only-child) + transition: $primary-transition + + &:first-child + opacity: 1 + + &:last-child + opacity: 0 + transform: rotate(-45deg) + + &:last-child, + &:first-child + // https://stackoverflow.com/questions/14729492/css3-transform-rotate-causing-1px-shift-in-chrome + -webkit-backface-visibility: hidden + position: absolute + left: 0 + top: 0 + + &.v-btn--active + .v-btn__content + :not(:only-child) + &:first-child + opacity: 0 + transform: rotate(45deg) + + &:last-child + opacity: 1 + transform: rotate(0) + + .v-icon + height: inherit + width: inherit + + &.v-btn--small + height: $button-floating-small-width + width: $button-floating-small-width + + .v-icon + font-size: $button-floating-small-icon-width + + + &.v-btn--large + height: $button-floating-large-width + width: $button-floating-large-width + + .v-icon + font-size: $button-floating-large-icon-width + + &--reverse + .v-btn__content + flex-direction: row-reverse + + &.v-btn--column + .v-btn__content + flex-direction: column-reverse + + &--fixed, &--absolute + margin: 0 + + // Position must have prepended .v-btn + // to account for tooltip + // TODO: Remove this once tooltips are + // converted to elements + &.v-btn--absolute + position: absolute + + &.v-btn--fixed + position: fixed + + &--top + &:not(.v-btn--absolute) + top: $grid-gutters.lg + + &.v-btn--absolute + top: -($button-floating-width / 2) + + &.v-btn--small + top: -($button-floating-small-width / 2) + + &.v-btn--large + top: -($button-floating-large-width / 2) + + &--bottom + &:not(.v-btn--absolute) + bottom: $grid-gutters.lg + + &.v-btn--absolute + bottom: -($button-floating-width / 2) + + &.v-btn--small + bottom: -($button-floating-small-width / 2) + + &.v-btn--large + bottom: -($button-floating-large-width / 2) + + &--left + left: $grid-gutters.lg + + &--right + right: $grid-gutters.lg + +/** Disabled */ +.v-btn + &.v-btn--disabled + box-shadow: none !important + pointer-events: none + + &:not(.v-btn--disabled):not(.v-btn--floating):not(.v-btn--icon) + .v-btn__content .v-icon + transition: none + +.v-btn--icon + padding: 0 + + +/** Loader */ +.v-btn + &--loader + pointer-events: none + + .v-btn__content + opacity: 0 + + &__loading + align-items: center + display: flex + height: 100% + justify-content: center + left: 0 + position: absolute + top: 0 + width: 100% + + .v-icon + &--left + margin-right: 1rem + line-height: inherit + + &--right + margin-left: 1rem + line-height: inherit + + +/** Custom Buttons */ +.v-btn + &.v-btn--outline + border: 1px solid currentColor + background: transparent !important + box-shadow: none + + &:hover + box-shadow: none + + &--block + display: flex + flex: 1 + margin: $button-margin-y 0 + width: 100% + + &--round + border-radius: 28px + + &:after + border-radius: 28px + +/** Themes */ +.v-btn:not(.v-btn--outline) + &.primary, + &.secondary, + &.accent, + &.success, + &.error, + &.warning, + &.info + color: $material-dark.text.primary diff --git a/packages/vuetify/src/stylus/components/_dialogs.styl b/packages/vuetify/src/stylus/components/_dialogs.styl index 2b0e22d1f74..19cbb2ece6d 100644 --- a/packages/vuetify/src/stylus/components/_dialogs.styl +++ b/packages/vuetify/src/stylus/components/_dialogs.styl @@ -70,7 +70,6 @@ &--scrollable, &--scrollable > form display: flex - flex: 1 1 0px > .v-card display: flex diff --git a/packages/vuetify/src/stylus/components/_speed-dial.styl b/packages/vuetify/src/stylus/components/_speed-dial.styl index b4f00b1141c..ddaf16109d2 100644 --- a/packages/vuetify/src/stylus/components/_speed-dial.styl +++ b/packages/vuetify/src/stylus/components/_speed-dial.styl @@ -77,9 +77,3 @@ display: flex justify-content: center position: absolute - - .v-btn - for n in (1..7) - &:nth-child({n}) - transition-delay: "%ss" % (n * .05) - diff --git a/packages/vuetify/src/stylus/trumps/_text.styl b/packages/vuetify/src/stylus/trumps/_text.styl index 2b8d760d20b..879ed2ee370 100644 --- a/packages/vuetify/src/stylus/trumps/_text.styl +++ b/packages/vuetify/src/stylus/trumps/_text.styl @@ -39,3 +39,4 @@ for $name, $weight in $font-weights white-space: nowrap !important overflow: hidden !important text-overflow: ellipsis !important + line-height: 1.1 !important diff --git a/packages/vuetify/test/unit/components/VCarousel/VCarousel.spec.js b/packages/vuetify/test/unit/components/VCarousel/VCarousel.spec.js index ae724957c6b..c94fd18846f 100644 --- a/packages/vuetify/test/unit/components/VCarousel/VCarousel.spec.js +++ b/packages/vuetify/test/unit/components/VCarousel/VCarousel.spec.js @@ -205,4 +205,44 @@ test('VCarousel.ts', ({ mount }) => { expect(wrapper.vm.height).toEqual(200) expect(wrapper.find('.v-carousel__item')[0].hasStyle('height', '200px')).toBe(true) }) + + it('should return correct transition direction when active item changed', async () => { + const vm = new Vue() + const wrapper = mount(VCarousel, { + propsData: { + value: 0 + }, + slots: { + default: [1, 2, 3].map(i => { + return { + vNode: vm.$createElement(VCarouselItem, { attrs: { src: i.toString() } }) + } + }) + } + }) + + // Change by carousel delimiters + wrapper.find('.v-carousel__next button')[0].trigger('click') + await wrapper.vm.$nextTick() + expect(wrapper.vm.isReverse).toBe(false) + wrapper.find('.v-carousel__prev button')[0].trigger('click') + await wrapper.vm.$nextTick() + expect(wrapper.vm.isReverse).toBe(true) + + // Change by navigation controls + wrapper.find('.v-carousel__controls__item')[1].trigger('click') + await wrapper.vm.$nextTick() + expect(wrapper.vm.isReverse).toBe(false) + wrapper.find('.v-carousel__controls__item')[0].trigger('click') + await wrapper.vm.$nextTick() + expect(wrapper.vm.isReverse).toBe(true) + + // Change by props + wrapper.setProps({ value: 1 }) + await wrapper.vm.$nextTick() + expect(wrapper.vm.isReverse).toBe(false) + wrapper.setProps({ value: 0 }) + await wrapper.vm.$nextTick() + expect(wrapper.vm.isReverse).toBe(true) + }) }) diff --git a/packages/vuetify/test/unit/components/VCarousel/__snapshots__/VCarousel.spec.js.snap b/packages/vuetify/test/unit/components/VCarousel/__snapshots__/VCarousel.spec.js.snap index 02780b1a301..0ac41b20333 100644 --- a/packages/vuetify/test/unit/components/VCarousel/__snapshots__/VCarousel.spec.js.snap +++ b/packages/vuetify/test/unit/components/VCarousel/__snapshots__/VCarousel.spec.js.snap @@ -10,6 +10,7 @@ exports[`VCarousel.ts should render component in RTL mode and match snapshot 1`]