@dimailn/vuetify 2.7.2-alpha56 → 2.7.2-alpha57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/json/attributes.json +3945 -417
  2. package/dist/json/tags.json +1120 -133
  3. package/dist/json/web-types.json +12516 -2651
  4. package/dist/vuetify.js +66 -76
  5. package/dist/vuetify.js.map +1 -1
  6. package/dist/vuetify.min.css +1 -1
  7. package/dist/vuetify.min.js +2 -2
  8. package/es5/directives/click-outside/index.js +19 -21
  9. package/es5/directives/click-outside/index.js.map +1 -1
  10. package/es5/directives/intersect/index.js +12 -17
  11. package/es5/directives/intersect/index.js.map +1 -1
  12. package/es5/directives/mutate/index.js +9 -11
  13. package/es5/directives/mutate/index.js.map +1 -1
  14. package/es5/directives/resize/index.js +8 -10
  15. package/es5/directives/resize/index.js.map +1 -1
  16. package/es5/directives/scroll/index.js +11 -12
  17. package/es5/directives/scroll/index.js.map +1 -1
  18. package/es5/directives/touch/index.js +6 -5
  19. package/es5/directives/touch/index.js.map +1 -1
  20. package/es5/framework.js +1 -1
  21. package/es5/services/theme/utils.js.map +1 -1
  22. package/lib/directives/click-outside/index.js +17 -19
  23. package/lib/directives/click-outside/index.js.map +1 -1
  24. package/lib/directives/intersect/index.js +12 -16
  25. package/lib/directives/intersect/index.js.map +1 -1
  26. package/lib/directives/mutate/index.js +9 -11
  27. package/lib/directives/mutate/index.js.map +1 -1
  28. package/lib/directives/resize/index.js +8 -8
  29. package/lib/directives/resize/index.js.map +1 -1
  30. package/lib/directives/scroll/index.js +8 -8
  31. package/lib/directives/scroll/index.js.map +1 -1
  32. package/lib/directives/touch/index.js +6 -5
  33. package/lib/directives/touch/index.js.map +1 -1
  34. package/lib/framework.js +1 -1
  35. package/lib/services/theme/utils.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/components/VMenu/__tests__/VMenuActivatorTest.spec.ts +25 -0
  38. package/src/components/VMenu/__tests__/test-with-directives.spec.ts +50 -0
  39. package/src/directives/click-outside/__tests__/click-outside-shadow-dom.spec.ts +2 -1
  40. package/src/directives/click-outside/__tests__/click-outside.spec.ts +2 -1
  41. package/src/directives/click-outside/index.ts +25 -18
  42. package/src/directives/intersect/__tests__/intersect.spec.ts +31 -13
  43. package/src/directives/intersect/index.ts +15 -19
  44. package/src/directives/mutate/__tests__/mutate.spec.ts +35 -27
  45. package/src/directives/mutate/index.ts +12 -6
  46. package/src/directives/resize/__tests__/resize.spec.ts +4 -4
  47. package/src/directives/resize/index.ts +11 -18
  48. package/src/directives/scroll/__tests__/scroll.spec.ts +5 -29
  49. package/src/directives/scroll/index.ts +14 -7
  50. package/src/directives/touch/index.ts +6 -5
  51. package/src/services/theme/utils.ts +1 -1
@@ -12,6 +12,14 @@ type ClickOutsideDirective = VNodeDirective & {
12
12
  value?: ((e: Event) => void) | ClickOutsideBindingArgs
13
13
  }
14
14
 
15
+ interface ClickOutsideState {
16
+ onClick: (e: Event) => void
17
+ onMousedown: (e: Event) => void
18
+ lastMousedownWasOutside: boolean
19
+ }
20
+
21
+ const clickOutsideState = new WeakMap<HTMLElement, ClickOutsideState>()
22
+
15
23
  function defaultConditional () {
16
24
  return true
17
25
  }
