@gorse/shards-vue 1.0.8 → 2.0.0

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 (56) hide show
  1. package/README.md +8 -5
  2. package/build/optimize.js +27 -15
  3. package/build/rollup.config.js +28 -38
  4. package/dist/shards-vue.common.js +3639 -6083
  5. package/dist/shards-vue.common.js.map +1 -1
  6. package/dist/shards-vue.common.min.js +27 -1
  7. package/dist/shards-vue.common.min.map +1 -1
  8. package/dist/shards-vue.esm.js +3637 -6081
  9. package/dist/shards-vue.esm.js.map +1 -1
  10. package/dist/shards-vue.esm.min.js +27 -1
  11. package/dist/shards-vue.esm.min.map +1 -1
  12. package/dist/shards-vue.umd.js +3641 -6086
  13. package/dist/shards-vue.umd.js.map +1 -1
  14. package/dist/shards-vue.umd.min.js +27 -1
  15. package/dist/shards-vue.umd.min.map +1 -1
  16. package/package.json +24 -25
  17. package/sandbox/Sandbox.vue +1 -17
  18. package/sandbox/index.html +12 -0
  19. package/sandbox/main.js +7 -0
  20. package/sandbox/vite.config.js +6 -0
  21. package/src/components/alert/Alert.vue +20 -11
  22. package/src/components/button/Button.vue +1 -0
  23. package/src/components/button/ButtonClose.vue +1 -0
  24. package/src/components/collapse/Collapse.vue +17 -9
  25. package/src/components/datepicker/Datepicker.vue +335 -36
  26. package/src/components/datepicker/README.md +1 -1
  27. package/src/components/dropdown/Dropdown.vue +9 -10
  28. package/src/components/form-checkbox/FormCheckbox.vue +52 -39
  29. package/src/components/form-input/FormInput.vue +13 -4
  30. package/src/components/form-radio/FormRadio.vue +15 -9
  31. package/src/components/form-select/FormSelect.vue +11 -2
  32. package/src/components/form-textarea/FormTextarea.vue +50 -22
  33. package/src/components/input-group/README.md +24 -12
  34. package/src/components/link/Link.vue +4 -8
  35. package/src/components/modal/Modal.vue +6 -4
  36. package/src/components/modal/README.md +2 -2
  37. package/src/components/navbar/NavbarToggle.vue +1 -1
  38. package/src/components/navbar/README.md +5 -3
  39. package/src/components/popover/Popover.vue +3 -2
  40. package/src/components/popover/README.md +3 -3
  41. package/src/components/slider/Slider.vue +13 -4
  42. package/src/components/tabs/Tab.vue +19 -2
  43. package/src/components/tabs/Tabs.vue +42 -6
  44. package/src/components/tabs/_TabButton.vue +1 -0
  45. package/src/components/tooltip/Tooltip.vue +3 -1
  46. package/src/directives/click-away.js +39 -0
  47. package/src/directives/toggle/toggle.js +12 -7
  48. package/src/directives/tooltip/tooltip.js +6 -11
  49. package/src/index.js +8 -6
  50. package/src/markdown/getting-started/README.md +6 -4
  51. package/src/mixins/checkbox-radio.mixin.js +5 -6
  52. package/src/mixins/root-listener.mixin.js +12 -6
  53. package/src/mixins/tooltip-popover.mixin.js +1 -1
  54. package/src/utils/events.js +66 -0
  55. package/src/utils/index.js +20 -18
  56. package/src/utils/target.js +23 -9
@@ -40,12 +40,22 @@ import dTabButton from './_TabButton.vue'
40
40
 
