fix(react,vue): add TextInput color parser

This commit is contained in:
zoomchan-cxj
2022-03-29 10:45:03 +08:00
parent 5a26e2ee7e
commit f9f0e2b963
16 changed files with 84 additions and 48 deletions
+4 -5
View File
@@ -305,7 +305,7 @@ import icon from './qb_icon_new.png';
| 参数 | 描述 | 类型 | 支持平台 |
| --------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | --------- |
| caretColor | 输入光标颜色。 `最低支持版本2.11.5` | [`color`](style/color.md) | `Android` |
| caretColor | 输入光标颜色。(也可设置为 Style 属性) `最低支持版本2.11.5` | [`color`](style/color.md) | `Android` |
| defaultValue | 提供一个文本框中的初始值。当用户开始输入的时候,值就可以改变。 在一些简单的使用情形下,如果你不想用监听消息然后更新 value 属性的方法来保持属性和状态同步的时候,就可以用 defaultValue 来代替。 | `string` | `ALL` |
| editable | 如果为 false,文本框是不可编辑的。 | `boolean` | `ALL` |
| keyboardType | 决定弹出的何种软键盘的。 注意,`password`仅在属性 `multiline=false` 单行文本框时生效。 | `enum(default, numeric, password, email, phone-pad)` | `ALL` |
@@ -319,10 +319,9 @@ import icon from './qb_icon_new.png';
| onLayout | 当组件挂载或者布局变化的时候调用,参数为`{ x, y, width, height }`。 | `Function` | `ALL` |
| onSelectionChange | 当输入框选择文字的范围被改变时调用。返回参数的样式如 `{ nativeEvent: { selection: { start, end } } }`。 | `Function` | `ALL` |
| placeholder | 如果没有任何文字输入,会显示此字符串。 | `string` | `ALL` |
| placeholderTextColor | 占位字符串显示的文字颜色。 | [`color`](style/color.md) | `ALL` |
| placeholderTextColors | - | [`color`](style/color.md) | `ALL` |
| placeholderTextColor | 占位字符串显示的文字颜色。(也可设置为 Style 属性)`最低支持版本2.13.4` | [`color`](style/color.md) | `ALL` |
| returnKeyType | 指定软键盘的回车键显示的样式。 | `enum(done, go, next, search, send)` | `ALL` |
| underlineColorAndroid | `TextInput` 下底线的颜色。 可以设置为'transparent'来去掉下底线。 | `string` | `Android` |
| underlineColorAndroid | `TextInput` 下底线的颜色。 可以设置为 'transparent' 来去掉下底线。(也可设置为 Style 属性) | [`color`](style/color.md) | `Android` |
| value | 指定 `TextInput` 组件的值。 | `string` | `ALL` |
| autoFocus | 组件渲染时自动获得焦点。 | `boolean` | `ALL` |
@@ -431,7 +430,7 @@ import icon from './qb_icon_new.png';
| 参数 | 描述 | 类型 | 支持平台 |
| ------------------ | ------------------------------------------------------------ | ------------------------------------ | --------- |
| collapsable | Android 里如果一个 `View` 只用于布局它的子组件,则它可能会为了优化而从原生布局树中移除,因此该节点 DOM 的引用会丢失 `(比如调用 measureInAppWindow 无法获取到大小和位置信息)`。 把此属性设为 `false` 可以禁用这个优化,以确保对应视图在原生结构中存在。 | `boolean` | `Android` |
| collapsable | Android 里如果一个 `View` 只用于布局它的子组件,则它可能会为了优化而从原生布局树中移除,因此该节点 DOM 的引用会丢失 `(比如调用 measureInAppWindow 无法获取到大小和位置信息)`。 把此属性设为 `false` 可以禁用这个优化,以确保对应视图在原生结构中存在。(也可设置为 Attribute 属性) | `boolean` | `Android` |
## 方法
+5 -4
View File
@@ -69,7 +69,7 @@
| 参数 | 描述 | 类型 | 支持平台 |
| ------------------ | ------------------------------------------------------------ | ------------------------------------ | --------- |
| collapsable | 如果一个 `div` 只用于布局它的子组件,则它可能会为了优化而从原生布局树中移除,因此该节点 DOM 的引用会丢失`(比如调用 measureInAppWindow 无法获取到大小和位置信息)`。 把此属性设为 `false` 可以禁用这个优化,以确保对应视图在原生结构中存在。 | `boolean` | `Android` |
| collapsable | 如果一个 `div` 只用于布局它的子组件,则它可能会为了优化而从原生布局树中移除,因此该节点 DOM 的引用会丢失`(比如调用 measureInAppWindow 无法获取到大小和位置信息)`。 把此属性设为 `false` 可以禁用这个优化,以确保对应视图在原生结构中存在。(也可设置为 Attribute 属性) | `boolean` | `Android` |
---
@@ -246,14 +246,15 @@
| 参数 | 描述 | 类型 | 支持平台 |
| --------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | --------- |
| caret-color | 输入光标颜色。 `最低支持版本2.11.5` | [`color`](style/color.md) | `Android` |
| caret-color | 输入光标颜色。(也可设置为 Style 属性) `最低支持版本2.11.5` | [`color`](style/color.md) | `Android` |
| defaultValue | 提供一个文本框中的初始值。当用户开始输入的时候,值就可以改变。 在一些简单的使用情形下,如果你不想用监听消息然后更新 value 属性的方法来保持属性和状态同步的时候,就可以用 defaultValue 来代替。 | `string` | `ALL` |
| disabled | 如果为 true | `boolean` | `ALL` |
| type | 决定弹出的何种软键盘的。 注意,`password`仅在属性 `multiline=false` 单行文本框时生效。 | `enum(default, numeric, password, email, phone-pad)` | `ALL` |
| maxlength | 限制文本框中最多的字符数。使用这个属性而不用JS 逻辑去实现,可以避免闪烁的现象。 | `numbers` | `ALL` |
| numberOfLines | 设置 `input` 的最大行数,在使用的时候必需同时设置 `multiline` 参数为 `true`。 | `number` | `ALL` |
| numberOfLines | 设置 input 最大显示行数,如果 TextInput 没有显式设置高度,会根据 numberOfLines 来计算高度撑开。在使用的时候必需同时设置 multiline 参数为 true。 | `number` | `Android` |
| placeholder | 如果没有任何文字输入,会显示此字符串。 | `string` | `ALL` |
| placeholderTextColor | 占位字符串显示的文字颜色。 | [`color`](style/color.md) | `ALL` |
| placeholder-text-color | 占位字符串显示的文字颜色。(也可设置为 Style 属性) `最低支持版本2.13.4` | [`color`](style/color.md) | `ALL` |
| underline-color-android | `input` 下底线的颜色。 可以设置为 'transparent' 来去掉下底线。(也可设置为 Style 属性) `最低支持版本2.13.4` | [`color`](style/color.md) | `Android` |
| returnKeyType | 指定软键盘的回车键显示的样式。 | `enum(done, go, next, search, send)` | `ALL` |
| value | 指定 `input` 组件的值。 | `string` | `ALL` |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -43,7 +43,7 @@
"@babel/polyfill": "^7.12.0",
"@babel/preset-env": "^7.12.0",
"@babel/preset-react": "^7.9.4",
"@hippy/debug-server-next": "^0.2.26",
"@hippy/debug-server-next": "^0.2.31",
"@hippy/hippy-dynamic-import-plugin": "^2.0.0",
"@hippy/hippy-hmr-plugin": "^0.0.2",
"@hippy/hippy-react-refresh-webpack-plugin": "^0.5.5",
@@ -14,7 +14,6 @@ const styles = StyleSheet.create({
input_style: {
width: 300,
marginVertical: 10,
placeholderTextColor: '#aaaaaa',
fontSize: 16,
color: '#242424',
height: 30,
@@ -80,6 +79,9 @@ export default class TextInputExpo extends Component {
this.input = ref;
}}
style={styles.input_style}
caretColor='yellow'
underlineColorAndroid='grey'
placeholderTextColor='#4c9afa'
placeholder="text"
defaultValue={textContent}
/>
+1 -1
View File
@@ -36,7 +36,7 @@
"@babel/plugin-transform-runtime": "^7.11.0",
"@babel/polyfill": "^7.12.0",
"@babel/preset-env": "^7.12.0",
"@hippy/debug-server-next": "^0.2.26",
"@hippy/debug-server-next": "^0.2.31",
"@hippy/hippy-dynamic-import-plugin": "^2.0.0",
"@hippy/hippy-hmr-plugin": "^0.0.2",
"@hippy/vue-css-loader": "^2.0.1",
@@ -8,8 +8,10 @@
<input
ref="input"
v-model="text"
caret-color="yellow"
placeholder="Text"
caret-color="yellow"
underline-color-android="grey"
placeholder-text-color="#40b883"
class="input"
@click="stopPropagation"
@keyboardWillShow="onKeyboardWillShow"
@@ -39,6 +41,9 @@
<label>数字:</label>
<input
type="number"
caret-color="yellow"
underline-color-android="grey"
placeholder-text-color="#40b883"
placeholder="Number"
class="input"
@change="textChange"
@@ -47,6 +52,9 @@
<label>密码:</label>
<input
type="password"
caret-color="yellow"
underline-color-android="grey"
placeholder-text-color="#40b883"
placeholder="Password"
class="input"
@change="textChange"
@@ -55,6 +63,9 @@
<label>文本(限制5个字符):</label>
<input
:maxlength="5"
caret-color="yellow"
underline-color-android="grey"
placeholder-text-color="#40b883"
placeholder="5 个字符"
class="input"
@change="textChange"
@@ -135,7 +146,6 @@ export default {
border-color: #ccc;
font-size: 16px;
margin: 20px;
placeholder-text-color: #aaa;
}
.demo-input .input-button {
border-color: #4c9afa;
@@ -18,6 +18,7 @@
ref="input"
v-model="bundleUrl"
caret-color="yellow"
placeholder="please input bundleUrl"
:multiple="true"
numberOfLines="4"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -179,6 +179,10 @@ interface TextInputProps extends LayoutableProps, ClickableProps {
}
const propsMap = {
caretColor: 'caret-color',
};
/**
* A foundational component for inputting text into the app via a keyboard. Props provide
* configurability for several features, such as auto-correction, auto-capitalization,
@@ -272,21 +276,26 @@ class TextInput extends React.Component<TextInputProps, {}> {
*/
public render() {
const nativeProps = { ...this.props };
['underlineColorAndroid', 'placeholderTextColor', 'placeholderTextColors']
.forEach((prop) => {
if (typeof this.props[prop] === 'string') {
['underlineColorAndroid', 'placeholderTextColor', 'placeholderTextColors', 'caretColor', 'caret-color']
.forEach((originalProp) => {
let prop = originalProp;
const value = this.props[originalProp];
if (typeof this.props[originalProp] === 'string') {
if (propsMap[originalProp]) {
prop = propsMap[originalProp];
}
if (Array.isArray(nativeProps.style)) {
nativeProps.style.push({
[prop]: this.props[prop],
[prop]: value,
});
} else if (nativeProps.style && typeof nativeProps.style === 'object') {
nativeProps.style[prop] = this.props[prop];
nativeProps.style[prop] = value;
} else {
nativeProps.style = {
[prop]: this.props[prop],
[prop]: value,
};
}
nativeProps[prop] = undefined;
delete nativeProps[originalProp];
}
});
@@ -310,7 +319,6 @@ class TextInput extends React.Component<TextInputProps, {}> {
ref={(ref) => {
this.instance = ref;
}}
// @ts-ignore
onChangeText={this.onChangeText}
onKeyboardWillShow={this.onKeyboardWillShow}
/>
@@ -350,8 +350,6 @@ class ElementNode extends ViewNode {
animationId: styleValue.animationId,
};
// Translate color
} else if (['caretColor', 'caret-color'].indexOf(styleKey) >= 0) {
this.attributes['caret-color'] = colorParse((styleValue as Color));
} else if (styleKey.toLowerCase().indexOf('colors') > -1) {
(this.style as any)[styleKey] = colorArrayParse((styleValue as Color[]));
} else if (styleKey.toLowerCase().indexOf('color') > -1) {
@@ -416,13 +414,6 @@ class ElementNode extends ViewNode {
return Device.platform.OS !== 'ios';
},
},
{
match: () => ['caretColor', 'caret-color'].indexOf(key) >= 0,
action: () => {
this.attributes['caret-color'] = colorParse(value);
return false;
},
},
{
match: () => ['style'].indexOf(key) >= 0,
action: () => {
@@ -43,7 +43,6 @@ function hippyVueCSSLoader(source) {
selectors: n.selectors,
declarations: n.declarations.map((dec) => {
let { value } = dec;
// FIXME: Should have a strict property with colors map.
if (dec.property && dec.property.toLowerCase().indexOf('color') > -1) {
value = translateColor(value, options);
}
@@ -30,12 +30,20 @@ test('Element.setAttribute("text") test', (t) => {
}, TypeError);
});
test('Element.setAttribute("caretColor") test', (t) => {
test('text-input color attribute test', (t) => {
const caretColorNode = new ElementNode('div');
caretColorNode.setAttribute('caretColor', '#abcdef');
t.is(caretColorNode.attributes['caret-color'], 4289449455);
caretColorNode.setAttribute('caret-color', '#abc');
t.is(caretColorNode.attributes['caret-color'], 4289379276);
caretColorNode.setAttribute('placeholderTextColor', '#abcdef');
t.is(caretColorNode.attributes.placeholderTextColor, 4289449455);
caretColorNode.setAttribute('placeholder-text-color', '#abcdef');
t.is(caretColorNode.attributes.placeholderTextColor, 4289449455);
caretColorNode.setAttribute('underlineColorAndroid', '#abc');
t.is(caretColorNode.attributes.underlineColorAndroid, 4289379276);
caretColorNode.setAttribute('underline-color-android', '#abc');
t.is(caretColorNode.attributes.underlineColorAndroid, 4289379276);
});
test('Element.setNativeProps test', (t) => {
@@ -59,7 +67,11 @@ test('Element.setNativeProps test', (t) => {
node.setNativeProps({ style: { cde: {} } });
t.deepEqual(node.style.cde, {});
node.setNativeProps({ style: { caretColor: '#abcdef' } });
t.is(node.attributes['caret-color'], 4289449455);
t.is(node.style['caret-color'], 4289449455);
node.setNativeProps({ style: { placeholderTextColor: '#abcdef' } });
t.is(node.style.placeholderTextColor, 4289449455);
node.setNativeProps({ style: { underlineColorAndroid: '#abcdef' } });
t.is(node.style.underlineColorAndroid, 4289449455);
});
test('Element.hasAttribute test', (t) => {
@@ -164,7 +176,17 @@ test('Element.setStyle test', (t) => {
node.setStyle('cde', {});
t.deepEqual(node.style.cde, {});
node.setStyle('caretColor', '#abcdef');
t.is(node.attributes['caret-color'], 4289449455);
t.is(node.style['caret-color'], 4289449455);
node.setStyle('caret-color', '#abcdef');
t.is(node.style['caret-color'], 4289449455);
node.setStyle('placeholderTextColor', '#abcdef');
t.is(node.style.placeholderTextColor, 4289449455);
node.setStyle('placeholder-text-color', '#abcdef');
t.is(node.style.placeholderTextColor, 4289449455);
node.setStyle('underlineColorAndroid', '#abcdef');
t.is(node.style.underlineColorAndroid, 4289449455);
node.setStyle('underline-color-android', '#abcdef');
t.is(node.style.underlineColorAndroid, 4289449455);
node.setStyle('backgroundImage', 'linear-gradient(to top right, red, yellow, blue 10%)');
t.deepEqual(node.style.linearGradient, { angle: 'totopright', colorStopList: [{ color: 4294901760 }, { color: 4294967040 }, { color: 4278190335, ratio: 0.1 }] });
node.setStyle('backgroundImage', 'linear-gradient(90deg, red, 10%, blue 10%)');
@@ -288,8 +288,6 @@ class ElementNode extends ViewNode {
this.attributes[key] = unicodeToChar(value);
break;
}
// FIXME: UpdateNode numberOfRows will makes Image flicker on Android.
// So make it working on iOS only.
case 'numberOfRows':
this.attributes[key] = value;
if (Native.Platform !== 'ios') {
@@ -300,6 +298,14 @@ class ElementNode extends ViewNode {
case 'caret-color':
this.attributes['caret-color'] = Native.parseColor(value);
break;
case 'placeholderTextColor':
case 'placeholder-text-color':
this.attributes.placeholderTextColor = Native.parseColor(value);
break;
case 'underlineColorAndroid':
case 'underline-color-android':
this.attributes.underlineColorAndroid = Native.parseColor(value);
break;
case 'nativeBackgroundAndroid': {
const nativeBackgroundAndroid = value;
if (typeof nativeBackgroundAndroid.color !== 'undefined') {
@@ -344,9 +350,6 @@ class ElementNode extends ViewNode {
v = v.toString();
}
break;
case 'caretColor':
this.attributes['caret-color'] = colorParser(v);
break;
case 'backgroundImage': {
[p, v] = parseBackgroundImage(p, v);
break;