@tamagui/input 1.143.1 → 2.0.0-1

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.
Files changed (133) hide show
  1. package/dist/cjs/Input.cjs +57 -122
  2. package/dist/cjs/Input.js +46 -115
  3. package/dist/cjs/Input.js.map +1 -1
  4. package/dist/cjs/Input.native.js +133 -71
  5. package/dist/cjs/Input.native.js.map +1 -1
  6. package/dist/cjs/TextArea.cjs +1 -1
  7. package/dist/cjs/TextArea.js +1 -1
  8. package/dist/cjs/TextArea.js.map +1 -1
  9. package/dist/cjs/TextArea.native.js +1 -1
  10. package/dist/cjs/TextArea.native.js.map +1 -1
  11. package/dist/cjs/v1/Input.cjs +190 -0
  12. package/dist/cjs/v1/Input.js +171 -0
  13. package/dist/cjs/v1/Input.js.map +6 -0
  14. package/dist/cjs/v1/Input.native.js +138 -0
  15. package/dist/cjs/v1/Input.native.js.map +1 -0
  16. package/dist/cjs/v1/TextArea.cjs +50 -0
  17. package/dist/cjs/v1/TextArea.js +43 -0
  18. package/dist/cjs/v1/TextArea.js.map +6 -0
  19. package/dist/cjs/v1/TextArea.native.js +53 -0
  20. package/dist/cjs/v1/TextArea.native.js.map +1 -0
  21. package/dist/cjs/v1/index.cjs +19 -0
  22. package/dist/cjs/v1/index.js +16 -0
  23. package/dist/cjs/v1/index.js.map +6 -0
  24. package/dist/cjs/v1/index.native.js +22 -0
  25. package/dist/cjs/v1/index.native.js.map +1 -0
  26. package/dist/cjs/v1/types.cjs +16 -0
  27. package/dist/cjs/v1/types.js +14 -0
  28. package/dist/cjs/v1/types.js.map +6 -0
  29. package/dist/cjs/v1/types.native.js +19 -0
  30. package/dist/cjs/v1/types.native.js.map +1 -0
  31. package/dist/esm/Input.js +47 -116
  32. package/dist/esm/Input.js.map +1 -1
  33. package/dist/esm/Input.mjs +58 -123
  34. package/dist/esm/Input.mjs.map +1 -1
  35. package/dist/esm/Input.native.js +134 -72
  36. package/dist/esm/Input.native.js.map +1 -1
  37. package/dist/esm/TextArea.js +1 -1
  38. package/dist/esm/TextArea.js.map +1 -1
  39. package/dist/esm/TextArea.mjs +1 -1
  40. package/dist/esm/TextArea.mjs.map +1 -1
  41. package/dist/esm/TextArea.native.js +1 -1
  42. package/dist/esm/TextArea.native.js.map +1 -1
  43. package/dist/esm/v1/Input.js +151 -0
  44. package/dist/esm/v1/Input.js.map +6 -0
  45. package/dist/esm/v1/Input.mjs +156 -0
  46. package/dist/esm/v1/Input.mjs.map +1 -0
  47. package/dist/esm/v1/Input.native.js +101 -0
  48. package/dist/esm/v1/Input.native.js.map +1 -0
  49. package/dist/esm/v1/TextArea.js +29 -0
  50. package/dist/esm/v1/TextArea.js.map +6 -0
  51. package/dist/esm/v1/TextArea.mjs +27 -0
  52. package/dist/esm/v1/TextArea.mjs.map +1 -0
  53. package/dist/esm/v1/TextArea.native.js +27 -0
  54. package/dist/esm/v1/TextArea.native.js.map +1 -0
  55. package/dist/esm/v1/index.js +3 -0
  56. package/dist/esm/v1/index.js.map +6 -0
  57. package/dist/esm/v1/index.mjs +3 -0
  58. package/dist/esm/v1/index.mjs.map +1 -0
  59. package/dist/esm/v1/index.native.js +3 -0
  60. package/dist/esm/v1/index.native.js.map +1 -0
  61. package/dist/esm/v1/types.js +1 -0
  62. package/dist/esm/v1/types.js.map +6 -0
  63. package/dist/esm/v1/types.mjs +2 -0
  64. package/dist/esm/v1/types.mjs.map +1 -0
  65. package/dist/esm/v1/types.native.js +2 -0
  66. package/dist/esm/v1/types.native.js.map +1 -0
  67. package/dist/jsx/Input.js +47 -116
  68. package/dist/jsx/Input.js.map +1 -1
  69. package/dist/jsx/Input.mjs +58 -123
  70. package/dist/jsx/Input.mjs.map +1 -1
  71. package/dist/jsx/Input.native.js +133 -71
  72. package/dist/jsx/Input.native.js.map +1 -1
  73. package/dist/jsx/TextArea.js +1 -1
  74. package/dist/jsx/TextArea.js.map +1 -1
  75. package/dist/jsx/TextArea.mjs +1 -1
  76. package/dist/jsx/TextArea.mjs.map +1 -1
  77. package/dist/jsx/TextArea.native.js +1 -1
  78. package/dist/jsx/TextArea.native.js.map +1 -1
  79. package/dist/jsx/v1/Input.js +151 -0
  80. package/dist/jsx/v1/Input.js.map +6 -0
  81. package/dist/jsx/v1/Input.mjs +156 -0
  82. package/dist/jsx/v1/Input.mjs.map +1 -0
  83. package/dist/jsx/v1/Input.native.js +138 -0
  84. package/dist/jsx/v1/Input.native.js.map +1 -0
  85. package/dist/jsx/v1/TextArea.js +29 -0
  86. package/dist/jsx/v1/TextArea.js.map +6 -0
  87. package/dist/jsx/v1/TextArea.mjs +27 -0
  88. package/dist/jsx/v1/TextArea.mjs.map +1 -0
  89. package/dist/jsx/v1/TextArea.native.js +53 -0
  90. package/dist/jsx/v1/TextArea.native.js.map +1 -0
  91. package/dist/jsx/v1/index.js +3 -0
  92. package/dist/jsx/v1/index.js.map +6 -0
  93. package/dist/jsx/v1/index.mjs +3 -0
  94. package/dist/jsx/v1/index.mjs.map +1 -0
  95. package/dist/jsx/v1/index.native.js +22 -0
  96. package/dist/jsx/v1/index.native.js.map +1 -0
  97. package/dist/jsx/v1/types.js +1 -0
  98. package/dist/jsx/v1/types.js.map +6 -0
  99. package/dist/jsx/v1/types.mjs +2 -0
  100. package/dist/jsx/v1/types.mjs.map +1 -0
  101. package/dist/jsx/v1/types.native.js +19 -0
  102. package/dist/jsx/v1/types.native.js.map +1 -0
  103. package/package.json +13 -13
  104. package/src/Input.native.tsx +145 -110
  105. package/src/Input.tsx +67 -137
  106. package/src/TextArea.tsx +4 -2
  107. package/src/index.ts +0 -1
  108. package/src/types.ts +52 -41
  109. package/src/v1/Input.native.tsx +154 -0
  110. package/src/v1/Input.tsx +191 -0
  111. package/src/v1/TextArea.tsx +35 -0
  112. package/src/v1/index.ts +3 -0
  113. package/src/v1/types.ts +65 -0
  114. package/types/Input.d.ts +47 -21
  115. package/types/Input.d.ts.map +1 -1
  116. package/types/Input.native.d.ts +52 -22
  117. package/types/Input.native.d.ts.map +1 -1
  118. package/types/TextArea.d.ts +25 -11
  119. package/types/TextArea.d.ts.map +1 -1
  120. package/types/index.d.ts +0 -1
  121. package/types/index.d.ts.map +1 -1
  122. package/types/types.d.ts +47 -21
  123. package/types/types.d.ts.map +1 -1
  124. package/types/v1/Input.d.ts +115 -0
  125. package/types/v1/Input.d.ts.map +1 -0
  126. package/types/v1/Input.native.d.ts +114 -0
  127. package/types/v1/Input.native.d.ts.map +1 -0
  128. package/types/v1/TextArea.d.ts +98 -0
  129. package/types/v1/TextArea.d.ts.map +1 -0
  130. package/types/v1/index.d.ts +4 -0
  131. package/types/v1/index.d.ts.map +1 -0
  132. package/types/v1/types.d.ts +39 -0
  133. package/types/v1/types.d.ts.map +1 -0
