@@ -60,6 +60,9 @@ export default {
60
60
// The computed height for auto resize.
61
61
// We avoid setting the style to null, which can override user manual resize.
62
62
styles . height = this . computedHeight
63
+ // We always add a vertical scrollbar to the textarea when auto-resize is
64
+ // enabled so that the computed height calcaultion returns a stable value.
65
+ styles . overflowY = 'scroll'
63
66
}
64
67
return styles
65
68
} ,
@@ -77,9 +80,10 @@ export default {
77
80
// If auto-resize is enabled, then we return null as we use CSS to control height.
78
81
return this . computedMinRows === this . computedMaxRows ? this . computedMinRows : null
79
82
} ,
80
- computedHeight ( ) /* istanbul ignore next: can't test getComputedProperties */ {
83
+ computedHeight ( ) /* istanbul ignore next: can't test getComputedStyle in JSDOM */ {
81
84
// We compare `computedRows` and `localValue` to `true`, a value
82
- // they both can't have at any time, to ensure reactivity
85
+ // they both can't have at any time, to ensure reactivity of this
86
+ // computed property.
83
87
if (
84
88
this . $isServer ||
85
89
this . dontResize ||
@@ -91,48 +95,50 @@ export default {
91
95
92
96
const el = this . $el
93
97
94
- // Element must be visible (not hidden) and in document
95
- // * Must* be checked after above checks
98
+ // Element must be visible (not hidden) and in document.
99
+ // Must be checked after above checks
96
100
if ( ! isVisible ( el ) ) {
97
101
return null
98
102
}
99
103
100
- // Remember old height (includes `px` units) and reset it temporarily to `auto`
101
- const oldHeight = el . style . height
102
- el . style . height = 'auto'
103
-
104
104
// Get current computed styles
105
105
const computedStyle = getCS ( el )
106
106
// Height of one line of text in px
107
107
const lineHeight = parseFloat ( computedStyle . lineHeight )
108
- // Minimum height for min rows (browser dependant)
109
- const minHeight = parseInt ( computedStyle . height , 10 ) || lineHeight * this . computedMinRows
110
- // Calculate height of content
111
- const offset =
108
+ // Calculate height of border and padding
109
+ const border =
112
110
( parseFloat ( computedStyle . borderTopWidth ) || 0 ) +
113
- ( parseFloat ( computedStyle . borderBottomWidth ) || 0 ) +
114
- ( parseFloat ( computedStyle . paddingTop ) || 0 ) +
115
- ( parseFloat ( computedStyle . paddingBottom ) || 0 )
116
- // Calculate content height in "rows"
117
- const contentRows = Math . max ( ( el . scrollHeight - offset ) / lineHeight , 2 )
111
+ ( parseFloat ( computedStyle . borderBottomWidth ) || 0 )
112
+ const padding =
113
+ ( parseFloat ( computedStyle . paddingTop ) || 0 ) + ( parseFloat ( computedStyle . paddingBottom ) || 0 )
114
+ // Calculate offset
115
+ const offset = border + padding
116
+ // Minimum height for min rows (which must be 2 rows or greater for cross-browser support)
117
+ const minHeight = lineHeight * this . computedMinRows + offset
118
+
119
+ // Get the current style height (with `px` units)
120
+ const oldHeight = el . style . height || computedStyle . height
121
+ // Probe scrollHeight by temporarily changing the height to `auto`
122
+ el . style . height = 'auto'
123
+ const scrollHeight = el . scrollHeight
124
+ // Place the original old height back on the element, just in case this computedProp
125
+ // returns the same value as before.
126
+ el . style . height = oldHeight
127
+
128
+ // Calculate content height in "rows" (scrollHeight includes padding but not border)
129
+ const contentRows = Math . max ( ( scrollHeight - padding ) / lineHeight , 2 )
118
130
// Calculate number of rows to display (limited within min/max rows)
119
131
const rows = Math . min ( Math . max ( contentRows , this . computedMinRows ) , this . computedMaxRows )
120
132
// Calculate the required height of the textarea including border and padding (in pixels)
121
133
const height = Math . max ( Math . ceil ( rows * lineHeight + offset ) , minHeight )
122
134
123
- // Place old height back on element, just in case this computed prop returns the same value
124
- el . style . height = oldHeight
125
-
126
- // Value of previous height (without px units appended)
127
- const oldHeightPx = parseFloat ( oldHeight ) || 0
128
-
129
- if ( this . noAutoShrink && oldHeightPx > height ) {
130
- // Computed height remains the larger of oldHeight and new height
131
- // When height is `sticky` (no-auto-shrink is true)
135
+ // Computed height remains the larger of oldHeight and new height,
136
+ // when height is in `sticky` mode (prop `no-auto-shrink` is true)
137
+ if ( this . noAutoShrink && ( parseFloat ( oldHeight ) || 0 ) > height ) {
132
138
return oldHeight
133
139
}
134
140
135
- // Return the new computed height in px units
141
+ // Return the new computed CSS height in px units
136
142
return `${ height } px`
137
143
}
138
144
} ,
0 commit comments