@dimailn/vuetify 2.7.2-alpha23 → 2.7.2-alpha24

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 (46) hide show
  1. package/dist/vuetify.js +40 -27
  2. package/dist/vuetify.js.map +1 -1
  3. package/dist/vuetify.min.css +1 -1
  4. package/dist/vuetify.min.js +2 -2
  5. package/es5/components/VBadge/VBadge.js +17 -14
  6. package/es5/components/VBadge/VBadge.js.map +1 -1
  7. package/es5/components/VInput/VInput.js +4 -0
  8. package/es5/components/VInput/VInput.js.map +1 -1
  9. package/es5/components/VSelect/VSelectList.js +1 -1
  10. package/es5/components/VSelect/VSelectList.js.map +1 -1
  11. package/es5/framework.js +1 -1
  12. package/es5/mixins/activatable/index.js +2 -1
  13. package/es5/mixins/activatable/index.js.map +1 -1
  14. package/es5/mixins/bootable/index.js +1 -2
  15. package/es5/mixins/bootable/index.js.map +1 -1
  16. package/es5/mixins/mouse/index.js +10 -5
  17. package/es5/mixins/mouse/index.js.map +1 -1
  18. package/es5/mixins/selectable/index.js +3 -0
  19. package/es5/mixins/selectable/index.js.map +1 -1
  20. package/lib/components/VBadge/VBadge.js +14 -13
  21. package/lib/components/VBadge/VBadge.js.map +1 -1
  22. package/lib/components/VInput/VInput.js +4 -0
  23. package/lib/components/VInput/VInput.js.map +1 -1
  24. package/lib/components/VSelect/VSelectList.js +2 -1
  25. package/lib/components/VSelect/VSelectList.js.map +1 -1
  26. package/lib/framework.js +1 -1
  27. package/lib/mixins/activatable/index.js +2 -1
  28. package/lib/mixins/activatable/index.js.map +1 -1
  29. package/lib/mixins/bootable/index.js +2 -4
  30. package/lib/mixins/bootable/index.js.map +1 -1
  31. package/lib/mixins/mouse/index.js +9 -5
  32. package/lib/mixins/mouse/index.js.map +1 -1
  33. package/lib/mixins/selectable/index.js +4 -0
  34. package/lib/mixins/selectable/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/VBadge/VBadge.ts +24 -25
  37. package/src/components/VBadge/__tests__/VBadge.spec.ts +47 -30
  38. package/src/components/VBadge/__tests__/__snapshots__/VBadge.spec.ts.snap +5 -5
  39. package/src/components/VInput/VInput.ts +4 -0
  40. package/src/components/VSelect/VSelectList.ts +1 -0
  41. package/src/mixins/activatable/index.ts +2 -1
  42. package/src/mixins/bootable/__tests__/bootable.spec.ts +17 -11
  43. package/src/mixins/bootable/index.ts +4 -3
  44. package/src/mixins/mouse/__tests__/mouse.spec.ts +54 -40
  45. package/src/mixins/mouse/index.ts +10 -6
  46. package/src/mixins/selectable/index.ts +4 -0
@@ -1,4 +1,4 @@
1
- import {Transition, h} from 'vue'
1
+ import { Transition, h, defineComponent, VNode, withDirectives, vShow } from 'vue'
2
2
  // Styles
3
3
  import './VBadge.sass'
4
4
 
@@ -8,30 +8,29 @@ import VIcon from '../VIcon/VIcon'
8
8
  // Mixins
9
9
  import Colorable from '../../mixins/colorable'
10
10
  import Themeable from '../../mixins/themeable'
11
- import Toggleable from '../../mixins/toggleable'
11
+ import { factory as ToggleableFactory } from '../../mixins/toggleable'
12
12
  import Transitionable from '../../mixins/transitionable'
13
13
  import { factory as PositionableFactory } from '../../mixins/positionable'
14
14
  import mergeData from '../../util/mergeData'
15
15
  // Utilities
