-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
BubbleInput.ts
83 lines (74 loc) · 2.33 KB
/
BubbleInput.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
import type { OkuElement } from '@oku-ui/primitive'
import { reactiveOmit, usePrevious, useSize } from '@oku-ui/use-composable'
import { defineComponent, h, mergeProps, reactive, ref, toRefs, watchEffect } from 'vue'
import type { PropType } from 'vue'
const BUBBLE_INPUT_NAME = 'OkuBubbleInput'
export type BubbleInputNaviteElement = OkuElement<'button'>
export type BubbleInputElement = Omit<HTMLButtonElement, 'checked'>
export interface BubbleInputProps {
checked: boolean
control: HTMLElement | null
bubbles: boolean
}
const bubbleInputPropsObject = {
props: {
checked: {
type: Boolean as PropType<boolean>,
required: true,
},
control: {
type: Object as PropType<HTMLElement | null>,
default: null,
},
bubbles: {
type: Boolean as PropType<boolean | undefined>,
default: true,
},
},
}
const bubbleInput = defineComponent({
name: BUBBLE_INPUT_NAME,
inheritAttrs: false,
props: {
...bubbleInputPropsObject.props,
},
setup(props, { attrs }) {
const { control, checked, bubbles, ...inputProps } = toRefs(props)
const _reactive = reactive(inputProps)
const reactiveInputProps = reactiveOmit(_reactive, (key, _value) => key === undefined)
const inputRef = ref<HTMLInputElement | null>(null)
const prevChecked = usePrevious(checked)
const controlSize = useSize(control)
watchEffect(() => {
const input = inputRef.value!
const inputProto = window.HTMLInputElement.prototype
const descriptor = Object.getOwnPropertyDescriptor(inputProto, 'checked')
const setChecked = descriptor?.set
if (prevChecked.value !== checked.value && setChecked) {
const event = new Event('input', { bubbles: bubbles.value })
setChecked.call(input, checked.value)
input.dispatchEvent(event)
}
})
return () => h('input', {
'type': 'radio',
'aria-hidden': true,
'defaultChecked': checked.value,
...mergeProps(attrs, reactiveInputProps),
'tabindex': -1,
'ref': inputRef,
'style': {
...attrs.style as any,
...controlSize.value,
position: 'absolute',
pointerEvents: 'none',
opacity: 0,
margin: '0px',
},
})
},
})
export const OkuBubbleInput = bubbleInput as typeof bubbleInput &
(new () => {
$props: BubbleInputNaviteElement
})