@tamagui/input 1.97.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.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/Input.js +137 -0
  3. package/dist/cjs/Input.js.map +6 -0
  4. package/dist/cjs/Input.native.js +169 -0
  5. package/dist/cjs/Input.native.js.map +6 -0
  6. package/dist/cjs/TextArea.js +42 -0
  7. package/dist/cjs/TextArea.js.map +6 -0
  8. package/dist/cjs/TextArea.native.js +81 -0
  9. package/dist/cjs/TextArea.native.js.map +6 -0
  10. package/dist/cjs/index.js +16 -0
  11. package/dist/cjs/index.js.map +6 -0
  12. package/dist/cjs/index.native.js +22 -0
  13. package/dist/cjs/index.native.js.map +6 -0
  14. package/dist/cjs/shared.js +109 -0
  15. package/dist/cjs/shared.js.map +6 -0
  16. package/dist/cjs/shared.native.js +152 -0
  17. package/dist/cjs/shared.native.js.map +6 -0
  18. package/dist/cjs/types.js +14 -0
  19. package/dist/cjs/types.js.map +6 -0
  20. package/dist/cjs/types.native.js +15 -0
  21. package/dist/cjs/types.native.js.map +6 -0
  22. package/dist/esm/Input.js +117 -0
  23. package/dist/esm/Input.js.map +6 -0
  24. package/dist/esm/Input.mjs +121 -0
  25. package/dist/esm/Input.native.js +145 -0
  26. package/dist/esm/Input.native.js.map +6 -0
  27. package/dist/esm/TextArea.js +28 -0
  28. package/dist/esm/TextArea.js.map +6 -0
  29. package/dist/esm/TextArea.mjs +25 -0
  30. package/dist/esm/TextArea.native.js +62 -0
  31. package/dist/esm/TextArea.native.js.map +6 -0
  32. package/dist/esm/index.js +3 -0
  33. package/dist/esm/index.js.map +6 -0
  34. package/dist/esm/index.mjs +2 -0
  35. package/dist/esm/index.native.js +3 -0
  36. package/dist/esm/index.native.js.map +6 -0
  37. package/dist/esm/shared.js +97 -0
  38. package/dist/esm/shared.js.map +6 -0
  39. package/dist/esm/shared.mjs +100 -0
  40. package/dist/esm/shared.native.js +131 -0
  41. package/dist/esm/shared.native.js.map +6 -0
  42. package/dist/esm/types.js +1 -0
  43. package/dist/esm/types.js.map +6 -0
  44. package/dist/esm/types.mjs +0 -0
  45. package/dist/esm/types.native.js +1 -0
  46. package/dist/esm/types.native.js.map +6 -0
  47. package/dist/jsx/Input.js +117 -0
  48. package/dist/jsx/Input.js.map +6 -0
  49. package/dist/jsx/Input.mjs +121 -0
  50. package/dist/jsx/Input.native.js +145 -0
  51. package/dist/jsx/Input.native.js.map +6 -0
  52. package/dist/jsx/TextArea.js +28 -0
  53. package/dist/jsx/TextArea.js.map +6 -0
  54. package/dist/jsx/TextArea.mjs +25 -0
  55. package/dist/jsx/TextArea.native.js +62 -0
  56. package/dist/jsx/TextArea.native.js.map +6 -0
  57. package/dist/jsx/index.js +3 -0
  58. package/dist/jsx/index.js.map +6 -0
  59. package/dist/jsx/index.mjs +2 -0
  60. package/dist/jsx/index.native.js +3 -0
  61. package/dist/jsx/index.native.js.map +6 -0
  62. package/dist/jsx/shared.js +97 -0
  63. package/dist/jsx/shared.js.map +6 -0
  64. package/dist/jsx/shared.mjs +100 -0
  65. package/dist/jsx/shared.native.js +131 -0
  66. package/dist/jsx/shared.native.js.map +6 -0
  67. package/dist/jsx/types.js +1 -0
  68. package/dist/jsx/types.js.map +6 -0
  69. package/dist/jsx/types.mjs +0 -0
  70. package/dist/jsx/types.native.js +1 -0
  71. package/dist/jsx/types.native.js.map +6 -0
  72. package/package.json +55 -0
  73. package/src/Input.native.tsx +148 -0
  74. package/src/Input.tsx +142 -0
  75. package/src/TextArea.tsx +27 -0
  76. package/src/index.ts +2 -0
  77. package/src/shared.tsx +129 -0
  78. package/src/types.ts +59 -0
  79. package/types/Input.d.ts +293 -0
  80. package/types/Input.d.ts.map +1 -0
  81. package/types/Input.native.d.ts +295 -0
  82. package/types/Input.native.d.ts.map +1 -0
  83. package/types/TextArea.d.ts +277 -0
  84. package/types/TextArea.d.ts.map +1 -0
  85. package/types/index.d.ts +3 -0
  86. package/types/index.d.ts.map +1 -0
  87. package/types/shared.d.ts +307 -0
  88. package/types/shared.d.ts.map +1 -0
  89. package/types/types.d.ts +40 -0
  90. package/types/types.d.ts.map +1 -0