@@ -55,8 +63,10 @@ function checkIsActive (e: PointerEvent, binding: ClickOutsideDirective): boolea
55
63
 
56
64
  function directive (e: PointerEvent, el: HTMLElement, binding: ClickOutsideDirective) {
57
65
  const handler = typeof binding.value === 'function' ? binding.value : binding.value!.handler
66
+ const state = clickOutsideState.get(el)
67
+ if (!state) return
58
68
 
59
- el._clickOutside!.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
69
+ state.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
60
70
  checkIsActive(e, binding) && handler && handler(e)
61
71
  }, 0)
62
72
  }
@@ -80,39 +90,36 @@ export const ClickOutside = {
80
90
  mounted (el: HTMLElement, binding: ClickOutsideDirective, vnode: VNode) {
81
91
  const onClick = (e: Event) => directive(e as PointerEvent, el, binding)
82
92
  const onMousedown = (e: Event) => {
83
- el._clickOutside!.lastMousedownWasOutside = checkEvent(e as PointerEvent, el, binding)
93
+ const state = clickOutsideState.get(el)
94
+ if (!state) return
95
+ state.lastMousedownWasOutside = checkEvent(e as PointerEvent, el, binding)
84
96
  }
85
97
 
98
+ clickOutsideState.set(el, {
99
+ onClick,
100
+ onMousedown,
101
+ lastMousedownWasOutside: true
102
+ })
103
+
86
104
  handleShadow(el, (app: HTMLElement) => {
87
105
  app.addEventListener('click', onClick, true)
88
106
  app.addEventListener('mousedown', onMousedown, true)
89
107
  })
90
-
91
- if (!el._clickOutside) {
92
- el._clickOutside = {
93
- lastMousedownWasOutside: true
94
- }
95
- }
96
-
97
- el._clickOutside[vnode.ctx.uid] = {
98
- onClick,
99
- onMousedown
100
- }
101
108
  },
102
109
 
103
110
  unmounted (el: HTMLElement, binding: ClickOutsideDirective, vnode: VNode) {
104
- if (!el._clickOutside) return
111
+ const state = clickOutsideState.get(el)
112
+ if (!state) return
105
113
 
106
114
  handleShadow(el, (app: HTMLElement) => {
107
- if (!app || !el._clickOutside?.[vnode.ctx.uid]) return
108
-
109
- const { onClick, onMousedown } = el._clickOutside[vnode.ctx.uid]!
115
+ if (!app) return
110
116
 
117
+ const { onClick, onMousedown } = state
111
118
  app.removeEventListener('click', onClick, true)
112
119
  app.removeEventListener('mousedown', onMousedown, true)
113
120
  })
114
121
 
115
- delete el._clickOutside[vnode.ctx.uid]
122
+ clickOutsideState.delete(el)
116
123
  }
117
124
  }
118
125
 
@@ -2,27 +2,45 @@
2
2
  import Intersect from '../'
3
3
 
4
4
  describe('intersect', () => {
5
+ let observerInstance: any
6
+
7
+ beforeEach(() => {
8
+ observerInstance = undefined
9
+ ;(global as any).IntersectionObserver = class IntersectionObserver {
10
+ callback: (entries: any, observer: any) => void
11
+ observe = jest.fn()
12
+ unobserve = jest.fn()
13
+
14
+ constructor (callback: (entries: any, observer: any) => void) {
15
+ this.callback = callback
16
+ observerInstance = this
17
+ }
18
+ }
19
+ })
20
+
5
21
  it('should bind event on mounted', () => {
6
22
  const callback = jest.fn()
7
23
  const el = document.createElement('div')
8
24
  document.body.appendChild(el)
9
25
 
10
26
  Intersect.mounted(el, {
27
+ instance: { $: { uid: 1 } },
11
28
  value: callback,
12
29
  modifiers: { quiet: true }
13
- } as any, { ctx: { uid: 1 } } as any)
30
+ } as any, {} as any)
14
31
 
15
- expect((el as any)._observe).toBeTruthy()
32
+ expect(observerInstance).toBeTruthy()
33
+ expect(observerInstance.observe).toHaveBeenCalledWith(el)
16
34
  expect(callback).not.toHaveBeenCalled()
17
35
 
18
36
  document.body.removeChild(el)
19
37
 
20
38
  Intersect.unmounted(el, {
39
+ instance: { $: { uid: 1 } },
21
40
  value: callback,
22
41
  modifiers: { quiet: true }
23
- } as any, { ctx: { uid: 1 } } as any)
24
-
25
- expect((el as any)._observe[1]).toBeFalsy()
42
+ } as any, {} as any)
43
+ expect(observerInstance.unobserve).toHaveBeenCalledWith(el)
26
44
  })
