diff --git a/package.json b/package.json index df2ba25274d..33e537c557a 100755 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "name": "@vuetify/vuetify-root", "private": true, "workspaces": [ "packages/*" diff --git a/packages/api-generator/src/locale/en/VField.json b/packages/api-generator/src/locale/en/VField.json index 82bc8788628..2ce083c09fc 100644 --- a/packages/api-generator/src/locale/en/VField.json +++ b/packages/api-generator/src/locale/en/VField.json @@ -2,7 +2,7 @@ "props": { "appendInnerIcon": "Creates a [v-icon](/api/v-icon/) component in the **append-inner** slot.", "baseColor": "Sets the color of the input when it is not focused.", - "centerAffix": "Automatically apply **[singleLine](/api/v-field/#props-single-line)** under the hood, and vertically align **appendInner**, **prependInner**, **clearIcon**, **label** and **input field** in the center.", + "centerAffix": "Vertically align **appendInner**, **prependInner**, **clearIcon** and **label** in the center.", "clearIcon": "The icon used when the **clearable** prop is set to true.", "dirty": "Manually apply the dirty state styling.", "disabled": "Removes the ability to click or target the input.", diff --git a/packages/api-generator/src/locale/en/VInput.json b/packages/api-generator/src/locale/en/VInput.json index d6f181d023a..47f3a7804c3 100644 --- a/packages/api-generator/src/locale/en/VInput.json +++ b/packages/api-generator/src/locale/en/VInput.json @@ -1,7 +1,7 @@ { "props": { "backgroundColor": "Changes the background-color of the input.", - "centerAffix": "Vertically align **append** and **prepend** in the center.", + "centerAffix": "Vertically align **appendInner**, **prependInner**, **clearIcon** and **label** in the center.", "direction": "Changes the direction of the input.", "hideDetails": "Hides hint and validation errors. When set to `auto` messages will be rendered only if there's a message (hint, error message, counter value etc) to display.", "hideSpinButtons": "Hides spin buttons on the input when type is set to `number`.", diff --git a/packages/api-generator/src/locale/en/VList.json b/packages/api-generator/src/locale/en/VList.json index f2db19cf83b..c45480c4d31 100644 --- a/packages/api-generator/src/locale/en/VList.json +++ b/packages/api-generator/src/locale/en/VList.json @@ -7,6 +7,8 @@ "link": "Applies `v-list-item` hover styles. Useful when using the item is an _activator_.", "nav": "An alternative styling that reduces `v-list-item` width and rounds the corners. Typically used with **[v-navigation-drawer](/components/navigation-drawers)**.", "subheader": "Removes the top padding from `v-list-subheader` components. When used as a **String**, renders a subheader for you.", - "slim": "Reduces horizontal spacing for badges, icons, tooltips, and avatars within slim list items to create a more compact visual representation." + "slim": "Reduces horizontal spacing for badges, icons, tooltips, and avatars within slim list items to create a more compact visual representation.", + "collapseIcon": "Icon to display when the list item is expanded.", + "expandIcon": "Icon to display when the list item is collapsed." } } diff --git a/packages/docs/src/components/app/Toc.vue b/packages/docs/src/components/app/Toc.vue index 22814196c7e..5daa54a2174 100644 --- a/packages/docs/src/components/app/Toc.vue +++ b/packages/docs/src/components/app/Toc.vue @@ -104,7 +104,7 @@ - + ## Usage diff --git a/packages/docs/src/pages/en/components/cards.md b/packages/docs/src/pages/en/components/cards.md index 148ebd52d76..ed260d8e50a 100644 --- a/packages/docs/src/pages/en/components/cards.md +++ b/packages/docs/src/pages/en/components/cards.md @@ -24,7 +24,7 @@ features: - + ## Usage diff --git a/packages/docs/src/pages/en/introduction/why-vuetify.md b/packages/docs/src/pages/en/introduction/why-vuetify.md index 048577a7981..5ac6e1cb89b 100644 --- a/packages/docs/src/pages/en/introduction/why-vuetify.md +++ b/packages/docs/src/pages/en/introduction/why-vuetify.md @@ -16,7 +16,7 @@ Learn more about what Vuetify is, how to create an application from scratch, bro - + ## What is Vuetify? diff --git a/packages/vuetify/src/components/VAppBar/VAppBar.tsx b/packages/vuetify/src/components/VAppBar/VAppBar.tsx index ec2b9b35708..87eb94ddb1e 100644 --- a/packages/vuetify/src/components/VAppBar/VAppBar.tsx +++ b/packages/vuetify/src/components/VAppBar/VAppBar.tsx @@ -20,7 +20,7 @@ import type { PropType } from 'vue' import type { VToolbarSlots } from '@/components/VToolbar/VToolbar' export const makeVAppBarProps = propsFactory({ - scrollBehavior: String as PropType<'hide' | 'inverted' | 'collapse' | 'elevate' | 'fade-image' | (string & {})>, + scrollBehavior: String as PropType<'hide' | 'fully-hide' | 'inverted' | 'collapse' | 'elevate' | 'fade-image' | (string & {})>, modelValue: { type: Boolean, default: true, diff --git a/packages/vuetify/src/components/VBtn/VBtn.sass b/packages/vuetify/src/components/VBtn/VBtn.sass index 8ed3b7b0f7f..3acf7c34624 100644 --- a/packages/vuetify/src/components/VBtn/VBtn.sass +++ b/packages/vuetify/src/components/VBtn/VBtn.sass @@ -168,6 +168,9 @@ .v-icon --v-icon-size-multiplier: #{calc(24/21)} + &.v-btn--block + min-width: 100% + .v-btn__loader align-items: center display: flex diff --git a/packages/vuetify/src/components/VDataTable/VDataTable.tsx b/packages/vuetify/src/components/VDataTable/VDataTable.tsx index 830538b1acb..7bc7b28a138 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTable.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTable.tsx @@ -21,7 +21,7 @@ import { provideDefaults } from '@/composables/defaults' import { makeFilterProps, useFilter } from '@/composables/filter' // Utilities -import { computed, toRef } from 'vue' +import { computed, toRef, toRefs } from 'vue' import { genericComponent, propsFactory, useRender } from '@/util' // Types @@ -130,6 +130,7 @@ export const VDataTable = genericComponent( const { groupBy } = createGroupBy(props) const { sortBy, multiSort, mustSort } = createSort(props) const { page, itemsPerPage } = createPagination(props) + const { disableSort } = toRefs(props) const { columns, @@ -152,10 +153,10 @@ export const VDataTable = genericComponent( }) const { toggleSort } = provideSort({ sortBy, multiSort, mustSort, page }) - const { sortByWithGroups, opened, extractRows, isGroupOpen, toggleGroup } = provideGroupBy({ groupBy, sortBy }) + const { sortByWithGroups, opened, extractRows, isGroupOpen, toggleGroup } = provideGroupBy({ groupBy, sortBy, disableSort }) const { sortedItems } = useSortedItems(props, filteredItems, sortByWithGroups, { - transform: item => item.columns, + transform: item => ({ ...item.raw, ...item.columns }), sortFunctions, sortRawFunctions, }) diff --git a/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx b/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx index f3e9c5293aa..13005194dc3 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx @@ -18,7 +18,7 @@ import { createSort, provideSort } from './composables/sort' import { provideDefaults } from '@/composables/defaults' // Utilities -import { computed, provide, toRef } from 'vue' +import { computed, provide, toRef, toRefs } from 'vue' import { genericComponent, propsFactory, useRender } from '@/util' // Types @@ -69,6 +69,7 @@ export const VDataTableServer = genericComponent parseInt(props.itemsLength, 10)) const { columns, headers } = createHeaders(props, { @@ -81,7 +82,7 @@ export const VDataTableServer = genericComponent item.columns, + transform: item => ({ ...item.raw, ...item.columns }), sortFunctions, sortRawFunctions, }) diff --git a/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.cy.tsx b/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.cy.tsx index 0cc1a79df2c..cde77da1731 100644 --- a/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.cy.tsx +++ b/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.cy.tsx @@ -14,6 +14,7 @@ const DESSERT_HEADERS = [ { title: 'Carbs (g)', key: 'carbs' }, { title: 'Protein (g)', key: 'protein' }, { title: 'Iron (%)', key: 'iron' }, + { title: 'Group', key: 'group' }, ] const DESSERT_ITEMS = [ @@ -24,6 +25,7 @@ const DESSERT_ITEMS = [ carbs: 24, protein: 4.0, iron: '1%', + group: 1, }, { name: 'Ice cream sandwich', @@ -32,6 +34,7 @@ const DESSERT_ITEMS = [ carbs: 37, protein: 4.3, iron: '1%', + group: 3, }, { name: 'Eclair', @@ -40,6 +43,7 @@ const DESSERT_ITEMS = [ carbs: 23, protein: 6.0, iron: '7%', + group: 2, }, { name: 'Cupcake', @@ -48,6 +52,7 @@ const DESSERT_ITEMS = [ carbs: 67, protein: 4.3, iron: '8%', + group: 2, }, { name: 'Gingerbread', @@ -56,6 +61,7 @@ const DESSERT_ITEMS = [ carbs: 49, protein: 3.9, iron: '16%', + group: 3, }, { name: 'Jelly bean', @@ -64,6 +70,7 @@ const DESSERT_ITEMS = [ carbs: 94, protein: 0.0, iron: '0%', + group: 1, }, { name: 'Lollipop', @@ -72,6 +79,7 @@ const DESSERT_ITEMS = [ carbs: 98, protein: 0, iron: '2%', + group: 2, }, { name: 'Honeycomb', @@ -80,6 +88,7 @@ const DESSERT_ITEMS = [ carbs: 87, protein: 6.5, iron: '45%', + group: 3, }, { name: 'Donut', @@ -88,6 +97,7 @@ const DESSERT_ITEMS = [ carbs: 51, protein: 4.9, iron: '22%', + group: 3, }, { name: 'KitKat', @@ -96,6 +106,7 @@ const DESSERT_ITEMS = [ carbs: 65, protein: 7, iron: '6%', + group: 1, }, ] @@ -356,4 +367,92 @@ describe('VDataTable', () => { cy.get('.v-data-table').find('h3').should('exist') }) }) + + describe('sort', () => { + it('should sort by sortBy', () => { + cy.mount(() => ( + + + + )) + cy.get('thead .v-data-table__td').eq(2).should('have.class', 'v-data-table__th--sorted') + .get('tbody td:nth-child(3)').then(rows => { + const actualFat = Array.from(rows).map(row => { + return Number(row.textContent) + }) + const expectedFat = DESSERT_ITEMS.map(d => d.fat).sort((a, b) => a - b) + expect(actualFat).to.deep.equal(expectedFat) + }) + cy.get('thead .v-data-table__td').eq(2).click() + .get('thead .v-data-table__td').eq(2).should('have.class', 'v-data-table__th--sorted') + .get('tbody td:nth-child(3)').then(rows => { + const actualFat = Array.from(rows).map(row => { + return Number(row.textContent) + }) + const expectedFat = DESSERT_ITEMS.map(d => d.fat).sort((a, b) => b - a) + expect(actualFat).to.deep.equal(expectedFat) + }) + }) + + it('should sort by groupBy and sortBy', () => { + cy.mount(() => ( + + + + )).get('tr.v-data-table-group-header-row .v-data-table__td button + span').then(rows => { + const actualGroup = Array.from(rows).map(row => { + return Number(row.textContent) + }) + const expectedGroup = [...new Set(DESSERT_ITEMS.map(d => d.group))].sort((a, b) => b - a) + expect(actualGroup).to.deep.equal(expectedGroup) + }).get('.v-data-table-group-header-row button').eq(0).click() + .get('.v-data-table__tr td:nth-child(3)').then(rows => { + const actualCalories = Array.from(rows).map(row => { + return Number(row.textContent) + }) + const expectedCalories = DESSERT_ITEMS.filter(d => d.group === 3).map(d => d.calories).sort((a, b) => b - a) + expect(actualCalories).to.deep.equal(expectedCalories) + }) + }) + + // https://github.com/vuetifyjs/vuetify/issues/20046 + it('should sort by groupBy while sort is disabled', () => { + cy.mount(() => ( + + + + )).get('tr.v-data-table-group-header-row .v-data-table__td button + span').then(rows => { + const actualGroup = Array.from(rows).map(row => { + return Number(row.textContent) + }) + const expectedGroup = [...new Set(DESSERT_ITEMS.map(d => d.group))].sort((a, b) => b - a) + expect(actualGroup).to.deep.equal(expectedGroup) + }).get('.v-data-table-group-header-row button').eq(0).click() + .get('.v-data-table__tr td:nth-child(3)').then(rows => { + const actualCalories = Array.from(rows).map(row => { + return Number(row.textContent) + }) + const expectedCalories = DESSERT_ITEMS.filter(d => d.group === 3).map(d => d.calories) + expect(actualCalories).to.deep.equal(expectedCalories) + }) + }) + }) }) diff --git a/packages/vuetify/src/components/VDataTable/composables/group.ts b/packages/vuetify/src/components/VDataTable/composables/group.ts index b66d3b3c14e..7f4ac2be468 100644 --- a/packages/vuetify/src/components/VDataTable/composables/group.ts +++ b/packages/vuetify/src/components/VDataTable/composables/group.ts @@ -51,15 +51,19 @@ export function createGroupBy (props: GroupProps) { return { groupBy } } -export function provideGroupBy (options: { groupBy: Ref, sortBy: Ref }) { - const { groupBy, sortBy } = options +export function provideGroupBy (options: { + groupBy: Ref + sortBy: Ref + disableSort?: Ref +}) { + const { disableSort, groupBy, sortBy } = options const opened = ref(new Set()) const sortByWithGroups = computed(() => { return groupBy.value.map(val => ({ ...val, order: val.order ?? false, - })).concat(sortBy.value) + })).concat(disableSort?.value ? [] : sortBy.value) }) function isGroupOpen (group: Group) { diff --git a/packages/vuetify/src/components/VDataTable/composables/sort.ts b/packages/vuetify/src/components/VDataTable/composables/sort.ts index 0c9beba1c2f..03581dac81f 100644 --- a/packages/vuetify/src/components/VDataTable/composables/sort.ts +++ b/packages/vuetify/src/components/VDataTable/composables/sort.ts @@ -4,7 +4,7 @@ import { useProxiedModel } from '@/composables/proxiedModel' // Utilities import { computed, inject, provide, toRef } from 'vue' -import { isEmpty, propsFactory } from '@/util' +import { getObjectValueByPath, isEmpty, propsFactory } from '@/util' // Types import type { InjectionKey, PropType, Ref } from 'vue' @@ -98,7 +98,6 @@ export function useSort () { export function useSortedItems ( props: { customKeySort: Record | undefined - disableSort?: Boolean }, items: Ref, sortBy: Ref, @@ -110,7 +109,7 @@ export function useSortedItems ( ) { const locale = useLocale() const sortedItems = computed(() => { - if (!sortBy.value.length || props.disableSort) return items.value + if (!sortBy.value.length) return items.value return sortItems(items.value, sortBy.value, locale.current.value, { transform: options?.transform, @@ -149,8 +148,8 @@ export function sortItems ( if (sortOrder === false) continue - let sortA = a[1][sortKey] - let sortB = b[1][sortKey] + let sortA = getObjectValueByPath(a[1], sortKey) + let sortB = getObjectValueByPath(b[1], sortKey) let sortARaw = a[0].raw let sortBRaw = b[0].raw diff --git a/packages/vuetify/src/components/VDatePicker/VDatePickerMonth.tsx b/packages/vuetify/src/components/VDatePicker/VDatePickerMonth.tsx index 384f9b762bc..c23b3b8cfac 100644 --- a/packages/vuetify/src/components/VDatePicker/VDatePickerMonth.tsx +++ b/packages/vuetify/src/components/VDatePicker/VDatePickerMonth.tsx @@ -93,6 +93,9 @@ export const VDatePickerMonth = genericComponent()({ if (model.value.length === 0) { rangeStart.value = undefined + } else if (model.value.length === 1) { + rangeStart.value = model.value[0] + rangeStop.value = undefined } if (!rangeStart.value) { rangeStart.value = _value diff --git a/packages/vuetify/src/components/VField/VField.sass b/packages/vuetify/src/components/VField/VField.sass index 6a698fabcf4..051542e5bdb 100644 --- a/packages/vuetify/src/components/VField/VField.sass +++ b/packages/vuetify/src/components/VField/VField.sass @@ -141,10 +141,6 @@ $root: & - @at-root #{selector.nest('.v-field.v-field--center-affix.v-field--variant-underlined, .v-field.v-field--center-affix.v-field--variant-plain', &)} - padding-top: unset - padding-bottom: unset - @at-root @include tools.density('v-input', $input-density) using ($modifier) @at-root #{selector.nest(&, $root)} @@ -199,8 +195,8 @@ align-items: center padding-top: 0 - .v-field:not(.v-field--center-affix).v-field--variant-underlined, - .v-field:not(.v-field--center-affix).v-field--variant-plain + .v-field.v-field--variant-underlined, + .v-field.v-field--variant-plain .v-field__append-inner, .v-field__clearable, .v-field__prepend-inner diff --git a/packages/vuetify/src/components/VField/VField.tsx b/packages/vuetify/src/components/VField/VField.tsx index 037cf02a23a..b3d658c127a 100644 --- a/packages/vuetify/src/components/VField/VField.tsx +++ b/packages/vuetify/src/components/VField/VField.tsx @@ -62,7 +62,10 @@ export const makeVFieldProps = propsFactory({ default: '$clear', }, active: Boolean, - centerAffix: Boolean, + centerAffix: { + type: Boolean, + default: undefined, + }, color: String, baseColor: String, dirty: Boolean, @@ -133,9 +136,8 @@ export const VField = genericComponent( const { roundedClasses } = useRounded(props) const { rtlClasses } = useRtl() - const isSingleLine = computed(() => props.singleLine || props.centerAffix) const isActive = computed(() => props.dirty || props.active) - const hasLabel = computed(() => !isSingleLine.value && !!(props.label || slots.label)) + const hasLabel = computed(() => !props.singleLine && !!(props.label || slots.label)) const uid = getUid() const id = computed(() => props.id || `input-${uid}`) @@ -240,7 +242,7 @@ export const VField = genericComponent( { 'v-field--active': isActive.value, 'v-field--appended': hasAppend, - 'v-field--center-affix': props.centerAffix, + 'v-field--center-affix': props.centerAffix ?? !isPlainOrUnderlined.value, 'v-field--disabled': props.disabled, 'v-field--dirty': props.dirty, 'v-field--error': props.error, @@ -249,7 +251,7 @@ export const VField = genericComponent( 'v-field--persistent-clear': props.persistentClear, 'v-field--prepended': hasPrepend, 'v-field--reverse': props.reverse, - 'v-field--single-line': isSingleLine.value, + 'v-field--single-line': props.singleLine, 'v-field--no-label': !label(), [`v-field--variant-${props.variant}`]: true, }, diff --git a/packages/vuetify/src/components/VInput/VInput.sass b/packages/vuetify/src/components/VInput/VInput.sass index 2441ec1dde6..11ded05238b 100644 --- a/packages/vuetify/src/components/VInput/VInput.sass +++ b/packages/vuetify/src/components/VInput/VInput.sass @@ -103,7 +103,7 @@ input[type=number] -moz-appearance: textfield - &--plain-underlined:not(&--center-affix) + &--plain-underlined .v-input__prepend, .v-input__append diff --git a/packages/vuetify/src/components/VInput/VInput.tsx b/packages/vuetify/src/components/VInput/VInput.tsx index f12b059b9d7..4234aeb0aad 100644 --- a/packages/vuetify/src/components/VInput/VInput.tsx +++ b/packages/vuetify/src/components/VInput/VInput.tsx @@ -40,7 +40,10 @@ export interface VInputSlot { export const makeVInputProps = propsFactory({ id: String, appendIcon: IconValue, - centerAffix: Boolean, + centerAffix: { + type: Boolean, + default: true, + }, prependIcon: IconValue, hideDetails: [Boolean, String] as PropType, hideSpinButtons: Boolean, diff --git a/packages/vuetify/src/components/VOtpInput/VOtpInput.tsx b/packages/vuetify/src/components/VOtpInput/VOtpInput.tsx index f1b59a088df..fac9e739a33 100644 --- a/packages/vuetify/src/components/VOtpInput/VOtpInput.tsx +++ b/packages/vuetify/src/components/VOtpInput/VOtpInput.tsx @@ -166,7 +166,7 @@ export const VOtpInput = genericComponent()({ e.preventDefault() e.stopPropagation() - const clipboardText = e?.clipboardData?.getData('Text') ?? '' + const clipboardText = e?.clipboardData?.getData('Text').slice(0, length.value) ?? '' if (isValidNumber(clipboardText)) return diff --git a/packages/vuetify/src/components/VTextField/VTextField.tsx b/packages/vuetify/src/components/VTextField/VTextField.tsx index 3e835143866..c2f09caf664 100644 --- a/packages/vuetify/src/components/VTextField/VTextField.tsx +++ b/packages/vuetify/src/components/VTextField/VTextField.tsx @@ -176,6 +176,7 @@ export const VTextField = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } + centerAffix={ !isPlainOrUnderlined.value } focused={ isFocused.value } > {{ @@ -201,7 +202,6 @@ export const VTextField = genericComponent()({ dirty={ isDirty.value || props.dirty } disabled={ isDisabled.value } focused={ isFocused.value } - centerAffix={ props.centerAffix } error={ isValid.value === false } > {{ diff --git a/packages/vuetify/src/components/VTextarea/VTextarea.tsx b/packages/vuetify/src/components/VTextarea/VTextarea.tsx index e675b3c0c1f..3d8a93007a1 100644 --- a/packages/vuetify/src/components/VTextarea/VTextarea.tsx +++ b/packages/vuetify/src/components/VTextarea/VTextarea.tsx @@ -18,7 +18,7 @@ import Intersect from '@/directives/intersect' // Utilities import { computed, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch, watchEffect } from 'vue' -import { callEvent, clamp, convertToUnit, filterInputAttrs, genericComponent, omit, propsFactory, useRender } from '@/util' +import { callEvent, clamp, convertToUnit, filterInputAttrs, genericComponent, propsFactory, useRender } from '@/util' // Types import type { PropType } from 'vue' @@ -48,8 +48,8 @@ export const makeVTextareaProps = propsFactory({ suffix: String, modelModifiers: Object as PropType>, - ...omit(makeVInputProps(), ['centerAffix']), - ...omit(makeVFieldProps(), ['centerAffix']), + ...makeVInputProps(), + ...makeVFieldProps(), }, 'VTextarea') type VTextareaSlots = Omit & { @@ -228,7 +228,7 @@ export const VTextarea = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } - centerAffix={ false } + centerAffix={ rows.value === 1 && !isPlainOrUnderlined.value } focused={ isFocused.value } > {{ @@ -253,7 +253,7 @@ export const VTextarea = genericComponent()({ { ...fieldProps } id={ id.value } active={ isActive.value || isDirty.value } - centerAffix={ false } + centerAffix={ rows.value === 1 && !isPlainOrUnderlined.value } dirty={ isDirty.value || props.dirty } disabled={ isDisabled.value } focused={ isFocused.value } diff --git a/packages/vuetify/src/labs/VDateInput/VDateInput.tsx b/packages/vuetify/src/labs/VDateInput/VDateInput.tsx index 5c30ea1b58a..e451bfc76e9 100644 --- a/packages/vuetify/src/labs/VDateInput/VDateInput.tsx +++ b/packages/vuetify/src/labs/VDateInput/VDateInput.tsx @@ -71,6 +71,8 @@ export const VDateInput = genericComponent()({ return adapter.isValid(model.value) ? adapter.format(model.value, 'keyboardDate') : '' }) + const isInteractive = computed(() => !props.disabled && !props.readonly) + function onKeydown (e: KeyboardEvent) { if (e.key !== 'Enter') return @@ -104,13 +106,15 @@ export const VDateInput = genericComponent()({ return ( = { new (): ComponentPublicInstance } | FunctionalComponent + export interface GlobalComponents extends _GlobalComponents {} } declare module '@vue/runtime-dom' { @@ -28,6 +31,7 @@ declare module '@vue/runtime-dom' { export interface SVGAttributes { $children?: VNodeChild } + export interface GlobalComponents extends _GlobalComponents {} } declare module '@vue/runtime-core' { @@ -43,8 +47,5 @@ declare module '@vue/runtime-core' { export interface ComponentCustomProperties { $vuetify: Vuetify } - - export interface GlobalComponents { - // @generate-components - } + export interface GlobalComponents extends _GlobalComponents {} }