@instructure/ui-text-input 8.23.1-snapshot.7 → 8.24.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.
- package/CHANGELOG.md +6 -0
- package/es/TextInput/index.js +59 -14
- package/es/TextInput/styles.js +16 -4
- package/lib/TextInput/index.js +59 -14
- package/lib/TextInput/styles.js +16 -4
- package/package.json +16 -17
- package/src/TextInput/index.tsx +74 -16
- package/src/TextInput/props.ts +6 -1
- package/src/TextInput/styles.ts +20 -4
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/TextInput/index.d.ts +6 -3
- package/types/TextInput/index.d.ts.map +1 -1
- package/types/TextInput/props.d.ts +4 -0
- package/types/TextInput/props.d.ts.map +1 -1
- package/types/TextInput/styles.d.ts.map +1 -1
- package/LICENSE.md +0 -27
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [8.24.0](https://github.com/instructure/instructure-ui/compare/v8.23.0...v8.24.0) (2022-04-26)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **ui-text-input:** fix empty TextInput before/after elements having padding ([a5786c9](https://github.com/instructure/instructure-ui/commit/a5786c9083448dc1d7d8b5eecac11788c8b26fec))
|
|
11
|
+
|
|
6
12
|
# [8.23.0](https://github.com/instructure/instructure-ui/compare/v8.22.0...v8.23.0) (2022-04-07)
|
|
7
13
|
|
|
8
14
|
**Note:** Version bump only for package @instructure/ui-text-input
|
package/es/TextInput/index.js
CHANGED
|
@@ -50,6 +50,8 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
50
50
|
super(props);
|
|
51
51
|
this.ref = null;
|
|
52
52
|
this._input = null;
|
|
53
|
+
this._beforeElement = null;
|
|
54
|
+
this._afterElement = null;
|
|
53
55
|
this._defaultId = void 0;
|
|
54
56
|
this._messagesId = void 0;
|
|
55
57
|
this._focusListener = null;
|
|
@@ -65,10 +67,16 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
65
67
|
|
|
66
68
|
this.makeStyleProps = () => {
|
|
67
69
|
const interaction = this.interaction;
|
|
70
|
+
const _this$state = this.state,
|
|
71
|
+
hasFocus = _this$state.hasFocus,
|
|
72
|
+
beforeElementHasWidth = _this$state.beforeElementHasWidth,
|
|
73
|
+
afterElementHasWidth = _this$state.afterElementHasWidth;
|
|
68
74
|
return {
|
|
69
75
|
disabled: interaction === 'disabled',
|
|
70
76
|
invalid: this.invalid,
|
|
71
|
-
focused:
|
|
77
|
+
focused: hasFocus,
|
|
78
|
+
beforeElementHasWidth,
|
|
79
|
+
afterElementHasWidth
|
|
72
80
|
};
|
|
73
81
|
};
|
|
74
82
|
|
|
@@ -107,7 +115,9 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
107
115
|
};
|
|
108
116
|
|
|
109
117
|
this.state = {
|
|
110
|
-
hasFocus: false
|
|
118
|
+
hasFocus: false,
|
|
119
|
+
beforeElementHasWidth: void 0,
|
|
120
|
+
afterElementHasWidth: void 0
|
|
111
121
|
};
|
|
112
122
|
this._defaultId = props.deterministicId();
|
|
113
123
|
this._messagesId = props.deterministicId('TextInput-messages');
|
|
@@ -116,11 +126,15 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
116
126
|
componentDidMount() {
|
|
117
127
|
var _this$props$makeStyle, _this$props;
|
|
118
128
|
|
|
119
|
-
(_this$props$makeStyle = (_this$props = this.props).makeStyles) === null || _this$props$makeStyle === void 0 ? void 0 : _this$props$makeStyle.call(_this$props, this.makeStyleProps());
|
|
120
|
-
|
|
121
129
|
if (this._input) {
|
|
122
130
|
this._focusListener = addEventListener(this._input, 'focus', this.handleFocus);
|
|
131
|
+
this.setState({
|
|
132
|
+
beforeElementHasWidth: this.getElementHasWidth(this._beforeElement),
|
|
133
|
+
afterElementHasWidth: this.getElementHasWidth(this._afterElement)
|
|
134
|
+
});
|
|
123
135
|
}
|
|
136
|
+
|
|
137
|
+
(_this$props$makeStyle = (_this$props = this.props).makeStyles) === null || _this$props$makeStyle === void 0 ? void 0 : _this$props$makeStyle.call(_this$props, this.makeStyleProps());
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
componentWillUnmount() {
|
|
@@ -129,9 +143,21 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
129
143
|
}
|
|
130
144
|
}
|
|
131
145
|
|
|
132
|
-
componentDidUpdate() {
|
|
146
|
+
componentDidUpdate(prevProps) {
|
|
133
147
|
var _this$props$makeStyle2, _this$props2;
|
|
134
148
|
|
|
149
|
+
if (prevProps.renderBeforeInput !== this.props.renderBeforeInput) {
|
|
150
|
+
this.setState({
|
|
151
|
+
beforeElementHasWidth: this.getElementHasWidth(this._beforeElement)
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (prevProps.renderAfterInput !== this.props.renderAfterInput) {
|
|
156
|
+
this.setState({
|
|
157
|
+
afterElementHasWidth: this.getElementHasWidth(this._afterElement)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
135
161
|
(_this$props$makeStyle2 = (_this$props2 = this.props).makeStyles) === null || _this$props$makeStyle2 === void 0 ? void 0 : _this$props$makeStyle2.call(_this$props2, this.makeStyleProps());
|
|
136
162
|
}
|
|
137
163
|
|
|
@@ -217,6 +243,19 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
217
243
|
}));
|
|
218
244
|
}
|
|
219
245
|
|
|
246
|
+
getElementHasWidth(element) {
|
|
247
|
+
if (!element) {
|
|
248
|
+
return void 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const computedStyle = getComputedStyle(element);
|
|
252
|
+
const width = computedStyle.width,
|
|
253
|
+
paddingInlineStart = computedStyle.paddingInlineStart,
|
|
254
|
+
paddingInlineEnd = computedStyle.paddingInlineEnd;
|
|
255
|
+
const elementWidth = parseFloat(width) - parseFloat(paddingInlineStart) - parseFloat(paddingInlineEnd);
|
|
256
|
+
return elementWidth > 0;
|
|
257
|
+
}
|
|
258
|
+
|
|
220
259
|
render() {
|
|
221
260
|
const _this$props4 = this.props,
|
|
222
261
|
width = _this$props4.width,
|
|
@@ -227,9 +266,9 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
227
266
|
messages = _this$props4.messages,
|
|
228
267
|
inputContainerRef = _this$props4.inputContainerRef,
|
|
229
268
|
styles = _this$props4.styles;
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
const renderBeforeOrAfter =
|
|
269
|
+
const beforeElement = renderBeforeInput ? callRenderProp(renderBeforeInput) : null;
|
|
270
|
+
const afterElement = renderAfterInput ? callRenderProp(renderAfterInput) : null;
|
|
271
|
+
const renderBeforeOrAfter = !!beforeElement || !!afterElement;
|
|
233
272
|
return jsx(FormField, {
|
|
234
273
|
id: this.id,
|
|
235
274
|
label: callRenderProp(renderLabel),
|
|
@@ -244,17 +283,23 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle,
|
|
|
244
283
|
css: styles === null || styles === void 0 ? void 0 : styles.facade
|
|
245
284
|
}, renderBeforeOrAfter ? jsx("div", null, jsx("span", {
|
|
246
285
|
css: styles === null || styles === void 0 ? void 0 : styles.layout
|
|
247
|
-
},
|
|
248
|
-
css: styles === null || styles === void 0 ? void 0 : styles.beforeElement
|
|
249
|
-
|
|
286
|
+
}, beforeElement && jsx("span", {
|
|
287
|
+
css: styles === null || styles === void 0 ? void 0 : styles.beforeElement,
|
|
288
|
+
ref: e => {
|
|
289
|
+
this._beforeElement = e;
|
|
290
|
+
}
|
|
291
|
+
}, beforeElement), jsx("span", {
|
|
250
292
|
css: styles === null || styles === void 0 ? void 0 : styles.innerWrapper
|
|
251
293
|
}, jsx("span", {
|
|
252
294
|
css: styles === null || styles === void 0 ? void 0 : styles.inputLayout
|
|
253
295
|
}, jsx("span", {
|
|
254
296
|
css: styles === null || styles === void 0 ? void 0 : styles.innerWrapper
|
|
255
|
-
}, this.renderInput()),
|
|
256
|
-
css: styles === null || styles === void 0 ? void 0 : styles.afterElement
|
|
257
|
-
|
|
297
|
+
}, this.renderInput()), afterElement && jsx("span", {
|
|
298
|
+
css: styles === null || styles === void 0 ? void 0 : styles.afterElement,
|
|
299
|
+
ref: e => {
|
|
300
|
+
this._afterElement = e;
|
|
301
|
+
}
|
|
302
|
+
}, afterElement))))) :
|
|
258
303
|
/* If no prepended or appended content, don't render Flex layout */
|
|
259
304
|
this.renderInput()));
|
|
260
305
|
}
|
package/es/TextInput/styles.js
CHANGED
|
@@ -38,7 +38,9 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
38
38
|
shouldNotWrap = props.shouldNotWrap;
|
|
39
39
|
const disabled = state.disabled,
|
|
40
40
|
invalid = state.invalid,
|
|
41
|
-
focused = state.focused
|
|
41
|
+
focused = state.focused,
|
|
42
|
+
beforeElementHasWidth = state.beforeElementHasWidth,
|
|
43
|
+
afterElementHasWidth = state.afterElementHasWidth;
|
|
42
44
|
const sizeVariants = {
|
|
43
45
|
small: {
|
|
44
46
|
fontSize: componentTheme.smallFontSize,
|
|
@@ -120,7 +122,6 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
120
122
|
flexDirection: 'row'
|
|
121
123
|
};
|
|
122
124
|
const flexItemBase = { ...viewBase,
|
|
123
|
-
minWidth: '0.0625rem',
|
|
124
125
|
flexShrink: 0
|
|
125
126
|
};
|
|
126
127
|
return {
|
|
@@ -168,11 +169,17 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
168
169
|
beforeElement: {
|
|
169
170
|
label: 'textInput__beforeElement',
|
|
170
171
|
...flexItemBase,
|
|
171
|
-
paddingInlineStart: componentTheme.padding
|
|
172
|
+
paddingInlineStart: componentTheme.padding,
|
|
173
|
+
// we only override the padding once the width is calculated,
|
|
174
|
+
// it needs the padding on render
|
|
175
|
+
...(beforeElementHasWidth === false && {
|
|
176
|
+
paddingInlineStart: 0
|
|
177
|
+
})
|
|
172
178
|
},
|
|
173
179
|
innerWrapper: {
|
|
174
180
|
label: 'textInput__innerWrapper',
|
|
175
181
|
...flexItemBase,
|
|
182
|
+
minWidth: '0.0625rem',
|
|
176
183
|
flexShrink: 1,
|
|
177
184
|
flexGrow: 1
|
|
178
185
|
},
|
|
@@ -183,7 +190,12 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
183
190
|
afterElement: {
|
|
184
191
|
label: 'textInput__afterElement',
|
|
185
192
|
...flexItemBase,
|
|
186
|
-
paddingInlineEnd: componentTheme.padding
|
|
193
|
+
paddingInlineEnd: componentTheme.padding,
|
|
194
|
+
// we only override the padding once the width is calculated,
|
|
195
|
+
// it needs the padding on render
|
|
196
|
+
...(afterElementHasWidth === false && {
|
|
197
|
+
paddingInlineEnd: 0
|
|
198
|
+
})
|
|
187
199
|
}
|
|
188
200
|
};
|
|
189
201
|
};
|
package/lib/TextInput/index.js
CHANGED
|
@@ -53,6 +53,8 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
53
53
|
super(props);
|
|
54
54
|
this.ref = null;
|
|
55
55
|
this._input = null;
|
|
56
|
+
this._beforeElement = null;
|
|
57
|
+
this._afterElement = null;
|
|
56
58
|
this._defaultId = void 0;
|
|
57
59
|
this._messagesId = void 0;
|
|
58
60
|
this._focusListener = null;
|
|
@@ -68,10 +70,16 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
68
70
|
|
|
69
71
|
this.makeStyleProps = () => {
|
|
70
72
|
const interaction = this.interaction;
|
|
73
|
+
const _this$state = this.state,
|
|
74
|
+
hasFocus = _this$state.hasFocus,
|
|
75
|
+
beforeElementHasWidth = _this$state.beforeElementHasWidth,
|
|
76
|
+
afterElementHasWidth = _this$state.afterElementHasWidth;
|
|
71
77
|
return {
|
|
72
78
|
disabled: interaction === 'disabled',
|
|
73
79
|
invalid: this.invalid,
|
|
74
|
-
focused:
|
|
80
|
+
focused: hasFocus,
|
|
81
|
+
beforeElementHasWidth,
|
|
82
|
+
afterElementHasWidth
|
|
75
83
|
};
|
|
76
84
|
};
|
|
77
85
|
|
|
@@ -110,7 +118,9 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
110
118
|
};
|
|
111
119
|
|
|
112
120
|
this.state = {
|
|
113
|
-
hasFocus: false
|
|
121
|
+
hasFocus: false,
|
|
122
|
+
beforeElementHasWidth: void 0,
|
|
123
|
+
afterElementHasWidth: void 0
|
|
114
124
|
};
|
|
115
125
|
this._defaultId = props.deterministicId();
|
|
116
126
|
this._messagesId = props.deterministicId('TextInput-messages');
|
|
@@ -119,11 +129,15 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
119
129
|
componentDidMount() {
|
|
120
130
|
var _this$props$makeStyle, _this$props;
|
|
121
131
|
|
|
122
|
-
(_this$props$makeStyle = (_this$props = this.props).makeStyles) === null || _this$props$makeStyle === void 0 ? void 0 : _this$props$makeStyle.call(_this$props, this.makeStyleProps());
|
|
123
|
-
|
|
124
132
|
if (this._input) {
|
|
125
133
|
this._focusListener = (0, _addEventListener.addEventListener)(this._input, 'focus', this.handleFocus);
|
|
134
|
+
this.setState({
|
|
135
|
+
beforeElementHasWidth: this.getElementHasWidth(this._beforeElement),
|
|
136
|
+
afterElementHasWidth: this.getElementHasWidth(this._afterElement)
|
|
137
|
+
});
|
|
126
138
|
}
|
|
139
|
+
|
|
140
|
+
(_this$props$makeStyle = (_this$props = this.props).makeStyles) === null || _this$props$makeStyle === void 0 ? void 0 : _this$props$makeStyle.call(_this$props, this.makeStyleProps());
|
|
127
141
|
}
|
|
128
142
|
|
|
129
143
|
componentWillUnmount() {
|
|
@@ -132,9 +146,21 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
132
146
|
}
|
|
133
147
|
}
|
|
134
148
|
|
|
135
|
-
componentDidUpdate() {
|
|
149
|
+
componentDidUpdate(prevProps) {
|
|
136
150
|
var _this$props$makeStyle2, _this$props2;
|
|
137
151
|
|
|
152
|
+
if (prevProps.renderBeforeInput !== this.props.renderBeforeInput) {
|
|
153
|
+
this.setState({
|
|
154
|
+
beforeElementHasWidth: this.getElementHasWidth(this._beforeElement)
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (prevProps.renderAfterInput !== this.props.renderAfterInput) {
|
|
159
|
+
this.setState({
|
|
160
|
+
afterElementHasWidth: this.getElementHasWidth(this._afterElement)
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
138
164
|
(_this$props$makeStyle2 = (_this$props2 = this.props).makeStyles) === null || _this$props$makeStyle2 === void 0 ? void 0 : _this$props$makeStyle2.call(_this$props2, this.makeStyleProps());
|
|
139
165
|
}
|
|
140
166
|
|
|
@@ -219,6 +245,19 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
219
245
|
}));
|
|
220
246
|
}
|
|
221
247
|
|
|
248
|
+
getElementHasWidth(element) {
|
|
249
|
+
if (!element) {
|
|
250
|
+
return void 0;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const computedStyle = getComputedStyle(element);
|
|
254
|
+
const width = computedStyle.width,
|
|
255
|
+
paddingInlineStart = computedStyle.paddingInlineStart,
|
|
256
|
+
paddingInlineEnd = computedStyle.paddingInlineEnd;
|
|
257
|
+
const elementWidth = parseFloat(width) - parseFloat(paddingInlineStart) - parseFloat(paddingInlineEnd);
|
|
258
|
+
return elementWidth > 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
222
261
|
render() {
|
|
223
262
|
const _this$props4 = this.props,
|
|
224
263
|
width = _this$props4.width,
|
|
@@ -229,9 +268,9 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
229
268
|
messages = _this$props4.messages,
|
|
230
269
|
inputContainerRef = _this$props4.inputContainerRef,
|
|
231
270
|
styles = _this$props4.styles;
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
const renderBeforeOrAfter =
|
|
271
|
+
const beforeElement = renderBeforeInput ? (0, _callRenderProp.callRenderProp)(renderBeforeInput) : null;
|
|
272
|
+
const afterElement = renderAfterInput ? (0, _callRenderProp.callRenderProp)(renderAfterInput) : null;
|
|
273
|
+
const renderBeforeOrAfter = !!beforeElement || !!afterElement;
|
|
235
274
|
return (0, _emotion.jsx)(_FormField.FormField, {
|
|
236
275
|
id: this.id,
|
|
237
276
|
label: (0, _callRenderProp.callRenderProp)(renderLabel),
|
|
@@ -246,17 +285,23 @@ let TextInput = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 =
|
|
|
246
285
|
css: styles === null || styles === void 0 ? void 0 : styles.facade
|
|
247
286
|
}, renderBeforeOrAfter ? (0, _emotion.jsx)("div", null, (0, _emotion.jsx)("span", {
|
|
248
287
|
css: styles === null || styles === void 0 ? void 0 : styles.layout
|
|
249
|
-
},
|
|
250
|
-
css: styles === null || styles === void 0 ? void 0 : styles.beforeElement
|
|
251
|
-
|
|
288
|
+
}, beforeElement && (0, _emotion.jsx)("span", {
|
|
289
|
+
css: styles === null || styles === void 0 ? void 0 : styles.beforeElement,
|
|
290
|
+
ref: e => {
|
|
291
|
+
this._beforeElement = e;
|
|
292
|
+
}
|
|
293
|
+
}, beforeElement), (0, _emotion.jsx)("span", {
|
|
252
294
|
css: styles === null || styles === void 0 ? void 0 : styles.innerWrapper
|
|
253
295
|
}, (0, _emotion.jsx)("span", {
|
|
254
296
|
css: styles === null || styles === void 0 ? void 0 : styles.inputLayout
|
|
255
297
|
}, (0, _emotion.jsx)("span", {
|
|
256
298
|
css: styles === null || styles === void 0 ? void 0 : styles.innerWrapper
|
|
257
|
-
}, this.renderInput()),
|
|
258
|
-
css: styles === null || styles === void 0 ? void 0 : styles.afterElement
|
|
259
|
-
|
|
299
|
+
}, this.renderInput()), afterElement && (0, _emotion.jsx)("span", {
|
|
300
|
+
css: styles === null || styles === void 0 ? void 0 : styles.afterElement,
|
|
301
|
+
ref: e => {
|
|
302
|
+
this._afterElement = e;
|
|
303
|
+
}
|
|
304
|
+
}, afterElement))))) :
|
|
260
305
|
/* If no prepended or appended content, don't render Flex layout */
|
|
261
306
|
this.renderInput()));
|
|
262
307
|
}
|
package/lib/TextInput/styles.js
CHANGED
|
@@ -45,7 +45,9 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
45
45
|
shouldNotWrap = props.shouldNotWrap;
|
|
46
46
|
const disabled = state.disabled,
|
|
47
47
|
invalid = state.invalid,
|
|
48
|
-
focused = state.focused
|
|
48
|
+
focused = state.focused,
|
|
49
|
+
beforeElementHasWidth = state.beforeElementHasWidth,
|
|
50
|
+
afterElementHasWidth = state.afterElementHasWidth;
|
|
49
51
|
const sizeVariants = {
|
|
50
52
|
small: {
|
|
51
53
|
fontSize: componentTheme.smallFontSize,
|
|
@@ -127,7 +129,6 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
127
129
|
flexDirection: 'row'
|
|
128
130
|
};
|
|
129
131
|
const flexItemBase = { ...viewBase,
|
|
130
|
-
minWidth: '0.0625rem',
|
|
131
132
|
flexShrink: 0
|
|
132
133
|
};
|
|
133
134
|
return {
|
|
@@ -175,11 +176,17 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
175
176
|
beforeElement: {
|
|
176
177
|
label: 'textInput__beforeElement',
|
|
177
178
|
...flexItemBase,
|
|
178
|
-
paddingInlineStart: componentTheme.padding
|
|
179
|
+
paddingInlineStart: componentTheme.padding,
|
|
180
|
+
// we only override the padding once the width is calculated,
|
|
181
|
+
// it needs the padding on render
|
|
182
|
+
...(beforeElementHasWidth === false && {
|
|
183
|
+
paddingInlineStart: 0
|
|
184
|
+
})
|
|
179
185
|
},
|
|
180
186
|
innerWrapper: {
|
|
181
187
|
label: 'textInput__innerWrapper',
|
|
182
188
|
...flexItemBase,
|
|
189
|
+
minWidth: '0.0625rem',
|
|
183
190
|
flexShrink: 1,
|
|
184
191
|
flexGrow: 1
|
|
185
192
|
},
|
|
@@ -190,7 +197,12 @@ const generateStyle = (componentTheme, props, state) => {
|
|
|
190
197
|
afterElement: {
|
|
191
198
|
label: 'textInput__afterElement',
|
|
192
199
|
...flexItemBase,
|
|
193
|
-
paddingInlineEnd: componentTheme.padding
|
|
200
|
+
paddingInlineEnd: componentTheme.padding,
|
|
201
|
+
// we only override the padding once the width is calculated,
|
|
202
|
+
// it needs the padding on render
|
|
203
|
+
...(afterElementHasWidth === false && {
|
|
204
|
+
paddingInlineEnd: 0
|
|
205
|
+
})
|
|
194
206
|
}
|
|
195
207
|
};
|
|
196
208
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-text-input",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.24.0",
|
|
4
4
|
"description": "A styled HTML text input component.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -23,23 +23,23 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@instructure/ui-babel-preset": "8.
|
|
27
|
-
"@instructure/ui-badge": "8.
|
|
28
|
-
"@instructure/ui-color-utils": "8.
|
|
29
|
-
"@instructure/ui-test-utils": "8.
|
|
30
|
-
"@instructure/ui-themes": "8.
|
|
26
|
+
"@instructure/ui-babel-preset": "8.24.0",
|
|
27
|
+
"@instructure/ui-badge": "8.24.0",
|
|
28
|
+
"@instructure/ui-color-utils": "8.24.0",
|
|
29
|
+
"@instructure/ui-test-utils": "8.24.0",
|
|
30
|
+
"@instructure/ui-themes": "8.24.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@babel/runtime": "^7.13.10",
|
|
34
|
-
"@instructure/emotion": "8.
|
|
35
|
-
"@instructure/shared-types": "8.
|
|
36
|
-
"@instructure/ui-dom-utils": "8.
|
|
37
|
-
"@instructure/ui-form-field": "8.
|
|
38
|
-
"@instructure/ui-icons": "8.
|
|
39
|
-
"@instructure/ui-prop-types": "8.
|
|
40
|
-
"@instructure/ui-react-utils": "8.
|
|
41
|
-
"@instructure/ui-tag": "8.
|
|
42
|
-
"@instructure/ui-testable": "8.
|
|
34
|
+
"@instructure/emotion": "8.24.0",
|
|
35
|
+
"@instructure/shared-types": "8.24.0",
|
|
36
|
+
"@instructure/ui-dom-utils": "8.24.0",
|
|
37
|
+
"@instructure/ui-form-field": "8.24.0",
|
|
38
|
+
"@instructure/ui-icons": "8.24.0",
|
|
39
|
+
"@instructure/ui-prop-types": "8.24.0",
|
|
40
|
+
"@instructure/ui-react-utils": "8.24.0",
|
|
41
|
+
"@instructure/ui-tag": "8.24.0",
|
|
42
|
+
"@instructure/ui-testable": "8.24.0",
|
|
43
43
|
"prop-types": "^15"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
@@ -48,6 +48,5 @@
|
|
|
48
48
|
"publishConfig": {
|
|
49
49
|
"access": "public"
|
|
50
50
|
},
|
|
51
|
-
"sideEffects": false
|
|
52
|
-
"gitHead": "67fb0a5bed0138c5152872999bf1138dd2fd8fd7"
|
|
51
|
+
"sideEffects": false
|
|
53
52
|
}
|
package/src/TextInput/index.tsx
CHANGED
|
@@ -75,7 +75,11 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
75
75
|
|
|
76
76
|
constructor(props: TextInputProps) {
|
|
77
77
|
super(props)
|
|
78
|
-
this.state = {
|
|
78
|
+
this.state = {
|
|
79
|
+
hasFocus: false,
|
|
80
|
+
beforeElementHasWidth: undefined,
|
|
81
|
+
afterElementHasWidth: undefined
|
|
82
|
+
}
|
|
79
83
|
this._defaultId = props.deterministicId!()
|
|
80
84
|
this._messagesId = props.deterministicId!('TextInput-messages')
|
|
81
85
|
}
|
|
@@ -83,8 +87,12 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
83
87
|
ref: Element | null = null
|
|
84
88
|
|
|
85
89
|
private _input: HTMLInputElement | null = null
|
|
86
|
-
private
|
|
87
|
-
private
|
|
90
|
+
private _beforeElement: HTMLSpanElement | null = null
|
|
91
|
+
private _afterElement: HTMLSpanElement | null = null
|
|
92
|
+
|
|
93
|
+
private readonly _defaultId: string
|
|
94
|
+
private readonly _messagesId: string
|
|
95
|
+
|
|
88
96
|
private _focusListener: { remove(): void } | null = null
|
|
89
97
|
|
|
90
98
|
handleRef = (el: Element | null) => {
|
|
@@ -96,15 +104,22 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
96
104
|
elementRef(el)
|
|
97
105
|
}
|
|
98
106
|
}
|
|
107
|
+
|
|
99
108
|
componentDidMount() {
|
|
100
|
-
this.props.makeStyles?.(this.makeStyleProps())
|
|
101
109
|
if (this._input) {
|
|
102
110
|
this._focusListener = addEventListener(
|
|
103
111
|
this._input,
|
|
104
112
|
'focus',
|
|
105
113
|
this.handleFocus
|
|
106
114
|
)
|
|
115
|
+
|
|
116
|
+
this.setState({
|
|
117
|
+
beforeElementHasWidth: this.getElementHasWidth(this._beforeElement),
|
|
118
|
+
afterElementHasWidth: this.getElementHasWidth(this._afterElement)
|
|
119
|
+
})
|
|
107
120
|
}
|
|
121
|
+
|
|
122
|
+
this.props.makeStyles?.(this.makeStyleProps())
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
componentWillUnmount() {
|
|
@@ -113,16 +128,30 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
113
128
|
}
|
|
114
129
|
}
|
|
115
130
|
|
|
116
|
-
componentDidUpdate() {
|
|
131
|
+
componentDidUpdate(prevProps: TextInputProps) {
|
|
132
|
+
if (prevProps.renderBeforeInput !== this.props.renderBeforeInput) {
|
|
133
|
+
this.setState({
|
|
134
|
+
beforeElementHasWidth: this.getElementHasWidth(this._beforeElement)
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
if (prevProps.renderAfterInput !== this.props.renderAfterInput) {
|
|
138
|
+
this.setState({
|
|
139
|
+
afterElementHasWidth: this.getElementHasWidth(this._afterElement)
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
117
143
|
this.props.makeStyles?.(this.makeStyleProps())
|
|
118
144
|
}
|
|
119
145
|
|
|
120
146
|
makeStyleProps = (): TextInputStyleProps => {
|
|
121
147
|
const { interaction } = this
|
|
148
|
+
const { hasFocus, beforeElementHasWidth, afterElementHasWidth } = this.state
|
|
122
149
|
return {
|
|
123
150
|
disabled: interaction === 'disabled',
|
|
124
151
|
invalid: this.invalid,
|
|
125
|
-
focused:
|
|
152
|
+
focused: hasFocus,
|
|
153
|
+
beforeElementHasWidth,
|
|
154
|
+
afterElementHasWidth
|
|
126
155
|
}
|
|
127
156
|
}
|
|
128
157
|
|
|
@@ -243,6 +272,22 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
243
272
|
)
|
|
244
273
|
}
|
|
245
274
|
|
|
275
|
+
getElementHasWidth(element: HTMLSpanElement | null) {
|
|
276
|
+
if (!element) {
|
|
277
|
+
return undefined
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const computedStyle = getComputedStyle(element)
|
|
281
|
+
const { width, paddingInlineStart, paddingInlineEnd } = computedStyle
|
|
282
|
+
|
|
283
|
+
const elementWidth =
|
|
284
|
+
parseFloat(width) -
|
|
285
|
+
parseFloat(paddingInlineStart) -
|
|
286
|
+
parseFloat(paddingInlineEnd)
|
|
287
|
+
|
|
288
|
+
return elementWidth > 0
|
|
289
|
+
}
|
|
290
|
+
|
|
246
291
|
render() {
|
|
247
292
|
const {
|
|
248
293
|
width,
|
|
@@ -255,11 +300,14 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
255
300
|
styles
|
|
256
301
|
} = this.props
|
|
257
302
|
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
303
|
+
const beforeElement: React.ReactNode = renderBeforeInput
|
|
304
|
+
? callRenderProp(renderBeforeInput)
|
|
305
|
+
: null
|
|
306
|
+
const afterElement: React.ReactNode = renderAfterInput
|
|
307
|
+
? callRenderProp(renderAfterInput)
|
|
308
|
+
: null
|
|
261
309
|
|
|
262
|
-
const renderBeforeOrAfter =
|
|
310
|
+
const renderBeforeOrAfter = !!beforeElement || !!afterElement
|
|
263
311
|
|
|
264
312
|
return (
|
|
265
313
|
<FormField
|
|
@@ -277,9 +325,14 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
277
325
|
{renderBeforeOrAfter ? (
|
|
278
326
|
<div>
|
|
279
327
|
<span css={styles?.layout}>
|
|
280
|
-
{
|
|
281
|
-
<span
|
|
282
|
-
{
|
|
328
|
+
{beforeElement && (
|
|
329
|
+
<span
|
|
330
|
+
css={styles?.beforeElement}
|
|
331
|
+
ref={(e) => {
|
|
332
|
+
this._beforeElement = e
|
|
333
|
+
}}
|
|
334
|
+
>
|
|
335
|
+
{beforeElement}
|
|
283
336
|
</span>
|
|
284
337
|
)}
|
|
285
338
|
<span css={styles?.innerWrapper}>
|
|
@@ -289,9 +342,14 @@ class TextInput extends Component<TextInputProps, TextInputState> {
|
|
|
289
342
|
*/}
|
|
290
343
|
<span css={styles?.inputLayout}>
|
|
291
344
|
<span css={styles?.innerWrapper}>{this.renderInput()}</span>
|
|
292
|
-
{
|
|
293
|
-
<span
|
|
294
|
-
{
|
|
345
|
+
{afterElement && (
|
|
346
|
+
<span
|
|
347
|
+
css={styles?.afterElement}
|
|
348
|
+
ref={(e) => {
|
|
349
|
+
this._afterElement = e
|
|
350
|
+
}}
|
|
351
|
+
>
|
|
352
|
+
{afterElement}
|
|
295
353
|
</span>
|
|
296
354
|
)}
|
|
297
355
|
</span>
|
package/src/TextInput/props.ts
CHANGED
|
@@ -183,7 +183,8 @@ type TextInputProps = TextInputOwnProps &
|
|
|
183
183
|
> &
|
|
184
184
|
// The component will handle pass this prop to FormField, but it shouldn't be
|
|
185
185
|
// listed as a prop
|
|
186
|
-
Pick<FormFieldProps, 'layout'> &
|
|
186
|
+
Pick<FormFieldProps, 'layout'> &
|
|
187
|
+
WithDeterministicIdProps
|
|
187
188
|
|
|
188
189
|
type TextInputStyle = ComponentStyle<
|
|
189
190
|
| 'textInput'
|
|
@@ -249,12 +250,16 @@ const allowedProps: AllowedPropKeys = [
|
|
|
249
250
|
|
|
250
251
|
type TextInputState = {
|
|
251
252
|
hasFocus: boolean
|
|
253
|
+
beforeElementHasWidth?: boolean
|
|
254
|
+
afterElementHasWidth?: boolean
|
|
252
255
|
}
|
|
253
256
|
|
|
254
257
|
type TextInputStyleProps = {
|
|
255
258
|
disabled: boolean
|
|
256
259
|
invalid: boolean
|
|
257
260
|
focused: TextInputState['hasFocus']
|
|
261
|
+
beforeElementHasWidth: TextInputState['beforeElementHasWidth']
|
|
262
|
+
afterElementHasWidth: TextInputState['afterElementHasWidth']
|
|
258
263
|
}
|
|
259
264
|
|
|
260
265
|
export type {
|