27
45
 
28
46
  it('should invoke callback once and unbind', () => {
@@ -33,21 +51,21 @@ describe('intersect', () => {
33
51
  const callback = jest.fn()
34
52
 
35
53
  Intersect.mounted(el, {
54
+ instance: { $: { uid: 1 } },
36
55
  value: callback,
37
56
  modifiers: { once: true }
38
- } as any, { ctx: { uid: 1 } } as any)
57
+ } as any, {} as any)
39
58
 
40
59
  expect(callback).toHaveBeenCalledTimes(0)
41
- expect((el as any)._observe[1]).toBeTruthy()
60
+ expect(observerInstance).toBeTruthy()
42
61
 
43
- ;(el as any)._observe[1].observer.callback([{ isIntersecting: false }])
62
+ observerInstance.callback([{ isIntersecting: false }], observerInstance)
44
63
 
45
- expect(callback).toHaveBeenCalledTimes(1)
46
- expect((el as any)._observe[1]).toBeTruthy()
64
+ expect(callback).toHaveBeenCalledTimes(0)
47
65
 
48
- ;(el as any)._observe[1].observer.callback([{ isIntersecting: true }])
66
+ observerInstance.callback([{ isIntersecting: true }], observerInstance)
49
67
 
50
- expect(callback).toHaveBeenCalledTimes(2)
51
- expect((el as any)._observe[1]).toBeFalsy()
68
+ expect(callback).toHaveBeenCalledTimes(1)
69
+ expect(observerInstance.unobserve).toHaveBeenCalledWith(el)
52
70
  })
53
71
  })
@@ -17,16 +17,13 @@ interface ObserveDirectiveBinding
17
17
  }
18
18
  }
19
19
 
