-
Notifications
You must be signed in to change notification settings - Fork 21
/
index.js
99 lines (81 loc) · 3.08 KB
/
index.js
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
export default function autosize(textarea, {viewportMarginBottom = 100} = {}) {
let previousValue = null
let isUserResized = false
let x
let y
let height
function onUserResize(event) {
if (x !== event.clientX || y !== event.clientY) {
const newHeight = textarea.style.height
if (height && height !== newHeight) {
isUserResized = true
textarea.style.maxHeight = ''
textarea.removeEventListener('mousemove', onUserResize)
}
height = newHeight
}
x = event.clientX
y = event.clientY
}
const document = textarea.ownerDocument
const documentElement = document.documentElement
function overflowOffset() {
let offsetTop = 0
let el = textarea
while (el !== document.body && el !== null) {
offsetTop += el.offsetTop || 0
el = el.offsetParent
}
const top = offsetTop - document.defaultView.pageYOffset
const bottom = documentElement.clientHeight - (top + textarea.offsetHeight)
return {top, bottom}
}
function sizeToFit() {
if (isUserResized) return
if (textarea.value === previousValue) return
if (textarea.offsetWidth <= 0 && textarea.offsetHeight <= 0) return
const {top, bottom} = overflowOffset()
if (top < 0 || bottom < 0) {
return
}
const textareaStyle = getComputedStyle(textarea)
const topBorderWidth = Number(textareaStyle.borderTopWidth.replace(/px/, ''))
const bottomBorderWidth = Number(textareaStyle.borderBottomWidth.replace(/px/, ''))
const isBorderBox = textareaStyle.boxSizing === 'border-box'
const borderAddOn = isBorderBox ? topBorderWidth + bottomBorderWidth : 0
const maxHeight = Number(textareaStyle.height.replace(/px/, '')) + bottom
const adjustedViewportMarginBottom = bottom < viewportMarginBottom ? bottom : viewportMarginBottom
textarea.style.maxHeight = `${maxHeight - adjustedViewportMarginBottom}px`
const container = textarea.parentElement
if (container instanceof HTMLElement) {
const containerHeight = container.style.height
container.style.height = getComputedStyle(container).height
textarea.style.height = 'auto'
textarea.style.height = `${textarea.scrollHeight + borderAddOn}px`
container.style.height = containerHeight
height = textarea.style.height
}
previousValue = textarea.value
}
function onFormReset() {
isUserResized = false
textarea.style.height = ''
textarea.style.maxHeight = ''
}
textarea.addEventListener('mousemove', onUserResize)
textarea.addEventListener('input', sizeToFit)
textarea.addEventListener('change', sizeToFit)
textarea.addEventListenter('paste', sizeToFit)
const form = textarea.form
if (form) form.addEventListener('reset', onFormReset)
if (textarea.value) sizeToFit()
return {
unsubscribe() {
textarea.removeEventListener('mousemove', onUserResize)
textarea.removeEventListener('input', sizeToFit)
textarea.removeEventListener('change', sizeToFit)
textarea.removeEventListener('paste', sizeToFit)
if (form) form.removeEventListener('reset', onFormReset)
}
}
}