16
- import mixins from '../../util/mixins'
17
16
  import {
18
17
  convertToUnit,
19
18
  getSlot,
20
19
  } from '../../util/helpers'
21
20
 
22
- // Types
23
- import { VNode } from 'vue'
24
-
25
- export default mixins(
26
- Colorable,
27
- PositionableFactory(['left', 'bottom']),
28
- Themeable,
29
- Toggleable,
30
- Transitionable,
31
- /* @vue/component */
32
- ).extend({
21
+ const Toggleable = ToggleableFactory('modelValue', 'update:modelValue')
22
+
23
+ export default defineComponent({
33
24
  name: 'v-badge',
34
25
 
26
+ mixins: [
27
+ Colorable,
28
+ PositionableFactory(['left', 'bottom']),
29
+ Themeable,
30
+ Toggleable,
31
+ Transitionable,
32
+ ],
33
+
35
34
  props: {
36
35
  avatar: Boolean,
37
36
  bordered: Boolean,
@@ -55,7 +54,7 @@ export default mixins(
55
54
  type: String,
56
55
  default: 'scale-rotate-transition',
57
56
  },
58
- value: { default: true },
57
+ modelValue: { default: true },
59
58
  },
60
59
 
61
60
  computed: {
@@ -136,13 +135,12 @@ export default mixins(
136
135
  'aria-live': this.$attrs['aria-live'] || 'polite',
137
136
  title: this.$attrs.title,
138
137
  role: this.$attrs.role || 'status',
139
- directives: [{
140
- name: 'show',
141
- value: this.isActive,
142
- }],
143
138
  })
144
139
 
145
- const badge = h('span', data, [this.genBadgeContent()])
140
+ const badge = withDirectives(
141
+ h('span', data, [this.genBadgeContent()]),
142
+ [[vShow, this.isActive]]
143
+ )
146
144
 
147
145
  if (!this.transition) return badge
148
146
 
@@ -150,7 +148,9 @@ export default mixins(
150
148
  name: this.transition,
151
149
  origin: this.origin,
152
150
  mode: this.mode,
153
- }, [badge])
151
+ }, {
152
+ default: () => [badge],
153
+ })
154
154
  },
155
155
  genBadgeContent () {
156
156
  // Dot prop shows no content
@@ -160,7 +160,7 @@ export default mixins(
160
160
 
161
161
  if (slot) return slot
162
162
  if (this.content) return String(this.content)
163
- if (this.icon) return h(VIcon, this.icon)
163
+ if (this.icon) return h(VIcon, { icon: this.icon })
164
164
 
165
165
  return undefined
166
166
  },
@@ -187,8 +187,7 @@ export default mixins(
187
187
  else children.push(badge)
188
188
 
189
189
  return h('span', mergeData({
190
- class: ['v-badge', this.classes]
191
- }, attrs)
192
- , children)
190
+ class: ['v-badge', this.classes],
191
+ }, attrs), children)
193
192
  },
194
193
  })
@@ -2,25 +2,26 @@
2
2
  import VBadge from '../VBadge'
3
3
 
4
4
  // Utilities
5
- import {
6
- mount,
7
- Wrapper,
8
- } from '@vue/test-utils'
9
- import { compileToFunctions } from 'vue-template-compiler'
5
+ import { mount, enableAutoUnmount, VueWrapper } from '@vue/test-utils'
10
6
 
11
7
  // Types
12
- import { ExtractVue } from '../../../util/mixins'
8
+ import { ComponentPublicInstance } from 'vue'
13
9
 