@@ -1,149 +1,184 @@
1
1
  import React from 'react'
2
- import { styled, useComposedRefs } from '@tamagui/core'
2
+ import { TextInput, type TextInputProps as RNTextInputProps } from 'react-native'
3
+ import { styled, useComposedRefs, useTheme, getTokenValue } from '@tamagui/core'
3
4
  import { registerFocusable } from '@tamagui/focusable'
4
-
5
- import type { NativeSyntheticEvent, TextInputChangeEventData } from 'react-native'
6
- import { TextInput } from 'react-native'
7
5
  import { styledBody } from './shared'
8
6
  import type { InputProps } from './types'
7
+
9
8
  const StyledInput = styled(TextInput, styledBody[0], styledBody[1])
10
9
 
11
- export const Input = StyledInput.styleable<InputProps>((inProps, forwardedRef) => {
10
+ /**
11
+ * A web-aligned input component for React Native.
12
+ * @see — Docs https://tamagui.dev/ui/inputs#input
13
+ */
14
+ export const Input = StyledInput.styleable<InputProps>((props, forwardedRef) => {
12
15
  const {
13
- // some of destructed props are just to avoid passing them to ...rest because they are not in native.
16
+ // Web props we need to convert
14
17
  type,
15
- //@ts-ignore
18
+ disabled,
19
+ readOnly,
20
+ id,
21
+ rows,
22
+ autoComplete,
23
+ enterKeyHint,
24
+
25
+ // Tamagui color props
26
+ placeholderTextColor,
27
+ selectionColor,
28
+
29
+ // Callbacks
30
+ onChange,
31
+ onInput,
32
+ onKeyDown,
33
+ onChangeText,
34
+ onSubmitEditing,
35
+ onSelectionChange,
36
+ selection,
37
+
38
+ // Web-only props to filter out
39
+ // @ts-ignore
16
40
  dirname,
17
- max,
18
41
  min,
42
+ max,
19
43
  minLength,
20
44
  multiple,
21
45
  name,
46
+ pattern,
22
47
  required,
23
48
  step,
24
- disabled,
25
- id,
26
- caretColor,
27
- onChange,
28
- onInput,
29
- rows,
30
- enterKeyHint,
31
- returnKeyType,
32
- onKeyDown,
33
- inputMode,
34
49
  tag,
35
- ...rest
36
- } = inProps
37
50
 
38
- const ref = React.useRef<HTMLInputElement>(null)
51
+ ...rest
52
+ } = props
39
53
 
54
+ const ref = React.useRef<any>(null)
55
+ const theme = useTheme()
40
56
  const composedRefs = useComposedRefs<any>(forwardedRef, ref)
41
57
 
42
- // TODO: later move most of the logic to the core package
43
-
58
+ // Convert web type to native props
44
59
  let secureTextEntry = false
45
- let cursorColor = caretColor
46
- let _returnKeyType = returnKeyType
47
- let _enterKeyHint = enterKeyHint
48
- if (enterKeyHint === 'go') {
49
- _returnKeyType = 'go'
50
- _enterKeyHint = undefined
51
- }
60
+ let keyboardType: RNTextInputProps['keyboardType'] = 'default'
61
+ let inputMode: RNTextInputProps['inputMode'] = undefined
52
62
 
53
- let _inputMode = inputMode
54
- if (type === 'email') {
55
- _inputMode = 'email'
56
- } else if (type === 'tel') {
57
- _inputMode = 'tel'
58
- } else if (type === 'search') {
59
- _inputMode = 'search'
60
- } else if (type === 'url') {
61
- _inputMode = 'url'
62
- } else if (type === 'password') {
63
- secureTextEntry = true
64
- _inputMode = 'text'
65
- } else if (type === 'number') {
66
- _inputMode = 'numeric'
67
- } else {
68
- _inputMode = 'text'
63
+ switch (type) {
64
+ case 'password':
65
+ secureTextEntry = true
66
+ break
67
+ case 'email':
68
+ keyboardType = 'email-address'
69
+ inputMode = 'email'
70
+ break
71
+ case 'tel':
72
+ keyboardType = 'phone-pad'
73
+ inputMode = 'tel'
74
+ break
75
+ case 'number':
76
+ keyboardType = 'numeric'
77
+ inputMode = 'numeric'
78
+ break
79
+ case 'url':
80
+ keyboardType = 'url'
81
+ inputMode = 'url'
82
+ break
83
+ case 'search':
84
+ inputMode = 'search'
85
+ break
69
86
  }
70
87
 
71
- let showSoftInputOnFocus = true
72
- if (inputMode === 'none') {
73
- showSoftInputOnFocus = false
88
+ // Convert enterKeyHint to returnKeyType
89
+ let returnKeyType: RNTextInputProps['returnKeyType'] = undefined
90
+ switch (enterKeyHint) {
91
+ case 'done':
92
+ returnKeyType = 'done'
93
+ break
94
+ case 'go':
95
+ returnKeyType = 'go'
96
+ break
97
+ case 'next':
98
+ returnKeyType = 'next'
99
+ break
100
+ case 'search':
101
+ returnKeyType = 'search'
102
+ break
103
+ case 'send':
104
+ returnKeyType = 'send'
105
+ break
74
106
  }
75
107
 
76
- const finalProps = {
77
- ...rest,
78
- inputMode: _inputMode,
79
- showSoftInputOnFocus,
80
- disabled,
81
- id,
82
- cursorColor,
83
- enterKeyHint: _enterKeyHint,
84
- returnKeyType: _returnKeyType,
85
- secureTextEntry,
86
- numberOfLines: rows || rest.numberOfLines,
87
- } as any
108
+ // Resolve color tokens
109
+ const resolvedPlaceholderColor = placeholderTextColor
110
+ ? getTokenValue(
111
+ theme[placeholderTextColor as any]?.val ?? placeholderTextColor,
112
+ 'color'
113
+ )
114
+ : undefined
115
+
116
+ const resolvedSelectionColor = selectionColor
117
+ ? getTokenValue(theme[selectionColor as any]?.val ?? selectionColor, 'color')
118
+ : undefined
119
+
120
+ // Register focusable
121
+ React.useEffect(() => {
122
+ if (!id || disabled) return
123
+ return registerFocusable(id, {
124
+ focusAndSelect: () => ref.current?.focus(),
125
+ focus: () => ref.current?.focus(),
126
+ })
127
+ }, [id, disabled])
88
128
 
89
- if (tag === 'textarea') {
90
- finalProps.multiline = true
129
+ // Handle web onChange/onInput -> native onChangeText
130
+ const handleChangeText = (text: string) => {
131
+ onChangeText?.(text)
132
+ if (onChange) {
133
+ onChange({ target: { value: text }, type: 'change' } as any)
134
+ }
135
+ if (onInput) {
136
+ onInput({ target: { value: text }, type: 'input' } as any)
137
+ }
91
138
  }
92
139
 
93
- if (onKeyDown) {
94
- finalProps.onKeyPress = (e) => {
140
+ // Handle onKeyDown via onKeyPress + onSubmitEditing
141
+ const handleKeyPress = (e: any) => {
142
+ if (onKeyDown) {
95
143
  const { key } = e.nativeEvent
96
- if (
97
- key === 'Backspace' ||
98
- (tag === 'textarea' && key === 'Enter') ||
99
- key.length === 1
100
- ) {
101
- onKeyDown({
102
- key,
103
- type: 'keydown',
104
- } as any)
144
+ if (key === 'Backspace' || key === 'Enter' || key.length === 1) {
145
+ onKeyDown({ key, type: 'keydown' } as any)
105
146
  }
106
147
  }
107
- finalProps.onSubmitEditing = (e) => {
108
- onKeyDown({
109
- key: 'Enter',
110
- type: 'keydown',
111
- } as any)
112
- }
113
148
  }
114
149
 
115
- if (onChange || onInput) {
116
- finalProps.onChange = (e: NativeSyntheticEvent<TextInputChangeEventData>) => {
117
- const { text } = e.nativeEvent
118
- if (onChange) {
119
- onChange({
120
- target: {
121
- value: text,
122
- },
123
- type: 'change',
124
- } as any)
125
- }
126
- if (onInput != null) {
127
- onInput({
128
- target: {
129
- value: text,
130
- },
131
- type: 'input',
132
- } as any)
133
- }
150
+ const handleSubmitEditing = (e: any) => {
151
+ if (onKeyDown) {
152
+ onKeyDown({ key: 'Enter', type: 'keydown' } as any)
153
+ }
154
+ if (onSubmitEditing) {
155
+ onSubmitEditing(e)
134
156
  }
135
157
  }
136
158
 
137
- React.useEffect(() => {
138
- if (!id) return
139
- if (disabled) return
159
+ // Handle selection change
160
+ const handleSelectionChange = (e: any) => {
161
+ onSelectionChange?.(e)
162
+ }
140
163
 
141
- return registerFocusable(id, {
142
- focusAndSelect: () => {
143
- ref.current?.focus()
144
- },
145
- focus: () => {},
146
- })
147
- }, [id, disabled])
148
- return <StyledInput onChange={(e) => {}} ref={composedRefs} {...finalProps} />
164
+ const finalProps: any = {
165
+ ...rest,
166
+ editable: !disabled && !readOnly,
167
+ secureTextEntry,
168
+ keyboardType,
169
+ inputMode,
170
+ returnKeyType,
171
+ multiline: tag === 'textarea' || (rows && rows > 1),
172
+ numberOfLines: rows,
173
+ selection,
174
+ placeholderTextColor: resolvedPlaceholderColor,
175
+ selectionColor: resolvedSelectionColor,
176
+ onChangeText: handleChangeText,
177
+ onKeyPress: onKeyDown ? handleKeyPress : undefined,
178
+ onSubmitEditing: onKeyDown || onSubmitEditing ? handleSubmitEditing : undefined,
179
+ onSelectionChange: onSelectionChange ? handleSelectionChange : undefined,
180
+ autoComplete: autoComplete as any,
181
+ }
182
+
183
+ return <StyledInput ref={composedRefs} {...finalProps} />
149
184
  })
package/src/Input.tsx CHANGED
@@ -1,148 +1,94 @@
1
- import { View, styled, useComposedRefs, useEvent, useTheme } from '@tamagui/core'
1
+ import { View, styled, useComposedRefs, useTheme } from '@tamagui/core'
2
2
  import { registerFocusable } from '@tamagui/focusable'
3
- import React, { type HTMLAttributes, type HTMLInputTypeAttribute } from 'react'
3
+ import React from 'react'
4
4
  import { styledBody } from './shared'
5
5
  import type { InputProps } from './types'
6
6
 
7
7
  const StyledInput = styled(View, styledBody[0], styledBody[1])
8
8
 
9
9
  /**
10
- * @summary An input is a text field that allows users to enter text.
10
+ * A web-aligned input component.
11
11
  * @see — Docs https://tamagui.dev/ui/inputs#input
12
12
  */
13
- export const Input = StyledInput.styleable<InputProps>((inProps, forwardedRef) => {
13
+ export const Input = StyledInput.styleable<InputProps>((props, forwardedRef) => {
14
14
  const {
15
- // some of destructed props are just to avoid passing them to ...rest because they are not in web.
16
- allowFontScaling,
17
- selectTextOnFocus,
18
- showSoftInputOnFocus,
19
- textContentType,
20
- passwordRules,
21
- textBreakStrategy,
22
- underlineColorAndroid,
23
- selection,
24
- lineBreakStrategyIOS,
25
- returnKeyLabel,
26
15
  disabled,
27
- onSubmitEditing,
28
- caretHidden,
29
- clearButtonMode,
30
- clearTextOnFocus,
31
- contextMenuHidden,
32
- dataDetectorTypes,
33
16
  id,
34
- enablesReturnKeyAutomatically,
35
- importantForAutofill,
36
- inlineImageLeft,
37
- inlineImagePadding,
38
- inputAccessoryViewID,
39
- keyboardAppearance,
40
- keyboardType,
41
- cursorColor,
42
- disableFullscreenUI,
43
- editable,
44
- maxFontSizeMultiplier,
45
- multiline,
46
- numberOfLines,
47
17
  onChangeText,
48
- onContentSizeChange,
49
- onEndEditing,
50
- onScroll,
18
+ onSubmitEditing,
51
19
  onSelectionChange,
52
- caretColor,
20
+ selection,
53
21
  placeholderTextColor,
54
- blurOnSubmit,
55
- enterKeyHint,
56
- returnKeyType,
57
- rejectResponderTermination,
58
- scrollEnabled,
59
- secureTextEntry,
60
22
  selectionColor,
61
- inputMode,
23
+ rows,
62
24
  ...rest
63
- } = inProps
25
+ } = props
64
26
 
65
27
  const ref = React.useRef<HTMLInputElement>(null)
66
28
  const theme = useTheme()
67
-
68
29
  const composedRefs = useComposedRefs(forwardedRef, ref)
69
30
 
70
- const _onSelectionChange = useEvent(() => {
71
- const start = ref.current?.selectionStart ?? 0
72
- const end = ref.current?.selectionEnd ?? 0
73
- onSelectionChange?.({
74
- nativeEvent: {
75
- selection: {
76
- end,
77
- start,
31
+ // Handle selection changes
32
+ React.useEffect(() => {
33
+ if (!onSelectionChange) return
34
+
35
+ const node = ref.current
36
+ if (!node) return
37
+
38
+ const handleSelectionChange = () => {
39
+ onSelectionChange({
40
+ nativeEvent: {
41
+ selection: {
42
+ start: node.selectionStart ?? 0,
43
+ end: node.selectionEnd ?? 0,
44
+ },
78
45
  },
79
- },
80
- } as any)
81
- })
46
+ })
47
+ }
82
48
 
49
+ node.addEventListener('select', handleSelectionChange)
50
+ return () => node.removeEventListener('select', handleSelectionChange)
51
+ }, [onSelectionChange])
52
+
53
+ // Sync selection prop
83
54
  React.useEffect(() => {
84
- if (onSelectionChange) {
85
- ref.current?.addEventListener('selectionchange', _onSelectionChange)
86
- return () => {
87
- ref.current?.removeEventListener('selectionchange', _onSelectionChange)
88
- }
55
+ if (selection && ref.current) {
56
+ ref.current.setSelectionRange(selection.start, selection.end ?? selection.start)
89
57
  }
90
- }, [])
58
+ }, [selection?.start, selection?.end])
91
59
 
60
+ // Register focusable
92
61
  React.useEffect(() => {
93
- if (selection) {
94
- ref.current?.setSelectionRange(selection.start || null, selection.end || null)
62
+ if (!id || disabled) return
63
+ return registerFocusable(id, {
64
+ focusAndSelect: () => ref.current?.focus(),
65
+ focus: () => ref.current?.focus(),
66
+ })
67
+ }, [id, disabled])
68
+
69
+ // Handle keyboard submit
70
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
71
+ if (e.key === 'Enter' && onSubmitEditing) {
72
+ onSubmitEditing({
73
+ nativeEvent: { text: (e.target as HTMLInputElement).value },
74
+ })
95
75
  }
96
- }, [selection?.start, selection?.end])
76
+ rest.onKeyDown?.(e)
77
+ }
78
+
79
+ // Handle change with onChangeText support
80
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
81
+ onChangeText?.(e.target.value)
82
+ rest.onChange?.(e)
83
+ }
97
84
 
98
85
  const finalProps = {
99
86
  ...rest,
100
87
  disabled,
101
- caretColor,
102
88
  id,
103
- enterKeyHint,
104
- ...(process.env.TAMAGUI_TARGET === 'web'
105
- ? {
106
- type: (() => {
107
- if (rest?.type) return rest.type
108
- if (secureTextEntry) return 'password'
109
- switch (keyboardType) {
110
- case 'number-pad':
111
- case 'numeric':
112
- return 'number'
113
- case 'email-address':
114
- return 'email'
115
- case 'phone-pad':
116
- return 'tel'
117
- case 'url':
118
- return 'url'
119
- default:
120
- return 'text'
121
- }
122
- })() satisfies HTMLInputTypeAttribute,
123
- inputMode: (() => {
124
- switch (keyboardType) {
125
- case 'number-pad':
126
- case 'numeric':
127
- return 'numeric'
128
- case 'decimal-pad':
129
- return 'decimal'
130
- case 'email-address':
131
- return 'email'
132
- case 'phone-pad':
133
- return 'tel'
134
- case 'url':
135
- return 'url'
136
- default:
137
- return undefined
138
- }
139
- })() satisfies HTMLAttributes<HTMLInputElement>['inputMode'],
140
- }
141
- : {
142
- keyboardType,
143
- secureTextEntry,
144
- inputMode,
145
- }),
89
+ rows,
90
+ onKeyDown: onSubmitEditing ? handleKeyDown : rest.onKeyDown,
91
+ onChange: onChangeText ? handleChange : rest.onChange,
146
92
  style: {
147
93
  ...(rest.style as any),
148
94
  ...(placeholderTextColor && {
@@ -155,34 +101,18 @@ export const Input = StyledInput.styleable<InputProps>((inProps, forwardedRef) =
155
101
  },
156
102
  } as any
157
103
 
158
- React.useEffect(() => {
159
- if (!id) return
160
- if (disabled) return
161
-
162
- return registerFocusable(id, {
163
- focusAndSelect: () => {
164
- ref.current?.focus()
165
- },
166
- focus: () => {},
167
- })
168
- }, [id, disabled])
169
-
170
104
  return (
171
105
  <>
172
- {process.env.TAMAGUI_TARGET === 'web' && (
173
- <style>
174
- {`
175
- input::selection, textarea::selection {
176
- background-color: var(--selectionBackground) !important;
177
- }
178
-
179
- input::placeholder, textarea::placeholder {
180
- color: var(--placeholderColor) !important;
181
- }
182
- `}
183
- </style>
184
- )}
185
-
106
+ <style>
107
+ {`
108
+ input::selection, textarea::selection {
109
+ background-color: var(--selectionColor) !important;
110
+ }
111
+ input::placeholder, textarea::placeholder {
112
+ color: var(--placeholderColor) !important;
113
+ }
114
+ `}
115
+ </style>
186
116
  <StyledInput ref={composedRefs} {...finalProps} />
187
117
  </>
188
118
  )
package/src/TextArea.tsx CHANGED
@@ -2,8 +2,10 @@ import { styled } from '@tamagui/web'
2
2
  import { Input } from './Input'
3
3
  import { defaultStyles, textAreaSizeVariant } from './shared'
4
4
 
5
+ export type { InputProps as TextAreaProps } from './types'
6
+
5
7
  /**
6
- * @summary A text area is a multi-line input field that allows users to enter text.
8
+ * A web-aligned textarea component (multi-line input).
7
9
  * @see — Docs https://tamagui.dev/ui/inputs#textarea
8
10
  */
9
11
  export const TextArea = styled(Input, {
@@ -19,7 +21,7 @@ export const TextArea = styled(Input, {
19
21
  false: {
20
22
  height: 'auto',
21
23
  ...defaultStyles,
22
- numberOfLines: 3,
24
+ rows: 3,
23
25
  },
24
26
  },
25
27
 
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export * from './Input'
2
2
  export * from './TextArea'
3
3
  export { inputSizeVariant, textAreaSizeVariant } from './shared'
4
- export type { InputProps } from './types'