@hero-design/rn-work-uikit 1.1.0 → 1.2.0-alpha.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/.cursorrules +57 -0
- package/CHANGELOG.md +6 -0
- package/DEVELOPMENT.md +118 -0
- package/eslint.config.js +20 -0
- package/lib/index.js +871 -5
- package/package.json +4 -1
- package/src/__tests__/__snapshots__/index.spec.tsx.snap +90 -115
- package/src/__tests__/theme-export-override.spec.ts +6 -0
- package/src/components/TextInput/ErrorOrHelpText.tsx +58 -0
- package/src/components/TextInput/FloatingLabel.tsx +120 -0
- package/src/components/TextInput/InputComponent.tsx +61 -0
- package/src/components/TextInput/InputRow.tsx +103 -0
- package/src/components/TextInput/MaxLengthMessage.tsx +66 -0
- package/src/components/TextInput/PrefixComponent.tsx +77 -0
- package/src/components/TextInput/StyledTextInput.tsx +134 -0
- package/src/components/TextInput/SuffixComponent.tsx +73 -0
- package/src/components/TextInput/__tests__/ErrorOrHelpText.spec.tsx +20 -0
- package/src/components/TextInput/__tests__/FloatingLabel.spec.tsx +203 -0
- package/src/components/TextInput/__tests__/InputComponent.spec.tsx +39 -0
- package/src/components/TextInput/__tests__/InputRow.spec.tsx +275 -0
- package/src/components/TextInput/__tests__/MaxLengthMessage.spec.tsx +17 -0
- package/src/components/TextInput/__tests__/PrefixComponent.spec.tsx +14 -0
- package/src/components/TextInput/__tests__/StyledTextInput.spec.tsx +114 -0
- package/src/components/TextInput/__tests__/SuffixComponent.spec.tsx +20 -0
- package/src/components/TextInput/__tests__/__snapshots__/StyledTextInput.spec.tsx.snap +571 -0
- package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +5671 -0
- package/src/components/TextInput/__tests__/getState.spec.tsx +89 -0
- package/src/components/TextInput/__tests__/index.spec.tsx +699 -0
- package/src/components/TextInput/constants.ts +1 -0
- package/src/components/TextInput/index.tsx +327 -0
- package/src/components/TextInput/types.ts +95 -0
- package/src/emotion.d.ts +15 -0
- package/src/index.ts +3 -0
- package/src/jest.d.ts +24 -0
- package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +15 -8
- package/src/theme/components/textInput.ts +33 -0
- package/src/utils/__tests__/helpers.spec.ts +92 -0
- package/src/utils/helpers.ts +113 -0
- package/testUtils/renderWithTheme.tsx +6 -3
- package/stats/1.1.0/rn-work-uikit-stats.html +0 -4842
package/lib/index.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var rn = require('@hero-design/rn');
|
|
4
3
|
var React = require('react');
|
|
4
|
+
var reactNative = require('react-native');
|
|
5
|
+
var rn = require('@hero-design/rn');
|
|
5
6
|
|
|
6
7
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
7
8
|
|
|
8
9
|
var React__default = /*#__PURE__*/_interopDefaultCompat(React);
|
|
9
10
|
|
|
11
|
+
function _arrayLikeToArray(r, a) {
|
|
12
|
+
(null == a || a > r.length) && (a = r.length);
|
|
13
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
14
|
+
return n;
|
|
15
|
+
}
|
|
16
|
+
function _arrayWithHoles(r) {
|
|
17
|
+
if (Array.isArray(r)) return r;
|
|
18
|
+
}
|
|
10
19
|
function _defineProperty(e, r, t) {
|
|
11
20
|
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
12
21
|
value: t,
|
|
@@ -15,6 +24,42 @@ function _defineProperty(e, r, t) {
|
|
|
15
24
|
writable: !0
|
|
16
25
|
}) : e[r] = t, e;
|
|
17
26
|
}
|
|
27
|
+
function _extends() {
|
|
28
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
|
29
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
30
|
+
var t = arguments[e];
|
|
31
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
32
|
+
}
|
|
33
|
+
return n;
|
|
34
|
+
}, _extends.apply(null, arguments);
|
|
35
|
+
}
|
|
36
|
+
function _iterableToArrayLimit(r, l) {
|
|
37
|
+
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
38
|
+
if (null != t) {
|
|
39
|
+
var e,
|
|
40
|
+
n,
|
|
41
|
+
i,
|
|
42
|
+
u,
|
|
43
|
+
a = [],
|
|
44
|
+
f = !0,
|
|
45
|
+
o = !1;
|
|
46
|
+
try {
|
|
47
|
+
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
48
|
+
} catch (r) {
|
|
49
|
+
o = !0, n = r;
|
|
50
|
+
} finally {
|
|
51
|
+
try {
|
|
52
|
+
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
53
|
+
} finally {
|
|
54
|
+
if (o) throw n;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return a;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function _nonIterableRest() {
|
|
61
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
62
|
+
}
|
|
18
63
|
function ownKeys(e, r) {
|
|
19
64
|
var t = Object.keys(e);
|
|
20
65
|
if (Object.getOwnPropertySymbols) {
|
|
@@ -36,6 +81,29 @@ function _objectSpread2(e) {
|
|
|
36
81
|
}
|
|
37
82
|
return e;
|
|
38
83
|
}
|
|
84
|
+
function _objectWithoutProperties(e, t) {
|
|
85
|
+
if (null == e) return {};
|
|
86
|
+
var o,
|
|
87
|
+
r,
|
|
88
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
89
|
+
if (Object.getOwnPropertySymbols) {
|
|
90
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
91
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
92
|
+
}
|
|
93
|
+
return i;
|
|
94
|
+
}
|
|
95
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
96
|
+
if (null == r) return {};
|
|
97
|
+
var t = {};
|
|
98
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
99
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
100
|
+
t[n] = r[n];
|
|
101
|
+
}
|
|
102
|
+
return t;
|
|
103
|
+
}
|
|
104
|
+
function _slicedToArray(r, e) {
|
|
105
|
+
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
106
|
+
}
|
|
39
107
|
function _toPrimitive(t, r) {
|
|
40
108
|
if ("object" != typeof t || !t) return t;
|
|
41
109
|
var e = t[Symbol.toPrimitive];
|
|
@@ -50,17 +118,187 @@ function _toPropertyKey(t) {
|
|
|
50
118
|
var i = _toPrimitive(t, "string");
|
|
51
119
|
return "symbol" == typeof i ? i : i + "";
|
|
52
120
|
}
|
|
121
|
+
function _unsupportedIterableToArray(r, a) {
|
|
122
|
+
if (r) {
|
|
123
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
124
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
125
|
+
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
var StyledContainer = rn.styled(reactNative.Pressable)(function (_ref) {
|
|
130
|
+
var theme = _ref.theme;
|
|
131
|
+
return {
|
|
132
|
+
width: '100%',
|
|
133
|
+
flexDirection: 'row',
|
|
134
|
+
paddingHorizontal: theme.__hd__.textInput.space.containerPadding,
|
|
135
|
+
minHeight: theme.__hd__.textInput.sizes.containerMinHeight,
|
|
136
|
+
marginTop: theme.__hd__.textInput.space.containerMarginTop
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
var StyledFloatingLabelContainer = rn.styled(reactNative.Animated.View)(function (_ref2) {
|
|
140
|
+
var themeVariant = _ref2.themeVariant;
|
|
141
|
+
return {
|
|
142
|
+
flexDirection: 'row',
|
|
143
|
+
flex: 1,
|
|
144
|
+
alignItems: themeVariant === 'text' ? 'center' : 'flex-start',
|
|
145
|
+
backgroundColor: 'transparent'
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
var StyledLabel = rn.styled(rn.Typography.Caption)(function (_ref3) {
|
|
149
|
+
var theme = _ref3.theme,
|
|
150
|
+
themeState = _ref3.themeState;
|
|
151
|
+
return {
|
|
152
|
+
color: theme.__hd__.textInput.colors.labels[themeState]
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
var StyledErrorRow = rn.styled(reactNative.View)(function (_ref4) {
|
|
156
|
+
var theme = _ref4.theme;
|
|
157
|
+
return {
|
|
158
|
+
marginRight: theme.__hd__.textInput.space.errorContainerMarginRight,
|
|
159
|
+
flexDirection: 'row',
|
|
160
|
+
alignItems: 'center',
|
|
161
|
+
flex: 1,
|
|
162
|
+
flexGrow: 4
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
var StyledError = rn.styled(rn.Typography.Caption)(function (_ref5) {
|
|
166
|
+
var theme = _ref5.theme;
|
|
167
|
+
return {
|
|
168
|
+
color: theme.__hd__.textInput.colors.error,
|
|
169
|
+
marginLeft: theme.__hd__.textInput.space.errorMarginLeft
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
var StyledCharacterCount = rn.styled(rn.Typography.Caption)(function (_ref6) {
|
|
173
|
+
var theme = _ref6.theme,
|
|
174
|
+
themeState = _ref6.themeState;
|
|
175
|
+
return {
|
|
176
|
+
color: theme.__hd__.textInput.colors.maxLengthLabels[themeState],
|
|
177
|
+
flex: 1,
|
|
178
|
+
flexGrow: 1,
|
|
179
|
+
textAlign: 'right'
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
var StyledHelperText = rn.Typography.Caption;
|
|
183
|
+
var StyledTextInput = rn.styled(reactNative.TextInput)(function (_ref7) {
|
|
184
|
+
var theme = _ref7.theme,
|
|
185
|
+
themeVariant = _ref7.themeVariant;
|
|
186
|
+
return {
|
|
187
|
+
textAlignVertical: themeVariant === 'text' ? 'center' : 'top',
|
|
188
|
+
fontSize: theme.__hd__.textInput.fontSizes.text,
|
|
189
|
+
flexGrow: 2,
|
|
190
|
+
paddingVertical: 0,
|
|
191
|
+
maxHeight: theme.__hd__.textInput.sizes.textInputMaxHeight,
|
|
192
|
+
minHeight: theme.__hd__.textInput.sizes.textInputMinHeight,
|
|
193
|
+
height: themeVariant === 'text' ? undefined : theme.__hd__.textInput.sizes.textareaHeight,
|
|
194
|
+
fontFamily: theme.__hd__.textInput.fonts.text
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
var StyledBorder = rn.styled(reactNative.View)(function (_ref8) {
|
|
198
|
+
var theme = _ref8.theme,
|
|
199
|
+
themeFocused = _ref8.themeFocused,
|
|
200
|
+
themeState = _ref8.themeState;
|
|
201
|
+
return _objectSpread2(_objectSpread2({}, reactNative.StyleSheet.absoluteFillObject), {}, {
|
|
202
|
+
borderWidth: theme.__hd__.textInput.borderWidths.container.normal,
|
|
203
|
+
borderRadius: theme.__hd__.textInput.radii.container,
|
|
204
|
+
borderColor: themeFocused ? theme.__hd__.textInput.colors.borders.focused : theme.__hd__.textInput.colors.borders[themeState]
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
var StyledInputWrapper = rn.styled(reactNative.View)(function (_ref9) {
|
|
208
|
+
var theme = _ref9.theme;
|
|
209
|
+
return {
|
|
210
|
+
flexDirection: 'column',
|
|
211
|
+
flex: 1,
|
|
212
|
+
backgroundColor: 'transparent',
|
|
213
|
+
borderRadius: theme.__hd__.textInput.radii.container,
|
|
214
|
+
marginBottom: theme.__hd__.textInput.space.inputWrapperMarginVertical,
|
|
215
|
+
marginTop: theme.__hd__.textInput.space.inputWrapperMarginVertical,
|
|
216
|
+
overflow: 'hidden'
|
|
217
|
+
};
|
|
218
|
+
});
|
|
219
|
+
var StyledInputRow = rn.styled(reactNative.View)(function (_ref10) {
|
|
220
|
+
var theme = _ref10.theme;
|
|
221
|
+
return {
|
|
222
|
+
flexDirection: 'row',
|
|
223
|
+
alignItems: 'center',
|
|
224
|
+
flexGrow: 2,
|
|
225
|
+
flexShrink: 1,
|
|
226
|
+
gap: theme.__hd__.textInput.space.prefixAndInputContainerGap
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
rn.styled(reactNative.View)(function (_ref11) {
|
|
230
|
+
var theme = _ref11.theme;
|
|
231
|
+
return {
|
|
232
|
+
paddingHorizontal: theme.__hd__.textInput.space.errorAndHelpTextContainerHorizontalPadding,
|
|
233
|
+
minHeight: theme.__hd__.textInput.sizes.errorAndHelpTextContainerHeight,
|
|
234
|
+
paddingTop: theme.__hd__.textInput.space.errorAndHelpTextContainerPaddingTop
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
var StyledBottomContainer = rn.styled(reactNative.View)(function () {
|
|
238
|
+
return {
|
|
239
|
+
flexDirection: 'row',
|
|
240
|
+
justifyContent: 'space-between',
|
|
241
|
+
alignItems: 'flex-start'
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
var StyledSuffixContainer = rn.styled(reactNative.View)(function () {
|
|
245
|
+
return {
|
|
246
|
+
flexDirection: 'row',
|
|
247
|
+
alignItems: 'center',
|
|
248
|
+
justifyContent: 'flex-end'
|
|
249
|
+
};
|
|
250
|
+
});
|
|
53
251
|
|
|
54
252
|
var getTextInputTheme = function getTextInputTheme(theme) {
|
|
55
253
|
var baseTextInputTheme = theme.__hd__.textInput;
|
|
56
254
|
// Override specific values here as needed
|
|
57
|
-
var colors = _objectSpread2({}, baseTextInputTheme.colors)
|
|
58
|
-
|
|
255
|
+
var colors = _objectSpread2(_objectSpread2({}, baseTextInputTheme.colors), {}, {
|
|
256
|
+
// Example: override specific colors
|
|
257
|
+
// text: theme.colors.customTextColor,
|
|
258
|
+
borders: {
|
|
259
|
+
"default": theme.colors.secondaryOutline,
|
|
260
|
+
error: theme.colors.onErrorSurface,
|
|
261
|
+
disabled: theme.colors.disabledOutline,
|
|
262
|
+
readonly: theme.colors.disabledOutline,
|
|
263
|
+
filled: theme.colors.secondaryOutline,
|
|
264
|
+
focused: theme.colors.primaryOutline
|
|
265
|
+
},
|
|
266
|
+
labels: {
|
|
267
|
+
"default": theme.colors.inactiveOnDefaultGlobalSurface,
|
|
268
|
+
error: theme.colors.onErrorSurface,
|
|
269
|
+
disabled: theme.colors.disabledOnDefaultGlobalSurface,
|
|
270
|
+
readonly: theme.colors.inactiveOnDefaultGlobalSurface,
|
|
271
|
+
filled: theme.colors.inactiveOnDefaultGlobalSurface,
|
|
272
|
+
focused: theme.colors.onDefaultGlobalSurface
|
|
273
|
+
},
|
|
274
|
+
maxLengthLabels: {
|
|
275
|
+
"default": theme.colors.onDefaultGlobalSurface,
|
|
276
|
+
error: theme.colors.onErrorSurface,
|
|
277
|
+
disabled: theme.colors.disabledOnDefaultGlobalSurface,
|
|
278
|
+
readonly: theme.colors.inactiveOnDefaultGlobalSurface,
|
|
279
|
+
filled: theme.colors.onDefaultGlobalSurface,
|
|
280
|
+
focused: theme.colors.onDefaultGlobalSurface
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
var space = _objectSpread2(_objectSpread2({}, baseTextInputTheme.space), {}, {
|
|
284
|
+
// Example: override specific spacing
|
|
285
|
+
// containerPadding: theme.space.large,
|
|
286
|
+
inputWrapperMarginVertical: theme.space.small,
|
|
287
|
+
prefixAndInputContainerGap: theme.space.xsmall
|
|
288
|
+
});
|
|
59
289
|
var fonts = _objectSpread2({}, baseTextInputTheme.fonts);
|
|
60
290
|
var fontSizes = _objectSpread2({}, baseTextInputTheme.fontSizes);
|
|
61
|
-
var borderWidths = _objectSpread2({}, baseTextInputTheme.borderWidths)
|
|
291
|
+
var borderWidths = _objectSpread2(_objectSpread2({}, baseTextInputTheme.borderWidths), {}, {
|
|
292
|
+
container: _objectSpread2(_objectSpread2({}, baseTextInputTheme.borderWidths.container), {}, {
|
|
293
|
+
normal: theme.borderWidths.medium
|
|
294
|
+
})
|
|
295
|
+
});
|
|
62
296
|
var radii = _objectSpread2({}, baseTextInputTheme.radii);
|
|
63
|
-
var sizes = _objectSpread2({}, baseTextInputTheme.sizes)
|
|
297
|
+
var sizes = _objectSpread2(_objectSpread2({}, baseTextInputTheme.sizes), {}, {
|
|
298
|
+
containerMinHeight: theme.sizes.xxxxlarge,
|
|
299
|
+
errorAndHelpTextContainerHeight: 0,
|
|
300
|
+
textInputMinHeight: baseTextInputTheme.fontSizes.text + theme.space.small
|
|
301
|
+
});
|
|
64
302
|
var lineHeights = _objectSpread2({}, baseTextInputTheme.lineHeights);
|
|
65
303
|
return {
|
|
66
304
|
colors: colors,
|
|
@@ -128,6 +366,634 @@ var withWorkTheme = function withWorkTheme(C, themeName) {
|
|
|
128
366
|
|
|
129
367
|
var defaultTheme = getTheme();
|
|
130
368
|
|
|
369
|
+
/**
|
|
370
|
+
* ErrorOrHelpText Component
|
|
371
|
+
*
|
|
372
|
+
* Displays either error messages or help text below the TextInput.
|
|
373
|
+
* Shows error messages with a danger icon when present, otherwise displays help text.
|
|
374
|
+
*
|
|
375
|
+
* Key Features:
|
|
376
|
+
* - Conditional rendering: error takes priority over help text
|
|
377
|
+
* - Error messages include a danger icon for visual clarity
|
|
378
|
+
* - Uses styled components for consistent theming
|
|
379
|
+
* - Includes proper test IDs for testing
|
|
380
|
+
*
|
|
381
|
+
* Rendering Logic:
|
|
382
|
+
* 1. If error exists: Show error message with danger icon
|
|
383
|
+
* 2. If no error but helpText exists: Show help text
|
|
384
|
+
* 3. If neither exists: Render nothing
|
|
385
|
+
*
|
|
386
|
+
* @param props - The component props (see ErrorOrHelpTextProps interface for details)
|
|
387
|
+
*/
|
|
388
|
+
var ErrorOrHelpText = function ErrorOrHelpText(_ref) {
|
|
389
|
+
var error = _ref.error,
|
|
390
|
+
helpText = _ref.helpText;
|
|
391
|
+
return error ?
|
|
392
|
+
/*#__PURE__*/
|
|
393
|
+
// Error state: Show error message with danger icon
|
|
394
|
+
React__default.default.createElement(StyledErrorRow, null, /*#__PURE__*/React__default.default.createElement(rn.Icon, {
|
|
395
|
+
testID: "input-error-icon",
|
|
396
|
+
icon: "circle-info",
|
|
397
|
+
size: "xsmall",
|
|
398
|
+
intent: "danger"
|
|
399
|
+
}), /*#__PURE__*/React__default.default.createElement(StyledError, {
|
|
400
|
+
testID: "input-error-message"
|
|
401
|
+
}, error)) :
|
|
402
|
+
// Help text state: Show help text if provided
|
|
403
|
+
!!helpText && /*#__PURE__*/React__default.default.createElement(StyledHelperText, null, helpText);
|
|
404
|
+
};
|
|
405
|
+
ErrorOrHelpText.displayName = 'ErrorOrHelpText';
|
|
406
|
+
var ErrorOrHelpText$1 = /*#__PURE__*/React__default.default.memo(ErrorOrHelpText);
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* SuffixComponent
|
|
410
|
+
*
|
|
411
|
+
* Renders suffix content (icons or custom elements) on the right side of the TextInput.
|
|
412
|
+
* Handles loading states and custom elements.
|
|
413
|
+
*
|
|
414
|
+
* Key Features:
|
|
415
|
+
* - Loading state handling: shows spinner when loading is true
|
|
416
|
+
* - Icon rendering: supports string icon names from the design system
|
|
417
|
+
* - Custom element support: can render any React element as suffix
|
|
418
|
+
* - State-aware styling: adjusts icon intent based on input state
|
|
419
|
+
* - Spinning animation: loading icons automatically spin
|
|
420
|
+
* - Proper test IDs for automated testing
|
|
421
|
+
*
|
|
422
|
+
* Rendering Priority:
|
|
423
|
+
* 1. Loading state: Shows 'loading' icon with spin animation
|
|
424
|
+
* 2. String icon name: Renders Icon component with state-based intent
|
|
425
|
+
* 3. Custom element: Renders the provided React element as-is
|
|
426
|
+
* 4. No suffix: Renders null
|
|
427
|
+
*
|
|
428
|
+
* Icon Intent Logic:
|
|
429
|
+
* - Disabled state: Uses 'disabled-text' intent
|
|
430
|
+
* - All other states: Uses 'text' intent
|
|
431
|
+
*
|
|
432
|
+
* @param props - The component props (see SuffixComponentProps interface for details)
|
|
433
|
+
*/
|
|
434
|
+
var SuffixComponent = function SuffixComponent(_ref) {
|
|
435
|
+
var state = _ref.state,
|
|
436
|
+
loading = _ref.loading,
|
|
437
|
+
suffix = _ref.suffix;
|
|
438
|
+
// Loading state overrides suffix
|
|
439
|
+
var actualSuffix = loading ? 'loading' : suffix;
|
|
440
|
+
if (typeof actualSuffix === 'string') {
|
|
441
|
+
// Render icon from design system
|
|
442
|
+
return /*#__PURE__*/React__default.default.createElement(rn.Icon, {
|
|
443
|
+
intent: state === 'disabled' ? 'disabled-text' : 'text',
|
|
444
|
+
testID: "input-suffix",
|
|
445
|
+
accessibilityLabel: "Suffix icon: ".concat(actualSuffix),
|
|
446
|
+
accessibilityRole: "image",
|
|
447
|
+
icon: actualSuffix,
|
|
448
|
+
spin: actualSuffix === 'loading' // Animate loading icon
|
|
449
|
+
,
|
|
450
|
+
size: "medium"
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
if (actualSuffix) {
|
|
454
|
+
// Render custom element
|
|
455
|
+
return suffix;
|
|
456
|
+
}
|
|
457
|
+
return null;
|
|
458
|
+
};
|
|
459
|
+
SuffixComponent.displayName = 'SuffixComponent';
|
|
460
|
+
var SuffixComponent$1 = /*#__PURE__*/React__default.default.memo(SuffixComponent);
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* MaxLengthMessage Component
|
|
464
|
+
*
|
|
465
|
+
* Displays character count information for TextInput fields with maximum length restrictions.
|
|
466
|
+
* Shows current/max character count with state-aware styling.
|
|
467
|
+
*
|
|
468
|
+
* Key Features:
|
|
469
|
+
* - Character count display: Shows "currentLength/maxLength" format
|
|
470
|
+
* - Conditional rendering: Only shows when maxLength is set and not hidden
|
|
471
|
+
* - State-aware styling: Colors change based on input state (error, disabled, etc.)
|
|
472
|
+
* - Real-time updates: Updates as user types to show current progress
|
|
473
|
+
* - Hide capability: Can be hidden via hideCharacterCount prop
|
|
474
|
+
*
|
|
475
|
+
* Display Logic:
|
|
476
|
+
* - Shows only when: maxLength is defined AND hideCharacterCount is false
|
|
477
|
+
* - Format: "currentLength/maxLength" (e.g., "25/100")
|
|
478
|
+
* - Hidden when: maxLength is undefined OR hideCharacterCount is true
|
|
479
|
+
*
|
|
480
|
+
* State-based Styling:
|
|
481
|
+
* - Uses themeState to apply appropriate colors from theme
|
|
482
|
+
* - Error state: Shows error color to indicate validation issues
|
|
483
|
+
* - Disabled state: Shows muted color for disabled inputs
|
|
484
|
+
* - Normal states: Shows standard text colors
|
|
485
|
+
*
|
|
486
|
+
* Usage Example:
|
|
487
|
+
* - Input with 25 characters and 100 max: displays "25/100"
|
|
488
|
+
* - Input approaching limit: color may change based on theme
|
|
489
|
+
* - Input over limit: error state styling applied
|
|
490
|
+
*
|
|
491
|
+
* @param props - The component props (see MaxLengthMessageProps interface for details)
|
|
492
|
+
*/
|
|
493
|
+
var MaxLengthMessage = function MaxLengthMessage(_ref) {
|
|
494
|
+
var maxLength = _ref.maxLength,
|
|
495
|
+
state = _ref.state,
|
|
496
|
+
currentLength = _ref.currentLength,
|
|
497
|
+
hideCharacterCount = _ref.hideCharacterCount;
|
|
498
|
+
if (!maxLength || hideCharacterCount) {
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
return /*#__PURE__*/React__default.default.createElement(StyledCharacterCount, {
|
|
502
|
+
themeState: state
|
|
503
|
+
}, currentLength, "/", maxLength);
|
|
504
|
+
};
|
|
505
|
+
MaxLengthMessage.displayName = 'MaxLengthMessage';
|
|
506
|
+
var MaxLengthMessage$1 = /*#__PURE__*/React__default.default.memo(MaxLengthMessage);
|
|
507
|
+
|
|
508
|
+
var LABEL_ANIMATION_DURATION = 150;
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* FloatingLabel Component
|
|
512
|
+
*
|
|
513
|
+
* Handles the animated floating label behavior for TextInput.
|
|
514
|
+
* The label starts positioned over the input and animates to a smaller size above the input
|
|
515
|
+
* when the field is focused or has content.
|
|
516
|
+
*
|
|
517
|
+
* Key Features:
|
|
518
|
+
* - Smooth scale and translate animations using React Native Animated API
|
|
519
|
+
* - Responds to focus state and content presence
|
|
520
|
+
* - Automatically appends "(Optional)" text for non-required fields
|
|
521
|
+
* - Supports different variants (text/textarea) with appropriate positioning
|
|
522
|
+
* - Maintains accessibility features with proper IDs and test IDs
|
|
523
|
+
* - Self-contained animation management
|
|
524
|
+
*
|
|
525
|
+
* Animation Behavior:
|
|
526
|
+
* - Scale: 1.5 → 1 (label shrinks when floating)
|
|
527
|
+
* - TranslateY: Variable based on variant → 0 (moves up)
|
|
528
|
+
* - Uses bezier easing for smooth transitions
|
|
529
|
+
*
|
|
530
|
+
* @param props - The component props (see FloatingLabelProps for details)
|
|
531
|
+
*/
|
|
532
|
+
var FloatingLabel = function FloatingLabel(_ref) {
|
|
533
|
+
var label = _ref.label,
|
|
534
|
+
variant = _ref.variant,
|
|
535
|
+
state = _ref.state,
|
|
536
|
+
isFocused = _ref.isFocused,
|
|
537
|
+
required = _ref.required,
|
|
538
|
+
accessibilityLabelledBy = _ref.accessibilityLabelledBy,
|
|
539
|
+
isEmptyValue = _ref.isEmptyValue;
|
|
540
|
+
var theme = useWorkTheme();
|
|
541
|
+
var shouldFloat = isFocused || !isEmptyValue;
|
|
542
|
+
var focusAnimation = React.useRef(new reactNative.Animated.Value(shouldFloat ? 1 : 0)).current;
|
|
543
|
+
React.useEffect(function () {
|
|
544
|
+
reactNative.Animated.timing(focusAnimation, {
|
|
545
|
+
toValue: shouldFloat ? 1 : 0,
|
|
546
|
+
duration: LABEL_ANIMATION_DURATION,
|
|
547
|
+
easing: reactNative.Easing.bezier(0.4, 0, 0.2, 1),
|
|
548
|
+
useNativeDriver: true
|
|
549
|
+
}).start();
|
|
550
|
+
}, [shouldFloat, focusAnimation]);
|
|
551
|
+
return /*#__PURE__*/React__default.default.createElement(StyledFloatingLabelContainer, {
|
|
552
|
+
themeVariant: variant,
|
|
553
|
+
style: [{
|
|
554
|
+
transformOrigin: 'left center'
|
|
555
|
+
}, {
|
|
556
|
+
transform: [{
|
|
557
|
+
translateY: focusAnimation.interpolate({
|
|
558
|
+
inputRange: [0, 1],
|
|
559
|
+
outputRange: [variant !== 'textarea' ? 12 : theme.space.small, 0]
|
|
560
|
+
})
|
|
561
|
+
}, {
|
|
562
|
+
scale: focusAnimation.interpolate({
|
|
563
|
+
inputRange: [0, 1],
|
|
564
|
+
outputRange: [1.333, 1]
|
|
565
|
+
})
|
|
566
|
+
}]
|
|
567
|
+
}]
|
|
568
|
+
}, /*#__PURE__*/React__default.default.createElement(reactNative.Animated.View, null, /*#__PURE__*/React__default.default.createElement(StyledLabel, {
|
|
569
|
+
nativeID: accessibilityLabelledBy,
|
|
570
|
+
testID: "input-label",
|
|
571
|
+
themeState: state,
|
|
572
|
+
numberOfLines: 1,
|
|
573
|
+
style: {
|
|
574
|
+
backgroundColor: 'transparent'
|
|
575
|
+
}
|
|
576
|
+
}, label, !required && ' (Optional)')));
|
|
577
|
+
};
|
|
578
|
+
FloatingLabel.displayName = 'FloatingLabel';
|
|
579
|
+
var FloatingLabel$1 = /*#__PURE__*/React__default.default.memo(FloatingLabel);
|
|
580
|
+
|
|
581
|
+
var _excluded$1 = ["state", "prefix"];
|
|
582
|
+
/**
|
|
583
|
+
* PrefixComponent
|
|
584
|
+
*
|
|
585
|
+
* Renders prefix content (icons or custom elements) on the left side of the TextInput,
|
|
586
|
+
* before the user's input cursor.
|
|
587
|
+
*
|
|
588
|
+
* Key Features:
|
|
589
|
+
* - Icon rendering: supports string icon names from the design system
|
|
590
|
+
* - Custom element support: can render any React element as prefix
|
|
591
|
+
* - State-aware styling: adjusts icon intent based on input state
|
|
592
|
+
* - Consistent sizing: uses 'xsmall' size for visual balance
|
|
593
|
+
* - Proper test IDs for automated testing
|
|
594
|
+
*
|
|
595
|
+
* Rendering Logic:
|
|
596
|
+
* 1. String icon name: Renders Icon component with state-based intent
|
|
597
|
+
* 2. Custom element: Renders the provided React element as-is
|
|
598
|
+
* 3. No prefix: Renders null
|
|
599
|
+
*
|
|
600
|
+
* Icon Intent Logic:
|
|
601
|
+
* - Disabled state: Uses 'disabled-text' intent for muted appearance
|
|
602
|
+
* - All other states: Uses 'text' intent for normal appearance
|
|
603
|
+
*
|
|
604
|
+
* Visual Positioning:
|
|
605
|
+
* - Positioned before the text input cursor
|
|
606
|
+
* - Uses smaller 'xsmall' size to avoid overwhelming the input
|
|
607
|
+
* - Maintains proper spacing via parent container
|
|
608
|
+
*
|
|
609
|
+
* @param props - The component props (see PrefixComponentProps interface for details)
|
|
610
|
+
*/
|
|
611
|
+
var PrefixComponent = function PrefixComponent(_ref) {
|
|
612
|
+
var state = _ref.state,
|
|
613
|
+
prefix = _ref.prefix,
|
|
614
|
+
rest = _objectWithoutProperties(_ref, _excluded$1);
|
|
615
|
+
var actualPrefix = typeof prefix === 'string' ? prefix : '';
|
|
616
|
+
if (typeof prefix === 'string' && actualPrefix) {
|
|
617
|
+
return /*#__PURE__*/React__default.default.createElement(reactNative.View, _extends({
|
|
618
|
+
testID: "input-prefix"
|
|
619
|
+
}, rest), /*#__PURE__*/React__default.default.createElement(rn.Icon, {
|
|
620
|
+
intent: state === 'disabled' ? 'disabled-text' : 'text',
|
|
621
|
+
icon: actualPrefix,
|
|
622
|
+
size: "xsmall",
|
|
623
|
+
testID: "input-prefix-icon",
|
|
624
|
+
accessibilityLabel: "Prefix icon: ".concat(actualPrefix),
|
|
625
|
+
accessibilityRole: "image"
|
|
626
|
+
}));
|
|
627
|
+
}
|
|
628
|
+
if (/*#__PURE__*/React__default.default.isValidElement(prefix)) {
|
|
629
|
+
return /*#__PURE__*/React__default.default.createElement(reactNative.View, _extends({
|
|
630
|
+
testID: "input-prefix"
|
|
631
|
+
}, rest), prefix);
|
|
632
|
+
}
|
|
633
|
+
return null;
|
|
634
|
+
};
|
|
635
|
+
PrefixComponent.displayName = 'PrefixComponent';
|
|
636
|
+
var PrefixComponent$1 = /*#__PURE__*/React__default.default.memo(PrefixComponent);
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* InputComponent
|
|
640
|
+
*
|
|
641
|
+
* Renders the actual text input element. Supports custom input rendering or uses the default StyledTextInput.
|
|
642
|
+
*
|
|
643
|
+
* Key Features:
|
|
644
|
+
* - Flexible rendering: supports custom input renderers via renderInputValue prop
|
|
645
|
+
* - Variant support: handles both 'text' and 'textarea' input types
|
|
646
|
+
* - Multiline handling: automatically enables multiline for textarea variant
|
|
647
|
+
* - Theme integration: applies theme colors for placeholder text
|
|
648
|
+
* - Ref forwarding: properly forwards refs to the underlying TextInput
|
|
649
|
+
*
|
|
650
|
+
* Rendering Logic:
|
|
651
|
+
* 1. If renderInputValue provided: Use custom renderer
|
|
652
|
+
* 2. Otherwise: Use default StyledTextInput with theme and variant support
|
|
653
|
+
*
|
|
654
|
+
* Multiline Behavior:
|
|
655
|
+
* - 'textarea' variant: Always multiline
|
|
656
|
+
* - 'text' variant: Single line unless explicitly set via nativeInputProps
|
|
657
|
+
*
|
|
658
|
+
* @param props - The component props (see InputComponentProps interface for details)
|
|
659
|
+
*/
|
|
660
|
+
var InputComponent = /*#__PURE__*/React__default.default.forwardRef(function (_ref, ref) {
|
|
661
|
+
var variant = _ref.variant,
|
|
662
|
+
nativeInputProps = _ref.nativeInputProps,
|
|
663
|
+
renderInputValue = _ref.renderInputValue;
|
|
664
|
+
var theme = useWorkTheme();
|
|
665
|
+
return renderInputValue ?
|
|
666
|
+
/*#__PURE__*/
|
|
667
|
+
// Custom input renderer provided
|
|
668
|
+
React__default.default.createElement(React__default.default.Fragment, null, renderInputValue(nativeInputProps)) :
|
|
669
|
+
/*#__PURE__*/
|
|
670
|
+
// Default styled input with theme and variant support
|
|
671
|
+
React__default.default.createElement(StyledTextInput, _extends({}, nativeInputProps, {
|
|
672
|
+
themeVariant: variant,
|
|
673
|
+
multiline: variant === 'textarea' || nativeInputProps.multiline,
|
|
674
|
+
ref: ref,
|
|
675
|
+
placeholderTextColor: theme.__hd__.textInput.colors.placeholder
|
|
676
|
+
}));
|
|
677
|
+
});
|
|
678
|
+
InputComponent.displayName = 'InputComponent';
|
|
679
|
+
var InputComponent$1 = /*#__PURE__*/React__default.default.memo(InputComponent);
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* InputRow Component
|
|
683
|
+
*
|
|
684
|
+
* Layout Structure:
|
|
685
|
+
* ┌─────────────────────────────────────────────────────────┐
|
|
686
|
+
* │ StyledInputRow │
|
|
687
|
+
* │ ┌──────────┐ ┌─────────────────────────────────────┐ │
|
|
688
|
+
* │ │ Prefix │ │ Input Field │ │
|
|
689
|
+
* │ │ (Icon or │ │ (TextInput or Custom) │ │
|
|
690
|
+
* │ │ Custom) │ │ flex: 1 │ │
|
|
691
|
+
* │ └──────────┘ └─────────────────────────────────────┘ │
|
|
692
|
+
* └─────────────────────────────────────────────────────────┘
|
|
693
|
+
*
|
|
694
|
+
* Rendering Behavior:
|
|
695
|
+
* - Components are always rendered but hidden with opacity in idle state
|
|
696
|
+
* - Uses accessibility props to hide components from screen readers when not visible
|
|
697
|
+
*
|
|
698
|
+
* Renders the main input row containing:
|
|
699
|
+
* 1. Conditionally visible prefix component (icon or custom element)
|
|
700
|
+
* 2. Conditionally visible input component (TextInput or custom rendered input)
|
|
701
|
+
*/
|
|
702
|
+
var InputRow = /*#__PURE__*/React__default.default.forwardRef(function (_ref, ref) {
|
|
703
|
+
var state = _ref.state,
|
|
704
|
+
isFocused = _ref.isFocused,
|
|
705
|
+
prefix = _ref.prefix,
|
|
706
|
+
variant = _ref.variant,
|
|
707
|
+
nativeInputProps = _ref.nativeInputProps,
|
|
708
|
+
renderInputValue = _ref.renderInputValue,
|
|
709
|
+
isEmptyValue = _ref.isEmptyValue;
|
|
710
|
+
var shouldShow = isFocused || !isEmptyValue;
|
|
711
|
+
var opacity = React.useRef(new reactNative.Animated.Value(shouldShow ? 1 : 0)).current;
|
|
712
|
+
React.useEffect(function () {
|
|
713
|
+
reactNative.Animated.timing(opacity, {
|
|
714
|
+
toValue: shouldShow ? 1 : 0,
|
|
715
|
+
duration: LABEL_ANIMATION_DURATION,
|
|
716
|
+
useNativeDriver: true
|
|
717
|
+
}).start();
|
|
718
|
+
}, [shouldShow, opacity]);
|
|
719
|
+
return /*#__PURE__*/React__default.default.createElement(StyledInputRow, null, /*#__PURE__*/React__default.default.createElement(reactNative.Animated.View, {
|
|
720
|
+
style: {
|
|
721
|
+
opacity: opacity
|
|
722
|
+
}
|
|
723
|
+
}, /*#__PURE__*/React__default.default.createElement(PrefixComponent$1, {
|
|
724
|
+
state: state,
|
|
725
|
+
prefix: prefix,
|
|
726
|
+
accessibilityElementsHidden: !shouldShow
|
|
727
|
+
})), /*#__PURE__*/React__default.default.createElement(reactNative.Animated.View, {
|
|
728
|
+
style: {
|
|
729
|
+
flex: 1,
|
|
730
|
+
opacity: opacity
|
|
731
|
+
},
|
|
732
|
+
testID: "input-row-input-wrapper",
|
|
733
|
+
accessibilityLabel: "Text input field",
|
|
734
|
+
accessibilityElementsHidden: !shouldShow
|
|
735
|
+
}, /*#__PURE__*/React__default.default.createElement(InputComponent$1, {
|
|
736
|
+
variant: variant,
|
|
737
|
+
nativeInputProps: nativeInputProps,
|
|
738
|
+
renderInputValue: renderInputValue,
|
|
739
|
+
ref: ref
|
|
740
|
+
})));
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
var _excluded = ["label", "prefix", "suffix", "style", "textStyle", "testID", "accessibilityLabelledBy", "error", "required", "editable", "disabled", "loading", "maxLength", "hideCharacterCount", "helpText", "value", "defaultValue", "renderInputValue", "allowFontScaling", "variant"];
|
|
744
|
+
var getState = function getState(_ref) {
|
|
745
|
+
var disabled = _ref.disabled,
|
|
746
|
+
error = _ref.error,
|
|
747
|
+
editable = _ref.editable,
|
|
748
|
+
loading = _ref.loading,
|
|
749
|
+
isEmptyValue = _ref.isEmptyValue;
|
|
750
|
+
if (disabled) {
|
|
751
|
+
return 'disabled';
|
|
752
|
+
}
|
|
753
|
+
if (error) {
|
|
754
|
+
return 'error';
|
|
755
|
+
}
|
|
756
|
+
if (!editable || loading) {
|
|
757
|
+
return 'readonly';
|
|
758
|
+
}
|
|
759
|
+
if (!isEmptyValue) {
|
|
760
|
+
return 'filled';
|
|
761
|
+
}
|
|
762
|
+
return 'default';
|
|
763
|
+
};
|
|
764
|
+
// Fix issue: Placeholder is not shown on iOS when multiline is true
|
|
765
|
+
// https://github.com/callstack/react-native-paper/pull/3331
|
|
766
|
+
var EMPTY_PLACEHOLDER_VALUE = ' ';
|
|
767
|
+
// Simplified style extraction functions
|
|
768
|
+
var extractBackgroundColor = function extractBackgroundColor(style) {
|
|
769
|
+
var flattened = reactNative.StyleSheet.flatten(style);
|
|
770
|
+
return flattened === null || flattened === void 0 ? void 0 : flattened.backgroundColor;
|
|
771
|
+
};
|
|
772
|
+
var extractBorderStyles = function extractBorderStyles(style) {
|
|
773
|
+
var flattened = reactNative.StyleSheet.flatten(style);
|
|
774
|
+
if (!flattened) return {};
|
|
775
|
+
var borderKeys = Object.keys(flattened).filter(function (key) {
|
|
776
|
+
return key.startsWith('border');
|
|
777
|
+
});
|
|
778
|
+
var borderStyles = {};
|
|
779
|
+
borderKeys.forEach(function (key) {
|
|
780
|
+
borderStyles[key] = flattened[key];
|
|
781
|
+
});
|
|
782
|
+
return borderStyles;
|
|
783
|
+
};
|
|
784
|
+
/**
|
|
785
|
+
* TextInput Layout Structure:
|
|
786
|
+
*
|
|
787
|
+
* ┌─────────────────────────────────────────────────────────────────────────┐
|
|
788
|
+
* │ StyledContainer (with StyledBorder overlay) │
|
|
789
|
+
* │ ┌─────────────────────────────────────────────────────────┐ │
|
|
790
|
+
* │ │ StyledInputWrapper │ │
|
|
791
|
+
* │ │ ┌─────────────────────────────────────────────────┐ │ │
|
|
792
|
+
* │ │ │ FloatingLabel (Optional) │ │ │
|
|
793
|
+
* │ │ │ "Label" or animated position │ │ ┌──────┐ │
|
|
794
|
+
* │ │ └─────────────────────────────────────────────────┘ │ │Suffix│ │
|
|
795
|
+
* │ │ │ │ Icon │ │
|
|
796
|
+
* │ │ ┌─────────────────────────────────────────────────┐ │ │ or │ │
|
|
797
|
+
* │ │ │ InputRow Component │ │ │Custom│ │
|
|
798
|
+
* │ │ │ ┌──────────┐ ┌─────────────────────────────┐ │ │ │(V- │ │
|
|
799
|
+
* │ │ │ │ Prefix │ │ Input Field │ │ │ │Center│ │
|
|
800
|
+
* │ │ │ │(Animated)│ │ (Animated TextInput) │ │ │ │ ed) │ │
|
|
801
|
+
* │ │ │ └──────────┘ └─────────────────────────────┘ │ │ └──────┘ │
|
|
802
|
+
* │ │ └─────────────────────────────────────────────────┘ │ │
|
|
803
|
+
* │ │ │ │
|
|
804
|
+
* │ │ ┌─────────────────────────────────────────────────┐ │ │
|
|
805
|
+
* │ │ │ StyledBottomContainer │ │ │
|
|
806
|
+
* │ │ │ ┌─────────────────┐ ┌─────────────────────┐ │ │ │
|
|
807
|
+
* │ │ │ │ Error/Help Text │ │ Character Count │ │ │ │
|
|
808
|
+
* │ │ │ │ (flex: 4) │ │ (flex: 1) │ │ │ │
|
|
809
|
+
* │ │ │ └─────────────────┘ └─────────────────────┘ │ │ │
|
|
810
|
+
* │ │ └─────────────────────────────────────────────────┘ │ │
|
|
811
|
+
* │ └─────────────────────────────────────────────────────────┘ │
|
|
812
|
+
* └─────────────────────────────────────────────────────────────────────────┘
|
|
813
|
+
*
|
|
814
|
+
* Note: StyledBorder uses StyleSheet.absoluteFillObject to overlay the entire
|
|
815
|
+
* StyledContainer, providing the border and background styling.
|
|
816
|
+
*/
|
|
817
|
+
var TextInput = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
818
|
+
var _ref3;
|
|
819
|
+
var label = _ref2.label,
|
|
820
|
+
prefix = _ref2.prefix,
|
|
821
|
+
suffix = _ref2.suffix,
|
|
822
|
+
style = _ref2.style,
|
|
823
|
+
textStyle = _ref2.textStyle,
|
|
824
|
+
testID = _ref2.testID,
|
|
825
|
+
accessibilityLabelledBy = _ref2.accessibilityLabelledBy,
|
|
826
|
+
error = _ref2.error,
|
|
827
|
+
required = _ref2.required,
|
|
828
|
+
_ref2$editable = _ref2.editable,
|
|
829
|
+
editable = _ref2$editable === void 0 ? true : _ref2$editable,
|
|
830
|
+
_ref2$disabled = _ref2.disabled,
|
|
831
|
+
disabled = _ref2$disabled === void 0 ? false : _ref2$disabled,
|
|
832
|
+
_ref2$loading = _ref2.loading,
|
|
833
|
+
loading = _ref2$loading === void 0 ? false : _ref2$loading,
|
|
834
|
+
maxLength = _ref2.maxLength,
|
|
835
|
+
_ref2$hideCharacterCo = _ref2.hideCharacterCount,
|
|
836
|
+
hideCharacterCount = _ref2$hideCharacterCo === void 0 ? false : _ref2$hideCharacterCo,
|
|
837
|
+
helpText = _ref2.helpText,
|
|
838
|
+
value = _ref2.value,
|
|
839
|
+
defaultValue = _ref2.defaultValue,
|
|
840
|
+
renderInputValue = _ref2.renderInputValue,
|
|
841
|
+
_ref2$allowFontScalin = _ref2.allowFontScaling,
|
|
842
|
+
allowFontScaling = _ref2$allowFontScalin === void 0 ? false : _ref2$allowFontScalin,
|
|
843
|
+
_ref2$variant = _ref2.variant,
|
|
844
|
+
variant = _ref2$variant === void 0 ? 'text' : _ref2$variant,
|
|
845
|
+
nativeProps = _objectWithoutProperties(_ref2, _excluded);
|
|
846
|
+
// Inline the simple getDisplayText function
|
|
847
|
+
var displayText = (_ref3 = value !== undefined ? value : defaultValue) !== null && _ref3 !== void 0 ? _ref3 : '';
|
|
848
|
+
var isEmptyValue = displayText.length === 0;
|
|
849
|
+
var _React$useState = React__default.default.useState(false),
|
|
850
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
851
|
+
isFocused = _React$useState2[0],
|
|
852
|
+
setIsFocused = _React$useState2[1];
|
|
853
|
+
var state = getState({
|
|
854
|
+
disabled: disabled,
|
|
855
|
+
error: error,
|
|
856
|
+
editable: editable,
|
|
857
|
+
loading: loading,
|
|
858
|
+
isEmptyValue: isEmptyValue
|
|
859
|
+
});
|
|
860
|
+
var theme = useWorkTheme();
|
|
861
|
+
var innerTextInput = React__default.default.useRef(null);
|
|
862
|
+
React__default.default.useImperativeHandle(ref, function () {
|
|
863
|
+
return {
|
|
864
|
+
// we don't expose this method, it's for testing https://medium.com/developer-rants/how-to-test-useref-without-mocking-useref-699165f4994e
|
|
865
|
+
getNativeTextInputRef: function getNativeTextInputRef() {
|
|
866
|
+
return innerTextInput.current;
|
|
867
|
+
},
|
|
868
|
+
focus: function focus() {
|
|
869
|
+
var _innerTextInput$curre;
|
|
870
|
+
(_innerTextInput$curre = innerTextInput.current) === null || _innerTextInput$curre === void 0 || _innerTextInput$curre.focus();
|
|
871
|
+
},
|
|
872
|
+
clear: function clear() {
|
|
873
|
+
var _innerTextInput$curre2;
|
|
874
|
+
return (_innerTextInput$curre2 = innerTextInput.current) === null || _innerTextInput$curre2 === void 0 ? void 0 : _innerTextInput$curre2.clear();
|
|
875
|
+
},
|
|
876
|
+
setNativeProps: function setNativeProps(args) {
|
|
877
|
+
var _innerTextInput$curre3;
|
|
878
|
+
return (_innerTextInput$curre3 = innerTextInput.current) === null || _innerTextInput$curre3 === void 0 ? void 0 : _innerTextInput$curre3.setNativeProps(args);
|
|
879
|
+
},
|
|
880
|
+
isFocused: function isFocused() {
|
|
881
|
+
var _innerTextInput$curre4;
|
|
882
|
+
return ((_innerTextInput$curre4 = innerTextInput.current) === null || _innerTextInput$curre4 === void 0 ? void 0 : _innerTextInput$curre4.isFocused()) || false;
|
|
883
|
+
},
|
|
884
|
+
blur: function blur() {
|
|
885
|
+
var _innerTextInput$curre5;
|
|
886
|
+
return (_innerTextInput$curre5 = innerTextInput.current) === null || _innerTextInput$curre5 === void 0 ? void 0 : _innerTextInput$curre5.blur();
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
}, [innerTextInput]);
|
|
890
|
+
// Simplified style extraction
|
|
891
|
+
var borderStyles = extractBorderStyles(textStyle);
|
|
892
|
+
var customBackgroundColor = extractBackgroundColor(style);
|
|
893
|
+
var backgroundColor = customBackgroundColor !== null && customBackgroundColor !== void 0 ? customBackgroundColor : theme.__hd__.textInput.colors.containerBackground;
|
|
894
|
+
// Simplified callback functions (removed unnecessary memoization for simple cases)
|
|
895
|
+
var handleFocus = React.useCallback(function (event) {
|
|
896
|
+
var _nativeProps$onFocus;
|
|
897
|
+
setIsFocused(true);
|
|
898
|
+
(_nativeProps$onFocus = nativeProps.onFocus) === null || _nativeProps$onFocus === void 0 || _nativeProps$onFocus.call(nativeProps, event);
|
|
899
|
+
}, [nativeProps]);
|
|
900
|
+
var handleBlur = React.useCallback(function (event) {
|
|
901
|
+
var _nativeProps$onBlur;
|
|
902
|
+
setIsFocused(false);
|
|
903
|
+
(_nativeProps$onBlur = nativeProps.onBlur) === null || _nativeProps$onBlur === void 0 || _nativeProps$onBlur.call(nativeProps, event);
|
|
904
|
+
}, [nativeProps]);
|
|
905
|
+
var handleChangeText = React.useCallback(function (text) {
|
|
906
|
+
var _nativeProps$onChange;
|
|
907
|
+
(_nativeProps$onChange = nativeProps.onChangeText) === null || _nativeProps$onChange === void 0 || _nativeProps$onChange.call(nativeProps, text);
|
|
908
|
+
}, [nativeProps]);
|
|
909
|
+
// Simplified callbacks - these don't need memoization as they're stable
|
|
910
|
+
var handleContainerPress = function handleContainerPress() {
|
|
911
|
+
var _innerTextInput$curre6;
|
|
912
|
+
(_innerTextInput$curre6 = innerTextInput.current) === null || _innerTextInput$curre6 === void 0 || _innerTextInput$curre6.focus();
|
|
913
|
+
};
|
|
914
|
+
// Create text input style without border properties
|
|
915
|
+
var textInputStyle = textStyle ? _objectSpread2({}, reactNative.StyleSheet.flatten(textStyle)) : {};
|
|
916
|
+
Object.keys(borderStyles).forEach(function (key) {
|
|
917
|
+
delete textInputStyle[key];
|
|
918
|
+
});
|
|
919
|
+
var nativeInputProps = _objectSpread2(_objectSpread2({
|
|
920
|
+
style: reactNative.StyleSheet.flatten([{
|
|
921
|
+
backgroundColor: backgroundColor,
|
|
922
|
+
color: theme.__hd__.textInput.colors.text
|
|
923
|
+
}, textInputStyle]),
|
|
924
|
+
testID: 'text-input',
|
|
925
|
+
accessibilityState: {
|
|
926
|
+
disabled: state === 'disabled' || state === 'readonly'
|
|
927
|
+
},
|
|
928
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
929
|
+
// @ts-ignore
|
|
930
|
+
accessibilityLabelledBy: accessibilityLabelledBy,
|
|
931
|
+
allowFontScaling: allowFontScaling
|
|
932
|
+
}, nativeProps), {}, {
|
|
933
|
+
onFocus: handleFocus,
|
|
934
|
+
onBlur: handleBlur,
|
|
935
|
+
onChangeText: handleChangeText,
|
|
936
|
+
editable: editable,
|
|
937
|
+
maxLength: maxLength,
|
|
938
|
+
value: value,
|
|
939
|
+
defaultValue: defaultValue,
|
|
940
|
+
placeholder: isFocused || label === undefined ? nativeProps.placeholder : EMPTY_PLACEHOLDER_VALUE
|
|
941
|
+
});
|
|
942
|
+
// Create container style without background color
|
|
943
|
+
var containerStyle = style ? _objectSpread2({}, reactNative.StyleSheet.flatten(style)) : {};
|
|
944
|
+
if (customBackgroundColor) {
|
|
945
|
+
delete containerStyle.backgroundColor;
|
|
946
|
+
}
|
|
947
|
+
var isDisabledOrReadonly = state === 'disabled' || state === 'readonly';
|
|
948
|
+
return /*#__PURE__*/React__default.default.createElement(StyledContainer, {
|
|
949
|
+
style: containerStyle,
|
|
950
|
+
onPress: handleContainerPress,
|
|
951
|
+
disabled: isDisabledOrReadonly,
|
|
952
|
+
accessibilityState: {
|
|
953
|
+
disabled: isDisabledOrReadonly
|
|
954
|
+
},
|
|
955
|
+
testID: testID
|
|
956
|
+
}, /*#__PURE__*/React__default.default.createElement(StyledBorder, {
|
|
957
|
+
themeFocused: isFocused,
|
|
958
|
+
themeState: state,
|
|
959
|
+
testID: "text-input-border",
|
|
960
|
+
pointerEvents: "none",
|
|
961
|
+
style: [{
|
|
962
|
+
backgroundColor: backgroundColor
|
|
963
|
+
}, borderStyles]
|
|
964
|
+
}), /*#__PURE__*/React__default.default.createElement(StyledInputWrapper, null, !!label && /*#__PURE__*/React__default.default.createElement(FloatingLabel$1, {
|
|
965
|
+
label: label,
|
|
966
|
+
variant: variant,
|
|
967
|
+
state: state,
|
|
968
|
+
isFocused: isFocused,
|
|
969
|
+
required: required,
|
|
970
|
+
accessibilityLabelledBy: accessibilityLabelledBy,
|
|
971
|
+
isEmptyValue: isEmptyValue
|
|
972
|
+
}), /*#__PURE__*/React__default.default.createElement(InputRow, {
|
|
973
|
+
state: state,
|
|
974
|
+
isFocused: isFocused,
|
|
975
|
+
prefix: prefix,
|
|
976
|
+
variant: variant,
|
|
977
|
+
nativeInputProps: nativeInputProps,
|
|
978
|
+
renderInputValue: renderInputValue,
|
|
979
|
+
ref: innerTextInput,
|
|
980
|
+
isEmptyValue: isEmptyValue
|
|
981
|
+
}), /*#__PURE__*/React__default.default.createElement(StyledBottomContainer, null, /*#__PURE__*/React__default.default.createElement(ErrorOrHelpText$1, {
|
|
982
|
+
error: error,
|
|
983
|
+
helpText: helpText
|
|
984
|
+
}), /*#__PURE__*/React__default.default.createElement(MaxLengthMessage$1, {
|
|
985
|
+
state: state,
|
|
986
|
+
currentLength: displayText.length,
|
|
987
|
+
maxLength: maxLength,
|
|
988
|
+
hideCharacterCount: hideCharacterCount
|
|
989
|
+
}))), /*#__PURE__*/React__default.default.createElement(StyledSuffixContainer, null, /*#__PURE__*/React__default.default.createElement(SuffixComponent$1, {
|
|
990
|
+
state: state,
|
|
991
|
+
loading: loading,
|
|
992
|
+
suffix: suffix
|
|
993
|
+
})));
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
exports.TextInput = TextInput;
|
|
131
997
|
exports.ThemeProvider = WorkThemeProvider;
|
|
132
998
|
exports.ThemeSwitcher = WorkThemeSwitcher;
|
|
133
999
|
exports.getTheme = getTheme;
|