@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.
- package/LICENSE +21 -0
- package/dist/cjs/Input.js +137 -0
- package/dist/cjs/Input.js.map +6 -0
- package/dist/cjs/Input.native.js +169 -0
- package/dist/cjs/Input.native.js.map +6 -0
- package/dist/cjs/TextArea.js +42 -0
- package/dist/cjs/TextArea.js.map +6 -0
- package/dist/cjs/TextArea.native.js +81 -0
- package/dist/cjs/TextArea.native.js.map +6 -0
- package/dist/cjs/index.js +16 -0
- package/dist/cjs/index.js.map +6 -0
- package/dist/cjs/index.native.js +22 -0
- package/dist/cjs/index.native.js.map +6 -0
- package/dist/cjs/shared.js +109 -0
- package/dist/cjs/shared.js.map +6 -0
- package/dist/cjs/shared.native.js +152 -0
- package/dist/cjs/shared.native.js.map +6 -0
- package/dist/cjs/types.js +14 -0
- package/dist/cjs/types.js.map +6 -0
- package/dist/cjs/types.native.js +15 -0
- package/dist/cjs/types.native.js.map +6 -0
- package/dist/esm/Input.js +117 -0
- package/dist/esm/Input.js.map +6 -0
- package/dist/esm/Input.mjs +121 -0
- package/dist/esm/Input.native.js +145 -0
- package/dist/esm/Input.native.js.map +6 -0
- package/dist/esm/TextArea.js +28 -0
- package/dist/esm/TextArea.js.map +6 -0
- package/dist/esm/TextArea.mjs +25 -0
- package/dist/esm/TextArea.native.js +62 -0
- package/dist/esm/TextArea.native.js.map +6 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +6 -0
- package/dist/esm/index.mjs +2 -0
- package/dist/esm/index.native.js +3 -0
- package/dist/esm/index.native.js.map +6 -0
- package/dist/esm/shared.js +97 -0
- package/dist/esm/shared.js.map +6 -0
- package/dist/esm/shared.mjs +100 -0
- package/dist/esm/shared.native.js +131 -0
- package/dist/esm/shared.native.js.map +6 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +6 -0
- package/dist/esm/types.mjs +0 -0
- package/dist/esm/types.native.js +1 -0
- package/dist/esm/types.native.js.map +6 -0
- package/dist/jsx/Input.js +117 -0
- package/dist/jsx/Input.js.map +6 -0
- package/dist/jsx/Input.mjs +121 -0
- package/dist/jsx/Input.native.js +145 -0
- package/dist/jsx/Input.native.js.map +6 -0
- package/dist/jsx/TextArea.js +28 -0
- package/dist/jsx/TextArea.js.map +6 -0
- package/dist/jsx/TextArea.mjs +25 -0
- package/dist/jsx/TextArea.native.js +62 -0
- package/dist/jsx/TextArea.native.js.map +6 -0
- package/dist/jsx/index.js +3 -0
- package/dist/jsx/index.js.map +6 -0
- package/dist/jsx/index.mjs +2 -0
- package/dist/jsx/index.native.js +3 -0
- package/dist/jsx/index.native.js.map +6 -0
- package/dist/jsx/shared.js +97 -0
- package/dist/jsx/shared.js.map +6 -0
- package/dist/jsx/shared.mjs +100 -0
- package/dist/jsx/shared.native.js +131 -0
- package/dist/jsx/shared.native.js.map +6 -0
- package/dist/jsx/types.js +1 -0
- package/dist/jsx/types.js.map +6 -0
- package/dist/jsx/types.mjs +0 -0
- package/dist/jsx/types.native.js +1 -0
- package/dist/jsx/types.native.js.map +6 -0
- package/package.json +55 -0
- package/src/Input.native.tsx +148 -0
- package/src/Input.tsx +142 -0
- package/src/TextArea.tsx +27 -0
- package/src/index.ts +2 -0
- package/src/shared.tsx +129 -0
- package/src/types.ts +59 -0
- package/types/Input.d.ts +293 -0
- package/types/Input.d.ts.map +1 -0
- package/types/Input.native.d.ts +295 -0
- package/types/Input.native.d.ts.map +1 -0
- package/types/TextArea.d.ts +277 -0
- package/types/TextArea.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
- package/types/shared.d.ts +307 -0
- package/types/shared.d.ts.map +1 -0
- package/types/types.d.ts +40 -0
- 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
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
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
|
+
})
|
package/src/TextArea.tsx
ADDED
|
@@ -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
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
|
+
]
|