mirror of https://github.com/vuejs/core.git
Merge remote-tracking branch 'upstream/minor'
This commit is contained in:
commit
fb58e65d3d
23
CHANGELOG.md
23
CHANGELOG.md
|
@ -1,3 +1,26 @@
|
||||||
|
# [3.5.0-alpha.1](https://github.com/vuejs/core/compare/v3.4.25...v3.5.0-alpha.1) (2024-04-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **reactivity:** fix call sequence of ontrigger in effect ([#10501](https://github.com/vuejs/core/issues/10501)) ([28841fe](https://github.com/vuejs/core/commit/28841fee43a45c37905c2c1ed9ace23067539045))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **compiler-sfc:** enable reactive props destructure by default ([d2dac0e](https://github.com/vuejs/core/commit/d2dac0e359c47d1ed0aa77eda488e76fd6466d2d))
|
||||||
|
* **reactivity:** `onEffectCleanup` API ([2cc5615](https://github.com/vuejs/core/commit/2cc5615590de77126e8df46136de0240dbde5004)), closes [#10173](https://github.com/vuejs/core/issues/10173)
|
||||||
|
* **reactivity:** add failSilently argument for onScopeDispose ([9a936aa](https://github.com/vuejs/core/commit/9a936aaec489c79433a32791ecf5ddb1739a62bd))
|
||||||
|
* **transition:** support directly nesting Teleport inside Transition ([#6548](https://github.com/vuejs/core/issues/6548)) ([0e6e3c7](https://github.com/vuejs/core/commit/0e6e3c7eb0e5320b7c1818e025cb4a490fede9c0)), closes [#5836](https://github.com/vuejs/core/issues/5836)
|
||||||
|
* **types:** provide internal options for directly using user types in language tools ([#10801](https://github.com/vuejs/core/issues/10801)) ([75c8cf6](https://github.com/vuejs/core/commit/75c8cf63a1ef30ac84f91282d66ad3f57c6612e9))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **reactivity:** optimize array tracking ([#9511](https://github.com/vuejs/core/issues/9511)) ([70196a4](https://github.com/vuejs/core/commit/70196a40cc078f50fcc1110c38c06fbcc70b205e)), closes [#4318](https://github.com/vuejs/core/issues/4318)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [3.4.25](https://github.com/vuejs/core/compare/v3.4.24...v3.4.25) (2024-04-24)
|
## [3.4.25](https://github.com/vuejs/core/compare/v3.4.24...v3.4.25) (2024-04-24)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-core",
|
"name": "@vue/compiler-core",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/compiler-core",
|
"description": "@vue/compiler-core",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/compiler-core.esm-bundler.js",
|
"module": "dist/compiler-core.esm-bundler.js",
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { type CompilerError, compile } from '../../src'
|
||||||
|
|
||||||
|
describe('validate html nesting', () => {
|
||||||
|
it('should warn with p > div', () => {
|
||||||
|
let err: CompilerError | undefined
|
||||||
|
compile(`<p><div></div></p>`, {
|
||||||
|
onWarn: e => (err = e),
|
||||||
|
})
|
||||||
|
expect(err).toBeDefined()
|
||||||
|
expect(err!.message).toMatch(`<div> cannot be child of <p>`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not warn with select > hr', () => {
|
||||||
|
let err: CompilerError | undefined
|
||||||
|
compile(`<select><hr></select>`, {
|
||||||
|
onWarn: e => (err = e),
|
||||||
|
})
|
||||||
|
expect(err).toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-dom",
|
"name": "@vue/compiler-dom",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/compiler-dom",
|
"description": "@vue/compiler-dom",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/compiler-dom.esm-bundler.js",
|
"module": "dist/compiler-dom.esm-bundler.js",
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
/**
|
||||||
|
* Copied from https://github.com/MananTank/validate-html-nesting
|
||||||
|
* with ISC license
|
||||||
|
*
|
||||||
|
* To avoid runtime dependency on validate-html-nesting
|
||||||
|
* This file should not change very often in the original repo
|
||||||
|
* but we may need to keep it up-to-date from time to time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns true if given parent-child nesting is valid HTML
|
||||||
|
*/
|
||||||
|
export function isValidHTMLNesting(parent: string, child: string): boolean {
|
||||||
|
// if we know the list of children that are the only valid children for the given parent
|
||||||
|
if (parent in onlyValidChildren) {
|
||||||
|
return onlyValidChildren[parent].has(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we know the list of parents that are the only valid parents for the given child
|
||||||
|
if (child in onlyValidParents) {
|
||||||
|
return onlyValidParents[child].has(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we know the list of children that are NOT valid for the given parent
|
||||||
|
if (parent in knownInvalidChildren) {
|
||||||
|
// check if the child is in the list of invalid children
|
||||||
|
// if so, return false
|
||||||
|
if (knownInvalidChildren[parent].has(child)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we know the list of parents that are NOT valid for the given child
|
||||||
|
if (child in knownInvalidParents) {
|
||||||
|
// check if the parent is in the list of invalid parents
|
||||||
|
// if so, return false
|
||||||
|
if (knownInvalidParents[child].has(parent)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const headings = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])
|
||||||
|
const emptySet = new Set([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* maps element to set of elements that can be it's children, no other */
|
||||||
|
const onlyValidChildren: Record<string, Set<string>> = {
|
||||||
|
head: new Set([
|
||||||
|
'base',
|
||||||
|
'basefront',
|
||||||
|
'bgsound',
|
||||||
|
'link',
|
||||||
|
'meta',
|
||||||
|
'title',
|
||||||
|
'noscript',
|
||||||
|
'noframes',
|
||||||
|
'style',
|
||||||
|
'script',
|
||||||
|
'template',
|
||||||
|
]),
|
||||||
|
optgroup: new Set(['option']),
|
||||||
|
select: new Set(['optgroup', 'option', 'hr']),
|
||||||
|
// table
|
||||||
|
table: new Set(['caption', 'colgroup', 'tbody', 'tfoot', 'thead']),
|
||||||
|
tr: new Set(['td', 'th']),
|
||||||
|
colgroup: new Set(['col']),
|
||||||
|
tbody: new Set(['tr']),
|
||||||
|
thead: new Set(['tr']),
|
||||||
|
tfoot: new Set(['tr']),
|
||||||
|
// these elements can not have any children elements
|
||||||
|
script: emptySet,
|
||||||
|
iframe: emptySet,
|
||||||
|
option: emptySet,
|
||||||
|
textarea: emptySet,
|
||||||
|
style: emptySet,
|
||||||
|
title: emptySet,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** maps elements to set of elements which can be it's parent, no other */
|
||||||
|
const onlyValidParents: Record<string, Set<string>> = {
|
||||||
|
// sections
|
||||||
|
html: emptySet,
|
||||||
|
body: new Set(['html']),
|
||||||
|
head: new Set(['html']),
|
||||||
|
// table
|
||||||
|
td: new Set(['tr']),
|
||||||
|
colgroup: new Set(['table']),
|
||||||
|
caption: new Set(['table']),
|
||||||
|
tbody: new Set(['table']),
|
||||||
|
tfoot: new Set(['table']),
|
||||||
|
col: new Set(['colgroup']),
|
||||||
|
th: new Set(['tr']),
|
||||||
|
thead: new Set(['table']),
|
||||||
|
tr: new Set(['tbody', 'thead', 'tfoot']),
|
||||||
|
// data list
|
||||||
|
dd: new Set(['dl', 'div']),
|
||||||
|
dt: new Set(['dl', 'div']),
|
||||||
|
// other
|
||||||
|
figcaption: new Set(['figure']),
|
||||||
|
// li: new Set(["ul", "ol"]),
|
||||||
|
summary: new Set(['details']),
|
||||||
|
area: new Set(['map']),
|
||||||
|
} as const
|
||||||
|
|
||||||
|
/** maps element to set of elements that can not be it's children, others can */
|
||||||
|
const knownInvalidChildren: Record<string, Set<string>> = {
|
||||||
|
p: new Set([
|
||||||
|
'address',
|
||||||
|
'article',
|
||||||
|
'aside',
|
||||||
|
'blockquote',
|
||||||
|
'center',
|
||||||
|
'details',
|
||||||
|
'dialog',
|
||||||
|
'dir',
|
||||||
|
'div',
|
||||||
|
'dl',
|
||||||
|
'fieldset',
|
||||||
|
'figure',
|
||||||
|
'footer',
|
||||||
|
'form',
|
||||||
|
'h1',
|
||||||
|
'h2',
|
||||||
|
'h3',
|
||||||
|
'h4',
|
||||||
|
'h5',
|
||||||
|
'h6',
|
||||||
|
'header',
|
||||||
|
'hgroup',
|
||||||
|
'hr',
|
||||||
|
'li',
|
||||||
|
'main',
|
||||||
|
'nav',
|
||||||
|
'menu',
|
||||||
|
'ol',
|
||||||
|
'p',
|
||||||
|
'pre',
|
||||||
|
'section',
|
||||||
|
'table',
|
||||||
|
'ul',
|
||||||
|
]),
|
||||||
|
svg: new Set([
|
||||||
|
'b',
|
||||||
|
'blockquote',
|
||||||
|
'br',
|
||||||
|
'code',
|
||||||
|
'dd',
|
||||||
|
'div',
|
||||||
|
'dl',
|
||||||
|
'dt',
|
||||||
|
'em',
|
||||||
|
'embed',
|
||||||
|
'h1',
|
||||||
|
'h2',
|
||||||
|
'h3',
|
||||||
|
'h4',
|
||||||
|
'h5',
|
||||||
|
'h6',
|
||||||
|
'hr',
|
||||||
|
'i',
|
||||||
|
'img',
|
||||||
|
'li',
|
||||||
|
'menu',
|
||||||
|
'meta',
|
||||||
|
'ol',
|
||||||
|
'p',
|
||||||
|
'pre',
|
||||||
|
'ruby',
|
||||||
|
's',
|
||||||
|
'small',
|
||||||
|
'span',
|
||||||
|
'strong',
|
||||||
|
'sub',
|
||||||
|
'sup',
|
||||||
|
'table',
|
||||||
|
'u',
|
||||||
|
'ul',
|
||||||
|
'var',
|
||||||
|
]),
|
||||||
|
} as const
|
||||||
|
|
||||||
|
/** maps element to set of elements that can not be it's parent, others can */
|
||||||
|
const knownInvalidParents: Record<string, Set<string>> = {
|
||||||
|
a: new Set(['a']),
|
||||||
|
button: new Set(['button']),
|
||||||
|
dd: new Set(['dd', 'dt']),
|
||||||
|
dt: new Set(['dd', 'dt']),
|
||||||
|
form: new Set(['form']),
|
||||||
|
li: new Set(['li']),
|
||||||
|
h1: headings,
|
||||||
|
h2: headings,
|
||||||
|
h3: headings,
|
||||||
|
h4: headings,
|
||||||
|
h5: headings,
|
||||||
|
h6: headings,
|
||||||
|
}
|
|
@ -19,13 +19,14 @@ import { transformShow } from './transforms/vShow'
|
||||||
import { transformTransition } from './transforms/Transition'
|
import { transformTransition } from './transforms/Transition'
|
||||||
import { stringifyStatic } from './transforms/stringifyStatic'
|
import { stringifyStatic } from './transforms/stringifyStatic'
|
||||||
import { ignoreSideEffectTags } from './transforms/ignoreSideEffectTags'
|
import { ignoreSideEffectTags } from './transforms/ignoreSideEffectTags'
|
||||||
|
import { validateHtmlNesting } from './transforms/validateHtmlNesting'
|
||||||
import { extend } from '@vue/shared'
|
import { extend } from '@vue/shared'
|
||||||
|
|
||||||
export { parserOptions }
|
export { parserOptions }
|
||||||
|
|
||||||
export const DOMNodeTransforms: NodeTransform[] = [
|
export const DOMNodeTransforms: NodeTransform[] = [
|
||||||
transformStyle,
|
transformStyle,
|
||||||
...(__DEV__ ? [transformTransition] : []),
|
...(__DEV__ ? [transformTransition, validateHtmlNesting] : []),
|
||||||
]
|
]
|
||||||
|
|
||||||
export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {
|
||||||
|
type CompilerError,
|
||||||
|
ElementTypes,
|
||||||
|
type NodeTransform,
|
||||||
|
NodeTypes,
|
||||||
|
} from '@vue/compiler-core'
|
||||||
|
import { isValidHTMLNesting } from '../htmlNesting'
|
||||||
|
|
||||||
|
export const validateHtmlNesting: NodeTransform = (node, context) => {
|
||||||
|
if (
|
||||||
|
node.type === NodeTypes.ELEMENT &&
|
||||||
|
node.tagType === ElementTypes.ELEMENT &&
|
||||||
|
context.parent &&
|
||||||
|
context.parent.type === NodeTypes.ELEMENT &&
|
||||||
|
context.parent.tagType === ElementTypes.ELEMENT &&
|
||||||
|
!isValidHTMLNesting(context.parent.tag, node.tag)
|
||||||
|
) {
|
||||||
|
const error = new SyntaxError(
|
||||||
|
`<${node.tag}> cannot be child of <${context.parent.tag}>, ` +
|
||||||
|
'according to HTML specifications. ' +
|
||||||
|
'This can cause hydration errors or ' +
|
||||||
|
'potentially disrupt future functionality.',
|
||||||
|
) as CompilerError
|
||||||
|
error.loc = node.loc
|
||||||
|
context.onWarn(error)
|
||||||
|
}
|
||||||
|
}
|
|
@ -597,11 +597,29 @@ const props = defineProps({ foo: String })
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
</script>`,
|
</script>`,
|
||||||
|
{
|
||||||
|
propsDestructure: false,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`const { foo } = __props`)
|
expect(content).toMatch(`const { foo } = __props`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('prohibiting reactive destructure', () => {
|
||||||
|
expect(() =>
|
||||||
|
compile(
|
||||||
|
`<script setup lang="ts">
|
||||||
|
const { foo } = defineProps<{
|
||||||
|
foo: Foo
|
||||||
|
}>()
|
||||||
|
</script>`,
|
||||||
|
{
|
||||||
|
propsDestructure: 'error',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
describe('errors', () => {
|
describe('errors', () => {
|
||||||
test('w/ both type and non-type args', () => {
|
test('w/ both type and non-type args', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
|
|
|
@ -6,7 +6,6 @@ describe('sfc reactive props destructure', () => {
|
||||||
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
||||||
return compileSFCScript(src, {
|
return compileSFCScript(src, {
|
||||||
inlineTemplate: true,
|
inlineTemplate: true,
|
||||||
propsDestructure: true,
|
|
||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-sfc",
|
"name": "@vue/compiler-sfc",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/compiler-sfc",
|
"description": "@vue/compiler-sfc",
|
||||||
"main": "dist/compiler-sfc.cjs.js",
|
"main": "dist/compiler-sfc.cjs.js",
|
||||||
"module": "dist/compiler-sfc.esm-browser.js",
|
"module": "dist/compiler-sfc.esm-browser.js",
|
||||||
|
|
|
@ -106,10 +106,11 @@ export interface SFCScriptCompileOptions {
|
||||||
*/
|
*/
|
||||||
hoistStatic?: boolean
|
hoistStatic?: boolean
|
||||||
/**
|
/**
|
||||||
* (**Experimental**) Enable reactive destructure for `defineProps`
|
* Set to `false` to disable reactive destructure for `defineProps` (pre-3.5
|
||||||
* @default false
|
* behavior), or set to `'error'` to throw hard error on props destructures.
|
||||||
|
* @default true
|
||||||
*/
|
*/
|
||||||
propsDestructure?: boolean
|
propsDestructure?: boolean | 'error'
|
||||||
/**
|
/**
|
||||||
* File system access methods to be used when resolving types
|
* File system access methods to be used when resolving types
|
||||||
* imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten
|
* imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten
|
||||||
|
|
|
@ -22,23 +22,17 @@ import { genPropsAccessExp } from '@vue/shared'
|
||||||
import { isCallOf, resolveObjectKey } from './utils'
|
import { isCallOf, resolveObjectKey } from './utils'
|
||||||
import type { ScriptCompileContext } from './context'
|
import type { ScriptCompileContext } from './context'
|
||||||
import { DEFINE_PROPS } from './defineProps'
|
import { DEFINE_PROPS } from './defineProps'
|
||||||
import { warnOnce } from '../warn'
|
|
||||||
|
|
||||||
export function processPropsDestructure(
|
export function processPropsDestructure(
|
||||||
ctx: ScriptCompileContext,
|
ctx: ScriptCompileContext,
|
||||||
declId: ObjectPattern,
|
declId: ObjectPattern,
|
||||||
) {
|
) {
|
||||||
if (!ctx.options.propsDestructure) {
|
if (ctx.options.propsDestructure === 'error') {
|
||||||
|
ctx.error(`Props destructure is explicitly prohibited via config.`, declId)
|
||||||
|
} else if (ctx.options.propsDestructure === false) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
warnOnce(
|
|
||||||
`This project is using reactive props destructure, which is an experimental ` +
|
|
||||||
`feature. It may receive breaking changes or be removed in the future, so ` +
|
|
||||||
`use at your own risk.\n` +
|
|
||||||
`To stay updated, follow the RFC at https://github.com/vuejs/rfcs/discussions/502.`,
|
|
||||||
)
|
|
||||||
|
|
||||||
ctx.propsDestructureDecl = declId
|
ctx.propsDestructureDecl = declId
|
||||||
|
|
||||||
const registerBinding = (
|
const registerBinding = (
|
||||||
|
@ -104,7 +98,7 @@ export function transformDestructuredProps(
|
||||||
ctx: ScriptCompileContext,
|
ctx: ScriptCompileContext,
|
||||||
vueImportAliases: Record<string, string>,
|
vueImportAliases: Record<string, string>,
|
||||||
) {
|
) {
|
||||||
if (!ctx.options.propsDestructure) {
|
if (ctx.options.propsDestructure === false) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compiler-ssr",
|
"name": "@vue/compiler-ssr",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/compiler-ssr",
|
"description": "@vue/compiler-ssr",
|
||||||
"main": "dist/compiler-ssr.cjs.js",
|
"main": "dist/compiler-ssr.cjs.js",
|
||||||
"types": "dist/compiler-ssr.d.ts",
|
"types": "dist/compiler-ssr.d.ts",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { defineComponent } from 'vue'
|
import { type DefineComponent, type Directive, defineComponent } from 'vue'
|
||||||
import { expectType } from './utils'
|
import { expectType } from './utils'
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
|
@ -6,6 +6,14 @@ declare module 'vue' {
|
||||||
test?(n: number): void
|
test?(n: number): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GlobalDirectives {
|
||||||
|
test: Directive
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GlobalComponents {
|
||||||
|
RouterView: DefineComponent<{}>
|
||||||
|
}
|
||||||
|
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
state?: 'stopped' | 'running'
|
state?: 'stopped' | 'running'
|
||||||
}
|
}
|
||||||
|
@ -46,6 +54,8 @@ export const Custom = defineComponent({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
expectType<Directive>(Custom.directives!.test)
|
||||||
|
expectType<DefineComponent<{}>>(Custom.components!.RouterView)
|
||||||
expectType<JSX.Element>(<Custom baz={1} />)
|
expectType<JSX.Element>(<Custom baz={1} />)
|
||||||
expectType<JSX.Element>(<Custom custom={1} baz={1} />)
|
expectType<JSX.Element>(<Custom custom={1} baz={1} />)
|
||||||
expectType<JSX.Element>(<Custom bar="bar" baz={1} />)
|
expectType<JSX.Element>(<Custom bar="bar" baz={1} />)
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
withKeys,
|
withKeys,
|
||||||
withModifiers,
|
withModifiers,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { type IsUnion, describe, expectType } from './utils'
|
import { type IsAny, type IsUnion, describe, expectType } from './utils'
|
||||||
|
|
||||||
describe('with object props', () => {
|
describe('with object props', () => {
|
||||||
interface ExpectedProps {
|
interface ExpectedProps {
|
||||||
|
@ -1501,18 +1501,108 @@ describe('should work when props type is incompatible with setup returned type '
|
||||||
|
|
||||||
describe('withKeys and withModifiers as pro', () => {
|
describe('withKeys and withModifiers as pro', () => {
|
||||||
const onKeydown = withKeys(e => {}, [''])
|
const onKeydown = withKeys(e => {}, [''])
|
||||||
|
// @ts-expect-error invalid modifiers
|
||||||
const onClick = withModifiers(e => {}, [''])
|
const onClick = withModifiers(e => {}, [''])
|
||||||
;<input onKeydown={onKeydown} onClick={onClick} />
|
;<input onKeydown={onKeydown} onClick={onClick} />
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #3367 expose components types
|
||||||
|
describe('expose component types', () => {
|
||||||
|
const child = defineComponent({
|
||||||
|
props: {
|
||||||
|
a: String,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const parent = defineComponent({
|
||||||
|
components: {
|
||||||
|
child,
|
||||||
|
child2: {
|
||||||
|
template: `<div></div>`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expectType<typeof child>(parent.components!.child)
|
||||||
|
expectType<Component>(parent.components!.child2)
|
||||||
|
|
||||||
|
// global components
|
||||||
|
expectType<Readonly<KeepAliveProps>>(
|
||||||
|
new parent.components!.KeepAlive().$props,
|
||||||
|
)
|
||||||
|
expectType<Readonly<KeepAliveProps>>(new child.components!.KeepAlive().$props)
|
||||||
|
|
||||||
|
// runtime-dom components
|
||||||
|
expectType<Readonly<TransitionProps>>(
|
||||||
|
new parent.components!.Transition().$props,
|
||||||
|
)
|
||||||
|
expectType<Readonly<TransitionProps>>(
|
||||||
|
new child.components!.Transition().$props,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('directive typing', () => {
|
||||||
|
const customDirective: Directive = {
|
||||||
|
created(_) {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const comp = defineComponent({
|
||||||
|
props: {
|
||||||
|
a: String,
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
customDirective,
|
||||||
|
localDirective: {
|
||||||
|
created(_, { arg }) {
|
||||||
|
expectType<string | undefined>(arg)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expectType<typeof customDirective>(comp.directives!.customDirective)
|
||||||
|
expectType<Directive>(comp.directives!.localDirective)
|
||||||
|
|
||||||
|
// global directive
|
||||||
|
expectType<typeof vShow>(comp.directives!.vShow)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('expose typing', () => {
|
||||||
|
const Comp = defineComponent({
|
||||||
|
expose: ['a', 'b'],
|
||||||
|
props: {
|
||||||
|
some: String,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return { a: 1, b: '2', c: 1 }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expectType<Array<'a' | 'b'>>(Comp.expose!)
|
||||||
|
|
||||||
|
const vm = new Comp()
|
||||||
|
// internal should still be exposed
|
||||||
|
vm.$props
|
||||||
|
|
||||||
|
expectType<number>(vm.a)
|
||||||
|
expectType<string>(vm.b)
|
||||||
|
|
||||||
|
// @ts-expect-error shouldn't be exposed
|
||||||
|
vm.c
|
||||||
|
})
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AllowedComponentProps,
|
AllowedComponentProps,
|
||||||
ComponentCustomProps,
|
ComponentCustomProps,
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
DefineComponent,
|
DefineComponent,
|
||||||
|
Directive,
|
||||||
EmitsOptions,
|
EmitsOptions,
|
||||||
ExtractPropTypes,
|
ExtractPropTypes,
|
||||||
|
KeepAliveProps,
|
||||||
|
TransitionProps,
|
||||||
VNodeProps,
|
VNodeProps,
|
||||||
|
vShow,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
|
|
||||||
// code generated by tsc / vue-tsc, make sure this continues to work
|
// code generated by tsc / vue-tsc, make sure this continues to work
|
||||||
|
@ -1533,3 +1623,146 @@ declare const MyButton: DefineComponent<
|
||||||
{}
|
{}
|
||||||
>
|
>
|
||||||
;<MyButton class="x" />
|
;<MyButton class="x" />
|
||||||
|
|
||||||
|
describe('__typeProps backdoor for union type for conditional props', () => {
|
||||||
|
interface CommonProps {
|
||||||
|
size?: 'xl' | 'l' | 'm' | 's' | 'xs'
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConditionalProps =
|
||||||
|
| {
|
||||||
|
color?: 'normal' | 'primary' | 'secondary'
|
||||||
|
appearance?: 'normal' | 'outline' | 'text'
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
color: 'white'
|
||||||
|
appearance: 'outline'
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = CommonProps & ConditionalProps
|
||||||
|
|
||||||
|
const Comp = defineComponent({
|
||||||
|
__typeProps: {} as Props,
|
||||||
|
})
|
||||||
|
// @ts-expect-error
|
||||||
|
;<Comp color="white" />
|
||||||
|
// @ts-expect-error
|
||||||
|
;<Comp color="white" appearance="normal" />
|
||||||
|
;<Comp color="white" appearance="outline" />
|
||||||
|
|
||||||
|
const c = new Comp()
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$props = { color: 'white' }
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$props = { color: 'white', appearance: 'text' }
|
||||||
|
c.$props = { color: 'white', appearance: 'outline' }
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('__typeEmits backdoor, 3.3+ object syntax', () => {
|
||||||
|
type Emits = {
|
||||||
|
change: [id: number]
|
||||||
|
update: [value: string]
|
||||||
|
}
|
||||||
|
|
||||||
|
const Comp = defineComponent({
|
||||||
|
__typeEmits: {} as Emits,
|
||||||
|
mounted() {
|
||||||
|
this.$props.onChange?.(123)
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$props.onChange?.('123')
|
||||||
|
this.$props.onUpdate?.('foo')
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$props.onUpdate?.(123)
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$emit('foo')
|
||||||
|
|
||||||
|
this.$emit('change', 123)
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$emit('change', '123')
|
||||||
|
|
||||||
|
this.$emit('update', 'test')
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$emit('update', 123)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
;<Comp onChange={id => id.toFixed(2)} />
|
||||||
|
;<Comp onUpdate={id => id.toUpperCase()} />
|
||||||
|
// @ts-expect-error
|
||||||
|
;<Comp onChange={id => id.slice(1)} />
|
||||||
|
// @ts-expect-error
|
||||||
|
;<Comp onUpdate={id => id.toFixed(2)} />
|
||||||
|
|
||||||
|
const c = new Comp()
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$emit('foo')
|
||||||
|
|
||||||
|
c.$emit('change', 123)
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$emit('change', '123')
|
||||||
|
|
||||||
|
c.$emit('update', 'test')
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$emit('update', 123)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('__typeEmits backdoor, call signature syntax', () => {
|
||||||
|
type Emits = {
|
||||||
|
(e: 'change', id: number): void
|
||||||
|
(e: 'update', value: string): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const Comp = defineComponent({
|
||||||
|
__typeEmits: {} as Emits,
|
||||||
|
mounted() {
|
||||||
|
this.$props.onChange?.(123)
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$props.onChange?.('123')
|
||||||
|
this.$props.onUpdate?.('foo')
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$props.onUpdate?.(123)
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$emit('foo')
|
||||||
|
|
||||||
|
this.$emit('change', 123)
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$emit('change', '123')
|
||||||
|
|
||||||
|
this.$emit('update', 'test')
|
||||||
|
// @ts-expect-error
|
||||||
|
this.$emit('update', 123)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
;<Comp onChange={id => id.toFixed(2)} />
|
||||||
|
;<Comp onUpdate={id => id.toUpperCase()} />
|
||||||
|
// @ts-expect-error
|
||||||
|
;<Comp onChange={id => id.slice(1)} />
|
||||||
|
// @ts-expect-error
|
||||||
|
;<Comp onUpdate={id => id.toFixed(2)} />
|
||||||
|
|
||||||
|
const c = new Comp()
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$emit('foo')
|
||||||
|
|
||||||
|
c.$emit('change', 123)
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$emit('change', '123')
|
||||||
|
|
||||||
|
c.$emit('update', 'test')
|
||||||
|
// @ts-expect-error
|
||||||
|
c.$emit('update', 123)
|
||||||
|
})
|
||||||
|
|
||||||
|
defineComponent({
|
||||||
|
props: {
|
||||||
|
foo: [String, null],
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
expectType<IsAny<typeof props.foo>>(false)
|
||||||
|
expectType<string | null | undefined>(props.foo)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { type Directive, type ObjectDirective, vModelText } from 'vue'
|
||||||
|
import { describe, expectType } from './utils'
|
||||||
|
|
||||||
|
type ExtractBinding<T> = T extends (
|
||||||
|
el: any,
|
||||||
|
binding: infer B,
|
||||||
|
vnode: any,
|
||||||
|
prev: any,
|
||||||
|
) => any
|
||||||
|
? B
|
||||||
|
: never
|
||||||
|
|
||||||
|
declare function testDirective<
|
||||||
|
Value,
|
||||||
|
Modifiers extends string = string,
|
||||||
|
Arg extends string = string,
|
||||||
|
>(): ExtractBinding<Directive<any, Value, Modifiers, Arg>>
|
||||||
|
|
||||||
|
describe('vmodel', () => {
|
||||||
|
expectType<ObjectDirective<any, any, 'trim' | 'number' | 'lazy', string>>(
|
||||||
|
vModelText,
|
||||||
|
)
|
||||||
|
// @ts-expect-error
|
||||||
|
expectType<ObjectDirective<any, any, 'not-valid', string>>(vModelText)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('custom', () => {
|
||||||
|
expectType<{
|
||||||
|
value: number
|
||||||
|
oldValue: number | null
|
||||||
|
arg?: 'Arg'
|
||||||
|
modifiers: Record<'a' | 'b', boolean>
|
||||||
|
}>(testDirective<number, 'a' | 'b', 'Arg'>())
|
||||||
|
|
||||||
|
expectType<{
|
||||||
|
value: number
|
||||||
|
oldValue: number | null
|
||||||
|
arg?: 'Arg'
|
||||||
|
modifiers: Record<'a' | 'b', boolean>
|
||||||
|
// @ts-expect-error
|
||||||
|
}>(testDirective<number, 'a', 'Arg'>())
|
||||||
|
|
||||||
|
expectType<{
|
||||||
|
value: number
|
||||||
|
oldValue: number | null
|
||||||
|
arg?: 'Arg'
|
||||||
|
modifiers: Record<'a' | 'b', boolean>
|
||||||
|
// @ts-expect-error
|
||||||
|
}>(testDirective<number, 'a' | 'b', 'Argx'>())
|
||||||
|
|
||||||
|
expectType<{
|
||||||
|
value: number
|
||||||
|
oldValue: number | null
|
||||||
|
arg?: 'Arg'
|
||||||
|
modifiers: Record<'a' | 'b', boolean>
|
||||||
|
// @ts-expect-error
|
||||||
|
}>(testDirective<string, 'a' | 'b', 'Arg'>())
|
||||||
|
})
|
|
@ -769,6 +769,32 @@ describe('reactivity/effect', () => {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('debug: the call sequence of onTrack', () => {
|
||||||
|
const seq: number[] = []
|
||||||
|
const s = ref(0)
|
||||||
|
|
||||||
|
const track1 = () => seq.push(1)
|
||||||
|
const track2 = () => seq.push(2)
|
||||||
|
|
||||||
|
effect(
|
||||||
|
() => {
|
||||||
|
s.value
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onTrack: track1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
effect(
|
||||||
|
() => {
|
||||||
|
s.value
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onTrack: track2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
expect(seq.toString()).toBe('1,2')
|
||||||
|
})
|
||||||
|
|
||||||
it('events: onTrigger', () => {
|
it('events: onTrigger', () => {
|
||||||
let events: DebuggerEvent[] = []
|
let events: DebuggerEvent[] = []
|
||||||
let dummy
|
let dummy
|
||||||
|
@ -807,6 +833,51 @@ describe('reactivity/effect', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('debug: the call sequence of onTrigger', () => {
|
||||||
|
const seq: number[] = []
|
||||||
|
const s = ref(0)
|
||||||
|
|
||||||
|
const trigger1 = () => seq.push(1)
|
||||||
|
const trigger2 = () => seq.push(2)
|
||||||
|
const trigger3 = () => seq.push(3)
|
||||||
|
const trigger4 = () => seq.push(4)
|
||||||
|
|
||||||
|
effect(
|
||||||
|
() => {
|
||||||
|
s.value
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onTrigger: trigger1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
effect(
|
||||||
|
() => {
|
||||||
|
s.value
|
||||||
|
effect(
|
||||||
|
() => {
|
||||||
|
s.value
|
||||||
|
effect(
|
||||||
|
() => {
|
||||||
|
s.value
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onTrigger: trigger4,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onTrigger: trigger3,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onTrigger: trigger2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
s.value++
|
||||||
|
expect(seq.toString()).toBe('1,2,3,4')
|
||||||
|
})
|
||||||
|
|
||||||
it('stop', () => {
|
it('stop', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const obj = reactive({ prop: 1 })
|
const obj = reactive({ prop: 1 })
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/reactivity",
|
"name": "@vue/reactivity",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/reactivity",
|
"description": "@vue/reactivity",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/reactivity.esm-bundler.js",
|
"module": "dist/reactivity.esm-bundler.js",
|
||||||
|
|
|
@ -27,12 +27,23 @@ export class Dep {
|
||||||
* Link between this dep and the current active effect
|
* Link between this dep and the current active effect
|
||||||
*/
|
*/
|
||||||
activeLink?: Link = undefined
|
activeLink?: Link = undefined
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Doubly linked list representing the subscribing effects (tail)
|
* Doubly linked list representing the subscribing effects (tail)
|
||||||
*/
|
*/
|
||||||
subs?: Link = undefined
|
subs?: Link = undefined
|
||||||
|
|
||||||
constructor(public computed?: ComputedRefImpl) {}
|
/**
|
||||||
|
* Doubly linked list representing the subscribing effects (head)
|
||||||
|
* DEV only, for invoking onTrigger hooks in correct order
|
||||||
|
*/
|
||||||
|
subsHead?: Link
|
||||||
|
|
||||||
|
constructor(public computed?: ComputedRefImpl) {
|
||||||
|
if (__DEV__) {
|
||||||
|
this.subsHead = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
track(debugInfo?: DebuggerEventExtraInfo): Link | undefined {
|
track(debugInfo?: DebuggerEventExtraInfo): Link | undefined {
|
||||||
if (!activeSub || !shouldTrack) {
|
if (!activeSub || !shouldTrack) {
|
||||||
|
@ -113,21 +124,28 @@ export class Dep {
|
||||||
notify(debugInfo?: DebuggerEventExtraInfo) {
|
notify(debugInfo?: DebuggerEventExtraInfo) {
|
||||||
startBatch()
|
startBatch()
|
||||||
try {
|
try {
|
||||||
for (let link = this.subs; link; link = link.prevSub) {
|
if (__DEV__) {
|
||||||
|
// subs are notified and batched in reverse-order and then invoked in
|
||||||
|
// original order at the end of the batch, but onTrigger hooks should
|
||||||
|
// be invoked in original order here.
|
||||||
|
for (let head = this.subsHead; head; head = head.nextSub) {
|
||||||
if (
|
if (
|
||||||
__DEV__ &&
|
__DEV__ &&
|
||||||
link.sub.onTrigger &&
|
head.sub.onTrigger &&
|
||||||
!(link.sub.flags & EffectFlags.NOTIFIED)
|
!(head.sub.flags & EffectFlags.NOTIFIED)
|
||||||
) {
|
) {
|
||||||
link.sub.onTrigger(
|
head.sub.onTrigger(
|
||||||
extend(
|
extend(
|
||||||
{
|
{
|
||||||
effect: link.sub,
|
effect: head.sub,
|
||||||
},
|
},
|
||||||
debugInfo,
|
debugInfo,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let link = this.subs; link; link = link.prevSub) {
|
||||||
link.sub.notify()
|
link.sub.notify()
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -152,6 +170,11 @@ function addSub(link: Link) {
|
||||||
link.prevSub = currentTail
|
link.prevSub = currentTail
|
||||||
if (currentTail) currentTail.nextSub = link
|
if (currentTail) currentTail.nextSub = link
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__DEV__ && link.dep.subsHead === undefined) {
|
||||||
|
link.dep.subsHead = link
|
||||||
|
}
|
||||||
|
|
||||||
link.dep.subs = link
|
link.dep.subs = link
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -375,13 +375,14 @@ export function refreshComputed(computed: ComputedRefImpl) {
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dep.version++
|
dep.version++
|
||||||
}
|
throw err
|
||||||
|
} finally {
|
||||||
activeSub = prevSub
|
activeSub = prevSub
|
||||||
shouldTrack = prevShouldTrack
|
shouldTrack = prevShouldTrack
|
||||||
cleanupDeps(computed)
|
cleanupDeps(computed)
|
||||||
computed.flags &= ~EffectFlags.RUNNING
|
computed.flags &= ~EffectFlags.RUNNING
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function removeSub(link: Link) {
|
function removeSub(link: Link) {
|
||||||
const { dep, prevSub, nextSub } = link
|
const { dep, prevSub, nextSub } = link
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/runtime-core",
|
"name": "@vue/runtime-core",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/runtime-core",
|
"description": "@vue/runtime-core",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/runtime-core.esm-bundler.js",
|
"module": "dist/runtime-core.esm-bundler.js",
|
||||||
|
|
|
@ -3,16 +3,17 @@ import type {
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
ComponentOptionsBase,
|
ComponentOptionsBase,
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
ComponentOptionsWithArrayProps,
|
ComponentProvideOptions,
|
||||||
ComponentOptionsWithObjectProps,
|
|
||||||
ComponentOptionsWithoutProps,
|
|
||||||
ComputedOptions,
|
ComputedOptions,
|
||||||
MethodOptions,
|
MethodOptions,
|
||||||
RenderFunction,
|
RenderFunction,
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
import type {
|
import type {
|
||||||
AllowedComponentProps,
|
AllowedComponentProps,
|
||||||
|
Component,
|
||||||
ComponentCustomProps,
|
ComponentCustomProps,
|
||||||
|
GlobalComponents,
|
||||||
|
GlobalDirectives,
|
||||||
SetupContext,
|
SetupContext,
|
||||||
} from './component'
|
} from './component'
|
||||||
import type {
|
import type {
|
||||||
|
@ -21,7 +22,11 @@ import type {
|
||||||
ExtractDefaultPropTypes,
|
ExtractDefaultPropTypes,
|
||||||
ExtractPropTypes,
|
ExtractPropTypes,
|
||||||
} from './componentProps'
|
} from './componentProps'
|
||||||
import type { EmitsOptions, EmitsToProps } from './componentEmits'
|
import type {
|
||||||
|
EmitsOptions,
|
||||||
|
EmitsToProps,
|
||||||
|
TypeEmitsToOptions,
|
||||||
|
} from './componentEmits'
|
||||||
import { extend, isFunction } from '@vue/shared'
|
import { extend, isFunction } from '@vue/shared'
|
||||||
import type { VNodeProps } from './vnode'
|
import type { VNodeProps } from './vnode'
|
||||||
import type {
|
import type {
|
||||||
|
@ -29,6 +34,8 @@ import type {
|
||||||
CreateComponentPublicInstance,
|
CreateComponentPublicInstance,
|
||||||
} from './componentPublicInstance'
|
} from './componentPublicInstance'
|
||||||
import type { SlotsType } from './componentSlots'
|
import type { SlotsType } from './componentSlots'
|
||||||
|
import type { Directive } from './directives'
|
||||||
|
import type { ComponentTypeEmits } from './apiSetupHelpers'
|
||||||
|
|
||||||
export type PublicProps = VNodeProps &
|
export type PublicProps = VNodeProps &
|
||||||
AllowedComponentProps &
|
AllowedComponentProps &
|
||||||
|
@ -55,6 +62,11 @@ export type DefineComponent<
|
||||||
Props = ResolveProps<PropsOrPropOptions, E>,
|
Props = ResolveProps<PropsOrPropOptions, E>,
|
||||||
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>,
|
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>,
|
||||||
S extends SlotsType = {},
|
S extends SlotsType = {},
|
||||||
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
MakeDefaultsOptional extends boolean = true,
|
||||||
> = ComponentPublicInstanceConstructor<
|
> = ComponentPublicInstanceConstructor<
|
||||||
CreateComponentPublicInstance<
|
CreateComponentPublicInstance<
|
||||||
Props,
|
Props,
|
||||||
|
@ -67,9 +79,12 @@ export type DefineComponent<
|
||||||
E,
|
E,
|
||||||
PP & Props,
|
PP & Props,
|
||||||
Defaults,
|
Defaults,
|
||||||
true,
|
MakeDefaultsOptional,
|
||||||
{},
|
{},
|
||||||
S
|
S,
|
||||||
|
LC & GlobalComponents,
|
||||||
|
Directives & GlobalDirectives,
|
||||||
|
Exposed
|
||||||
>
|
>
|
||||||
> &
|
> &
|
||||||
ComponentOptionsBase<
|
ComponentOptionsBase<
|
||||||
|
@ -85,7 +100,11 @@ export type DefineComponent<
|
||||||
Defaults,
|
Defaults,
|
||||||
{},
|
{},
|
||||||
string,
|
string,
|
||||||
S
|
S,
|
||||||
|
LC & GlobalComponents,
|
||||||
|
Directives & GlobalDirectives,
|
||||||
|
Exposed,
|
||||||
|
Provide
|
||||||
> &
|
> &
|
||||||
PP
|
PP
|
||||||
|
|
||||||
|
@ -153,147 +172,114 @@ export function defineComponent<
|
||||||
},
|
},
|
||||||
): DefineSetupFnComponent<Props, E, S>
|
): DefineSetupFnComponent<Props, E, S>
|
||||||
|
|
||||||
// overload 2: object format with no props
|
// overload 2: defineComponent with options object, infer props from options
|
||||||
// (uses user defined props interface)
|
|
||||||
// return type is for Vetur and TSX support
|
|
||||||
export function defineComponent<
|
export function defineComponent<
|
||||||
Props = {},
|
// props
|
||||||
RawBindings = {},
|
TypeProps,
|
||||||
D = {},
|
RuntimePropsOptions extends
|
||||||
C extends ComputedOptions = {},
|
ComponentObjectPropsOptions = ComponentObjectPropsOptions,
|
||||||
M extends MethodOptions = {},
|
RuntimePropsKeys extends string = string,
|
||||||
|
// emits
|
||||||
|
TypeEmits extends ComponentTypeEmits = {},
|
||||||
|
RuntimeEmitsOptions extends EmitsOptions = {},
|
||||||
|
RuntimeEmitsKeys extends string = string,
|
||||||
|
// other options
|
||||||
|
Data = {},
|
||||||
|
SetupBindings = {},
|
||||||
|
Computed extends ComputedOptions = {},
|
||||||
|
Methods extends MethodOptions = {},
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = {},
|
InjectOptions extends ComponentInjectOptions = {},
|
||||||
EE extends string = string,
|
InjectKeys extends string = string,
|
||||||
S extends SlotsType = {},
|
Slots extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
LocalComponents extends Record<string, Component> = {},
|
||||||
II extends string = string,
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
// resolved types
|
||||||
|
ResolvedEmits extends EmitsOptions = {} extends RuntimeEmitsOptions
|
||||||
|
? TypeEmitsToOptions<TypeEmits>
|
||||||
|
: RuntimeEmitsOptions,
|
||||||
|
InferredProps = unknown extends TypeProps
|
||||||
|
? string extends RuntimePropsKeys
|
||||||
|
? ComponentObjectPropsOptions extends RuntimePropsOptions
|
||||||
|
? {}
|
||||||
|
: ExtractPropTypes<RuntimePropsOptions>
|
||||||
|
: { [key in RuntimePropsKeys]?: any }
|
||||||
|
: TypeProps,
|
||||||
|
ResolvedProps = Readonly<InferredProps & EmitsToProps<ResolvedEmits>>,
|
||||||
>(
|
>(
|
||||||
options: ComponentOptionsWithoutProps<
|
options: {
|
||||||
Props,
|
props?: (RuntimePropsOptions & ThisType<void>) | RuntimePropsKeys[]
|
||||||
RawBindings,
|
/**
|
||||||
D,
|
* @private for language-tools use only
|
||||||
C,
|
*/
|
||||||
M,
|
__typeProps?: TypeProps
|
||||||
|
/**
|
||||||
|
* @private for language-tools use only
|
||||||
|
*/
|
||||||
|
__typeEmits?: TypeEmits
|
||||||
|
} & ComponentOptionsBase<
|
||||||
|
ResolvedProps,
|
||||||
|
SetupBindings,
|
||||||
|
Data,
|
||||||
|
Computed,
|
||||||
|
Methods,
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
RuntimeEmitsOptions,
|
||||||
EE,
|
RuntimeEmitsKeys,
|
||||||
I,
|
{}, // Defaults
|
||||||
II,
|
InjectOptions,
|
||||||
S
|
InjectKeys,
|
||||||
>,
|
Slots,
|
||||||
): DefineComponent<
|
LocalComponents,
|
||||||
Props,
|
Directives,
|
||||||
RawBindings,
|
Exposed,
|
||||||
D,
|
Provide
|
||||||
C,
|
> &
|
||||||
M,
|
ThisType<
|
||||||
|
CreateComponentPublicInstance<
|
||||||
|
ResolvedProps,
|
||||||
|
SetupBindings,
|
||||||
|
Data,
|
||||||
|
Computed,
|
||||||
|
Methods,
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
ResolvedEmits,
|
||||||
EE,
|
RuntimeEmitsKeys,
|
||||||
PublicProps,
|
{},
|
||||||
ResolveProps<Props, E>,
|
false,
|
||||||
ExtractDefaultPropTypes<Props>,
|
InjectOptions,
|
||||||
S
|
Slots,
|
||||||
|
LocalComponents,
|
||||||
|
Directives,
|
||||||
|
Exposed
|
||||||
>
|
>
|
||||||
|
|
||||||
// overload 3: object format with array props declaration
|
|
||||||
// props inferred as { [key in PropNames]?: any }
|
|
||||||
// return type is for Vetur and TSX support
|
|
||||||
export function defineComponent<
|
|
||||||
PropNames extends string,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C extends ComputedOptions = {},
|
|
||||||
M extends MethodOptions = {},
|
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
E extends EmitsOptions = {},
|
|
||||||
EE extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
Props = Readonly<{ [key in PropNames]?: any }>,
|
|
||||||
>(
|
|
||||||
options: ComponentOptionsWithArrayProps<
|
|
||||||
PropNames,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
I,
|
|
||||||
II,
|
|
||||||
S
|
|
||||||
>,
|
>,
|
||||||
): DefineComponent<
|
): DefineComponent<
|
||||||
Props,
|
InferredProps,
|
||||||
RawBindings,
|
SetupBindings,
|
||||||
D,
|
Data,
|
||||||
C,
|
Computed,
|
||||||
M,
|
Methods,
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
ResolvedEmits,
|
||||||
EE,
|
RuntimeEmitsKeys,
|
||||||
PublicProps,
|
PublicProps,
|
||||||
ResolveProps<Props, E>,
|
ResolvedProps,
|
||||||
ExtractDefaultPropTypes<Props>,
|
ExtractDefaultPropTypes<RuntimePropsOptions>,
|
||||||
S
|
Slots,
|
||||||
>
|
LocalComponents,
|
||||||
|
Directives,
|
||||||
// overload 4: object format with object props declaration
|
Exposed,
|
||||||
// see `ExtractPropTypes` in ./componentProps.ts
|
Provide,
|
||||||
export function defineComponent<
|
// MakeDefaultsOptional - if TypeProps is provided, set to false to use
|
||||||
// the Readonly constraint allows TS to treat the type of { required: true }
|
// user props types verbatim
|
||||||
// as constant instead of boolean.
|
unknown extends TypeProps ? true : false
|
||||||
PropsOptions extends Readonly<ComponentPropsOptions>,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C extends ComputedOptions = {},
|
|
||||||
M extends MethodOptions = {},
|
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
E extends EmitsOptions = {},
|
|
||||||
EE extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
>(
|
|
||||||
options: ComponentOptionsWithObjectProps<
|
|
||||||
PropsOptions,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
I,
|
|
||||||
II,
|
|
||||||
S
|
|
||||||
>,
|
|
||||||
): DefineComponent<
|
|
||||||
PropsOptions,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
PublicProps,
|
|
||||||
ResolveProps<PropsOptions, E>,
|
|
||||||
ExtractDefaultPropTypes<PropsOptions>,
|
|
||||||
S
|
|
||||||
>
|
>
|
||||||
|
|
||||||
// implementation, close to no-op
|
// implementation, close to no-op
|
||||||
|
|
|
@ -16,8 +16,8 @@ import {
|
||||||
} from './component'
|
} from './component'
|
||||||
import type { EmitFn, EmitsOptions, ObjectEmitsOptions } from './componentEmits'
|
import type { EmitFn, EmitsOptions, ObjectEmitsOptions } from './componentEmits'
|
||||||
import type {
|
import type {
|
||||||
|
ComponentOptionsBase,
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
ComponentOptionsWithoutProps,
|
|
||||||
ComputedOptions,
|
ComputedOptions,
|
||||||
MethodOptions,
|
MethodOptions,
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
|
@ -135,9 +135,11 @@ export function defineEmits<EE extends string = string>(
|
||||||
export function defineEmits<E extends EmitsOptions = EmitsOptions>(
|
export function defineEmits<E extends EmitsOptions = EmitsOptions>(
|
||||||
emitOptions: E,
|
emitOptions: E,
|
||||||
): EmitFn<E>
|
): EmitFn<E>
|
||||||
export function defineEmits<
|
export function defineEmits<T extends ComponentTypeEmits>(): T extends (
|
||||||
T extends ((...args: any[]) => any) | Record<string, any[]>,
|
...args: any[]
|
||||||
>(): T extends (...args: any[]) => any ? T : ShortEmits<T>
|
) => any
|
||||||
|
? T
|
||||||
|
: ShortEmits<T>
|
||||||
// implementation
|
// implementation
|
||||||
export function defineEmits() {
|
export function defineEmits() {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
@ -146,6 +148,10 @@ export function defineEmits() {
|
||||||
return null as any
|
return null as any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ComponentTypeEmits =
|
||||||
|
| ((...args: any[]) => any)
|
||||||
|
| Record<string, any[]>
|
||||||
|
|
||||||
type RecordToUnion<T extends Record<string, any>> = T[keyof T]
|
type RecordToUnion<T extends Record<string, any>> = T[keyof T]
|
||||||
|
|
||||||
type ShortEmits<T extends Record<string, any>> = UnionToIntersection<
|
type ShortEmits<T extends Record<string, any>> = UnionToIntersection<
|
||||||
|
@ -191,15 +197,33 @@ export function defineOptions<
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
>(
|
>(
|
||||||
options?: ComponentOptionsWithoutProps<
|
options?: ComponentOptionsBase<
|
||||||
{},
|
{},
|
||||||
RawBindings,
|
RawBindings,
|
||||||
D,
|
D,
|
||||||
C,
|
C,
|
||||||
M,
|
M,
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends
|
Extends,
|
||||||
> & { emits?: undefined; expose?: undefined; slots?: undefined },
|
{}
|
||||||
|
> & {
|
||||||
|
/**
|
||||||
|
* props should be defined via defineProps().
|
||||||
|
*/
|
||||||
|
props: never
|
||||||
|
/**
|
||||||
|
* emits should be defined via defineEmits().
|
||||||
|
*/
|
||||||
|
emits?: never
|
||||||
|
/**
|
||||||
|
* expose should be defined via defineExpose().
|
||||||
|
*/
|
||||||
|
expose?: never
|
||||||
|
/**
|
||||||
|
* slots should be defined via defineSlots().
|
||||||
|
*/
|
||||||
|
slots?: never
|
||||||
|
},
|
||||||
): void {
|
): void {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warnRuntimeUsage(`defineOptions`)
|
warnRuntimeUsage(`defineOptions`)
|
||||||
|
|
|
@ -87,6 +87,13 @@ import {
|
||||||
import type { SchedulerJob } from './scheduler'
|
import type { SchedulerJob } from './scheduler'
|
||||||
import type { LifecycleHooks } from './enums'
|
import type { LifecycleHooks } from './enums'
|
||||||
|
|
||||||
|
// Augment GlobalComponents
|
||||||
|
import type { TeleportProps } from './components/Teleport'
|
||||||
|
import type { SuspenseProps } from './components/Suspense'
|
||||||
|
import type { KeepAliveProps } from './components/KeepAlive'
|
||||||
|
import type { BaseTransitionProps } from './components/BaseTransition'
|
||||||
|
import type { DefineComponent } from './apiDefineComponent'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public utility type for extracting the instance type of a component.
|
* Public utility type for extracting the instance type of a component.
|
||||||
* Works with all valid component definition types. This is intended to replace
|
* Works with all valid component definition types. This is intended to replace
|
||||||
|
@ -125,6 +132,45 @@ export type ComponentInstance<T> = T extends { new (): ComponentPublicInstance }
|
||||||
*/
|
*/
|
||||||
export interface ComponentCustomProps {}
|
export interface ComponentCustomProps {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For globally defined Directives
|
||||||
|
* Here is an example of adding a directive `VTooltip` as global directive:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import VTooltip from 'v-tooltip'
|
||||||
|
*
|
||||||
|
* declare module '@vue/runtime-core' {
|
||||||
|
* interface GlobalDirectives {
|
||||||
|
* VTooltip
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface GlobalDirectives extends Record<string, Directive> {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For globally defined Components
|
||||||
|
* Here is an example of adding a component `RouterView` as global component:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { RouterView } from 'vue-router'
|
||||||
|
*
|
||||||
|
* declare module '@vue/runtime-core' {
|
||||||
|
* interface GlobalComponents {
|
||||||
|
* RouterView
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface GlobalComponents extends Record<string, Component> {
|
||||||
|
Teleport: DefineComponent<TeleportProps>
|
||||||
|
Suspense: DefineComponent<SuspenseProps>
|
||||||
|
KeepAlive: DefineComponent<KeepAliveProps>
|
||||||
|
BaseTransition: DefineComponent<BaseTransitionProps>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default allowed non-declared props on component in TSX
|
* Default allowed non-declared props on component in TSX
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
EMPTY_OBJ,
|
EMPTY_OBJ,
|
||||||
|
type OverloadParameters,
|
||||||
type UnionToIntersection,
|
type UnionToIntersection,
|
||||||
camelize,
|
camelize,
|
||||||
extend,
|
extend,
|
||||||
|
@ -28,6 +29,7 @@ import {
|
||||||
compatModelEmit,
|
compatModelEmit,
|
||||||
compatModelEventPrefix,
|
compatModelEventPrefix,
|
||||||
} from './compat/componentVModel'
|
} from './compat/componentVModel'
|
||||||
|
import type { ComponentTypeEmits } from './apiSetupHelpers'
|
||||||
|
|
||||||
export type ObjectEmitsOptions = Record<
|
export type ObjectEmitsOptions = Record<
|
||||||
string,
|
string,
|
||||||
|
@ -36,7 +38,8 @@ export type ObjectEmitsOptions = Record<
|
||||||
|
|
||||||
export type EmitsOptions = ObjectEmitsOptions | string[]
|
export type EmitsOptions = ObjectEmitsOptions | string[]
|
||||||
|
|
||||||
export type EmitsToProps<T extends EmitsOptions> = T extends string[]
|
export type EmitsToProps<T extends EmitsOptions | ComponentTypeEmits> =
|
||||||
|
T extends string[]
|
||||||
? {
|
? {
|
||||||
[K in `on${Capitalize<T[number]>}`]?: (...args: any[]) => any
|
[K in `on${Capitalize<T[number]>}`]?: (...args: any[]) => any
|
||||||
}
|
}
|
||||||
|
@ -54,6 +57,23 @@ export type EmitsToProps<T extends EmitsOptions> = T extends string[]
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
|
|
||||||
|
export type TypeEmitsToOptions<T extends ComponentTypeEmits> =
|
||||||
|
T extends Record<string, any[]>
|
||||||
|
? {
|
||||||
|
[K in keyof T]: T[K] extends [...args: infer Args]
|
||||||
|
? (...args: Args) => any
|
||||||
|
: () => any
|
||||||
|
}
|
||||||
|
: T extends (...args: any[]) => any
|
||||||
|
? ParametersToFns<OverloadParameters<T>>
|
||||||
|
: {}
|
||||||
|
|
||||||
|
type ParametersToFns<T extends any[]> = {
|
||||||
|
[K in T[0]]: K extends `${infer C}`
|
||||||
|
? (...args: T extends [C, ...infer Args] ? Args : never) => any
|
||||||
|
: never
|
||||||
|
}
|
||||||
|
|
||||||
export type ShortEmitsToObject<E> =
|
export type ShortEmitsToObject<E> =
|
||||||
E extends Record<string, any[]>
|
E extends Record<string, any[]>
|
||||||
? {
|
? {
|
||||||
|
|
|
@ -55,7 +55,11 @@ import type {
|
||||||
ExtractDefaultPropTypes,
|
ExtractDefaultPropTypes,
|
||||||
ExtractPropTypes,
|
ExtractPropTypes,
|
||||||
} from './componentProps'
|
} from './componentProps'
|
||||||
import type { EmitsOptions, EmitsToProps } from './componentEmits'
|
import type {
|
||||||
|
EmitsOptions,
|
||||||
|
EmitsToProps,
|
||||||
|
TypeEmitsToOptions,
|
||||||
|
} from './componentEmits'
|
||||||
import type { Directive } from './directives'
|
import type { Directive } from './directives'
|
||||||
import {
|
import {
|
||||||
type ComponentPublicInstance,
|
type ComponentPublicInstance,
|
||||||
|
@ -77,7 +81,10 @@ import {
|
||||||
import type { OptionMergeFunction } from './apiCreateApp'
|
import type { OptionMergeFunction } from './apiCreateApp'
|
||||||
import { LifecycleHooks } from './enums'
|
import { LifecycleHooks } from './enums'
|
||||||
import type { SlotsType } from './componentSlots'
|
import type { SlotsType } from './componentSlots'
|
||||||
import { normalizePropsOrEmits } from './apiSetupHelpers'
|
import {
|
||||||
|
type ComponentTypeEmits,
|
||||||
|
normalizePropsOrEmits,
|
||||||
|
} from './apiSetupHelpers'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for declaring custom options.
|
* Interface for declaring custom options.
|
||||||
|
@ -113,7 +120,11 @@ export interface ComponentOptionsBase<
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string,
|
II extends string = string,
|
||||||
S extends SlotsType = {},
|
S extends SlotsType = {},
|
||||||
> extends LegacyOptions<Props, D, C, M, Mixin, Extends, I, II>,
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
> extends LegacyOptions<Props, D, C, M, Mixin, Extends, I, II, Provide>,
|
||||||
ComponentInternalOptions,
|
ComponentInternalOptions,
|
||||||
ComponentCustomOptions {
|
ComponentCustomOptions {
|
||||||
setup?: (
|
setup?: (
|
||||||
|
@ -137,13 +148,16 @@ export interface ComponentOptionsBase<
|
||||||
// Luckily `render()` doesn't need any arguments nor does it care about return
|
// Luckily `render()` doesn't need any arguments nor does it care about return
|
||||||
// type.
|
// type.
|
||||||
render?: Function
|
render?: Function
|
||||||
components?: Record<string, Component>
|
// NOTE: extending both LC and Record<string, Component> allows objects to be forced
|
||||||
directives?: Record<string, Directive>
|
// to be of type Component, while still inferring LC generic
|
||||||
|
components?: LC & Record<string, Component>
|
||||||
|
// NOTE: extending both Directives and Record<string, Directive> allows objects to be forced
|
||||||
|
// to be of type Directive, while still inferring Directives generic
|
||||||
|
directives?: Directives & Record<string, Directive>
|
||||||
inheritAttrs?: boolean
|
inheritAttrs?: boolean
|
||||||
emits?: (E | EE[]) & ThisType<void>
|
emits?: (E | EE[]) & ThisType<void>
|
||||||
slots?: S
|
slots?: S
|
||||||
// TODO infer public instance type based on exposed keys
|
expose?: Exposed[]
|
||||||
expose?: string[]
|
|
||||||
serverPrefetch?(): void | Promise<any>
|
serverPrefetch?(): void | Promise<any>
|
||||||
|
|
||||||
// Runtime compiler only -----------------------------------------------------
|
// Runtime compiler only -----------------------------------------------------
|
||||||
|
@ -212,151 +226,6 @@ export interface RuntimeCompilerOptions {
|
||||||
delimiters?: [string, string]
|
delimiters?: [string, string]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ComponentOptionsWithoutProps<
|
|
||||||
Props = {},
|
|
||||||
RawBindings = {},
|
|
||||||
D = {},
|
|
||||||
C extends ComputedOptions = {},
|
|
||||||
M extends MethodOptions = {},
|
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
E extends EmitsOptions = EmitsOptions,
|
|
||||||
EE extends string = string,
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
PE = Props & EmitsToProps<E>,
|
|
||||||
> = ComponentOptionsBase<
|
|
||||||
PE,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
{},
|
|
||||||
I,
|
|
||||||
II,
|
|
||||||
S
|
|
||||||
> & {
|
|
||||||
props?: undefined
|
|
||||||
} & ThisType<
|
|
||||||
CreateComponentPublicInstance<
|
|
||||||
PE,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
PE,
|
|
||||||
{},
|
|
||||||
false,
|
|
||||||
I,
|
|
||||||
S
|
|
||||||
>
|
|
||||||
>
|
|
||||||
|
|
||||||
export type ComponentOptionsWithArrayProps<
|
|
||||||
PropNames extends string = string,
|
|
||||||
RawBindings = {},
|
|
||||||
D = {},
|
|
||||||
C extends ComputedOptions = {},
|
|
||||||
M extends MethodOptions = {},
|
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
E extends EmitsOptions = EmitsOptions,
|
|
||||||
EE extends string = string,
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>,
|
|
||||||
> = ComponentOptionsBase<
|
|
||||||
Props,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
{},
|
|
||||||
I,
|
|
||||||
II,
|
|
||||||
S
|
|
||||||
> & {
|
|
||||||
props: PropNames[]
|
|
||||||
} & ThisType<
|
|
||||||
CreateComponentPublicInstance<
|
|
||||||
Props,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
Props,
|
|
||||||
{},
|
|
||||||
false,
|
|
||||||
I,
|
|
||||||
S
|
|
||||||
>
|
|
||||||
>
|
|
||||||
|
|
||||||
export type ComponentOptionsWithObjectProps<
|
|
||||||
PropsOptions = ComponentObjectPropsOptions,
|
|
||||||
RawBindings = {},
|
|
||||||
D = {},
|
|
||||||
C extends ComputedOptions = {},
|
|
||||||
M extends MethodOptions = {},
|
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
E extends EmitsOptions = EmitsOptions,
|
|
||||||
EE extends string = string,
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
Props = Prettify<Readonly<ExtractPropTypes<PropsOptions> & EmitsToProps<E>>>,
|
|
||||||
Defaults = ExtractDefaultPropTypes<PropsOptions>,
|
|
||||||
> = ComponentOptionsBase<
|
|
||||||
Props,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
Defaults,
|
|
||||||
I,
|
|
||||||
II,
|
|
||||||
S
|
|
||||||
> & {
|
|
||||||
props: PropsOptions & ThisType<void>
|
|
||||||
} & ThisType<
|
|
||||||
CreateComponentPublicInstance<
|
|
||||||
Props,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
Props,
|
|
||||||
Defaults,
|
|
||||||
false,
|
|
||||||
I,
|
|
||||||
S
|
|
||||||
>
|
|
||||||
>
|
|
||||||
|
|
||||||
export type ComponentOptions<
|
export type ComponentOptions<
|
||||||
Props = {},
|
Props = {},
|
||||||
RawBindings = any,
|
RawBindings = any,
|
||||||
|
@ -366,7 +235,15 @@ export type ComponentOptions<
|
||||||
Mixin extends ComponentOptionsMixin = any,
|
Mixin extends ComponentOptionsMixin = any,
|
||||||
Extends extends ComponentOptionsMixin = any,
|
Extends extends ComponentOptionsMixin = any,
|
||||||
E extends EmitsOptions = any,
|
E extends EmitsOptions = any,
|
||||||
S extends SlotsType = any,
|
EE extends string = string,
|
||||||
|
Defaults = {},
|
||||||
|
I extends ComponentInjectOptions = {},
|
||||||
|
II extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
> = ComponentOptionsBase<
|
> = ComponentOptionsBase<
|
||||||
Props,
|
Props,
|
||||||
RawBindings,
|
RawBindings,
|
||||||
|
@ -376,8 +253,15 @@ export type ComponentOptions<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
string,
|
EE,
|
||||||
S
|
Defaults,
|
||||||
|
I,
|
||||||
|
II,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed,
|
||||||
|
Provide
|
||||||
> &
|
> &
|
||||||
ThisType<
|
ThisType<
|
||||||
CreateComponentPublicInstance<
|
CreateComponentPublicInstance<
|
||||||
|
@ -389,7 +273,13 @@ export type ComponentOptions<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
Readonly<Props>
|
Readonly<Props>,
|
||||||
|
Defaults,
|
||||||
|
false,
|
||||||
|
I,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
|
|
||||||
|
@ -404,6 +294,12 @@ export type ComponentOptionsMixin = ComponentOptionsBase<
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
any
|
any
|
||||||
>
|
>
|
||||||
|
|
||||||
|
@ -465,6 +361,7 @@ interface LegacyOptions<
|
||||||
Extends extends ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin,
|
||||||
I extends ComponentInjectOptions,
|
I extends ComponentInjectOptions,
|
||||||
II extends string,
|
II extends string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
> {
|
> {
|
||||||
compatConfig?: CompatConfig
|
compatConfig?: CompatConfig
|
||||||
|
|
||||||
|
@ -498,7 +395,7 @@ interface LegacyOptions<
|
||||||
computed?: C
|
computed?: C
|
||||||
methods?: M
|
methods?: M
|
||||||
watch?: ComponentWatchOptions
|
watch?: ComponentWatchOptions
|
||||||
provide?: ComponentProvideOptions
|
provide?: Provide
|
||||||
inject?: I | II[]
|
inject?: I | II[]
|
||||||
|
|
||||||
// assets
|
// assets
|
||||||
|
@ -1199,3 +1096,203 @@ function mergeWatchOptions(
|
||||||
}
|
}
|
||||||
return merged
|
return merged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated legacy types, kept because they were previously exported ---------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
export type ComponentOptionsWithoutProps<
|
||||||
|
Props = {},
|
||||||
|
RawBindings = {},
|
||||||
|
D = {},
|
||||||
|
C extends ComputedOptions = {},
|
||||||
|
M extends MethodOptions = {},
|
||||||
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
|
E extends EmitsOptions = {},
|
||||||
|
EE extends string = string,
|
||||||
|
I extends ComponentInjectOptions = {},
|
||||||
|
II extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
TE extends ComponentTypeEmits = {},
|
||||||
|
ResolvedEmits extends EmitsOptions = {} extends E
|
||||||
|
? TypeEmitsToOptions<TE>
|
||||||
|
: E,
|
||||||
|
PE = Props & EmitsToProps<ResolvedEmits>,
|
||||||
|
> = ComponentOptionsBase<
|
||||||
|
PE,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
E,
|
||||||
|
EE,
|
||||||
|
{},
|
||||||
|
I,
|
||||||
|
II,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed,
|
||||||
|
Provide
|
||||||
|
> & {
|
||||||
|
props?: never
|
||||||
|
/**
|
||||||
|
* @private for language-tools use only
|
||||||
|
*/
|
||||||
|
__typeProps?: Props
|
||||||
|
/**
|
||||||
|
* @private for language-tools use only
|
||||||
|
*/
|
||||||
|
__typeEmits?: TE
|
||||||
|
} & ThisType<
|
||||||
|
CreateComponentPublicInstance<
|
||||||
|
PE,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
ResolvedEmits,
|
||||||
|
EE,
|
||||||
|
{},
|
||||||
|
false,
|
||||||
|
I,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed
|
||||||
|
>
|
||||||
|
>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
export type ComponentOptionsWithArrayProps<
|
||||||
|
PropNames extends string = string,
|
||||||
|
RawBindings = {},
|
||||||
|
D = {},
|
||||||
|
C extends ComputedOptions = {},
|
||||||
|
M extends MethodOptions = {},
|
||||||
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
|
E extends EmitsOptions = EmitsOptions,
|
||||||
|
EE extends string = string,
|
||||||
|
I extends ComponentInjectOptions = {},
|
||||||
|
II extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>,
|
||||||
|
> = ComponentOptionsBase<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
E,
|
||||||
|
EE,
|
||||||
|
{},
|
||||||
|
I,
|
||||||
|
II,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed,
|
||||||
|
Provide
|
||||||
|
> & {
|
||||||
|
props: PropNames[]
|
||||||
|
} & ThisType<
|
||||||
|
CreateComponentPublicInstance<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
E,
|
||||||
|
Props,
|
||||||
|
{},
|
||||||
|
false,
|
||||||
|
I,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed
|
||||||
|
>
|
||||||
|
>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
export type ComponentOptionsWithObjectProps<
|
||||||
|
PropsOptions = ComponentObjectPropsOptions,
|
||||||
|
RawBindings = {},
|
||||||
|
D = {},
|
||||||
|
C extends ComputedOptions = {},
|
||||||
|
M extends MethodOptions = {},
|
||||||
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
|
E extends EmitsOptions = EmitsOptions,
|
||||||
|
EE extends string = string,
|
||||||
|
I extends ComponentInjectOptions = {},
|
||||||
|
II extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
Props = Prettify<Readonly<ExtractPropTypes<PropsOptions> & EmitsToProps<E>>>,
|
||||||
|
Defaults = ExtractDefaultPropTypes<PropsOptions>,
|
||||||
|
> = ComponentOptionsBase<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
E,
|
||||||
|
EE,
|
||||||
|
Defaults,
|
||||||
|
I,
|
||||||
|
II,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed,
|
||||||
|
Provide
|
||||||
|
> & {
|
||||||
|
props: PropsOptions & ThisType<void>
|
||||||
|
} & ThisType<
|
||||||
|
CreateComponentPublicInstance<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
E,
|
||||||
|
Props,
|
||||||
|
Defaults,
|
||||||
|
false,
|
||||||
|
I,
|
||||||
|
S,
|
||||||
|
LC,
|
||||||
|
Directives
|
||||||
|
>
|
||||||
|
>
|
||||||
|
|
|
@ -67,7 +67,7 @@ export interface PropOptions<T = any, D = T> {
|
||||||
skipFactory?: boolean
|
skipFactory?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PropType<T> = PropConstructor<T> | PropConstructor<T>[]
|
export type PropType<T> = PropConstructor<T> | (PropConstructor<T> | null)[]
|
||||||
|
|
||||||
type PropConstructor<T = any> =
|
type PropConstructor<T = any> =
|
||||||
| { new (...args: any[]): T & {} }
|
| { new (...args: any[]): T & {} }
|
||||||
|
@ -107,8 +107,10 @@ type DefaultKeys<T> = {
|
||||||
: never
|
: never
|
||||||
}[keyof T]
|
}[keyof T]
|
||||||
|
|
||||||
type InferPropType<T> = [T] extends [null]
|
type InferPropType<T, NullAsAny = true> = [T] extends [null]
|
||||||
? any // null & true would fail to infer
|
? NullAsAny extends true
|
||||||
|
? any
|
||||||
|
: null
|
||||||
: [T] extends [{ type: null | true }]
|
: [T] extends [{ type: null | true }]
|
||||||
? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
|
? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
|
||||||
: [T] extends [ObjectConstructor | { type: ObjectConstructor }]
|
: [T] extends [ObjectConstructor | { type: ObjectConstructor }]
|
||||||
|
@ -119,8 +121,8 @@ type InferPropType<T> = [T] extends [null]
|
||||||
? Date
|
? Date
|
||||||
: [T] extends [(infer U)[] | { type: (infer U)[] }]
|
: [T] extends [(infer U)[] | { type: (infer U)[] }]
|
||||||
? U extends DateConstructor
|
? U extends DateConstructor
|
||||||
? Date | InferPropType<U>
|
? Date | InferPropType<U, false>
|
||||||
: InferPropType<U>
|
: InferPropType<U, false>
|
||||||
: [T] extends [Prop<infer V, infer D>]
|
: [T] extends [Prop<infer V, infer D>]
|
||||||
? unknown extends V
|
? unknown extends V
|
||||||
? IfAny<V, V, D>
|
? IfAny<V, V, D>
|
||||||
|
@ -594,7 +596,7 @@ function validatePropName(key: string) {
|
||||||
|
|
||||||
// use function string name to check type constructors
|
// use function string name to check type constructors
|
||||||
// so that it works across vms / iframes.
|
// so that it works across vms / iframes.
|
||||||
function getType(ctor: Prop<any>): string {
|
function getType(ctor: Prop<any> | null): string {
|
||||||
// Early return for null to avoid unnecessary computations
|
// Early return for null to avoid unnecessary computations
|
||||||
if (ctor === null) {
|
if (ctor === null) {
|
||||||
return 'null'
|
return 'null'
|
||||||
|
@ -614,7 +616,7 @@ function getType(ctor: Prop<any>): string {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSameType(a: Prop<any>, b: Prop<any>): boolean {
|
function isSameType(a: Prop<any> | null, b: Prop<any> | null): boolean {
|
||||||
return getType(a) === getType(b)
|
return getType(a) === getType(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,24 +709,27 @@ type AssertionResult = {
|
||||||
/**
|
/**
|
||||||
* dev only
|
* dev only
|
||||||
*/
|
*/
|
||||||
function assertType(value: unknown, type: PropConstructor): AssertionResult {
|
function assertType(
|
||||||
|
value: unknown,
|
||||||
|
type: PropConstructor | null,
|
||||||
|
): AssertionResult {
|
||||||
let valid
|
let valid
|
||||||
const expectedType = getType(type)
|
const expectedType = getType(type)
|
||||||
if (isSimpleType(expectedType)) {
|
if (expectedType === 'null') {
|
||||||
|
valid = value === null
|
||||||
|
} else if (isSimpleType(expectedType)) {
|
||||||
const t = typeof value
|
const t = typeof value
|
||||||
valid = t === expectedType.toLowerCase()
|
valid = t === expectedType.toLowerCase()
|
||||||
// for primitive wrapper objects
|
// for primitive wrapper objects
|
||||||
if (!valid && t === 'object') {
|
if (!valid && t === 'object') {
|
||||||
valid = value instanceof type
|
valid = value instanceof (type as PropConstructor)
|
||||||
}
|
}
|
||||||
} else if (expectedType === 'Object') {
|
} else if (expectedType === 'Object') {
|
||||||
valid = isObject(value)
|
valid = isObject(value)
|
||||||
} else if (expectedType === 'Array') {
|
} else if (expectedType === 'Array') {
|
||||||
valid = isArray(value)
|
valid = isArray(value)
|
||||||
} else if (expectedType === 'null') {
|
|
||||||
valid = value === null
|
|
||||||
} else {
|
} else {
|
||||||
valid = value instanceof type
|
valid = value instanceof (type as PropConstructor)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
valid,
|
valid,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {
|
import {
|
||||||
|
type Component,
|
||||||
type ComponentInternalInstance,
|
type ComponentInternalInstance,
|
||||||
getExposeProxy,
|
getExposeProxy,
|
||||||
isStatefulComponent,
|
isStatefulComponent,
|
||||||
|
@ -35,6 +36,7 @@ import {
|
||||||
type ComponentInjectOptions,
|
type ComponentInjectOptions,
|
||||||
type ComponentOptionsBase,
|
type ComponentOptionsBase,
|
||||||
type ComponentOptionsMixin,
|
type ComponentOptionsMixin,
|
||||||
|
type ComponentProvideOptions,
|
||||||
type ComputedOptions,
|
type ComputedOptions,
|
||||||
type ExtractComputedReturns,
|
type ExtractComputedReturns,
|
||||||
type InjectToObject,
|
type InjectToObject,
|
||||||
|
@ -51,6 +53,7 @@ import { markAttrsAccessed } from './componentRenderUtils'
|
||||||
import { currentRenderingInstance } from './componentRenderContext'
|
import { currentRenderingInstance } from './componentRenderContext'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { installCompatInstanceProperties } from './compat/instance'
|
import { installCompatInstanceProperties } from './compat/instance'
|
||||||
|
import type { Directive } from './directives'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom properties added to component instances in any way and can be accessed through `this`
|
* Custom properties added to component instances in any way and can be accessed through `this`
|
||||||
|
@ -99,6 +102,10 @@ type MixinToOptionTypes<T> =
|
||||||
infer Defaults,
|
infer Defaults,
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
any
|
any
|
||||||
>
|
>
|
||||||
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
|
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
|
||||||
|
@ -157,6 +164,9 @@ export type CreateComponentPublicInstance<
|
||||||
MakeDefaultsOptional extends boolean = false,
|
MakeDefaultsOptional extends boolean = false,
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
S extends SlotsType = {},
|
S extends SlotsType = {},
|
||||||
|
LC extends Record<string, Component> = {},
|
||||||
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
|
PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
|
||||||
PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,
|
PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,
|
||||||
PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,
|
PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,
|
||||||
|
@ -167,6 +177,7 @@ export type CreateComponentPublicInstance<
|
||||||
EnsureNonVoid<M>,
|
EnsureNonVoid<M>,
|
||||||
PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &
|
PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &
|
||||||
EnsureNonVoid<Defaults>,
|
EnsureNonVoid<Defaults>,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
> = ComponentPublicInstance<
|
> = ComponentPublicInstance<
|
||||||
PublicP,
|
PublicP,
|
||||||
PublicB,
|
PublicB,
|
||||||
|
@ -190,11 +201,22 @@ export type CreateComponentPublicInstance<
|
||||||
Defaults,
|
Defaults,
|
||||||
{},
|
{},
|
||||||
string,
|
string,
|
||||||
S
|
S,
|
||||||
|
LC,
|
||||||
|
Directives,
|
||||||
|
Exposed,
|
||||||
|
Provide
|
||||||
>,
|
>,
|
||||||
I,
|
I,
|
||||||
S
|
S,
|
||||||
|
Exposed
|
||||||
>
|
>
|
||||||
|
|
||||||
|
export type ExposedKeys<
|
||||||
|
T,
|
||||||
|
Exposed extends string & keyof T,
|
||||||
|
> = '' extends Exposed ? T : Pick<T, Exposed>
|
||||||
|
|
||||||
// public properties exposed on the proxy, which is used as the render context
|
// public properties exposed on the proxy, which is used as the render context
|
||||||
// in templates (as `this` in the render option)
|
// in templates (as `this` in the render option)
|
||||||
export type ComponentPublicInstance<
|
export type ComponentPublicInstance<
|
||||||
|
@ -210,6 +232,7 @@ export type ComponentPublicInstance<
|
||||||
Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>,
|
Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>,
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
S extends SlotsType = {},
|
S extends SlotsType = {},
|
||||||
|
Exposed extends string = '',
|
||||||
> = {
|
> = {
|
||||||
$: ComponentInternalInstance
|
$: ComponentInternalInstance
|
||||||
$data: D
|
$data: D
|
||||||
|
@ -233,13 +256,16 @@ export type ComponentPublicInstance<
|
||||||
: (...args: any) => any,
|
: (...args: any) => any,
|
||||||
options?: WatchOptions,
|
options?: WatchOptions,
|
||||||
): WatchStopHandle
|
): WatchStopHandle
|
||||||
} & IfAny<P, P, Omit<P, keyof ShallowUnwrapRef<B>>> &
|
} & ExposedKeys<
|
||||||
|
IfAny<P, P, Omit<P, keyof ShallowUnwrapRef<B>>> &
|
||||||
ShallowUnwrapRef<B> &
|
ShallowUnwrapRef<B> &
|
||||||
UnwrapNestedRefs<D> &
|
UnwrapNestedRefs<D> &
|
||||||
ExtractComputedReturns<C> &
|
ExtractComputedReturns<C> &
|
||||||
M &
|
M &
|
||||||
ComponentCustomProperties &
|
ComponentCustomProperties &
|
||||||
InjectToObject<I>
|
InjectToObject<I>,
|
||||||
|
Exposed
|
||||||
|
>
|
||||||
|
|
||||||
export type PublicPropertiesMap = Record<
|
export type PublicPropertiesMap = Record<
|
||||||
string,
|
string,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { SchedulerJobFlags, toRaw } from '@vue/reactivity'
|
||||||
import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling'
|
import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling'
|
||||||
import { PatchFlags, ShapeFlags, isArray, isFunction } from '@vue/shared'
|
import { PatchFlags, ShapeFlags, isArray, isFunction } from '@vue/shared'
|
||||||
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
|
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
|
||||||
|
import { isTeleport } from './Teleport'
|
||||||
import type { RendererElement } from '../renderer'
|
import type { RendererElement } from '../renderer'
|
||||||
|
|
||||||
type Hook<T = () => void> = T | T[]
|
type Hook<T = () => void> = T | T[]
|
||||||
|
@ -151,27 +152,7 @@ const BaseTransitionImpl: ComponentOptions = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let child: VNode = children[0]
|
const child: VNode = findNonCommentChild(children)
|
||||||
if (children.length > 1) {
|
|
||||||
let hasFound = false
|
|
||||||
// locate first non-comment child
|
|
||||||
for (const c of children) {
|
|
||||||
if (c.type !== Comment) {
|
|
||||||
if (__DEV__ && hasFound) {
|
|
||||||
// warn more than one non-comment child
|
|
||||||
warn(
|
|
||||||
'<transition> can only be used on a single element or component. ' +
|
|
||||||
'Use <transition-group> for lists.',
|
|
||||||
)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
child = c
|
|
||||||
hasFound = true
|
|
||||||
if (!__DEV__) break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// there's no need to track reactivity for these props so use the raw
|
// there's no need to track reactivity for these props so use the raw
|
||||||
// props for a bit better perf
|
// props for a bit better perf
|
||||||
const rawProps = toRaw(props)
|
const rawProps = toRaw(props)
|
||||||
|
@ -193,7 +174,7 @@ const BaseTransitionImpl: ComponentOptions = {
|
||||||
|
|
||||||
// in the case of <transition><keep-alive/></transition>, we need to
|
// in the case of <transition><keep-alive/></transition>, we need to
|
||||||
// compare the type of the kept-alive children.
|
// compare the type of the kept-alive children.
|
||||||
const innerChild = getKeepAliveChild(child)
|
const innerChild = getInnerChild(child)
|
||||||
if (!innerChild) {
|
if (!innerChild) {
|
||||||
return emptyPlaceholder(child)
|
return emptyPlaceholder(child)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +188,7 @@ const BaseTransitionImpl: ComponentOptions = {
|
||||||
setTransitionHooks(innerChild, enterHooks)
|
setTransitionHooks(innerChild, enterHooks)
|
||||||
|
|
||||||
const oldChild = instance.subTree
|
const oldChild = instance.subTree
|
||||||
const oldInnerChild = oldChild && getKeepAliveChild(oldChild)
|
const oldInnerChild = oldChild && getInnerChild(oldChild)
|
||||||
|
|
||||||
// handle mode
|
// handle mode
|
||||||
if (
|
if (
|
||||||
|
@ -267,6 +248,30 @@ if (__COMPAT__) {
|
||||||
BaseTransitionImpl.__isBuiltIn = true
|
BaseTransitionImpl.__isBuiltIn = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findNonCommentChild(children: VNode[]): VNode {
|
||||||
|
let child: VNode = children[0]
|
||||||
|
if (children.length > 1) {
|
||||||
|
let hasFound = false
|
||||||
|
// locate first non-comment child
|
||||||
|
for (const c of children) {
|
||||||
|
if (c.type !== Comment) {
|
||||||
|
if (__DEV__ && hasFound) {
|
||||||
|
// warn more than one non-comment child
|
||||||
|
warn(
|
||||||
|
'<transition> can only be used on a single element or component. ' +
|
||||||
|
'Use <transition-group> for lists.',
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
child = c
|
||||||
|
hasFound = true
|
||||||
|
if (!__DEV__) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
|
||||||
// export the public type for h/tsx inference
|
// export the public type for h/tsx inference
|
||||||
// also to avoid inline import() in generated d.ts files
|
// also to avoid inline import() in generated d.ts files
|
||||||
export const BaseTransition = BaseTransitionImpl as unknown as {
|
export const BaseTransition = BaseTransitionImpl as unknown as {
|
||||||
|
@ -457,8 +462,12 @@ function emptyPlaceholder(vnode: VNode): VNode | undefined {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getKeepAliveChild(vnode: VNode): VNode | undefined {
|
function getInnerChild(vnode: VNode): VNode | undefined {
|
||||||
if (!isKeepAlive(vnode)) {
|
if (!isKeepAlive(vnode)) {
|
||||||
|
if (isTeleport(vnode.type) && vnode.children) {
|
||||||
|
return findNonCommentChild(vnode.children as VNode[])
|
||||||
|
}
|
||||||
|
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
// #7121 ensure get the child component subtree in case
|
// #7121 ensure get the child component subtree in case
|
||||||
|
|
|
@ -26,19 +26,29 @@ import type { ComponentPublicInstance } from './componentPublicInstance'
|
||||||
import { mapCompatDirectiveHook } from './compat/customDirective'
|
import { mapCompatDirectiveHook } from './compat/customDirective'
|
||||||
import { pauseTracking, resetTracking, traverse } from '@vue/reactivity'
|
import { pauseTracking, resetTracking, traverse } from '@vue/reactivity'
|
||||||
|
|
||||||
export interface DirectiveBinding<V = any> {
|
export interface DirectiveBinding<
|
||||||
|
Value = any,
|
||||||
|
Modifiers extends string = string,
|
||||||
|
Arg extends string = string,
|
||||||
|
> {
|
||||||
instance: ComponentPublicInstance | null
|
instance: ComponentPublicInstance | null
|
||||||
value: V
|
value: Value
|
||||||
oldValue: V | null
|
oldValue: Value | null
|
||||||
arg?: string
|
arg?: Arg
|
||||||
modifiers: DirectiveModifiers
|
modifiers: DirectiveModifiers<Modifiers>
|
||||||
dir: ObjectDirective<any, V>
|
dir: ObjectDirective<any, Value>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DirectiveHook<T = any, Prev = VNode<any, T> | null, V = any> = (
|
export type DirectiveHook<
|
||||||
el: T,
|
HostElement = any,
|
||||||
binding: DirectiveBinding<V>,
|
Prev = VNode<any, HostElement> | null,
|
||||||
vnode: VNode<any, T>,
|
Value = any,
|
||||||
|
Modifiers extends string = string,
|
||||||
|
Arg extends string = string,
|
||||||
|
> = (
|
||||||
|
el: HostElement,
|
||||||
|
binding: DirectiveBinding<Value, Modifiers, Arg>,
|
||||||
|
vnode: VNode<any, HostElement>,
|
||||||
prevVNode: Prev,
|
prevVNode: Prev,
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
|
@ -47,25 +57,52 @@ export type SSRDirectiveHook = (
|
||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
) => Data | undefined
|
) => Data | undefined
|
||||||
|
|
||||||
export interface ObjectDirective<T = any, V = any> {
|
export interface ObjectDirective<
|
||||||
created?: DirectiveHook<T, null, V>
|
HostElement = any,
|
||||||
beforeMount?: DirectiveHook<T, null, V>
|
Value = any,
|
||||||
mounted?: DirectiveHook<T, null, V>
|
Modifiers extends string = string,
|
||||||
beforeUpdate?: DirectiveHook<T, VNode<any, T>, V>
|
Arg extends string = string,
|
||||||
updated?: DirectiveHook<T, VNode<any, T>, V>
|
> {
|
||||||
beforeUnmount?: DirectiveHook<T, null, V>
|
created?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>
|
||||||
unmounted?: DirectiveHook<T, null, V>
|
beforeMount?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>
|
||||||
|
mounted?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>
|
||||||
|
beforeUpdate?: DirectiveHook<
|
||||||
|
HostElement,
|
||||||
|
VNode<any, HostElement>,
|
||||||
|
Value,
|
||||||
|
Modifiers,
|
||||||
|
Arg
|
||||||
|
>
|
||||||
|
updated?: DirectiveHook<
|
||||||
|
HostElement,
|
||||||
|
VNode<any, HostElement>,
|
||||||
|
Value,
|
||||||
|
Modifiers,
|
||||||
|
Arg
|
||||||
|
>
|
||||||
|
beforeUnmount?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>
|
||||||
|
unmounted?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>
|
||||||
getSSRProps?: SSRDirectiveHook
|
getSSRProps?: SSRDirectiveHook
|
||||||
deep?: boolean
|
deep?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FunctionDirective<T = any, V = any> = DirectiveHook<T, any, V>
|
export type FunctionDirective<
|
||||||
|
HostElement = any,
|
||||||
|
V = any,
|
||||||
|
Modifiers extends string = string,
|
||||||
|
Arg extends string = string,
|
||||||
|
> = DirectiveHook<HostElement, any, V, Modifiers, Arg>
|
||||||
|
|
||||||
export type Directive<T = any, V = any> =
|
export type Directive<
|
||||||
| ObjectDirective<T, V>
|
HostElement = any,
|
||||||
| FunctionDirective<T, V>
|
Value = any,
|
||||||
|
Modifiers extends string = string,
|
||||||
|
Arg extends string = string,
|
||||||
|
> =
|
||||||
|
| ObjectDirective<HostElement, Value, Modifiers, Arg>
|
||||||
|
| FunctionDirective<HostElement, Value, Modifiers, Arg>
|
||||||
|
|
||||||
export type DirectiveModifiers = Record<string, boolean>
|
export type DirectiveModifiers<K extends string = string> = Record<K, boolean>
|
||||||
|
|
||||||
export function validateDirectiveName(name: string) {
|
export function validateDirectiveName(name: string) {
|
||||||
if (isBuiltInDirective(name)) {
|
if (isBuiltInDirective(name)) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ export {
|
||||||
withDefaults,
|
withDefaults,
|
||||||
type DefineProps,
|
type DefineProps,
|
||||||
type ModelRef,
|
type ModelRef,
|
||||||
|
type ComponentTypeEmits,
|
||||||
} from './apiSetupHelpers'
|
} from './apiSetupHelpers'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -249,6 +250,8 @@ export type {
|
||||||
SetupContext,
|
SetupContext,
|
||||||
ComponentCustomProps,
|
ComponentCustomProps,
|
||||||
AllowedComponentProps,
|
AllowedComponentProps,
|
||||||
|
GlobalComponents,
|
||||||
|
GlobalDirectives,
|
||||||
ComponentInstance,
|
ComponentInstance,
|
||||||
} from './component'
|
} from './component'
|
||||||
export type {
|
export type {
|
||||||
|
@ -259,9 +262,6 @@ export type {
|
||||||
export type {
|
export type {
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
ComponentOptionsWithoutProps,
|
|
||||||
ComponentOptionsWithObjectProps,
|
|
||||||
ComponentOptionsWithArrayProps,
|
|
||||||
ComponentCustomOptions,
|
ComponentCustomOptions,
|
||||||
ComponentOptionsBase,
|
ComponentOptionsBase,
|
||||||
ComponentProvideOptions,
|
ComponentProvideOptions,
|
||||||
|
@ -271,7 +271,11 @@ export type {
|
||||||
RuntimeCompilerOptions,
|
RuntimeCompilerOptions,
|
||||||
ComponentInjectOptions,
|
ComponentInjectOptions,
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
export type { EmitsOptions, ObjectEmitsOptions } from './componentEmits'
|
export type {
|
||||||
|
EmitsOptions,
|
||||||
|
ObjectEmitsOptions,
|
||||||
|
EmitsToProps,
|
||||||
|
} from './componentEmits'
|
||||||
export type {
|
export type {
|
||||||
ComponentPublicInstance,
|
ComponentPublicInstance,
|
||||||
ComponentCustomProperties,
|
ComponentCustomProperties,
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Note: this file is auto concatenated to the end of the bundled d.ts during
|
||||||
|
// build.
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
Teleport: DefineComponent<TeleportProps>
|
||||||
|
Suspense: DefineComponent<SuspenseProps>
|
||||||
|
KeepAlive: DefineComponent<KeepAliveProps>
|
||||||
|
BaseTransition: DefineComponent<BaseTransitionProps>
|
||||||
|
}
|
||||||
|
}
|
|
@ -88,10 +88,14 @@ describe('defineCustomElement', () => {
|
||||||
|
|
||||||
describe('props', () => {
|
describe('props', () => {
|
||||||
const E = defineCustomElement({
|
const E = defineCustomElement({
|
||||||
props: ['foo', 'bar', 'bazQux'],
|
props: {
|
||||||
|
foo: [String, null],
|
||||||
|
bar: Object,
|
||||||
|
bazQux: null,
|
||||||
|
},
|
||||||
render() {
|
render() {
|
||||||
return [
|
return [
|
||||||
h('div', null, this.foo),
|
h('div', null, this.foo || ''),
|
||||||
h('div', null, this.bazQux || (this.bar && this.bar.x)),
|
h('div', null, this.bazQux || (this.bar && this.bar.x)),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,7 +43,7 @@ describe('runtime-dom: v-on directive', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('it should support key modifiers and system modifiers', () => {
|
test('it should support key modifiers and system modifiers', () => {
|
||||||
const keyNames = ['ctrl', 'shift', 'meta', 'alt']
|
const keyNames = ['ctrl', 'shift', 'meta', 'alt'] as const
|
||||||
|
|
||||||
keyNames.forEach(keyName => {
|
keyNames.forEach(keyName => {
|
||||||
const el = document.createElement('div')
|
const el = document.createElement('div')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/runtime-dom",
|
"name": "@vue/runtime-dom",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/runtime-dom",
|
"description": "@vue/runtime-dom",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/runtime-dom.esm-bundler.js",
|
"module": "dist/runtime-dom.esm-bundler.js",
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
import {
|
import {
|
||||||
|
type Component,
|
||||||
type ComponentInjectOptions,
|
type ComponentInjectOptions,
|
||||||
type ComponentInternalInstance,
|
type ComponentInternalInstance,
|
||||||
|
type ComponentObjectPropsOptions,
|
||||||
type ComponentOptions,
|
type ComponentOptions,
|
||||||
|
type ComponentOptionsBase,
|
||||||
type ComponentOptionsMixin,
|
type ComponentOptionsMixin,
|
||||||
type ComponentOptionsWithArrayProps,
|
type ComponentProvideOptions,
|
||||||
type ComponentOptionsWithObjectProps,
|
|
||||||
type ComponentOptionsWithoutProps,
|
|
||||||
type ComponentPropsOptions,
|
|
||||||
type ComputedOptions,
|
type ComputedOptions,
|
||||||
type ConcreteComponent,
|
type ConcreteComponent,
|
||||||
|
type CreateComponentPublicInstance,
|
||||||
type DefineComponent,
|
type DefineComponent,
|
||||||
|
type Directive,
|
||||||
type EmitsOptions,
|
type EmitsOptions,
|
||||||
|
type EmitsToProps,
|
||||||
type ExtractPropTypes,
|
type ExtractPropTypes,
|
||||||
type MethodOptions,
|
type MethodOptions,
|
||||||
type RenderFunction,
|
type RenderFunction,
|
||||||
|
@ -41,98 +44,79 @@ export function defineCustomElement<Props, RawBindings = object>(
|
||||||
) => RawBindings | RenderFunction,
|
) => RawBindings | RenderFunction,
|
||||||
): VueElementConstructor<Props>
|
): VueElementConstructor<Props>
|
||||||
|
|
||||||
// overload 2: object format with no props
|
// overload 2: defineCustomElement with options object, infer props from options
|
||||||
export function defineCustomElement<
|
export function defineCustomElement<
|
||||||
Props = {},
|
// props
|
||||||
RawBindings = {},
|
RuntimePropsOptions extends
|
||||||
D = {},
|
ComponentObjectPropsOptions = ComponentObjectPropsOptions,
|
||||||
C extends ComputedOptions = {},
|
PropsKeys extends string = string,
|
||||||
M extends MethodOptions = {},
|
// emits
|
||||||
|
RuntimeEmitsOptions extends EmitsOptions = {},
|
||||||
|
EmitsKeys extends string = string,
|
||||||
|
// other options
|
||||||
|
Data = {},
|
||||||
|
SetupBindings = {},
|
||||||
|
Computed extends ComputedOptions = {},
|
||||||
|
Methods extends MethodOptions = {},
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = EmitsOptions,
|
InjectOptions extends ComponentInjectOptions = {},
|
||||||
EE extends string = string,
|
InjectKeys extends string = string,
|
||||||
I extends ComponentInjectOptions = {},
|
Slots extends SlotsType = {},
|
||||||
II extends string = string,
|
LocalComponents extends Record<string, Component> = {},
|
||||||
S extends SlotsType = {},
|
Directives extends Record<string, Directive> = {},
|
||||||
|
Exposed extends string = string,
|
||||||
|
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||||
|
// resolved types
|
||||||
|
InferredProps = string extends PropsKeys
|
||||||
|
? ComponentObjectPropsOptions extends RuntimePropsOptions
|
||||||
|
? {}
|
||||||
|
: ExtractPropTypes<RuntimePropsOptions>
|
||||||
|
: { [key in PropsKeys]?: any },
|
||||||
|
ResolvedProps = InferredProps & EmitsToProps<RuntimeEmitsOptions>,
|
||||||
>(
|
>(
|
||||||
options: ComponentOptionsWithoutProps<
|
options: {
|
||||||
Props,
|
props?: (RuntimePropsOptions & ThisType<void>) | PropsKeys[]
|
||||||
RawBindings,
|
} & ComponentOptionsBase<
|
||||||
D,
|
ResolvedProps,
|
||||||
C,
|
SetupBindings,
|
||||||
M,
|
Data,
|
||||||
|
Computed,
|
||||||
|
Methods,
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
RuntimeEmitsOptions,
|
||||||
EE,
|
EmitsKeys,
|
||||||
I,
|
{}, // Defaults
|
||||||
II,
|
InjectOptions,
|
||||||
S
|
InjectKeys,
|
||||||
> & { styles?: string[] },
|
Slots,
|
||||||
): VueElementConstructor<Props>
|
LocalComponents,
|
||||||
|
Directives,
|
||||||
// overload 3: object format with array props declaration
|
Exposed,
|
||||||
export function defineCustomElement<
|
Provide
|
||||||
PropNames extends string,
|
> &
|
||||||
RawBindings,
|
ThisType<
|
||||||
D,
|
CreateComponentPublicInstance<
|
||||||
C extends ComputedOptions = {},
|
Readonly<ResolvedProps>,
|
||||||
M extends MethodOptions = {},
|
SetupBindings,
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Data,
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Computed,
|
||||||
E extends EmitsOptions = Record<string, any>,
|
Methods,
|
||||||
EE extends string = string,
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
>(
|
|
||||||
options: ComponentOptionsWithArrayProps<
|
|
||||||
PropNames,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
RuntimeEmitsOptions,
|
||||||
EE,
|
EmitsKeys,
|
||||||
I,
|
{},
|
||||||
II,
|
false,
|
||||||
S
|
InjectOptions,
|
||||||
> & { styles?: string[] },
|
Slots,
|
||||||
): VueElementConstructor<{ [K in PropNames]: any }>
|
LocalComponents,
|
||||||
|
Directives,
|
||||||
// overload 4: object format with object props declaration
|
Exposed
|
||||||
export function defineCustomElement<
|
>
|
||||||
PropsOptions extends Readonly<ComponentPropsOptions>,
|
>,
|
||||||
RawBindings,
|
): VueElementConstructor<ResolvedProps>
|
||||||
D,
|
|
||||||
C extends ComputedOptions = {},
|
|
||||||
M extends MethodOptions = {},
|
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
|
||||||
E extends EmitsOptions = Record<string, any>,
|
|
||||||
EE extends string = string,
|
|
||||||
I extends ComponentInjectOptions = {},
|
|
||||||
II extends string = string,
|
|
||||||
S extends SlotsType = {},
|
|
||||||
>(
|
|
||||||
options: ComponentOptionsWithObjectProps<
|
|
||||||
PropsOptions,
|
|
||||||
RawBindings,
|
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M,
|
|
||||||
Mixin,
|
|
||||||
Extends,
|
|
||||||
E,
|
|
||||||
EE,
|
|
||||||
I,
|
|
||||||
II,
|
|
||||||
S
|
|
||||||
> & { styles?: string[] },
|
|
||||||
): VueElementConstructor<ExtractPropTypes<PropsOptions>>
|
|
||||||
|
|
||||||
// overload 5: defining a custom element from the returned value of
|
// overload 5: defining a custom element from the returned value of
|
||||||
// `defineComponent`
|
// `defineComponent`
|
||||||
|
|
|
@ -39,14 +39,17 @@ function onCompositionEnd(e: Event) {
|
||||||
|
|
||||||
const assignKey = Symbol('_assign')
|
const assignKey = Symbol('_assign')
|
||||||
|
|
||||||
type ModelDirective<T> = ObjectDirective<
|
type ModelDirective<T, Modifiers extends string = string> = ObjectDirective<
|
||||||
T & { [assignKey]: AssignerFn; _assigning?: boolean }
|
T & { [assignKey]: AssignerFn; _assigning?: boolean },
|
||||||
|
any,
|
||||||
|
Modifiers
|
||||||
>
|
>
|
||||||
|
|
||||||
// We are exporting the v-model runtime directly as vnode hooks so that it can
|
// We are exporting the v-model runtime directly as vnode hooks so that it can
|
||||||
// be tree-shaken in case v-model is never used.
|
// be tree-shaken in case v-model is never used.
|
||||||
export const vModelText: ModelDirective<
|
export const vModelText: ModelDirective<
|
||||||
HTMLInputElement | HTMLTextAreaElement
|
HTMLInputElement | HTMLTextAreaElement,
|
||||||
|
'trim' | 'number' | 'lazy'
|
||||||
> = {
|
> = {
|
||||||
created(el, { modifiers: { lazy, trim, number } }, vnode) {
|
created(el, { modifiers: { lazy, trim, number } }, vnode) {
|
||||||
el[assignKey] = getModelAssigner(vnode)
|
el[assignKey] = getModelAssigner(vnode)
|
||||||
|
@ -183,7 +186,7 @@ export const vModelRadio: ModelDirective<HTMLInputElement> = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
export const vModelSelect: ModelDirective<HTMLSelectElement, 'number'> = {
|
||||||
// <select multiple> value need to be deep traversed
|
// <select multiple> value need to be deep traversed
|
||||||
deep: true,
|
deep: true,
|
||||||
created(el, { value, modifiers: { number } }, vnode) {
|
created(el, { value, modifiers: { number } }, vnode) {
|
||||||
|
@ -363,3 +366,10 @@ export function initVModelForSSR() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type VModelDirective =
|
||||||
|
| typeof vModelText
|
||||||
|
| typeof vModelCheckbox
|
||||||
|
| typeof vModelSelect
|
||||||
|
| typeof vModelRadio
|
||||||
|
| typeof vModelDynamic
|
||||||
|
|
|
@ -1,33 +1,40 @@
|
||||||
import {
|
import {
|
||||||
type ComponentInternalInstance,
|
type ComponentInternalInstance,
|
||||||
DeprecationTypes,
|
DeprecationTypes,
|
||||||
|
type Directive,
|
||||||
type LegacyConfig,
|
type LegacyConfig,
|
||||||
compatUtils,
|
compatUtils,
|
||||||
getCurrentInstance,
|
getCurrentInstance,
|
||||||
} from '@vue/runtime-core'
|
} from '@vue/runtime-core'
|
||||||
import { hyphenate, isArray } from '@vue/shared'
|
import { hyphenate, isArray } from '@vue/shared'
|
||||||
|
|
||||||
const systemModifiers = ['ctrl', 'shift', 'alt', 'meta']
|
const systemModifiers = ['ctrl', 'shift', 'alt', 'meta'] as const
|
||||||
|
type SystemModifiers = (typeof systemModifiers)[number]
|
||||||
|
type CompatModifiers = keyof typeof keyNames
|
||||||
|
|
||||||
|
export type VOnModifiers = SystemModifiers | ModifierGuards | CompatModifiers
|
||||||
type KeyedEvent = KeyboardEvent | MouseEvent | TouchEvent
|
type KeyedEvent = KeyboardEvent | MouseEvent | TouchEvent
|
||||||
|
|
||||||
const modifierGuards: Record<
|
const modifierGuards = {
|
||||||
string,
|
stop: (e: Event) => e.stopPropagation(),
|
||||||
(e: Event, modifiers: string[]) => void | boolean
|
prevent: (e: Event) => e.preventDefault(),
|
||||||
> = {
|
self: (e: Event) => e.target !== e.currentTarget,
|
||||||
stop: e => e.stopPropagation(),
|
ctrl: (e: Event) => !(e as KeyedEvent).ctrlKey,
|
||||||
prevent: e => e.preventDefault(),
|
shift: (e: Event) => !(e as KeyedEvent).shiftKey,
|
||||||
self: e => e.target !== e.currentTarget,
|
alt: (e: Event) => !(e as KeyedEvent).altKey,
|
||||||
ctrl: e => !(e as KeyedEvent).ctrlKey,
|
meta: (e: Event) => !(e as KeyedEvent).metaKey,
|
||||||
shift: e => !(e as KeyedEvent).shiftKey,
|
left: (e: Event) => 'button' in e && (e as MouseEvent).button !== 0,
|
||||||
alt: e => !(e as KeyedEvent).altKey,
|
middle: (e: Event) => 'button' in e && (e as MouseEvent).button !== 1,
|
||||||
meta: e => !(e as KeyedEvent).metaKey,
|
right: (e: Event) => 'button' in e && (e as MouseEvent).button !== 2,
|
||||||
left: e => 'button' in e && (e as MouseEvent).button !== 0,
|
|
||||||
middle: e => 'button' in e && (e as MouseEvent).button !== 1,
|
|
||||||
right: e => 'button' in e && (e as MouseEvent).button !== 2,
|
|
||||||
exact: (e, modifiers) =>
|
exact: (e, modifiers) =>
|
||||||
systemModifiers.some(m => (e as any)[`${m}Key`] && !modifiers.includes(m)),
|
systemModifiers.some(m => (e as any)[`${m}Key`] && !modifiers.includes(m)),
|
||||||
}
|
} satisfies Record<
|
||||||
|
string,
|
||||||
|
| ((e: Event) => void | boolean)
|
||||||
|
| ((e: Event, modifiers: string[]) => void | boolean)
|
||||||
|
>
|
||||||
|
|
||||||
|
type ModifierGuards = keyof typeof modifierGuards
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
@ -36,7 +43,7 @@ export const withModifiers = <
|
||||||
T extends (event: Event, ...args: unknown[]) => any,
|
T extends (event: Event, ...args: unknown[]) => any,
|
||||||
>(
|
>(
|
||||||
fn: T & { _withMods?: { [key: string]: T } },
|
fn: T & { _withMods?: { [key: string]: T } },
|
||||||
modifiers: string[],
|
modifiers: VOnModifiers[],
|
||||||
) => {
|
) => {
|
||||||
const cache = fn._withMods || (fn._withMods = {})
|
const cache = fn._withMods || (fn._withMods = {})
|
||||||
const cacheKey = modifiers.join('.')
|
const cacheKey = modifiers.join('.')
|
||||||
|
@ -44,7 +51,7 @@ export const withModifiers = <
|
||||||
cache[cacheKey] ||
|
cache[cacheKey] ||
|
||||||
(cache[cacheKey] = ((event, ...args) => {
|
(cache[cacheKey] = ((event, ...args) => {
|
||||||
for (let i = 0; i < modifiers.length; i++) {
|
for (let i = 0; i < modifiers.length; i++) {
|
||||||
const guard = modifierGuards[modifiers[i]]
|
const guard = modifierGuards[modifiers[i] as ModifierGuards]
|
||||||
if (guard && guard(event, modifiers)) return
|
if (guard && guard(event, modifiers)) return
|
||||||
}
|
}
|
||||||
return fn(event, ...args)
|
return fn(event, ...args)
|
||||||
|
@ -54,7 +61,7 @@ export const withModifiers = <
|
||||||
|
|
||||||
// Kept for 2.x compat.
|
// Kept for 2.x compat.
|
||||||
// Note: IE11 compat for `spacebar` and `del` is removed for now.
|
// Note: IE11 compat for `spacebar` and `del` is removed for now.
|
||||||
const keyNames: Record<string, string | string[]> = {
|
const keyNames = {
|
||||||
esc: 'escape',
|
esc: 'escape',
|
||||||
space: ' ',
|
space: ' ',
|
||||||
up: 'arrow-up',
|
up: 'arrow-up',
|
||||||
|
@ -62,7 +69,7 @@ const keyNames: Record<string, string | string[]> = {
|
||||||
right: 'arrow-right',
|
right: 'arrow-right',
|
||||||
down: 'arrow-down',
|
down: 'arrow-down',
|
||||||
delete: 'backspace',
|
delete: 'backspace',
|
||||||
}
|
} satisfies Record<string, string | string[]>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
@ -101,7 +108,13 @@ export const withKeys = <T extends (event: KeyboardEvent) => any>(
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventKey = hyphenate(event.key)
|
const eventKey = hyphenate(event.key)
|
||||||
if (modifiers.some(k => k === eventKey || keyNames[k] === eventKey)) {
|
if (
|
||||||
|
modifiers.some(
|
||||||
|
k =>
|
||||||
|
k === eventKey ||
|
||||||
|
keyNames[k as unknown as CompatModifiers] === eventKey,
|
||||||
|
)
|
||||||
|
) {
|
||||||
return fn(event)
|
return fn(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,3 +146,5 @@ export const withKeys = <T extends (event: KeyboardEvent) => any>(
|
||||||
}) as T)
|
}) as T)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type VOnDirective = Directive<any, any, VOnModifiers>
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import {
|
import {
|
||||||
type App,
|
type App,
|
||||||
type CreateAppFunction,
|
type CreateAppFunction,
|
||||||
|
type DefineComponent,
|
||||||
DeprecationTypes,
|
DeprecationTypes,
|
||||||
|
type Directive,
|
||||||
type ElementNamespace,
|
type ElementNamespace,
|
||||||
type HydrationRenderer,
|
type HydrationRenderer,
|
||||||
type Renderer,
|
type Renderer,
|
||||||
|
@ -25,6 +27,11 @@ import {
|
||||||
isSVGTag,
|
isSVGTag,
|
||||||
isString,
|
isString,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
|
import type { TransitionProps } from './components/Transition'
|
||||||
|
import type { TransitionGroupProps } from './components/TransitionGroup'
|
||||||
|
import type { vShow } from './directives/vShow'
|
||||||
|
import type { VOnDirective } from './directives/vOn'
|
||||||
|
import type { VModelDirective } from './directives/vModel'
|
||||||
|
|
||||||
declare module '@vue/reactivity' {
|
declare module '@vue/reactivity' {
|
||||||
export interface RefUnwrapBailTypes {
|
export interface RefUnwrapBailTypes {
|
||||||
|
@ -32,6 +39,22 @@ declare module '@vue/reactivity' {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
interface GlobalComponents {
|
||||||
|
Transition: DefineComponent<TransitionProps>
|
||||||
|
TransitionGroup: DefineComponent<TransitionGroupProps>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GlobalDirectives {
|
||||||
|
vShow: typeof vShow
|
||||||
|
vOn: VOnDirective
|
||||||
|
vBind: VModelDirective
|
||||||
|
vIf: Directive<any, boolean>
|
||||||
|
VOnce: Directive
|
||||||
|
VSlot: Directive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const rendererOptions = /*#__PURE__*/ extend({ patchProp }, nodeOps)
|
const rendererOptions = /*#__PURE__*/ extend({ patchProp }, nodeOps)
|
||||||
|
|
||||||
// lazy create the renderer - this makes core renderer logic tree-shakable
|
// lazy create the renderer - this makes core renderer logic tree-shakable
|
||||||
|
|
|
@ -74,7 +74,7 @@ function eventHandler(
|
||||||
let handler = getter()
|
let handler = getter()
|
||||||
if (!handler) return
|
if (!handler) return
|
||||||
|
|
||||||
if (modifiers) handler = withModifiers(handler, modifiers)
|
if (modifiers) handler = withModifiers(handler, modifiers as any[])
|
||||||
if (keys) handler = withKeys(handler, keys)
|
if (keys) handler = withKeys(handler, keys)
|
||||||
handler && handler(...args)
|
handler && handler(...args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/server-renderer",
|
"name": "@vue/server-renderer",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "@vue/server-renderer",
|
"description": "@vue/server-renderer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/server-renderer.esm-bundler.js",
|
"module": "dist/server-renderer.esm-bundler.js",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/shared",
|
"name": "@vue/shared",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "internal utils shared across @vue packages",
|
"description": "internal utils shared across @vue packages",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/shared.esm-bundler.js",
|
"module": "dist/shared.esm-bundler.js",
|
||||||
|
|
|
@ -23,3 +23,34 @@ export type Awaited<T> = T extends null | undefined
|
||||||
: T // non-object or non-thenable
|
: T // non-object or non-thenable
|
||||||
|
|
||||||
export type Data = Record<string, unknown>
|
export type Data = Record<string, unknown>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility for extracting the parameters from a function overload (for typed emits)
|
||||||
|
* https://github.com/microsoft/TypeScript/issues/32164#issuecomment-1146737709
|
||||||
|
*/
|
||||||
|
export type OverloadParameters<T extends (...args: any[]) => any> = Parameters<
|
||||||
|
OverloadUnion<T>
|
||||||
|
>
|
||||||
|
|
||||||
|
type OverloadProps<TOverload> = Pick<TOverload, keyof TOverload>
|
||||||
|
|
||||||
|
type OverloadUnionRecursive<
|
||||||
|
TOverload,
|
||||||
|
TPartialOverload = unknown,
|
||||||
|
> = TOverload extends (...args: infer TArgs) => infer TReturn
|
||||||
|
? TPartialOverload extends TOverload
|
||||||
|
? never
|
||||||
|
:
|
||||||
|
| OverloadUnionRecursive<
|
||||||
|
TPartialOverload & TOverload,
|
||||||
|
TPartialOverload &
|
||||||
|
((...args: TArgs) => TReturn) &
|
||||||
|
OverloadProps<TOverload>
|
||||||
|
>
|
||||||
|
| ((...args: TArgs) => TReturn)
|
||||||
|
: never
|
||||||
|
|
||||||
|
type OverloadUnion<TOverload extends (...args: any[]) => any> = Exclude<
|
||||||
|
OverloadUnionRecursive<(() => never) & TOverload>,
|
||||||
|
TOverload extends () => never ? never : () => never
|
||||||
|
>
|
||||||
|
|
|
@ -292,7 +292,7 @@ describe('INSTANCE_SCOPED_SLOTS', () => {
|
||||||
components: {
|
components: {
|
||||||
child: {
|
child: {
|
||||||
compatConfig: { RENDER_FUNCTION: false },
|
compatConfig: { RENDER_FUNCTION: false },
|
||||||
render() {
|
render(this: LegacyPublicInstance) {
|
||||||
normalSlots = this.$slots
|
normalSlots = this.$slots
|
||||||
scopedSlots = this.$scopedSlots
|
scopedSlots = this.$scopedSlots
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vue/compat",
|
"name": "@vue/compat",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "Vue 3 compatibility build for Vue 2",
|
"description": "Vue 3 compatibility build for Vue 2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/vue.runtime.esm-bundler.js",
|
"module": "dist/vue.runtime.esm-bundler.js",
|
||||||
|
|
|
@ -1725,6 +1725,95 @@ describe('e2e: Transition', () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('transition with Teleport', () => {
|
||||||
|
test(
|
||||||
|
'apply transition to teleport child',
|
||||||
|
async () => {
|
||||||
|
await page().evaluate(() => {
|
||||||
|
const { createApp, ref, h } = (window as any).Vue
|
||||||
|
createApp({
|
||||||
|
template: `
|
||||||
|
<div id="target"></div>
|
||||||
|
<div id="container">
|
||||||
|
<transition>
|
||||||
|
<Teleport to="#target">
|
||||||
|
<!-- comment -->
|
||||||
|
<Comp v-if="toggle" class="test">content</Comp>
|
||||||
|
</Teleport>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
<button id="toggleBtn" @click="click">button</button>
|
||||||
|
`,
|
||||||
|
components: {
|
||||||
|
Comp: {
|
||||||
|
setup() {
|
||||||
|
return () => h('div', { class: 'test' }, 'content')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup: () => {
|
||||||
|
const toggle = ref(false)
|
||||||
|
const click = () => (toggle.value = !toggle.value)
|
||||||
|
return { toggle, click }
|
||||||
|
},
|
||||||
|
}).mount('#app')
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(await html('#target')).toBe('<!-- comment --><!--v-if-->')
|
||||||
|
expect(await html('#container')).toBe(
|
||||||
|
'<!--teleport start--><!--teleport end-->',
|
||||||
|
)
|
||||||
|
|
||||||
|
const classWhenTransitionStart = () =>
|
||||||
|
page().evaluate(() => {
|
||||||
|
;(document.querySelector('#toggleBtn') as any)!.click()
|
||||||
|
return Promise.resolve().then(() => {
|
||||||
|
// find the class of teleported node
|
||||||
|
return document
|
||||||
|
.querySelector('#target div')!
|
||||||
|
.className.split(/\s+/g)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// enter
|
||||||
|
expect(await classWhenTransitionStart()).toStrictEqual([
|
||||||
|
'test',
|
||||||
|
'v-enter-from',
|
||||||
|
'v-enter-active',
|
||||||
|
])
|
||||||
|
await nextFrame()
|
||||||
|
expect(await classList('.test')).toStrictEqual([
|
||||||
|
'test',
|
||||||
|
'v-enter-active',
|
||||||
|
'v-enter-to',
|
||||||
|
])
|
||||||
|
await transitionFinish()
|
||||||
|
expect(await html('#target')).toBe(
|
||||||
|
'<!-- comment --><div class="test">content</div>',
|
||||||
|
)
|
||||||
|
|
||||||
|
// leave
|
||||||
|
expect(await classWhenTransitionStart()).toStrictEqual([
|
||||||
|
'test',
|
||||||
|
'v-leave-from',
|
||||||
|
'v-leave-active',
|
||||||
|
])
|
||||||
|
await nextFrame()
|
||||||
|
expect(await classList('.test')).toStrictEqual([
|
||||||
|
'test',
|
||||||
|
'v-leave-active',
|
||||||
|
'v-leave-to',
|
||||||
|
])
|
||||||
|
await transitionFinish()
|
||||||
|
expect(await html('#target')).toBe('<!-- comment --><!--v-if-->')
|
||||||
|
expect(await html('#container')).toBe(
|
||||||
|
'<!--teleport start--><!--teleport end-->',
|
||||||
|
)
|
||||||
|
},
|
||||||
|
E2E_TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
describe('transition with v-show', () => {
|
describe('transition with v-show', () => {
|
||||||
test(
|
test(
|
||||||
'named transition with v-show',
|
'named transition with v-show',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vue",
|
"name": "vue",
|
||||||
"version": "3.4.25",
|
"version": "3.5.0-alpha.1",
|
||||||
"description": "The progressive JavaScript framework for building modern web UI.",
|
"description": "The progressive JavaScript framework for building modern web UI.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"module": "dist/vue.runtime.esm-bundler.js",
|
"module": "dist/vue.runtime.esm-bundler.js",
|
||||||
|
|
Loading…
Reference in New Issue