41
41
  export default {
42
42
  name: 'd-tabs',
43
+ emits: ['update:modelValue', 'input'],
43
44
  components: {
44
45
  dTabButton
45
46
  },
47
+ provide() {
48
+ return {
49
+ dTabs: {
50
+ parent: this,
51
+ registerTab: tab => this.registerTab(tab),
52
+ unregisterTab: tab => this.unregisterTab(tab)
53
+ }
54
+ }
55
+ },
46
56
  data() {
47
57
  return {
48
- currentTab: this.value,
58
+ currentTab: this.modelValue !== undefined ? this.modelValue : this.value,
49
59
  tabs: [],
50
60
  // eslint-disable-next-line
51
61
  _tabsContainerID: null
@@ -57,10 +67,13 @@ export default {
57
67
  return
58
68
  }
59
69
 
70
+ this.$emit('update:modelValue', newVal)
60
71
  this.$emit('input', newVal)
61
- this.tabs[newVal].$emit('click')
72
+ if (this.tabs[newVal]) {
73
+ this.tabs[newVal].$emit('click')
74
+ }
62
75
  },
63
- value (newVal, oldVal) {
76
+ computedValue (newVal, oldVal) {
64
77
  if (newVal === oldVal) {
65
78
  return
66
79
  }
@@ -98,6 +111,10 @@ export default {
98
111
  /**
99
112
  * The value used to set the current tab.
100
113
  */
114
+ modelValue: {
115
+ type: Number,
116
+ default: undefined
117
+ },
101
118
  value: {
102
119
  type: Number,
103
120
  default: null
@@ -139,6 +156,9 @@ export default {
139
156
  }
140
157
  },
141
158
  computed: {
159
+ computedValue() {
160
+ return this.modelValue !== undefined ? this.modelValue : this.value
161
+ },
142
162
  computedID() {
143
163
  return this.id || `dr-tabs-${guid()}`
144
164
  },
@@ -224,6 +244,7 @@ export default {
224
244
  const tab = this.tabs[index]
225
245
 
226
246
  if (!tab) {
247
+ this.$emit('update:modelValue', this.currentTab)
227
248
  this.$emit('input', this.currentTab)
228
249
  return
229
250
  }
@@ -238,17 +259,32 @@ export default {
238
259
 
239
260
  this.tabs.forEach(_tab => {
240
261
  if (_tab === tab) {
241
- this.$set(_tab, 'localActiveState', true)
262
+ _tab.localActiveState = true
242
263
  return
243
264
  }
244
265
 
245
- this.$set(_tab, 'localActiveState', false)
266
+ _tab.localActiveState = false
246
267
  })
247
268
 
248
269
  this.currentTab = index
249
270
  },
271
+ registerTab(tab) {
272
+ if (this.tabs.indexOf(tab) === -1) {
273
+ this.tabs.push(tab)
274
+ }
275
+
276
+ this.$nextTick(this.updateTabs)
277
+ },
278
+ unregisterTab(tab) {
279
+ const index = this.tabs.indexOf(tab)
280
+
281
+ if (index !== -1) {
282
+ this.tabs.splice(index, 1)
283
+ }
284
+
285
+ this.$nextTick(this.updateTabs)
286
+ },
250
287
  updateTabs() {
251
- this.tabs = this.$children.filter(child => child._isTab)
252
288
  let tabIndex = null
253
289
 
254
290
  this.tabs.forEach((tab, index) => {
@@ -26,6 +26,7 @@ import { KEYCODES } from '../../utils/constants';
26
26
 
27
27
  export default {
28
28
  name: 'd-tab-button',
29
+ emits: ['click'],
29
30
  props: {
30
31
  /**
31
32
  * The element ID.
@@ -10,10 +10,12 @@
10
10
  import Tooltip from '../../utils/tooltip.class'
11
11
  import TooltipPopoverMixin from '../../mixins/tooltip-popover.mixin'
12
12
  import { TP_PLACEMENTS } from '../../utils/constants'
13
+ import { getEventBus } from '../../utils/events'
13
14
 
14
15
  export default {
15
16
  name: 'd-tooltip',
16
17
  mixins: [ TooltipPopoverMixin ],
18
+ emits: ['show', 'shown', 'hide', 'hidden', 'update:show', 'update:disabled', 'enabled', 'disabled'],
17
19
  props: {
18
20
  /**
19
21
  * Title.
@@ -104,7 +106,7 @@ export default {
104
106
  this._TPInstance = new Tooltip(
105
107
  target,
106
108
  this.getUpdatedConfig(),
107
- this.$root
109
+ getEventBus(this)
108
110
  )
109
111
  }
110
112
 
@@ -0,0 +1,39 @@
1
+ const KEY = '__DR_CLICK_AWAY__'
2
+
3
+ function onClickAway(el, binding, event) {
4
+ if (!el || el === event.target || el.contains(event.target)) {
5
+ return
6
+ }
7
+
8
+ if (typeof binding.value === 'function') {
9
+ binding.value(event)
10
+ }
11
+ }
12
+
13
+ export default {
14
+ beforeMount(el, binding) {
15
+ if (typeof document === 'undefined') {
16
+ return
17
+ }
18
+
19
+ const handler = event => onClickAway(el, binding, event)
20
+
21
+ el[KEY] = handler
22
+ document.addEventListener('click', handler)
23
+ document.addEventListener('touchstart', handler)
24
+ },
25
+
26
+ unmounted(el) {
27
+ if (typeof document === 'undefined') {
28
+ return
29
+ }
30
+
31
+ if (!el[KEY]) {
32
+ return
33
+ }
34
+
35
+ document.removeEventListener('click', el[KEY])
36
+ document.removeEventListener('touchstart', el[KEY])
37
+ delete el[KEY]
38
+ }
39
+ }
@@ -1,17 +1,20 @@
1
1
  import target from '../../utils/target'
2
+ import { unbindTargets } from '../../utils/target'
2
3
  import { COLLAPSE_EVENTS } from '../../utils/constants'
3
4
  import { setAttr, addClass, removeClass } from '../../utils'
5
+ import { getEventBus } from '../../utils/events'
4
6
 
5
7
  const inBrowser = typeof window !== 'undefined'
6
8
  const DR_TOGGLE = '__DRTOGGLE'
7
9
 
8
10
  export default {
9
- bind(element, binding, vnode) {
10
- const targets = target(vnode, binding, { click: true }, ({ targets, vnode }) => {
11
- targets.forEach(target => vnode.context.$root.$emit(COLLAPSE_EVENTS.TOGGLE, target));
11
+ beforeMount(element, binding) {
12
+ const bus = getEventBus(binding.instance)
13
+ const targets = target(element, binding, { click: true }, ({ targets }) => {
14
+ targets.forEach(target => bus.$emit(COLLAPSE_EVENTS.TOGGLE, target));
12
15
  });
13
16
 
14
- if (inBrowser && vnode.context && targets.length > 0) {
17
+ if (inBrowser && targets.length > 0) {
15
18
  setAttr(element, 'aria-controls', targets.join(' '))
16
19
  setAttr(element, 'aria-expanded', 'false')
17
20
 
@@ -31,15 +34,17 @@ export default {
31
34
  addClass(element, 'collapsed');
32
35
  }
33
36
  }
34
- vnode.context.$root.$on(COLLAPSE_EVENTS.STATE, element[DR_TOGGLE])
37
+ bus.$on(COLLAPSE_EVENTS.STATE, element[DR_TOGGLE])
35
38
  }
36
39
  },
37
- unbind(element, binding, vnode) {
40
+ unmounted(element, binding) {
41
+ unbindTargets(element, binding, { click: true })
42
+
38
43
  if (!element[DR_TOGGLE]) {
39
44
  return
40
45
  }
41
46
 
42
- vnode.context.$root.$off(COLLAPSE_EVENTS.STATE, element[DR_TOGGLE])
47
+ getEventBus(binding.instance).$off(COLLAPSE_EVENTS.STATE, element[DR_TOGGLE])
43
48
  element[DR_TOGGLE] = null
44
49
  }
45
50
  }
@@ -1,4 +1,5 @@
1
1
  import Tooltip from '../../utils/tooltip.class'
2
+ import { getEventBus } from '../../utils/events'
2
3
 
3
4
  const inBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'
4
5
  const KEY = '_DR_TOOLTIP_'
@@ -103,7 +104,7 @@ function applyTooltip(el, bindings, vnode) {
103
104
  const parsedBindings = parseBindings(bindings)
104
105
 
105
106
  if (!el[KEY]) {
106
- el[KEY] = new Tooltip(el, parsedBindings, vnode.context.$root)
107
+ el[KEY] = new Tooltip(el, parsedBindings, getEventBus(bindings.instance))
107
108
  return
108
109
  }
109
110
 
@@ -111,27 +112,21 @@ function applyTooltip(el, bindings, vnode) {
111
112
  }
112
113
 
113
114
  export default {
114
- bind (el, bindings, vnode) {
115
+ beforeMount (el, bindings, vnode) {
115
116
  applyTooltip(el, bindings, vnode)
116
117
  },
117
118
 
118
- inserted(el, bindings, vnode) {
119
+ mounted(el, bindings, vnode) {
119
120
  applyTooltip(el, bindings, vnode)
120
121
  },
121
122
 
122
- update (el, bindings, vnode) {
123
+ updated (el, bindings, vnode) {
123
124
  if (bindings.value !== bindings.oldValue) {
124
125
  applyTooltip(el, bindings, vnode)
125
126
  }
126
127
  },
127
128
 
128
- componentUpdated (el, bindings, vnode) {
129
- if (bindings.value !== bindings.oldValue) {
130
- applyTooltip(el, bindings, vnode)
131
- }
132
- },
133
-
134
- unbind (el) {
129
+ unmounted (el) {
135
130
  if (!inBrowser) {
136
131
  return
137
132
  }
package/src/index.js CHANGED
@@ -1,27 +1,29 @@
1
1
  import * as components from './components'
2
2
  import * as directives from './directives'
3
3
  import { vueUse } from './utils'
4
+ import { installEventBus } from './utils/events'
4
5
 
5
6
  const VuePlugin = {
6
- install: function (Vue) {
7
- if (Vue._shards_vue_installed) {
7
+ install: function (app) {
8
+ if (app._shards_vue_installed) {
8
9
  return
9
10
  }
10
11
 
11
- Vue._shards_vue_installed = true;
12
+ app._shards_vue_installed = true
13
+ installEventBus(app)
12
14
 
13
15
  // Register component plugins
14
16
  for (let component in components) {
15
- Vue.use(components[component])
17
+ app.use(components[component])
16
18
  }
17
19
 
18
20
  // Register directive plugins
19
21
  for (let directive in directives) {
20
- Vue.use(directives[directive])
22
+ app.use(directives[directive])
21
23
  }
22
24
  }
23
25
  }
24
26
 
25
27
  vueUse(VuePlugin)
26
28
 
27
- export default VuePlugin
29
+ export default VuePlugin
@@ -24,14 +24,15 @@ npm i @gorse/shards-vue
24
24
  You can register the entire UI kit as a Vue plugin in your app's entry point:
25
25
 
26
26
  ```javascript
27
- import Vue from 'vue'
27
+ import { createApp } from 'vue'
28
28
  import ShardsVue from '@gorse/shards-vue'
29
+ import App from './App.vue'
29
30
 
30
31
  // Import base styles (Bootstrap and Shards)
31
32
  import 'bootstrap/dist/css/bootstrap.css'
32
33
  import '@gorse/shards-ui/dist/css/shards.css'
33
34
 
34
- Vue.use(ShardsVue);
35
+ createApp(App).use(ShardsVue).mount('#app')
35
36
  ```
36
37
 
37
38
  ## Registering Components as Vue Plugins
@@ -39,14 +40,15 @@ Vue.use(ShardsVue);
39
40
  If you'd like to register only certain components as Vue plugins, make sure to import just the component you'd like to use.
40
41
 
41
42
  ```javascript
42
- import Vue from 'vue'
43
+ import { createApp } from 'vue'
44
+ import App from './App.vue'
43
45
 
44
46
  // Import base styles (Bootstrap and Shards)
45
47
  import 'bootstrap/dist/css/bootstrap.css'
46
48
  import '@gorse/shards-ui/dist/css/shards.css'
47
49
 
48
50
  import { Button } from '@gorse/shards-vue/src/components'
49
- Vue.use(Button)
51
+ createApp(App).use(Button).mount('#app')
50
52
 
51
53
  ```
52
54
 
@@ -1,15 +1,14 @@
1
1
  export default {
2
2
  data() {
3
3
  return {
4
- localChecked: this.checked,
4
+ localChecked: this.modelValue !== undefined ? this.modelValue : this.checked,
5
5
  hasFocus: false
6
6
  }
7
7
  },
8
- model: {
9
- prop: 'checked',
10
- event: 'input'
11
- },
12
8
  props: {
9
+ modelValue: {
10
+ default: undefined
11
+ },
13
12
  value: {},
14
13
  checked: {},
15
14
  buttonTheme: {
@@ -20,7 +19,7 @@ export default {
20
19
  computed: {
21
20
  computedLocalChecked: {
22
21
  get() {
23
- this.isChild ? this.$parent.localChecked : this.localChecked
22
+ return this.isChild ? this.$parent.localChecked : this.localChecked
24
23
  },
25
24
  set (val) {
26
25
  if (this.isChild) {
@@ -1,4 +1,5 @@
1
1
  import { isArray } from '../utils';
2
+ import { getEventBus } from '../utils/events';
2
3
 
3
4
  const _DR_RL_ = '_DR_RL_';
4
5
 
@@ -9,24 +10,29 @@ export default {
9
10
  this[_DR_RL_] = []
10
11
  }
11
12
 
12
- this[_DR_RL_].push({ event, callback })
13
- this.$root.$on(event, callback)
13
+ const bus = getEventBus(this)
14
+ const boundCallback = callback.bind(this)
15
+
16
+ this[_DR_RL_].push({ event, callback: boundCallback })
17
+ bus.$on(event, boundCallback)
14
18
 
15
19
  return this
16
20
  },
17
21
  emitOnRoot(event, ...args) {
18
- this.$root.$emit(event, ...args)
22
+ getEventBus(this).$emit(event, ...args)
19
23
  return this
20
24
  }
21
25
  },
22
- beforeDestroy() {
23
- if (!this[_DR_RL_] && !isArray(this[_DR_RL_])) {
26
+ beforeUnmount() {
27
+ if (!this[_DR_RL_] || !isArray(this[_DR_RL_])) {
24
28
  return
25
29
  }
26
30
 
31
+ const bus = getEventBus(this)
32
+
27
33
  while (this[_DR_RL_].length > 0) {
28
34
  const { event, callback } = this[_DR_RL_].shift()
29
- this.$root.$off(event, callback)
35
+ bus.$off(event, callback)
30
36
  }
31
37
  }
32
38
  }
@@ -88,7 +88,7 @@ export default {
88
88
  /**
89
89
  * Clean up everything before the instance is destroyed.
90
90
  */
91
- beforeDestroy() {
91
+ beforeUnmount() {
92
92
  this._disableDOMObserver()
93
93
 
94
94
  if (this._TPInstance) {
@@ -46,3 +46,69 @@ export class CancelableEvent {
46
46
  }
47
47
  }
48
48
  }
49
+
50
+ export function createEventBus() {
51
+ const listeners = Object.create(null)
52
+
53
+ return {
54
+ $on(event, callback) {
55
+ if (!listeners[event]) {
56
+ listeners[event] = new Set()
57
+ }
58
+
59
+ listeners[event].add(callback)
60
+ },
61
+
62
+ $off(event, callback) {
63
+ if (!listeners[event]) {
64
+ return
65
+ }
66
+
67
+ if (callback) {
68
+ listeners[event].delete(callback)
69
+ } else {
70
+ listeners[event].clear()
71
+ }
72
+ },
73
+
74
+ $emit(event, ...args) {
75
+ if (!listeners[event]) {
76
+ return
77
+ }
78
+
79
+ listeners[event].forEach(callback => callback(...args))
80
+ }
81
+ }
82
+ }
83
+
84
+ const fallbackEventBus = createEventBus()
85
+
86
+ export function installEventBus(app) {
87
+ if (!app || !app.config || !app.config.globalProperties) {
88
+ return fallbackEventBus
89
+ }
90
+
91
+ if (!app.config.globalProperties.$shardsVueBus) {
92
+ app.config.globalProperties.$shardsVueBus = createEventBus()
93
+ }
94
+
95
+ return app.config.globalProperties.$shardsVueBus
96
+ }
97
+
98
+ export function getEventBus(instance) {
99
+ if (instance && instance.$shardsVueBus) {
100
+ return instance.$shardsVueBus
101
+ }
102
+
103
+ if (
104
+ instance
105
+ && instance.appContext
106
+ && instance.appContext.config
107
+ && instance.appContext.config.globalProperties
108
+ && instance.appContext.config.globalProperties.$shardsVueBus
109
+ ) {
110
+ return instance.appContext.config.globalProperties.$shardsVueBus
111
+ }
112
+
113
+ return fallbackEventBus
114
+ }
@@ -2,50 +2,52 @@
2
2
  /* UTILITY FUNCTIONS
3
3
  /*--------------------------------------------------------------------------*/
4
4
 
5
- // Install a Vue plugin if Vue is available on the window object.
5
+ import { installEventBus } from './events'
6
+
7
+ // Preserve legacy module side-effect calls without auto-installing in Vue 3.
6
8
  export function vueUse(VuePlugin) {
7
- if (typeof window !== 'undefined' && window.Vue) {
8
- window.Vue.use(VuePlugin)
9
- }
9
+ return VuePlugin
10
10
  }
11
11
 
12
12
  // Register a component plugin.
13
- export function registerComponent(Vue, name, definition) {
14
- Vue._shards_vue_components_ = Vue._shards_vue_components_ || {}
15
- const loaded = Vue._shards_vue_components_[name]
13
+ export function registerComponent(app, name, definition) {
14
+ installEventBus(app)
15
+ app._shards_vue_components_ = app._shards_vue_components_ || {}
16
+ const loaded = app._shards_vue_components_[name]
16
17
 
17
18
  if (!loaded && definition && name) {
18
- Vue._shards_vue_components_[name] = true
19
- Vue.component(name, definition)
19
+ app._shards_vue_components_[name] = true
20
+ app.component(name, definition)
20
21
  }
21
22
 
22
23
  return loaded
23
24
  }
24
25
 
25
26
  // Register a group of components.
26
- export function registerComponents(Vue, components) {
27
+ export function registerComponents(app, components) {
27
28
  for (let component in components) {
28
- registerComponent(Vue, component, components[component])
29
+ registerComponent(app, component, components[component])
29
30
  }
30
31
  }
31
32
 
32
33
  // Register a directive as being loaded. returns true if directive plugin already registered
33
- export function registerDirective(Vue, name, definition) {
34
- Vue._shards_vue_directives_ = Vue._shards_vue_directives_ || {}
35
- const loaded = Vue._shards_vue_directives_[name]
34
+ export function registerDirective(app, name, definition) {
35
+ installEventBus(app)
36
+ app._shards_vue_directives_ = app._shards_vue_directives_ || {}
37
+ const loaded = app._shards_vue_directives_[name]
36
38
 
37
39
  if (!loaded && definition && name) {
38
- Vue._shards_vue_directives_[name] = true
39
- Vue.directive(name, definition)
40
+ app._shards_vue_directives_[name] = true
41
+ app.directive(name, definition)
40
42
  }
41
43
 
42
44
  return loaded
43
45
  }
44
46
 
45
47
  // Register a group of directives as being loaded.
46
- export function registerDirectives(Vue, directives) {
48
+ export function registerDirectives(app, directives) {
47
49
  for (let directive in directives) {
48
- registerDirective(Vue, directive, directives[directive])
50
+ registerDirective(app, directive, directives[directive])
49
51
  }
50
52
  }
51
53
 
@@ -6,7 +6,15 @@ const allListenTypes = {
6
6
 
7
7
  const BEL_KEY = '__DR_BOUND_EVENT_LISTENERS__'
8
8
 
9
- const bindTargets = (vnode, binding, listenTypes, callback) => {
9
+ const getElement = el => el && (el.elm || el.el || el)
10
+
11
+ const bindTargets = (el, binding, listenTypes, callback) => {
12
+ const element = getElement(el)
13
+
14
+ if (!element) {
15
+ return []
16
+ }
17
+
10
18
  const targets = Object.keys(binding.modifiers || {}).filter(t => !allListenTypes[t])
11
19
 
12
20
  if (binding.value) {
@@ -14,29 +22,35 @@ const bindTargets = (vnode, binding, listenTypes, callback) => {
14
22
  }
15
23
 
16
24
  const listener = () => {
17
- callback({ targets, vnode })
25
+ callback({ targets, el: element, binding })
18
26
  }
19
27
 
20
28
  Object.keys(allListenTypes).forEach(type => {
21
29
  if (listenTypes[type] || binding.modifiers[type]) {
22
- vnode.elm.addEventListener(type, listener)
23
- const boundListeners = vnode.elm[BEL_KEY] || {}
30
+ element.addEventListener(type, listener)
31
+ const boundListeners = element[BEL_KEY] || {}
24
32
  boundListeners[type] = boundListeners[type] || []
25
33
  boundListeners[type].push(listener)
26
- vnode.elm[BEL_KEY] = boundListeners
34
+ element[BEL_KEY] = boundListeners
27
35
  }
28
36
  })
29
37
 
30
38
  return targets
31
39
  }
32
40
 
33
- const unbindTargets = (vnode, binding, listenTypes) => {
41
+ const unbindTargets = (el, binding, listenTypes) => {
42
+ const element = getElement(el)
43
+
44
+ if (!element) {
45
+ return
46
+ }
47
+
34
48
  Object.keys(allListenTypes).forEach(type => {
35
49
  if (listenTypes[type] || binding.modifiers[type]) {
36
- const boundListeners = vnode.elm[BEL_KEY] && vnode.elm[BEL_KEY][type]
50
+ const boundListeners = element[BEL_KEY] && element[BEL_KEY][type]
37
51
  if (boundListeners) {
38
- boundListeners.forEach(listener => vnode.elm.removeEventListener(type, listener))
39
- delete vnode.elm[BEL_KEY][type]
52
+ boundListeners.forEach(listener => element.removeEventListener(type, listener))
53
+ delete element[BEL_KEY][type]
40
54
  }
41
55
  }
42
56
  })