20
- // Расширяем HTMLElement для хранения данных наблюдателя
21
- declare global {
22
- interface HTMLElement {
23
- _observe?: Record<
24
- number,
25
- { init: boolean, observer: IntersectionObserver }
26
- >
27
- }
20
+ interface IntersectState {
21
+ init: boolean
22
+ observer: IntersectionObserver
28
23
  }
29
24
 
25
+ const intersectState = new WeakMap<HTMLElement, IntersectState>()
26
+
30
27
  function mounted (
31
28
  el: HTMLElement,
32
29
  binding: ObserveDirectiveBinding,
@@ -48,8 +45,8 @@ function mounted (
48
45
  entries: IntersectionObserverEntry[] = [],
49
46
  observer: IntersectionObserver
50
47
  ) => {
51
- const _observe = el._observe?.[vnode.ctx!.uid]
52
- if (!_observe) return // Just in case, should never fire
48
+ const state = intersectState.get(el)
49
+ if (!state) return // Just in case, should never fire
53
50
 
54
51
  const isIntersecting = entries.some(entry => entry.isIntersecting)
55
52
 
@@ -58,20 +55,19 @@ function mounted (
58
55
  if (
59
56
  handler &&
60
57
  typeof handler === 'function' &&
61
- (!modifiers.quiet || _observe.init) &&
62
- (!modifiers.once || isIntersecting || _observe.init)
58
+ (!modifiers.quiet || state.init) &&
59
+ (!modifiers.once || isIntersecting || state.init)
63
60
  ) {
64
61
  handler(entries, observer, isIntersecting)
65
62
  }
66
63
 
67
64
  if (isIntersecting && modifiers.once) unmounted(el, binding, vnode)
68
- else _observe.init = true
65
+ else state.init = true
69
66
  },
70
67
  options
71
68
  )
72
69
 
73
- el._observe = Object(el._observe)
74
- el._observe![vnode.ctx!.uid] = { init: false, observer }
70
+ intersectState.set(el, { init: false, observer })
75
71
 
76
72
  observer.observe(el)
77
73
  }
@@ -93,11 +89,11 @@ function unmounted (
93
89
  binding: ObserveDirectiveBinding,
94
90
  vnode: VNode
95
91
  ) {
96
- const observe = el._observe?.[vnode.ctx!.uid]
97
- if (!observe) return
92
+ const state = intersectState.get(el)
93
+ if (!state) return
98
94
 
99
- observe.observer.unobserve(el)
100
- delete el._observe![vnode.ctx!.uid]
95
+ state.observer.unobserve(el)
96
+ intersectState.delete(el)
101
97
  }
102
98
 
103
99
  export const Intersect: ObjectDirective<
@@ -1,17 +1,18 @@
1
1
  // Directives
2
2
  import Mutate from '../'
3
3
 
4
+ const observers: any[] = [];
5
+
4
6
  (global as any).MutationObserver = class { // Mock MutationObserver
5
7
  _callback: Function
6
-
7
8
  _observe = jest.fn()
9
+ disconnect = jest.fn()
8
10
 
9
11
  constructor (callback) {
10
12
  this._callback = callback
13
+ observers.push(this)
11
14
  }
12
15
 
13
- disconnect () {}
14
-
15
16
  observe (_, options) {
16
17
  this._observe(options)
17
18
  }
@@ -22,26 +23,30 @@ import Mutate from '../'
22
23
  }
23
24
 
24
25
  describe('mutate.ts', () => {
26
+ beforeEach(() => {
27
+ observers.length = 0
28
+ })
29
+
25
30
  it('should bind event on inserted', () => {
26
31
  const callback = jest.fn()
27
32
  const el = document.createElement('div') as any
28
33
  document.body.appendChild(el)
29
34
 
30
35
  Mutate.mounted(el, {
36
+ instance: { $: { uid: 1 } },
31
37
  value: callback
32
- } as any, { ctx: { uid: 1 } } as any)
38
+ } as any, {} as any)
33
39
 
34
- expect(el._mutate).toBeTruthy()
40
+ expect(observers).toHaveLength(1)
35
41
  expect(callback).not.toHaveBeenCalled()
36
42
 
37
43
  document.body.removeChild(el)
38
44
 
39
45
  Mutate.unmounted(el, {
46
+ instance: { $: { uid: 1 } },
40
47
  value: callback
41
- } as any, { ctx: { uid: 1 } } as any)
42
-
43
- const uid = Object.keys(el._mutate)[0]
44
- expect(el._mutate[uid]).toBeFalsy()
48
+ } as any, {} as any)
49
+ expect(observers[0].disconnect).toHaveBeenCalled()
45
50
  })
46
51
 
47
52
  it('should fire event on mutation', () => {
@@ -50,19 +55,20 @@ describe('mutate.ts', () => {
50
55
  document.body.appendChild(el)
51
56
 
52
57
  Mutate.mounted(el, {
58
+ instance: { $: { uid: 1 } },
53
59
  value: callback
54
- } as any, { ctx: { uid: 1 } } as any)
60
+ } as any, {} as any)
55
61
 
56
- const uid = Object.keys(el._mutate)[0]
57
- el._mutate[uid]?.observer?.trigger([{}])
62
+ observers[0]?.trigger([{} as any])
58
63
 
59
64
  expect(callback).toHaveBeenCalledTimes(1)
60
65
 
61
66
  document.body.removeChild(el)
62
67
 
63
68
  Mutate.unmounted(el, {
69
+ instance: { $: { uid: 1 } },
64
70
  value: callback
65
- } as any, { ctx: { uid: 1 } } as any)
71
+ } as any, {} as any)
66
72
  })