14
10
  describe('VBadge.ts', () => {
15
- type Instance = ExtractVue<typeof VBadge>
16
- let mountFunction: (options?: object) => Wrapper<Instance>
11
+ type Instance = ComponentPublicInstance
12
+ let mountFunction: (options?: object) => VueWrapper<Instance>
13
+
14
+ enableAutoUnmount(afterEach)
17
15
 
18
16
  beforeEach(() => {
19
17
  mountFunction = (options = {}) => {
20
18
  return mount(VBadge, {
21
- mocks: {
22
- $vuetify: {
23
- lang: { t: (text = '') => text },
19
+ global: {
20
+ mocks: {
21
+ $vuetify: {
22
+ lang: { t: (text = '') => text },
23
+ rtl: false,
24
+ },
24
25
  },
25
26
  },
26
27
  ...options,
@@ -31,22 +32,22 @@ describe('VBadge.ts', () => {
31
32
  it('should render component and match snapshot', async () => {
32
33
  const wrapper = mountFunction({
33
34
  slots: {
34
- badge: [compileToFunctions('<span>content</span>')],
35
- default: [compileToFunctions('<span>element</span>')],
35
+ badge: '<span>content</span>',
36
+ default: '<span>element</span>',
36
37
  },
37
38
  })
38
39
 
39
40
  expect(wrapper.html()).toMatchSnapshot()
40
41
  })
41
42
 
42
- it('should render component with with value=false and match snapshot', async () => {
43
+ it('should render component with with modelValue=false and match snapshot', async () => {
43
44
  const wrapper = mountFunction({
44
- propsData: {
45
- value: false,
45
+ props: {
46
+ modelValue: false,
46
47
  },
47
48
  slots: {
48
- badge: [compileToFunctions('<span>content</span>')],
49
- default: [compileToFunctions('<span>element</span>')],
49
+ badge: '<span>content</span>',
50
+ default: '<span>element</span>',
50
51
  },
51
52
  })
52
53
 
@@ -55,7 +56,7 @@ describe('VBadge.ts', () => {
55
56
 
56
57
  it('should render component with bottom prop', () => {
57
58
  const wrapper = mountFunction({
58
- propsData: {
59
+ props: {
59
60
  bottom: true,
60
61
  },
61
62
  })
@@ -65,7 +66,7 @@ describe('VBadge.ts', () => {
65
66
 
66
67
  it('should render component with left prop', () => {
67
68
  const wrapper = mountFunction({
68
- propsData: {
69
+ props: {
69
70
  left: true,
70
71
  },
71
72
  })
@@ -75,7 +76,7 @@ describe('VBadge.ts', () => {
75
76
 
76
77
  it('should render component with overlap prop', () => {
77
78
  const wrapper = mountFunction({
78
- propsData: {
79
+ props: {
79
80
  overlap: true,
80
81
  },
81
82
  })
@@ -85,11 +86,11 @@ describe('VBadge.ts', () => {
85
86
 
86
87
  it('should render component with color prop', () => {
87
88
  const wrapper = mountFunction({
88
- propsData: {
89
+ props: {
89
90
  color: 'green lighten-1',
90
91
  },
91
92
  slots: {
92
- badge: [compileToFunctions('<span>content</span>')],
93
+ badge: '<span>content</span>',
93
94
  },
94
95
  })
95
96
 
@@ -104,9 +105,17 @@ describe('VBadge.ts', () => {
104
105
  render: jest.fn(),
105
106
  }
106
107
 
107
- mountFunction({
108
- stubs: {
109
- transition: transitionStub,
108
+ const wrapper = mount(VBadge, {
109
+ global: {
110
+ mocks: {
111
+ $vuetify: {
112
+ lang: { t: (text = '') => text },
113
+ rtl: false,
114
+ },
115
+ },
116
+ stubs: {
117
+ transition: transitionStub,
118
+ },
110
119
  },
111
120
  })
112
121
 
@@ -119,12 +128,20 @@ describe('VBadge.ts', () => {
119
128
  render: jest.fn(),
120
129
  }
121
130
 
122
- mountFunction({
123
- propsData: {
131
+ const wrapper = mount(VBadge, {
132
+ props: {
124
133
  transition: '',
125
134
  },
126
- stubs: {
127
- transition: transitionStub,
135
+ global: {
136
+ mocks: {
137
+ $vuetify: {
138
+ lang: { t: (text = '') => text },
139
+ rtl: false,
140
+ },
141
+ },
142
+ stubs: {
143
+ transition: transitionStub,
144
+ },
128
145
  },
129
146
  })
130
147
 
@@ -6,11 +6,11 @@ exports[`VBadge.ts should render component and match snapshot 1`] = `
6
6
  element
7
7
  </span>
8
8
  <span class="v-badge__wrapper">
9
- <span aria-atomic="true"
9
+ <span class="v-badge__badge primary"
10
+ aria-atomic="true"
10
11
  aria-label="$vuetify.badge"
11
12
  aria-live="polite"
12
13
  role="status"
13
- class="v-badge__badge primary"
14
14
  >
15
15
  <span>
16
16
  content
@@ -20,17 +20,17 @@ exports[`VBadge.ts should render component and match snapshot 1`] = `
20
20
  </span>
21
21
  `;
22
22
 
23
- exports[`VBadge.ts should render component with with value=false and match snapshot 1`] = `
23
+ exports[`VBadge.ts should render component with with modelValue=false and match snapshot 1`] = `
24
24
  <span class="v-badge theme--light">
25
25
  <span>
26
26
  element
27
27
  </span>
28
28
  <span class="v-badge__wrapper">
29
- <span aria-atomic="true"
29
+ <span class="v-badge__badge primary"
30
+ aria-atomic="true"
30
31
  aria-label="$vuetify.badge"
31
32
  aria-live="polite"
32
33
  role="status"
33
- class="v-badge__badge primary"
34
34
  style="display: none;"
35
35
  >
36
36
  <span>
@@ -107,6 +107,10 @@ export default baseMixins.extend({
107
107
  set (val: any) {
108
108
  this.lazyValue = val
109
109
  this.$emit(this.$_modelEvent, val)
110
+
111
+ if('$_emitChangeEvent' in this) {
112
+ this.$emit('change', val)
113
+ }
110
114
  },
111
115
  },
112
116
  isDirty (): boolean {
@@ -176,6 +176,7 @@ export default mixins(Colorable, Themeable).extend({
176
176
  attrs: {
177
177
  ...tile.attrs,
178
178
  ...tile.props,
179
+ ...tile.on
179
180
  },
180
181
  on: tile.on,
181
182
  })
@@ -92,7 +92,8 @@ export default baseMixins.extend({
92
92
  attrs: {
93
93
  ...this.genActivatorListeners(),
94
94
  ...this.genActivatorAttributes(),
95
- }
95
+ },
96
+ on: this.genActivatorListeners()
96
97
  })) || []
97
98
 
98
99
  node = Array.isArray(node) ? node : [node]
@@ -4,18 +4,22 @@ import Bootable from '../index'
4
4
  // Utilities
5
5
  import {
6
6
  mount,
7
- Wrapper,
7
+ enableAutoUnmount,
8
+ VueWrapper,
8
9
  } from '@vue/test-utils'
10
+ import { h, nextTick, Comment } from 'vue'
9
11
 
10
12
  describe('Bootable.ts', () => {
11
13
  type Instance = InstanceType<typeof Bootable>
12
- let mountFunction: (options?: object) => Wrapper<Instance>
14
+ let mountFunction: (options?: object) => VueWrapper<Instance>
15
+
16
+ enableAutoUnmount(afterEach)
13
17
 
14
18
  beforeEach(() => {
15
19
  mountFunction = (options = {}) => {
16
20
  return mount({
17
21
  mixins: [Bootable],
18
- render: h => h('div'),
22
+ render: () => h('div'),
19
23
  }, {
20
24
  ...options,
21
25
  })
@@ -31,13 +35,13 @@ describe('Bootable.ts', () => {
31
35
 
32
36
  expect(wrapper.vm.isBooted).toBe(false)
33
37
  wrapper.vm.isActive = true
34
- await wrapper.vm.$nextTick()
38
+ await nextTick()
35
39
  expect(wrapper.vm.isBooted).toBe(true)
36
40
  })
37
41
 
38
42
  it('should return lazy content', async () => {
39
43
  const wrapper = mountFunction({
40
- propsData: {
44
+ props: {
41
45
  eager: true,
42
46
  },
43
47
  })
@@ -50,18 +54,20 @@ describe('Bootable.ts', () => {
50
54
  }),
51
55
  })
52
56
 
53
- expect(wrapperLazy.vm.showLazyContent(() => 'content')).toMatchObject([{ isComment: true }])
57
+ const lazyResult = wrapperLazy.vm.showLazyContent(() => 'content')
58
+ expect(Array.isArray(lazyResult)).toBe(true)
59
+ expect(lazyResult[0].type).toBe(Comment)
54
60
  wrapperLazy.vm.isActive = true
55
- await wrapper.vm.$nextTick()
61
+ await nextTick()
56
62
  expect(wrapperLazy.vm.showLazyContent(() => 'content')).toBe('content')
57
63
  wrapperLazy.vm.isActive = false
58
- await wrapper.vm.$nextTick()
64
+ await nextTick()
59
65
  expect(wrapperLazy.vm.showLazyContent(() => 'content')).toBe('content')
60
66
  })
61
67
 
62
68
  it('should show if lazy and active at boot', async () => {
63
69
  const wrapper = mountFunction({
64
- propsData: {
70
+ props: {
65
71
  eager: true,
66
72
  },
67
73
  })
@@ -77,8 +83,8 @@ describe('Bootable.ts', () => {
77
83
  expect(wrapper.vm.isActive).toBe(false)
78
84
  expect(wrapper.vm.isBooted).toBe(false)
79
85
 
80
- wrapper.setData({ isActive: true })
81
- await wrapper.vm.$nextTick()
86
+ wrapper.vm.isActive = true
87
+ await nextTick()
82
88
  expect(wrapper.vm.isBooted).toBe(true)
83
89
  })
84
90
  })
@@ -1,9 +1,10 @@
1
1
  // Utilities
2
2
  import { removed } from '../../util/console'
3
- import {h} from 'vue'
4
3
 
5
4
  // Types
6
- import { defineComponent, VNode, App } from 'vue'
5
+ import type { VNode, App } from 'vue'
6
+
7
+ import { defineComponent, h, Comment } from 'vue'
7
8
  interface Toggleable extends App {
8
9
  isActive?: boolean
9
10
  }
@@ -49,7 +50,7 @@ export default defineComponent({
49
50
 
50
51
  methods: {
51
52
  showLazyContent (content?: () => VNode[]): VNode[] {
52
- return (this.hasContent && content) ? content() : [h()]
53
+ return (this.hasContent && content) ? content() : [h(Comment)]
53
54
  },
54
55
  },
55
56
  })
@@ -2,89 +2,103 @@ import Mouse from '../index'
2
2
 
3
3
  import {
4
4
  mount,
5
- Wrapper,
6
- MountOptions,
5
+ VueWrapper,
6
+ MountingOptions,
7
7
  } from '@vue/test-utils'
8
- import { ExtractVue } from '../../../util/mixins'
8
+ import { ComponentPublicInstance, h, defineComponent } from 'vue'
9
9
 
10
- const Mock = Mouse.extend({
11
- render: h => h('div'),
10
+ const Mock = defineComponent({
11
+ mixins: [Mouse],
12
+ render: () => h('div'),
12
13
  })
13
14
 
14
15
  describe('mouse.ts', () => {
15
- type Instance = ExtractVue<typeof Mock>
16
- let mountFunction: (options?: MountOptions<Instance>) => Wrapper<Instance>
16
+ type Instance = ComponentPublicInstance & InstanceType<typeof Mock>
17
+ let mountFunction: (options?: MountingOptions<Instance>) => VueWrapper<Instance>
18
+
17
19
  beforeEach(() => {
18
- mountFunction = (options?: MountOptions<Instance>) => {
20
+ mountFunction = (options?: MountingOptions<Instance>) => {
19
21
  return mount(Mock, options)
20
22
  }
21
23
  })
22
24
 
23
25
  it('should generate mouse event handlers', async () => {
24
- const noop = e => e
26
+ const noop = (e: any) => e
25
27
  const wrapper = mount(Mock, {
26
- listeners: {
27
- click: noop,
28
+ attrs: {
29
+ onClick: noop,
28
30
  },
29
31
  })
30
32
 
31
- expect(typeof wrapper.vm.getMouseEventHandlers({ click: { event: 'click' } }, noop).click).toBe('function')
33
+ const handlers = wrapper.vm.getMouseEventHandlers({ click: { event: 'click' } }, noop)
34
+ expect(typeof handlers.click).toBe('function')
32
35
  })
33
36
 
34
37
  it('should generate default mouse event handlers', async () => {
35
- const noop = e => e
38
+ const noop = (e: any) => e
36
39
  const wrapper = mount(Mock, {
37
- listeners: {
38
- 'click:foo': noop,
40
+ attrs: {
41
+ 'onClick:foo': noop,
39
42
  },
40
43
  })
41
44
 
42
- expect(typeof wrapper.vm.getDefaultMouseEventHandlers(':foo', noop).click).toBe('function')
43
- expect(Object.keys(typeof wrapper.vm.getDefaultMouseEventHandlers('', noop))).toHaveLength(6)
45
+ const handlers = wrapper.vm.getDefaultMouseEventHandlers(':foo', noop)
46
+ // Для события click с суффиксом :foo, ключ будет 'click'
47
+ expect(typeof handlers.click).toBe('function')
48
+
49
+ // Тест для пустого суффикса
50
+ const wrapper2 = mount(Mock, {
51
+ attrs: {
52
+ onClick: noop,
53
+ onMouseenter: noop,
54
+ onMouseleave: noop,
55
+ onMousedown: noop,
56
+ onMouseup: noop,
57
+ onMousemove: noop,
58
+ },
59
+ })
60
+ const emptySuffixHandlers = wrapper2.vm.getDefaultMouseEventHandlers('', noop)
61
+ expect(Object.keys(emptySuffixHandlers)).toHaveLength(6)
44
62
  })
45
63
 
46
64
  it('should emit events', async () => {
47
- const fn = jest.fn()
48
65
  const wrapper = mount(Mock, {
49
- listeners: {
50
- click: fn,
66
+ attrs: {
67
+ onClick: () => {},
51
68
  },
52
69
  })
53
70
 
54
- const { click } = wrapper.vm.getMouseEventHandlers({ click: { event: 'click' } }, () => {})
71
+ const handlers = wrapper.vm.getMouseEventHandlers({ click: { event: 'click' } }, () => ({}))
72
+ const click = handlers.click
55
73
  Array.isArray(click) ? click[0](null) : click(null)
56
- expect(fn).toHaveBeenCalledTimes(1)
74
+ expect(wrapper.emitted()).toBeTruthy()
57
75
  })
58
76
 
59
77
  it('should handle prevent modifier', async () => {
60
- const fn = jest.fn()
61
78
  const wrapper = mount(Mock, {
62
- listeners: {
63
- click: fn,
79
+ attrs: {
80
+ onClick: () => {},
64
81
  },
65
82
  })
66
- const event = { preventDefault: () => {} }
67
- const spy = jest.spyOn(event, 'preventDefault')
83
+ const event = { preventDefault: jest.fn() } as unknown as MouseEvent
68
84
 
69
- const { click } = wrapper.vm.getMouseEventHandlers({ click: { event: 'click', prevent: true } }, () => {})
70
- Array.isArray(click) ? click[0](event as MouseEvent) : click(event as MouseEvent)
71
- expect(fn).toHaveBeenCalledTimes(1)
72
- expect(spy).toHaveBeenCalledTimes(1)
85
+ const handlers = wrapper.vm.getMouseEventHandlers({ click: { event: 'click', prevent: true } }, () => ({}))
86
+ const click = handlers.click
87
+ Array.isArray(click) ? click[0](event) : click(event)
88
+ expect(event.preventDefault).toHaveBeenCalledTimes(1)
73
89
  })
74
90
 
75
91
  it('should handle stop modifier', async () => {
76
- const fn = jest.fn()
77
92
  const wrapper = mount(Mock, {
78
- listeners: {
79
- click: fn,
93
+ attrs: {
94
+ onClick: () => {},
80
95
  },
81
96
  })
82
- const event = { stopPropagation: () => {} }
83
- const spy = jest.spyOn(event, 'stopPropagation')
97
+ const event = { stopPropagation: jest.fn() } as unknown as MouseEvent
84
98
 
85
- const { click } = wrapper.vm.getMouseEventHandlers({ click: { event: 'click', stop: true } }, () => {})
86
- Array.isArray(click) ? click[0](event as MouseEvent) : click(event as MouseEvent)
87
- expect(fn).toHaveBeenCalledTimes(1)
88
- expect(spy).toHaveBeenCalledTimes(1)
99
+ const handlers = wrapper.vm.getMouseEventHandlers({ click: { event: 'click', stop: true } }, () => ({}))
100
+ const click = handlers.click
101
+ Array.isArray(click) ? click[0](event) : click(event)
102
+ expect(event.stopPropagation).toHaveBeenCalledTimes(1)
89
103
  })
90
104
  })
@@ -1,4 +1,5 @@
1
- import {defineComponent} from 'vue'
1
+ import { defineComponent } from 'vue'
2
+ import { upperFirst } from '../../util/helpers'
2
3
 
3
4
  export type MouseHandler = (e: MouseEvent | TouchEvent) => any
4
5
 
@@ -12,6 +13,7 @@ export type MouseEvents = {
12
13
  prevent?: boolean
13
14
  button?: number
14
15
  result?: any
16
+ originalKey?: string
15
17
  }
16
18
  }
17
19
 
@@ -19,9 +21,8 @@ export type MouseEventsMap = {
19
21
  [event: string]: MouseHandler | MouseHandler[]
20
22
  }
21
23
 
22
- function mapEventName(str) {
23
- let newStr = "on" + str;
24
- return newStr.charAt(0).toUpperCase() + newStr.slice(1);
24
+ function mapEventName (str: string): string {
25
+ return `on${upperFirst(str)}`
25
26
  }
26
27
 
27
28
  export default defineComponent({
@@ -32,7 +33,9 @@ export default defineComponent({
32
33
  const listeners = Object.keys(this.$attrs)
33
34
  .filter(key => key.endsWith(suffix))
34
35
  .reduce((acc, key) => {
35
- acc[key] = { event: key.slice(0, -suffix.length) }
36
+ const eventName = suffix ? key.slice(0, -suffix.length) : key
37
+ const cleanEventName = eventName.startsWith('on') ? eventName.slice(2).toLowerCase() : eventName.toLowerCase()
38
+ acc[cleanEventName] = { event: cleanEventName, originalKey: key }
36
39
  return acc
37
40
  }, {} as MouseEvents)
38
41
 
@@ -47,7 +50,8 @@ export default defineComponent({
47
50
  for (const event in events) {
48
51
  const eventOptions = events[event]
49
52
 
50
- if (!this.$attrs[mapEventName(event)]) continue
53
+ const attrName = eventOptions.originalKey || (event.includes(':') ? event : mapEventName(event))
54
+ if (!this.$attrs[attrName]) continue
51
55
 
52
56
  // TODO somehow pull in modifiers
53
57
 
@@ -40,6 +40,10 @@ export default mixins(
40
40
  }
41
41
  },
42
42
 
43
+ created() {
44
+ this.$_emitChangeEvent = true
45
+ },
46
+
43
47
  computed: {
44
48
  computedColor (): string | undefined {
45
49
  if (!this.isActive) return undefined