@@ -0,0 +1,131 @@
1
+ import { validStyles, stylePropsTextOnly } from "@tamagui/core";
2
+ import { getVariableValue, isWeb } from "@tamagui/core";
3
+ import { getButtonSized } from "@tamagui/get-button-sized";
4
+ import { getFontSized } from "@tamagui/get-font-sized";
5
+ import { getSpace } from "@tamagui/get-token";
6
+ function _define_property(obj, key, value) {
7
+ return key in obj ? Object.defineProperty(obj, key, {
8
+ value,
9
+ enumerable: !0,
10
+ configurable: !0,
11
+ writable: !0
12
+ }) : obj[key] = value, obj;
13
+ }
14
+ function _object_spread(target) {
15
+ for (var i = 1; i < arguments.length; i++) {
16
+ var source = arguments[i] != null ? arguments[i] : {}, ownKeys2 = Object.keys(source);
17
+ typeof Object.getOwnPropertySymbols == "function" && (ownKeys2 = ownKeys2.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
18
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
19
+ }))), ownKeys2.forEach(function(key) {
20
+ _define_property(target, key, source[key]);
21
+ });
22
+ }
23
+ return target;
24
+ }
25
+ function ownKeys(object, enumerableOnly) {
26
+ var keys = Object.keys(object);
27
+ if (Object.getOwnPropertySymbols) {
28
+ var symbols = Object.getOwnPropertySymbols(object);
29
+ enumerableOnly && (symbols = symbols.filter(function(sym) {
30
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
31
+ })), keys.push.apply(keys, symbols);
32
+ }
33
+ return keys;
34
+ }
35
+ function _object_spread_props(target, source) {
36
+ return source = source ?? {}, Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function(key) {
37
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
38
+ }), target;
39
+ }
40
+ var defaultStyles = _object_spread_props(_object_spread({
41
+ size: "$true",
42
+ fontFamily: "$body",
43
+ borderWidth: 1,
44
+ outlineWidth: 0,
45
+ color: "$color"
46
+ }, isWeb ? {
47
+ tabIndex: 0
48
+ } : {
49
+ focusable: !0
50
+ }), {
51
+ borderColor: "$borderColor",
52
+ backgroundColor: "$background",
53
+ // this fixes a flex bug where it overflows container
54
+ minWidth: 0,
55
+ hoverStyle: {
56
+ borderColor: "$borderColorHover"
57
+ },
58
+ focusStyle: {
59
+ borderColor: "$borderColorFocus"
60
+ },
61
+ focusVisibleStyle: {
62
+ outlineColor: "$outlineColor",
63
+ outlineWidth: 2,
64
+ outlineStyle: "solid"
65
+ }
66
+ }), inputSizeVariant = function() {
67
+ var val = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "$true", extras = arguments.length > 1 ? arguments[1] : void 0;
68
+ if (extras.props.multiline || extras.props.numberOfLines > 1)
69
+ return textAreaSizeVariant(val, extras);
70
+ var buttonStyles = getButtonSized(val, extras), paddingHorizontal = getSpace(val, {
71
+ shift: -1,
72
+ bounds: [
73
+ 2
74
+ ]
75
+ }), fontStyle = getFontSized(val, extras);
76
+ return !isWeb && fontStyle && delete fontStyle.lineHeight, _object_spread_props(_object_spread({}, fontStyle, buttonStyles), {
77
+ paddingHorizontal
78
+ });
79
+ }, textAreaSizeVariant = function() {
80
+ var val = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "$true", extras = arguments.length > 1 ? arguments[1] : void 0, props = extras.props, buttonStyles = getButtonSized(val, extras), fontStyle = getFontSized(val, extras), _props_rows, lines = (_props_rows = props.rows) !== null && _props_rows !== void 0 ? _props_rows : props.numberOfLines, height = typeof lines == "number" ? lines * getVariableValue(fontStyle.lineHeight) : "auto", paddingVertical = getSpace(val, {
81
+ shift: -2,
82
+ bounds: [
83
+ 2
84
+ ]
85
+ }), paddingHorizontal = getSpace(val, {
86
+ shift: -1,
87
+ bounds: [
88
+ 2
89
+ ]
90
+ });
91
+ return _object_spread_props(_object_spread({}, buttonStyles, fontStyle), {
92
+ paddingVertical,
93
+ paddingHorizontal,
94
+ height
95
+ });
96
+ }, INPUT_NAME = "Input", styledBody = [
97
+ {
98
+ name: INPUT_NAME,
99
+ tag: "input",
100
+ variants: {
101
+ unstyled: {
102
+ false: defaultStyles
103
+ },
104
+ size: {
105
+ "...size": inputSizeVariant
106
+ },
107
+ disabled: {
108
+ true: {}
109
+ }
110
+ },
111
+ defaultVariants: {
112
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
113
+ }
114
+ },
115
+ {
116
+ isInput: !0,
117
+ accept: {
118
+ placeholderTextColor: "color",
119
+ selectionColor: "color"
120
+ },
121
+ validStyles: _object_spread({}, validStyles, stylePropsTextOnly)
122
+ }
123
+ ];
124
+ export {
125
+ INPUT_NAME,
126
+ defaultStyles,
127
+ inputSizeVariant,
128
+ styledBody,
129
+ textAreaSizeVariant
130
+ };
131
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/Users/n8/tamagui/packages/input/src/shared.tsx"],
4
+ "mappings": "AACA,SAASA,aAAaC,0BAA0B;AAChD,SAASC,kBAAkBC,aAAa;AACxC,SAASC,sBAAsB;AAC/B,SAASC,oBAAoB;AAC7B,SAASC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAElB,IAAMC,gBAAgB,qBAAA,eAAA;EAC3BC,MAAM;EACNC,YAAY;EACZC,aAAa;EACbC,cAAc;EACdC,OAAO;GAEHT,QACA;EACEU,UAAU;AACZ,IACA;EACEC,WAAW;AACb,CAAA,GAAA;EAEJC,aAAa;EACbC,iBAAiB;;EAGjBC,UAAU;EAEVC,YAAY;IACVH,aAAa;EACf;EAEAI,YAAY;IACVJ,aAAa;EACf;EAEAK,mBAAmB;IACjBC,cAAc;IACdV,cAAc;IACdW,cAAc;EAChB;IAGWC,mBAAmD,WAAA;MAC9DC,MAAAA,UAAAA,SAAAA,KAAAA,UAAAA,CAAAA,MAAAA,SAAAA,UAAAA,CAAAA,IAAM,SACNC,SAAAA,UAAAA,SAAAA,IAAAA,UAAAA,CAAAA,IAAAA;AAEA,MAAIA,OAAOC,MAAMC,aAAaF,OAAOC,MAAME,gBAAgB;AACzD,WAAOC,oBAAoBL,KAAKC,MAAAA;AAElC,MAAMK,eAAe1B,eAAeoB,KAAKC,MAAAA,GACnCM,oBAAoBzB,SAASkB,KAAK;IACtCQ,OAAO;IACPC,QAAQ;MAAC;;EACX,CAAA,GACMC,YAAY7B,aAAamB,KAAYC,MAAAA;AAE3C,SAAI,CAACtB,SAAS+B,aACZ,OAAOA,UAAU,YAEZ,qBAAA,eAAA,CAAA,GACFA,WACAJ,YAAAA,GAAAA;IACHC;;AAEJ,GAEaF,sBAAsD,WAAA;MACjEL,MAAAA,UAAAA,SAAAA,KAAAA,UAAAA,CAAAA,MAAAA,SAAAA,UAAAA,CAAAA,IAAM,SACNC,SAAAA,UAAAA,SAAAA,IAAAA,UAAAA,CAAAA,IAAAA,QAEQC,QAAUD,OAAVC,OACFI,eAAe1B,eAAeoB,KAAKC,MAAAA,GACnCS,YAAY7B,aAAamB,KAAYC,MAAAA,GAC7BC,aAARS,SAAQT,cAAAA,MAAMU,UAAI,QAAVV,gBAAAA,SAAAA,cAAcA,MAAME,eAC5BS,SACJ,OAAOF,SAAU,WAAWA,QAAQjC,iBAAiBgC,UAAUI,UAAU,IAAI,QACzEC,kBAAkBjC,SAASkB,KAAK;IACpCQ,OAAO;IACPC,QAAQ;MAAC;;EACX,CAAA,GACMF,oBAAoBzB,SAASkB,KAAK;IACtCQ,OAAO;IACPC,QAAQ;MAAC;;EACX,CAAA;AACA,SAAO,qBAAA,eAAA,CAAA,GACFH,cACAI,SAAAA,GAAAA;IACHK;IACAR;IACAM;;AAEJ,GACaG,aAAa,SAEbC,aAAa;EACxB;IACEC,MAAMF;IACNG,KAAK;IACLC,UAAU;MACRC,UAAU;QACRC,OAAOvC;MACT;MAEAC,MAAM;QACJ,WAAWe;MACb;MAEAwB,UAAU;QACRC,MAAM,CAAC;MACT;IACF;IAEAC,iBAAiB;MACfJ,UAAUK,QAAQC,IAAIC,qBAAqB;IAC7C;EACF;EACA;IACEC,SAAS;IACTC,QAAQ;MACNC,sBAAsB;MACtBC,gBAAgB;IAClB;IACAxD,aAAa,eAAA,CAAA,GACRA,aACAC,kBAAAA;EAEP;;",
5
+ "names": ["validStyles", "stylePropsTextOnly", "getVariableValue", "isWeb", "getButtonSized", "getFontSized", "getSpace", "defaultStyles", "size", "fontFamily", "borderWidth", "outlineWidth", "color", "tabIndex", "focusable", "borderColor", "backgroundColor", "minWidth", "hoverStyle", "focusStyle", "focusVisibleStyle", "outlineColor", "outlineStyle", "inputSizeVariant", "val", "extras", "props", "multiline", "numberOfLines", "textAreaSizeVariant", "buttonStyles", "paddingHorizontal", "shift", "bounds", "fontStyle", "lines", "rows", "height", "lineHeight", "paddingVertical", "INPUT_NAME", "styledBody", "name", "tag", "variants", "unstyled", "false", "disabled", "true", "defaultVariants", "process", "env", "TAMAGUI_HEADLESS", "isInput", "accept", "placeholderTextColor", "selectionColor"]
6
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "mappings": "",
5
+ "names": []
6
+ }
File without changes
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "mappings": "",
5
+ "names": []
6
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@tamagui/input",
3
+ "version": "1.97.0",
4
+ "sideEffects": [
5
+ "*.css"
6
+ ],
7
+ "source": "src/index.ts",
8
+ "types": "./types/index.d.ts",
9
+ "main": "dist/cjs",
10
+ "module": "dist/esm",
11
+ "module:jsx": "dist/jsx",
12
+ "files": [
13
+ "src",
14
+ "types",
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tamagui-build",
19
+ "watch": "tamagui-build --watch",
20
+ "lint": "../../node_modules/.bin/biome check src",
21
+ "lint:fix": "../../node_modules/.bin/biome check --apply-unsafe src",
22
+ "clean": "tamagui-build clean",
23
+ "clean:build": "tamagui-build clean:build"
24
+ },
25
+ "exports": {
26
+ "./package.json": "./package.json",
27
+ ".": {
28
+ "types": "./types/index.d.ts",
29
+ "import": "./dist/esm/index.mjs",
30
+ "require": "./dist/cjs/index.js",
31
+ "react-native": "./dist/cjs/index.native.js"
32
+ }
33
+ },
34
+ "dependencies": {
35
+ "@tamagui/font-size": "1.97.0",
36
+ "@tamagui/get-button-sized": "1.97.0",
37
+ "@tamagui/helpers": "1.97.0",
38
+ "@tamagui/helpers-tamagui": "1.97.0",
39
+ "@tamagui/stacks": "1.97.0",
40
+ "@tamagui/text": "1.97.0",
41
+ "@tamagui/web": "1.97.0"
42
+ },
43
+ "peerDependencies": {
44
+ "react": "*"
45
+ },
46
+ "devDependencies": {
47
+ "@tamagui/build": "1.97.0",
48
+ "react": "^18.2.0",
49
+ "vitest": "^0.34.3"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14"
55
+ }
@@ -0,0 +1,148 @@
1
+ import { styled, useComposedRefs } from '@tamagui/core'
2
+ import { registerFocusable } from '@tamagui/focusable'
3
+ import React, { useEffect } from 'react'
4
+ import type { NativeSyntheticEvent, TextInputChangeEventData } from 'react-native'
5
+ import { TextInput } from 'react-native'
6
+ import { styledBody } from './shared'
7
+ import type { InputProps } from './types'
8
+ const StyledInput = styled(TextInput, styledBody[0], styledBody[1])
9
+
10
+ export const Input = StyledInput.styleable<InputProps>((inProps, forwardedRef) => {
11
+ const {
12
+ // some of destructed props are just to avoid passing them to ...rest because they are not in native.
13
+ type,
14
+ //@ts-ignore
15
+ dirname,
16
+ max,
17
+ min,
18
+ minLength,
19
+ multiple,
20
+ name,
21
+ required,
22
+ step,
23
+ disabled,
24
+ id,
25
+ caretColor,
26
+ onChange,
27
+ onInput,
28
+ rows,
29
+ enterKeyHint,
30
+ returnKeyType,
31
+ onKeyDown,
32
+ inputMode,
33
+ tag,
34
+ ...rest
35
+ } = inProps
36
+
37
+ const ref = React.useRef<HTMLInputElement>(null)
38
+
39
+ const composedRefs = useComposedRefs<any>(forwardedRef, ref)
40
+
41
+ // TODO: later move most of the logic to the core package
42
+
43
+ let secureTextEntry = false
44
+ let cursorColor = caretColor
45
+ let _returnKeyType = returnKeyType
46
+ let _enterKeyHint = enterKeyHint
47
+ if (enterKeyHint === 'go') {
48
+ _returnKeyType = 'go'
49
+ _enterKeyHint = undefined
50
+ }
51
+
52
+ let _inputMode = inputMode
53
+ if (type === 'email') {
54
+ _inputMode = 'email'
55
+ } else if (type === 'tel') {
56
+ _inputMode = 'tel'
57
+ } else if (type === 'search') {
58
+ _inputMode = 'search'
59
+ } else if (type === 'url') {
60
+ _inputMode = 'url'
61
+ } else if (type === 'password') {
62
+ secureTextEntry = true
63
+ _inputMode = 'text'
64
+ } else if (type === 'number') {
65
+ _inputMode = 'numeric'
66
+ } else {
67
+ _inputMode = 'text'
68
+ }
69
+
70
+ let showSoftInputOnFocus = true
71
+ if (inputMode === 'none') {
72
+ showSoftInputOnFocus = false
73
+ }
74
+
75
+ const finalProps = {
76
+ ...rest,
77
+ inputMode: _inputMode,
78
+ showSoftInputOnFocus,
79
+ disabled,
80
+ id,
81
+ cursorColor,
82
+ enterKeyHint: _enterKeyHint,
83
+ returnKeyType: _returnKeyType,
84
+ secureTextEntry,
85
+ numberOfLines: rows || rest.numberOfLines,
86
+ } as any
87
+
88
+ if (tag === 'textarea') {
89
+ finalProps.multiline = true
90
+ }
91
+
92
+ if (onKeyDown) {
93
+ finalProps.onKeyPress = (e) => {
94
+ const { key } = e.nativeEvent
95
+ if (
96
+ key === 'Backspace' ||
97
+ (tag === 'textarea' && key === 'Enter') ||
98
+ key.length === 1
99
+ ) {
100
+ onKeyDown({
101
+ key,
102
+ type: 'keydown',
103
+ } as any)
104
+ }
105
+ }
106
+ finalProps.onSubmitEditing = (e) => {
107
+ onKeyDown({
108
+ key: 'Enter',
109
+ type: 'keydown',
110
+ } as any)
111
+ }
112
+ }
113
+
114
+ if (onChange || onInput) {
115
+ finalProps.onChange = (e: NativeSyntheticEvent<TextInputChangeEventData>) => {
116
+ const { text } = e.nativeEvent
117
+ if (onChange) {
118
+ onChange({
119
+ target: {
120
+ value: text,
121
+ },
122
+ type: 'change',
123
+ } as any)
124
+ }
125
+ if (onInput != null) {
126
+ onInput({
127
+ target: {
128
+ value: text,
129
+ },
130
+ type: 'input',
131
+ } as any)
132
+ }
133
+ }
134
+ }
135
+
136
+ useEffect(() => {
137
+ if (!id) return
138
+ if (disabled) return
139
+
140
+ return registerFocusable(id, {
141
+ focusAndSelect: () => {
142
+ ref.current?.focus()
143
+ },
144
+ focus: () => {},
145
+ })
146
+ }, [id, disabled])
147
+ return <StyledInput onChange={(e) => {}} ref={composedRefs} {...finalProps} />
148
+ })
package/src/Input.tsx ADDED
@@ -0,0 +1,142 @@
1
+ import { View, styled, useComposedRefs, useEvent, useTheme } from '@tamagui/core'
2
+ import { registerFocusable } from '@tamagui/focusable'
3
+ import React, { useEffect } from 'react'
4
+ import { styledBody } from './shared'
5
+ import type { InputProps } from './types'
6
+ const StyledInput = styled(View, styledBody[0], styledBody[1])
7
+
8
+ export const Input = StyledInput.styleable<InputProps>((inProps, forwardedRef) => {
9
+ const {
10
+ // some of destructed props are just to avoid passing them to ...rest because they are not in web.
11
+ allowFontScaling,
12
+ selectTextOnFocus,
13
+ showSoftInputOnFocus,
14
+ textContentType,
15
+ passwordRules,
16
+ textBreakStrategy,
17
+ underlineColorAndroid,
18
+ selection,
19
+ lineBreakStrategyIOS,
20
+ returnKeyLabel,
21
+ disabled,
22
+ onSubmitEditing,
23
+ caretHidden,
24
+ clearButtonMode,
25
+ clearTextOnFocus,
26
+ contextMenuHidden,
27
+ dataDetectorTypes,
28
+ id,
29
+ enablesReturnKeyAutomatically,
30
+ importantForAutofill,
31
+ inlineImageLeft,
32
+ inlineImagePadding,
33
+ inputAccessoryViewID,
34
+ keyboardAppearance,
35
+ keyboardType,
36
+ cursorColor,
37
+ disableFullscreenUI,
38
+ editable,
39
+ maxFontSizeMultiplier,
40
+ multiline,
41
+ numberOfLines,
42
+ onChangeText,
43
+ onContentSizeChange,
44
+ onEndEditing,
45
+ onScroll,
46
+ onSelectionChange,
47
+ caretColor,
48
+ placeholderTextColor,
49
+ blurOnSubmit,
50
+ enterKeyHint,
51
+ returnKeyType,
52
+ rejectResponderTermination,
53
+ scrollEnabled,
54
+ secureTextEntry,
55
+ selectionColor,
56
+ inputMode,
57
+ ...rest
58
+ } = inProps
59
+
60
+ const ref = React.useRef<HTMLInputElement>(null)
61
+ const theme = useTheme()
62
+
63
+ const composedRefs = useComposedRefs(forwardedRef, ref)
64
+
65
+ const _onSelectionChange = useEvent(() => {
66
+ const start = ref.current?.selectionStart ?? 0
67
+ const end = ref.current?.selectionEnd ?? 0
68
+ onSelectionChange?.({
69
+ nativeEvent: {
70
+ selection: {
71
+ end,
72
+ start,
73
+ },
74
+ },
75
+ } as any)
76
+ })
77
+
78
+ useEffect(() => {
79
+ if (onSelectionChange) {
80
+ ref.current?.addEventListener('selectionchange', _onSelectionChange)
81
+ return () => {
82
+ ref.current?.removeEventListener('selectionchange', _onSelectionChange)
83
+ }
84
+ }
85
+ }, [])
86
+
87
+ useEffect(() => {
88
+ if (selection) {
89
+ ref.current?.setSelectionRange(selection.start || null, selection.end || null)
90
+ }
91
+ }, [selection?.start, selection?.end])
92
+
93
+ const finalProps = {
94
+ ...rest,
95
+ inputMode,
96
+ disabled,
97
+ caretColor,
98
+ id,
99
+ enterKeyHint,
100
+ style: {
101
+ ...(rest.style as any),
102
+ ...(placeholderTextColor && {
103
+ '--placeholderColor':
104
+ theme[placeholderTextColor]?.variable || placeholderTextColor,
105
+ }),
106
+ ...(selectionColor && {
107
+ '--selectionColor': theme[selectionColor]?.variable || selectionColor,
108
+ }),
109
+ },
110
+ } as any
111
+
112
+ useEffect(() => {
113
+ if (!id) return
114
+ if (disabled) return
115
+
116
+ return registerFocusable(id, {
117
+ focusAndSelect: () => {
118
+ ref.current?.focus()
119
+ },
120
+ focus: () => {},
121
+ })
122
+ }, [id, disabled])
123
+
124
+ return (
125
+ <>
126
+ {process.env.TAMAGUI_TARGET === 'web' && (
127
+ <style>
128
+ {`
129
+ input::selection, textarea::selection {
130
+ background-color: var(--selectionBackground) !important;
131
+ }
132
+
133
+ input::placeholder, textarea::placeholder {
134
+ color: var(--placeholderColor) !important;
135
+ }
136
+ `}
137
+ </style>
138
+ )}
139
+ <StyledInput ref={composedRefs} {...finalProps} />
140
+ </>
141
+ )
142
+ })
@@ -0,0 +1,27 @@
1
+ import { styled } from '@tamagui/web'
2
+ import { Input } from './Input'
3
+ import { defaultStyles, textAreaSizeVariant } from './shared'
4
+ export const TextArea = styled(Input, {
5
+ name: 'TextArea',
6
+ tag: 'textarea',
7
+ // this attribute fixes firefox newline issue
8
+ whiteSpace: 'pre-wrap',
9
+
10
+ variants: {
11
+ unstyled: {
12
+ false: {
13
+ height: 'auto',
14
+ ...defaultStyles,
15
+ numberOfLines: 3,
16
+ },
17
+ },
18
+
19
+ size: {
20
+ '...size': textAreaSizeVariant,
21
+ },
22
+ } as const,
23
+
24
+ defaultVariants: {
25
+ unstyled: process.env.TAMAGUI_HEADLESS === '1',
26
+ },
27
+ })
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './Input'
2
+ export * from './TextArea'
package/src/shared.tsx ADDED
@@ -0,0 +1,129 @@
1
+ import type { SizeVariantSpreadFunction } from '@tamagui/core'
2
+ import { validStyles, stylePropsTextOnly } from '@tamagui/core'
3
+ import { getVariableValue, isWeb } from '@tamagui/core'
4
+ import { getButtonSized } from '@tamagui/get-button-sized'
5
+ import { getFontSized } from '@tamagui/get-font-sized'
6
+ import { getSpace } from '@tamagui/get-token'
7
+
8
+ export const defaultStyles = {
9
+ size: '$true',
10
+ fontFamily: '$body',
11
+ borderWidth: 1,
12
+ outlineWidth: 0,
13
+ color: '$color',
14
+
15
+ ...(isWeb
16
+ ? {
17
+ tabIndex: 0,
18
+ }
19
+ : {
20
+ focusable: true,
21
+ }),
22
+
23
+ borderColor: '$borderColor',
24
+ backgroundColor: '$background',
25
+
26
+ // this fixes a flex bug where it overflows container
27
+ minWidth: 0,
28
+
29
+ hoverStyle: {
30
+ borderColor: '$borderColorHover',
31
+ },
32
+
33
+ focusStyle: {
34
+ borderColor: '$borderColorFocus',
35
+ },
36
+
37
+ focusVisibleStyle: {
38
+ outlineColor: '$outlineColor',
39
+ outlineWidth: 2,
40
+ outlineStyle: 'solid',
41
+ },
42
+ } as const
43
+
44
+ export const inputSizeVariant: SizeVariantSpreadFunction<any> = (
45
+ val = '$true',
46
+ extras
47
+ ) => {
48
+ if (extras.props.multiline || extras.props.numberOfLines > 1) {
49
+ return textAreaSizeVariant(val, extras)
50
+ }
51
+ const buttonStyles = getButtonSized(val, extras)
52
+ const paddingHorizontal = getSpace(val, {
53
+ shift: -1,
54
+ bounds: [2],
55
+ })
56
+ const fontStyle = getFontSized(val as any, extras)
57
+ // lineHeight messes up input on native
58
+ if (!isWeb && fontStyle) {
59
+ delete fontStyle['lineHeight']
60
+ }
61
+ return {
62
+ ...fontStyle,
63
+ ...buttonStyles,
64
+ paddingHorizontal,
65
+ }
66
+ }
67
+
68
+ export const textAreaSizeVariant: SizeVariantSpreadFunction<any> = (
69
+ val = '$true',
70
+ extras
71
+ ) => {
72
+ const { props } = extras
73
+ const buttonStyles = getButtonSized(val, extras)
74
+ const fontStyle = getFontSized(val as any, extras)!
75
+ const lines = props.rows ?? props.numberOfLines
76
+ const height =
77
+ typeof lines === 'number' ? lines * getVariableValue(fontStyle.lineHeight) : 'auto'
78
+ const paddingVertical = getSpace(val, {
79
+ shift: -2,
80
+ bounds: [2],
81
+ })
82
+ const paddingHorizontal = getSpace(val, {
83
+ shift: -1,
84
+ bounds: [2],
85
+ })
86
+ return {
87
+ ...buttonStyles,
88
+ ...fontStyle,
89
+ paddingVertical,
90
+ paddingHorizontal,
91
+ height,
92
+ }
93
+ }
94
+ export const INPUT_NAME = 'Input'
95
+
96
+ export const styledBody = [
97
+ {
98
+ name: INPUT_NAME,
99
+ tag: 'input',
100
+ variants: {
101
+ unstyled: {
102
+ false: defaultStyles,
103
+ },
104
+
105
+ size: {
106
+ '...size': inputSizeVariant,
107
+ },
108
+
109
+ disabled: {
110
+ true: {},
111
+ },
112
+ } as const,
113
+
114
+ defaultVariants: {
115
+ unstyled: process.env.TAMAGUI_HEADLESS === '1',
116
+ },
117
+ },
118
+ {
119
+ isInput: true,
120
+ accept: {
121
+ placeholderTextColor: 'color',
122
+ selectionColor: 'color',
123
+ } as const,
124
+ validStyles: {
125
+ ...validStyles,
126
+ ...stylePropsTextOnly,
127
+ },
128
+ },
129
+ ]