67
73
 
68
74
  it('should fire event once', () => {
@@ -71,18 +77,18 @@ describe('mutate.ts', () => {
71
77
  document.body.appendChild(el)
72
78
 
73
79
  Mutate.mounted(el, {
80
+ instance: { $: { uid: 1 } },
74
81
  value: callback,
75
82
  modifiers: {
76
83
  once: true
77
84
  }
78
- } as any, { ctx: { uid: 1 } } as any)
85
+ } as any, {} as any)
79
86
 
80
- const uid = Object.keys(el._mutate)[0]
81
- el._mutate[uid]?.observer?.trigger([{}])
87
+ observers[0]?.trigger([{} as any])
82
88
 
83
89
  expect(callback).toHaveBeenCalledTimes(1)
84
90
  // Once modifier should remove the observer
85
- expect(Object.keys(el._mutate)).toHaveLength(0)
91
+ expect(observers[0].disconnect).toHaveBeenCalled()
86
92
 
87
93
  document.body.removeChild(el)
88
94
  })
@@ -93,6 +99,7 @@ describe('mutate.ts', () => {
93
99
  document.body.appendChild(el)
94
100
 
95
101
  Mutate.mounted(el, {
102
+ instance: { $: { uid: 1 } },
96
103
  value: {
97
104
  options: {
98
105
  attributes: false,
@@ -100,17 +107,17 @@ describe('mutate.ts', () => {
100
107
  },
101
108
  handler: callback
102
109
  }
103
- } as any, { ctx: { uid: 1 } } as any)
110
+ } as any, {} as any)
104
111
 
105
- const uid = Object.keys(el._mutate)[0]
106
- el._mutate[uid]?.observer?.trigger([{}])
112
+ observers[0]?.trigger([{} as any])
107
113
 
108
114
  expect(callback).toHaveBeenCalledTimes(1)
109
- expect(el._mutate[uid].observer._observe).toHaveBeenLastCalledWith({ attributes: false, subtree: true })
115
+ expect(observers[0]._observe).toHaveBeenLastCalledWith({ attributes: false, subtree: true })
110
116
 
111
117
  document.body.removeChild(el)
112
118
 
113
119
  Mutate.unmounted(el, {
120
+ instance: { $: { uid: 1 } },
114
121
  value: {
115
122
  options: {
116
123
  attributes: false,
@@ -118,7 +125,7 @@ describe('mutate.ts', () => {
118
125
  },
119
126
  handler: callback
120
127
  }
121
- } as any, { ctx: { uid: 1 } } as any)
128
+ } as any, {} as any)
122
129
  })
123
130
 
124
131
  it('should work with observer modifiers', () => {
@@ -127,29 +134,30 @@ describe('mutate.ts', () => {
127
134
  document.body.appendChild(el)
128
135
 
129
136
  Mutate.mounted(el, {
137
+ instance: { $: { uid: 1 } },
130
138
  value: callback,
131
139
  modifiers: {
132
140
  attr: true,
133
141
  child: true,
134
142
  sub: true
135
143
  }
136
- } as any, { ctx: { uid: 1 } } as any)
144
+ } as any, {} as any)
137
145
 
138
- const uid = Object.keys(el._mutate)[0]
139
- el._mutate[uid]?.observer?.trigger([{}])
146
+ observers[0]?.trigger([{} as any])
140
147
 
141
148
  expect(callback).toHaveBeenCalledTimes(1)
142
- expect(el._mutate[uid].observer._observe).toHaveBeenLastCalledWith({ attributes: true, childList: true, subtree: true })
149
+ expect(observers[0]._observe).toHaveBeenLastCalledWith({ attributes: true, childList: true, subtree: true })
143
150
 
144
151
  document.body.removeChild(el)
145
152
 
146
153
  Mutate.unmounted(el, {
154
+ instance: { $: { uid: 1 } },
147
155
  value: callback,
148
156
  modifiers: {
149
157
  attr: true,
150
158
  child: true,
151
159
  sub: true
152
160
  }
153
- } as any, { ctx: { uid: 1 } } as any)
161
+ } as any, {} as any)
154
162
  })
