-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
/
Copy pathvOn.ts
99 lines (89 loc) · 2.78 KB
/
vOn.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import {
ElementTypes,
ErrorCodes,
createCompilerError,
} from '@vue/compiler-dom'
import type { DirectiveTransform } from '../transform'
import { IRNodeTypes, type KeyOverride, type SetEventIRNode } from '../ir'
import { resolveModifiers } from '@vue/compiler-dom'
import { extend, makeMap } from '@vue/shared'
import { resolveExpression } from '../utils'
import { EMPTY_EXPRESSION } from './utils'
const delegatedEvents = /*#__PURE__*/ makeMap(
'beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,' +
'keyup,mousedown,mousemove,mouseout,mouseover,mouseup,pointerdown,' +
'pointermove,pointerout,pointerover,pointerup,touchend,touchmove,' +
'touchstart',
)
export const transformVOn: DirectiveTransform = (dir, node, context) => {
let { arg, exp, loc, modifiers } = dir
const isComponent = node.tagType === ElementTypes.COMPONENT
const isSlotOutlet = node.tag === 'slot'
if (!exp && !modifiers.length) {
context.options.onError(
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
)
}
arg = resolveExpression(arg!)
const { keyModifiers, nonKeyModifiers, eventOptionModifiers } =
resolveModifiers(
arg.isStatic ? `on${arg.content}` : arg,
modifiers,
null,
loc,
)
let keyOverride: KeyOverride | undefined
const isStaticClick = arg.isStatic && arg.content.toLowerCase() === 'click'
// normalize click.right and click.middle since they don't actually fire
if (nonKeyModifiers.includes('middle')) {
if (keyOverride) {
// TODO error here
}
if (isStaticClick) {
arg = extend({}, arg, { content: 'mouseup' })
} else if (!arg.isStatic) {
keyOverride = ['click', 'mouseup']
}
}
if (nonKeyModifiers.includes('right')) {
if (isStaticClick) {
arg = extend({}, arg, { content: 'contextmenu' })
} else if (!arg.isStatic) {
keyOverride = ['click', 'contextmenu']
}
}
if (isComponent || isSlotOutlet) {
const handler = exp || EMPTY_EXPRESSION
return {
key: arg,
value: handler,
handler: true,
handlerModifiers: {
keys: keyModifiers,
nonKeys: nonKeyModifiers,
options: eventOptionModifiers,
},
}
}
// Only delegate if:
// - no dynamic event name
// - no event option modifiers (passive, capture, once)
// - is a delegatable event
const delegate =
arg.isStatic && !eventOptionModifiers.length && delegatedEvents(arg.content)
const operation: SetEventIRNode = {
type: IRNodeTypes.SET_EVENT,
element: context.reference(),
key: arg,
value: exp,
modifiers: {
keys: keyModifiers,
nonKeys: nonKeyModifiers,
options: eventOptionModifiers,
},
keyOverride,
delegate,
effect: !arg.isStatic,
}
context.registerEffect([arg], operation)
}