} from './errors'
export { resolveModifiers } from './transforms/vOn'
export { isValidHTMLNesting } from './htmlNesting'
+export { postTransformTransition } from './transforms/Transition'
export * from '@vue/compiler-core'
import {
+ type CompilerError,
type ComponentNode,
ElementTypes,
type IfBranchNode,
) {
const component = context.isBuiltInComponent(node.tag)
if (component === TRANSITION) {
- return () => {
- if (!node.children.length) {
- return
- }
+ return postTransformTransition(node, context.onError)
+ }
+ }
+}
- // warn multiple transition children
- if (hasMultipleChildren(node)) {
- context.onError(
- createDOMCompilerError(
- DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN,
- {
- start: node.children[0].loc.start,
- end: node.children[node.children.length - 1].loc.end,
- source: '',
- },
- ),
- )
- }
+export function postTransformTransition(
+ node: ComponentNode,
+ onError: (error: CompilerError) => void,
+): () => void {
+ return () => {
+ if (!node.children.length) {
+ return
+ }
+
+ if (hasMultipleChildren(node)) {
+ onError(
+ createDOMCompilerError(DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN, {
+ start: node.children[0].loc.start,
+ end: node.children[node.children.length - 1].loc.end,
+ source: '',
+ }),
+ )
+ }
- // check if it's s single child w/ v-show
- // if yes, inject "persisted: true" to the transition props
- const child = node.children[0]
- if (child.type === NodeTypes.ELEMENT) {
- for (const p of child.props) {
- if (p.type === NodeTypes.DIRECTIVE && p.name === 'show') {
- node.props.push({
- type: NodeTypes.ATTRIBUTE,
- name: 'persisted',
- nameLoc: node.loc,
- value: undefined,
- loc: node.loc,
- })
- }
- }
+ // check if it's s single child w/ v-show
+ // if yes, inject "persisted: true" to the transition props
+ const child = node.children[0]
+ if (child.type === NodeTypes.ELEMENT) {
+ for (const p of child.props) {
+ if (p.type === NodeTypes.DIRECTIVE && p.name === 'show') {
+ node.props.push({
+ type: NodeTypes.ATTRIBUTE,
+ name: 'persisted',
+ nameLoc: node.loc,
+ value: undefined,
+ loc: node.loc,
+ })
}
}
}
transformText,
transformVBind,
transformVIf,
+ transformVShow,
transformVSlot,
} from '@vue/compiler-vapor'
-import { expect } from 'vitest'
+import { transformTransition } from '../../src/transforms/transformTransition'
+import { DOMErrorCodes } from '@vue/compiler-dom'
const compileWithElementTransform = makeCompile({
nodeTransforms: [
transformElement,
transformVSlot,
transformChildren,
+ transformTransition,
],
directiveTransforms: {
bind: transformVBind,
+ show: transformVShow,
},
})
// should preserve key
expect(code).contains('n0.$key = _ctx.key')
})
+
+ test('warns if multiple children', () => {
+ const onError = vi.fn()
+ compileWithElementTransform(
+ `<Transition>
+ <h1>foo</h1>
+ <h2>bar</h2>
+ </Transition>`,
+ {
+ onError,
+ },
+ )
+ expect(onError).toHaveBeenCalled()
+ expect(onError.mock.calls).toMatchObject([
+ [{ code: DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN }],
+ ])
+ })
+
+ test('inject persisted when child has v-show', () => {
+ expect(
+ compileWithElementTransform(`
+ <Transition>
+ <div v-show="ok" />
+ </Transition>
+ `).code,
+ ).toMatchSnapshot()
+ })
+
+ // TODO more tests
})
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: transition > basic 1`] = `
-"import { VaporTransition as _VaporTransition, createComponent as _createComponent, template as _template } from 'vue';
+"import { VaporTransition as _VaporTransition, applyVShow as _applyVShow, createComponent as _createComponent, template as _template } from 'vue';
const t0 = _template("<h1>foo</h1>")
export function render(_ctx) {
- const n1 = _createComponent(_VaporTransition, { appear: () => ("") }, {
+ const n1 = _createComponent(_VaporTransition, {
+ appear: () => (""),
+ persisted: () => ("")
+ }, {
"default": () => {
const n0 = t0()
+ _applyVShow(n0, () => (_ctx.show))
+ return n0
+ }
+ }, true)
+ return n1
+}"
+`;
+
+exports[`compiler: transition > inject persisted when child has v-show 1`] = `
+"import { VaporTransition as _VaporTransition, applyVShow as _applyVShow, createComponent as _createComponent, template as _template } from 'vue';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+ const n1 = _createComponent(_VaporTransition, { persisted: () => ("") }, {
+ "default": () => {
+ const n0 = t0()
+ _applyVShow(n0, () => (_ctx.ok))
return n0
}
}, true)
import { transformComment } from './transforms/transformComment'
import { transformSlotOutlet } from './transforms/transformSlotOutlet'
import { transformVSlot } from './transforms/vSlot'
+import { transformTransition } from './transforms/transformTransition'
import type { HackOptions } from './ir'
export { wrapTemplate } from './transforms/utils'
extend({}, resolvedOptions, {
nodeTransforms: [
...nodeTransforms,
+ ...(__DEV__ ? [transformTransition] : []),
...(options.nodeTransforms || []), // user transforms
],
directiveTransforms: extend(
--- /dev/null
+import type { NodeTransform } from '@vue/compiler-vapor'
+import { ElementTypes, NodeTypes } from '@vue/compiler-core'
+import { isTransitionTag } from '../utils'
+import { postTransformTransition } from '@vue/compiler-dom'
+
+export const transformTransition: NodeTransform = (node, context) => {
+ if (
+ node.type === NodeTypes.ELEMENT &&
+ node.tagType === ElementTypes.COMPONENT
+ ) {
+ if (isTransitionTag(node.tag)) {
+ return postTransformTransition(node, context.options.onError)
+ }
+ }
+}