155
163
  })
@@ -17,6 +17,12 @@ type MutateModifiers = {
17
17
  char?: boolean
18
18
  };
19
19
 
20
+ interface MutateState {
21
+ observer: MutationObserver
22
+ }
23
+
24
+ const mutateState = new WeakMap<HTMLElement, MutateState>()
25
+
20
26
  function mounted (
21
27
  el: HTMLElement,
22
28
  binding: DirectiveBinding<MutateValue>,
@@ -51,7 +57,7 @@ function mounted (
51
57
  const observer = new MutationObserver(
52
58
  (mutationsList: MutationRecord[], observer: MutationObserver) => {
53
59
  /* istanbul ignore if */
54
- if (!el._mutate) return // Just in case, should never fire
60
+ if (!mutateState.has(el)) return // Just in case, should never fire
55
61
 
56
62
  callback(mutationsList, observer)
57
63
 
@@ -61,8 +67,7 @@ function mounted (
61
67
  )
62
68
 
63
69
  observer.observe(el, options)
64
- el._mutate = Object(el._mutate)
65
- el._mutate![vnode.ctx!.uid] = { observer }
70
+ mutateState.set(el, { observer })
66
71
  }
67
72
 
68
73
  function unmounted (
@@ -70,10 +75,11 @@ function unmounted (
70
75
  binding: DirectiveBinding<MutateValue>,
71
76
  vnode: VNode
72
77
  ) {
73
- if (!el._mutate?.[vnode.ctx!.uid]) return
78
+ const state = mutateState.get(el)
79
+ if (!state) return
74
80
 
75
- el._mutate[vnode.ctx!.uid]!.observer.disconnect()
76
- delete el._mutate[vnode.ctx!.uid]
81
+ state.observer.disconnect()
82
+ mutateState.delete(el)
77
83
  }
78
84
 
79
85
  export const Mutate = {
@@ -8,10 +8,10 @@ describe('resize.ts', () => {
8
8
  jest.spyOn(window, 'removeEventListener')
9
9
  const el = {}
10
10
 
11
- Resize.mounted(el as HTMLElement, { value: callback } as any, { ctx: { uid: 1 } } as any)
11
+ Resize.mounted(el as HTMLElement, { instance: { $: { uid: 1 } }, value: callback } as any, {} as any)
12
12
  expect(callback).toHaveBeenCalled()
13
13
  expect(window.addEventListener).toHaveBeenCalledWith('resize', callback, { passive: true })
14
- Resize.unmounted(el as HTMLElement, { value: callback } as any, { ctx: { uid: 1 } } as any)
14
+ Resize.unmounted(el as HTMLElement, { instance: { $: { uid: 1 } }, value: callback } as any, {} as any)
15
15
  expect(window.removeEventListener).toHaveBeenCalledWith('resize', callback, { passive: true })
16
16
  })
17
17
 
@@ -21,10 +21,10 @@ describe('resize.ts', () => {
21
21
  jest.spyOn(window, 'removeEventListener')
22
22
  const el = {}
23
23
 
24
- Resize.mounted(el as HTMLElement, { value: callback, modifiers: { quiet: true } } as any, { ctx: { uid: 1 } } as any)
24
+ Resize.mounted(el as HTMLElement, { instance: { $: { uid: 1 } }, value: callback, modifiers: { quiet: true } } as any, {} as any)
25
25
  expect(callback).not.toHaveBeenCalled()
26
26
  expect(window.addEventListener).toHaveBeenCalledWith('resize', callback, { passive: true })
27
- Resize.unmounted(el as HTMLElement, { value: callback, modifiers: { quiet: true } } as any, { ctx: { uid: 1 } } as any)
27
+ Resize.unmounted(el as HTMLElement, { instance: { $: { uid: 1 } }, value: callback, modifiers: { quiet: true } } as any, {} as any)
28
28
  expect(window.removeEventListener).toHaveBeenCalledWith('resize', callback, { passive: true })
29
29
  })
30
30
  })
@@ -5,18 +5,13 @@ interface ResizeDirectiveBinding extends DirectiveBinding {
5
5
  options?: boolean | AddEventListenerOptions
6
6
  }
7
7
 
8
- declare global {
9
- interface HTMLElement {
10
- _onResize?: Record<
11
- number,
12
- {
13
- callback: () => void
14
- options: boolean | AddEventListenerOptions
15
- }
16
- >
17
- }
8
+ interface ResizeState {
9
+ callback: () => void
10
+ options: boolean | AddEventListenerOptions
18
11
  }
19
12
 
13
+ const resizeState = new WeakMap<HTMLElement, ResizeState>()
14
+
20
15
  function mounted (
21
16
  el: HTMLElement,
22
17
  binding: ResizeDirectiveBinding,
@@ -27,11 +22,10 @@ function mounted (
27
22
 
28
23
  window.addEventListener('resize', callback, options)
29
24
 
30
- el._onResize = Object(el._onResize)
31
- el._onResize![vnode.ctx!.uid] = {
25
+ resizeState.set(el, {
32
26
  callback,
33
27
  options
34
- }
28
+ })
35
29
 
36
30
  if (!binding.modifiers || !binding.modifiers.quiet) {
37
31
  callback()
@@ -43,13 +37,12 @@ function unmounted (
43
37
  binding: ResizeDirectiveBinding,
44
38
  vnode: VNode
45
39
  ) {
46
- if (!el._onResize?.[vnode.ctx!.uid]) return
47
-
48
- const { callback, options } = el._onResize[vnode.ctx!.uid]!
40
+ const state = resizeState.get(el)
41
+ if (!state) return
42
+ const { callback, options } = state
49
43
 
50
44
  window.removeEventListener('resize', callback, options)
51
-
52
- delete el._onResize[vnode.ctx!.uid]
45
+ resizeState.delete(el)
53
46
  }
54
47
 
55
48
  export const Resize: ObjectDirective = {
@@ -12,9 +12,10 @@ describe('scroll.ts', () => {
12
12
  let vnode
13
13
 
14
14
  beforeEach(() => {
15
- vnode = { ctx: { uid: 1 } } as any
15
+ vnode = {} as any
16
16
  options = { passive: true }
17
17
  binding = {
18
+ instance: { $: { uid: 1 } },
18
19
  value: jest.fn(),
19
20
  modifiers: {},
20
21
  arg: null
@@ -32,16 +33,10 @@ describe('scroll.ts', () => {
32
33
  mounted(el, binding, vnode)
33
34
 
34
35
  expect(spyOnWindowAddListener).toHaveBeenCalledWith('scroll', binding.value, options)
35
- expect(el._onScroll[1]).toEqual({
36
- handler: binding.value,
37
- options,
38
- target: window
39
- })
40
36
 
41
37
  unmounted(el, binding, vnode)
42
38
 
43
39
  expect(spyOnWindowRemoveListener).toHaveBeenCalledWith('scroll', binding.value, options)
44
- expect(el._onScroll[1]).toBeUndefined()
45
40
  })
46
41
 
47
42
  it('should work with a provided valid querySelector string', () => {
@@ -66,16 +61,10 @@ describe('scroll.ts', () => {
66
61
  mounted(el, binding, vnode)
67
62
 
68
63
  expect(spyOnFooAddListener).toHaveBeenCalledWith('scroll', binding.value, options)
69
- expect(el._onScroll[1]).toEqual({
70
- handler: binding.value,
71
- options,
72
- target
73
- })
74
64
 
75
65
  unmounted(el, binding, vnode)
76
66
 
77
67
  expect(spyOnFooRemoveListener).toHaveBeenCalledWith('scroll', binding.value, options)
78
- expect(el._onScroll[1]).toBeUndefined()
79
68
 
80
69
  document.body.removeChild(target)
81
70
  })
@@ -86,16 +75,10 @@ describe('scroll.ts', () => {
86
75
  mounted(el, binding, vnode)
87
76
 
88
77
  expect(el.addEventListener).toHaveBeenCalledWith('scroll', binding.value, options)
89
- expect(el._onScroll[1]).toEqual({
90
- handler: binding.value,
91
- options,
92
- target: undefined
93
- })
94
78
 
95
79
  unmounted(el, binding, vnode)
96
80
 
97
81
  expect(el.removeEventListener).toHaveBeenCalledWith('scroll', binding.value, options)
98
- expect(el._onScroll[1]).toBeUndefined()
99
82
  })
100
83
 
101
84
  it('should not remove listeners if no _onScroll property present', () => {
@@ -106,25 +89,18 @@ describe('scroll.ts', () => {
106
89
 
107
90
  it('should accept an object for the value with handler and/or options', () => {
108
91
  const handler = binding.value
92
+ jest.spyOn(window, 'addEventListener')
109
93
 
110
94
  binding.value = { handler }
111
95
 
112
96
  mounted(el, binding, vnode)
113
97
 
114
- expect(el._onScroll[1]).toEqual({
115
- handler,
116
- target: window,
117
- options: { passive: true }
118
- })
98
+ expect(window.addEventListener).toHaveBeenLastCalledWith('scroll', handler, { passive: true })
119
99
 
120
100
  binding.value = { handler, options: { passive: false } }
121
101
 
122
102
  mounted(el, binding, vnode)
123
103
 
124
- expect(el._onScroll[1]).toEqual({
125
- handler,
126
- target: window,
127
- options: { passive: false }
128
- })
104
+ expect(window.addEventListener).toHaveBeenLastCalledWith('scroll', handler, { passive: false })
129
105
  })
130
106
  })
@@ -13,6 +13,14 @@ interface ScrollDirectiveBinding extends Omit<DirectiveBinding, 'modifiers'> {
13
13
  }
14
14
  }
15
15
 
16
+ interface ScrollState {
17
+ handler: EventListener | EventListenerObject
18
+ options: boolean | AddEventListenerOptions
19
+ target?: EventTarget
20
+ }
21
+
22
+ const scrollState = new WeakMap<HTMLElement, ScrollState>()
23
+
16
24
  function mounted (
17
25
  el: HTMLElement,
18
26
  binding: ScrollDirectiveBinding,
@@ -38,13 +46,12 @@ function mounted (
38
46
 
39
47
  target.addEventListener('scroll', handler, options)
40
48
 
41
- el._onScroll = Object(el._onScroll)
42
- el._onScroll![vnode.ctx!.uid] = {
49
+ scrollState.set(el, {
43
50
  handler,
44
51
  options,
45
52
  // Don't reference self
46
53
  target: self ? undefined : target
47
- }
54
+ })
48
55
  }
49
56
 
50
57
  function unmounted (
@@ -52,12 +59,12 @@ function unmounted (
52
59
  binding: ScrollDirectiveBinding,
53
60
  vnode: VNode
54
61
  ) {
55
- if (!el._onScroll?.[vnode.ctx!.uid]) return
56
-
57
- const { handler, options, target = el } = el._onScroll[vnode.ctx!.uid]!
62
+ const state = scrollState.get(el)
63
+ if (!state) return
64
+ const { handler, options, target = el } = state
58
65
 
59
66
  target.removeEventListener('scroll', handler, options)
60
- delete el._onScroll[vnode.ctx!.uid]
67
+ scrollState.delete(el)
61
68
  }
62
69
 
63
70
  export const Scroll: ObjectDirective = {