Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types): add generics to components #14230

Merged
merged 7 commits into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ module.exports = {
allowTemplateLiterals: true,
}],

indent: 'off',
'@typescript-eslint/indent': ['error', 2, {
...require('eslint-config-standard').rules.indent[2],
ignoredNodes: [...require('eslint-config-standard').rules.indent[2].ignoredNodes, 'TSTypeParameterInstantiation'],
flatTernaryExpressions: true,
offsetTernaryExpressions: false,
}],

'func-call-spacing': 'off',
'@typescript-eslint/func-call-spacing': require('eslint-config-standard').rules['func-call-spacing'],

// Handled by tsc
'no-redeclare': 'off',

Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
"@babel/preset-typescript": "^7.15.0",
"@mdi/js": "^5.9.55",
"@octokit/core": "^3.5.1",
"@typescript-eslint/eslint-plugin": "^4.30.0",
"@typescript-eslint/parser": "^4.30.0",
"@vue/compiler-sfc": "^3.2.8",
"@typescript-eslint/eslint-plugin": "^4.32.0",
"@typescript-eslint/parser": "^4.32.0",
"@vue/compiler-sfc": "^3.2.19",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"conventional-changelog-cli": "^2.1.1",
Expand Down Expand Up @@ -65,7 +65,7 @@
"semver": "^6.2.0",
"shelljs": "^0.8.4",
"typescript": "^4.4.2",
"vue": "^3.2.8",
"vue": "^3.2.19",
"vue-analytics": "^5.16.1",
"vue-meta": "^2.4.0",
"vue-router": "^3.5.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/api-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"dependencies": {
"deepmerge": "^4.0.0",
"rimraf": "^3.0.2",
"vue": "^3.2.8",
"vue": "^3.2.19",
"vuetify": "^3.0.0-alpha.11"
},
"devDependencies": {
Expand Down
8 changes: 4 additions & 4 deletions packages/vuetify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@
"@types/jest": "^26.0.24",
"@types/node": "^14.17.14",
"@types/resize-observer-browser": "^0.1.6",
"@vitejs/plugin-vue": "^1.6.0",
"@vitejs/plugin-vue-jsx": "^1.1.7",
"@vue/babel-plugin-jsx": "^1.0.7",
"@vitejs/plugin-vue": "^1.9.2",
"@vitejs/plugin-vue-jsx": "^1.2.0",
"@vue/babel-plugin-jsx": "^1.1.0",
"@vue/test-utils": "2.0.0-rc.9",
"@vueuse/head": "^0.6.0",
"acorn-walk": "^8.1.1",
Expand Down Expand Up @@ -147,7 +147,7 @@
"vue-router": "^4.0.11"
},
"peerDependencies": {
"vue": "^3.2.8"
"vue": "^3.2.19"
},
"publishConfig": {
"access": "public"
Expand Down
9 changes: 7 additions & 2 deletions packages/vuetify/src/components/VDialog/VDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import { useProxiedModel } from '@/composables/proxiedModel'

// Utilities
import { nextTick, ref, watch } from 'vue'
import { defineComponent, IN_BROWSER } from '@/util'
import { genericComponent, IN_BROWSER } from '@/util'

export const VDialog = defineComponent({
// Types
import type { OverlaySlots } from '@/components/VOverlay/VOverlay'

export const VDialog = genericComponent<new () => {
$slots: OverlaySlots
}>()({
name: 'VDialog',

inheritAttrs: false,
Expand Down
32 changes: 23 additions & 9 deletions packages/vuetify/src/components/VField/VField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useProxiedModel } from '@/composables/proxiedModel'
import { computed, ref, toRef, watch, watchEffect } from 'vue'
import {
convertToUnit,
defineComponent,
genericComponent,
getUid,
nullifyTransforms,
propsFactory,
Expand All @@ -28,6 +28,7 @@ import {

// Types
import type { PropType, Ref } from 'vue'
import type { MakeSlots } from '@/util'

const allowedVariants = ['underlined', 'outlined', 'filled', 'contained', 'plain'] as const
type Variant = typeof allowedVariants[number]
Expand All @@ -45,12 +46,7 @@ export interface DefaultInputSlot {
}

export interface VFieldSlot extends DefaultInputSlot {
props: {
id: string
class: string
onFocus: () => void
onBlur: () => void
}
props: Record<string, unknown>
}

export const makeVFieldProps = propsFactory({
Expand Down Expand Up @@ -79,7 +75,26 @@ export const makeVFieldProps = propsFactory({
...makeValidationProps(),
}, 'v-field')

export const VField = defineComponent({
export const VField = genericComponent<new <T>() => {
$props: {
modelValue?: T
'onUpdate:modelValue'?: (val: T) => any
}
$slots: MakeSlots<{
prependInner: [DefaultInputSlot]
clear: []
appendInner: [DefaultInputSlot]
label: [DefaultInputSlot]
prepend: [DefaultInputSlot]
append: [DefaultInputSlot]
details: [DefaultInputSlot]
loader: [{
color: string | undefined
isActive: boolean
}]
default: [VFieldSlot]
}>
}>()({
name: 'VField',

inheritAttrs: false,
Expand Down Expand Up @@ -347,5 +362,4 @@ export const VField = defineComponent({
},
})

// eslint-disable-next-line @typescript-eslint/no-redeclare
export type VField = InstanceType<typeof VField>
9 changes: 4 additions & 5 deletions packages/vuetify/src/components/VFileInput/VFileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { defineComponent, humanReadableFileSize, pick, useRender, wrapInArray }

// Types
import type { PropType } from 'vue'
import type { VFieldSlot } from '@/components/VField/VField'

export const VFileInput = defineComponent({
name: 'VFileInput',
Expand Down Expand Up @@ -105,7 +104,7 @@ export const VFileInput = defineComponent({
}

useRender(() => {
const hasCounter = (slots.counter || props.counter || counterValue.value)
const hasCounter = !!(slots.counter || props.counter || counterValue.value)
const [_, restAttrs] = pick(attrs, ['class'])

return (
Expand Down Expand Up @@ -137,7 +136,7 @@ export const VFileInput = defineComponent({
isActive,
inputRef,
props: { class: fieldClass, ...slotProps },
}: VFieldSlot) => (
}) => (
<>
<input
ref={ inputRef }
Expand Down Expand Up @@ -177,7 +176,7 @@ export const VFileInput = defineComponent({
</>
),

details: hasCounter ? () => (
details: hasCounter && (() => (
<>
<span />

Expand All @@ -186,7 +185,7 @@ export const VFileInput = defineComponent({
v-slots={ slots.counter }
/>
</>
) : undefined,
)),
}}
/>
)
Expand Down
9 changes: 7 additions & 2 deletions packages/vuetify/src/components/VMenu/VMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ import { makeTransitionProps } from '@/composables/transition'
import { useProxiedModel } from '@/composables/proxiedModel'

// Utilities
import { defineComponent, getUid } from '@/util'
import { computed } from 'vue'
import { genericComponent, getUid } from '@/util'

export const VMenu = defineComponent({
// Types
import type { OverlaySlots } from '@/components/VOverlay/VOverlay'

export const VMenu = genericComponent<new () => {
$slots: OverlaySlots
}>()({
name: 'VMenu',

inheritAttrs: false,
Expand Down
16 changes: 12 additions & 4 deletions packages/vuetify/src/components/VOverlay/VOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import { useRtl } from '@/composables/rtl'
import { useTeleport } from '@/composables/teleport'
import { makeDimensionProps, useDimension } from '@/composables/dimensions'
import { makeLazyProps, useLazy } from '@/composables/lazy'
import { useStack } from '@/composables/stack'

// Directives
import { ClickOutside } from '@/directives/click-outside'

// Utilities
import {
convertToUnit,
defineComponent,
genericComponent,
getScrollParent,
standardEasing,
useRender,
Expand All @@ -38,9 +39,9 @@ import {
} from 'vue'

// Types
import type { PropType } from 'vue'
import type { PropType, Ref } from 'vue'
import type { MakeSlots } from '@/util'
import type { BackgroundColorData } from '@/composables/color'
import { useStack } from '@/composables/stack'

interface ScrimProps {
[key: string]: unknown
Expand All @@ -65,7 +66,14 @@ function Scrim (props: ScrimProps) {
)
}

export const VOverlay = defineComponent({
export type OverlaySlots = MakeSlots<{
default: [{ isActive: Ref<boolean> }]
activator: [{ isActive: boolean, props: Dictionary<any> }]
}>

export const VOverlay = genericComponent<new () => {
$slots: OverlaySlots
}>()({
name: 'VOverlay',

directives: { ClickOutside },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ import { defineComponent } from '@/util'
export const VPaginationBtn = defineComponent({
...VBtn,
name: 'VPaginationBtn',
})
}) as typeof VBtn
7 changes: 3 additions & 4 deletions packages/vuetify/src/components/VTextField/VTextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { defineComponent, pick, useRender } from '@/util'

// Types
import type { PropType } from 'vue'
import type { VFieldSlot } from '@/components/VField/VField'

const dirtyTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month']

Expand Down Expand Up @@ -89,7 +88,7 @@ export const VTextField = defineComponent({
}

useRender(() => {
const hasCounter = (slots.counter || props.counter || props.counterValue)
const hasCounter = !!(slots.counter || props.counter || props.counterValue)
const [_, restAttrs] = pick(attrs, ['class'])

return (
Expand Down Expand Up @@ -122,7 +121,7 @@ export const VTextField = defineComponent({
isReadonly,
inputRef,
props: { class: fieldClass, ...slotProps },
}: VFieldSlot) => {
}) => {
const showPlaceholder = isActive || props.persistentPlaceholder
return (
<>
Expand Down Expand Up @@ -158,7 +157,7 @@ export const VTextField = defineComponent({
</>
)
},
details: hasCounter && (({ isFocused }: VFieldSlot) => (
details: hasCounter && (({ isFocused }) => (
<>
<span />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { makeRoundedProps, useRounded } from '@/composables/rounded'
// Utilities
import { defineComponent, inject, toRef } from 'vue'

export default defineComponent({
export const VTimelineDivider = defineComponent({
name: 'VTimelineDivider',

props: {
Expand Down Expand Up @@ -84,3 +84,5 @@ export default defineComponent({
)
},
})

export type VTimelineDivider = InstanceType<typeof VTimelineDivider>
7 changes: 2 additions & 5 deletions packages/vuetify/src/components/VTimeline/VTimelineItem.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Types
import type { ComponentPublicInstance } from 'vue'

// Components
import { VTimelineSymbol } from './shared'
import VTimelineDivider from './VTimelineDivider'
import { VTimelineDivider } from './VTimelineDivider'

// Composables
import { makeTagProps } from '@/composables/tag'
Expand Down Expand Up @@ -45,7 +42,7 @@ export const VTimelineItem = defineComponent({
const { dimensionStyles } = useDimension(props)

const dotSize = ref(0)
const dotRef = ref<ComponentPublicInstance>()
const dotRef = ref<VTimelineDivider>()
watch(dotRef, newValue => {
if (!newValue) return
dotSize.value = newValue.$el.querySelector('.v-timeline-divider__dot')?.getBoundingClientRect().width ?? 0
Expand Down
7 changes: 5 additions & 2 deletions packages/vuetify/src/components/VTooltip/VTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import { makeTransitionProps } from '@/composables/transition'

// Utilities
import { computed } from 'vue'
import { defineComponent, getUid } from '@/util'
import { genericComponent, getUid } from '@/util'

// Types
import type { PropType } from 'vue'
import type { OverlaySlots } from '@/components/VOverlay/VOverlay'
import type { StrategyProps } from '@/components/VOverlay/positionStrategies'

export const VTooltip = defineComponent({
export const VTooltip = genericComponent<new () => {
$slots: OverlaySlots
}>()({
name: 'VTooltip',

inheritAttrs: false,
Expand Down
2 changes: 1 addition & 1 deletion packages/vuetify/src/composables/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export interface GroupItemProvide {

export const makeGroupProps = propsFactory({
modelValue: {
type: [Number, Boolean, String, Array, Object],
type: null,
default: undefined,
},
multiple: Boolean,
Expand Down
Loading