mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-01-12 22:51:09 +08:00
[add] UIManager: 'blur', 'focus' and 'measureInWindow'
This commit is contained in:
24
src/apis/StyleSheet/processTransform.js
Normal file
24
src/apis/StyleSheet/processTransform.js
Normal file
@@ -0,0 +1,24 @@
|
||||
// { scale: 2 } => 'scale(2)'
|
||||
const mapTransform = (transform) => {
|
||||
var key = Object.keys(transform)[0]
|
||||
return `${key}(${transform[key]})`
|
||||
}
|
||||
|
||||
// [1,2,3,4,5,6] => 'matrix3d(1,2,3,4,5,6)'
|
||||
const convertTransformMatrix = (transformMatrix) => {
|
||||
var matrix = transformMatrix.join(',')
|
||||
return `matrix3d(${matrix})`
|
||||
}
|
||||
|
||||
const processTransform = (style) => {
|
||||
if (style) {
|
||||
if (style.transform) {
|
||||
style.transform = style.transform.map(mapTransform).join(' ')
|
||||
} else if (style.transformMatrix) {
|
||||
style.transformMatrix = convertTransformMatrix(style.transformMatrix)
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
module.exports = processTransform
|
||||
@@ -73,8 +73,28 @@ suite('apis/UIManager', () => {
|
||||
})
|
||||
})
|
||||
|
||||
suite('measureInWindow', () => {
|
||||
test('provides correct layout to callback', () => {
|
||||
const node = createNode({ height: '10px', width: '10px' })
|
||||
const middle = createNode({ padding: '20px' })
|
||||
const context = createNode({ padding: '20px' })
|
||||
middle.appendChild(node)
|
||||
context.appendChild(middle)
|
||||
document.body.appendChild(context)
|
||||
|
||||
UIManager.measureInWindow(node, (x, y, width, height) => {
|
||||
assert.equal(x, 40)
|
||||
assert.equal(y, 40)
|
||||
assert.equal(width, 10)
|
||||
assert.equal(height, 10)
|
||||
})
|
||||
|
||||
document.body.removeChild(context)
|
||||
})
|
||||
})
|
||||
|
||||
suite('updateView', () => {
|
||||
test('adds new className to existing className', () => {
|
||||
test('add new className to existing className', () => {
|
||||
const node = createNode()
|
||||
node.className = 'existing'
|
||||
const props = { className: 'extra' }
|
||||
@@ -89,7 +109,20 @@ suite('apis/UIManager', () => {
|
||||
assert.equal(node.getAttribute('style'), 'color: red; opacity: 0;')
|
||||
})
|
||||
|
||||
test('sets attribute values', () => {
|
||||
test('replaces input and textarea text', () => {
|
||||
const node = createNode()
|
||||
node.value = 'initial'
|
||||
const textProp = { text: 'expected-text' }
|
||||
const valueProp = { value: 'expected-value' }
|
||||
|
||||
UIManager.updateView(node, textProp)
|
||||
assert.equal(node.value, 'expected-text')
|
||||
|
||||
UIManager.updateView(node, valueProp)
|
||||
assert.equal(node.value, 'expected-value')
|
||||
})
|
||||
|
||||
test('sets other attribute values', () => {
|
||||
const node = createNode()
|
||||
const props = { 'aria-level': '4', 'data-of-type': 'string' }
|
||||
UIManager.updateView(node, props)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import CSSPropertyOperations from 'react/lib/CSSPropertyOperations'
|
||||
import flattenStyle from '../StyleSheet/flattenStyle'
|
||||
import processTransform from '../StyleSheet/processTransform'
|
||||
|
||||
const measureAll = (node, callback, relativeToNativeNode) => {
|
||||
const _measureLayout = (node, relativeToNativeNode, callback) => {
|
||||
const relativeNode = relativeToNativeNode || node.parentNode
|
||||
const relativeRect = relativeNode.getBoundingClientRect()
|
||||
const { height, left, top, width } = node.getBoundingClientRect()
|
||||
@@ -10,23 +12,52 @@ const measureAll = (node, callback, relativeToNativeNode) => {
|
||||
}
|
||||
|
||||
const UIManager = {
|
||||
blur(node) {
|
||||
try { node.blur() } catch (err) {}
|
||||
},
|
||||
|
||||
focus(node) {
|
||||
try { node.focus() } catch (err) {}
|
||||
},
|
||||
|
||||
measure(node, callback) {
|
||||
measureAll(node, callback)
|
||||
_measureLayout(node, null, callback)
|
||||
},
|
||||
|
||||
measureInWindow(node, callback) {
|
||||
const { height, left, top, width } = node.getBoundingClientRect()
|
||||
callback(left, top, width, height)
|
||||
},
|
||||
|
||||
measureLayout(node, relativeToNativeNode, onFail, onSuccess) {
|
||||
measureAll(node, (x, y, width, height) => onSuccess(x, y, width, height), relativeToNativeNode)
|
||||
const relativeTo = relativeToNativeNode || node.parentNode
|
||||
_measureLayout(node, relativeTo, onSuccess)
|
||||
},
|
||||
|
||||
updateView(node, props) {
|
||||
for (const prop in props) {
|
||||
let nativeProp
|
||||
const value = props[prop]
|
||||
if (prop === 'style') {
|
||||
CSSPropertyOperations.setValueForStyles(node, value)
|
||||
} else if (prop === 'className') {
|
||||
node.classList.add(value)
|
||||
} else {
|
||||
node.setAttribute(prop, value)
|
||||
|
||||
switch(prop) {
|
||||
case 'style':
|
||||
// convert styles to DOM-styles
|
||||
CSSPropertyOperations.setValueForStyles(node, processTransform(flattenStyle(value)))
|
||||
break;
|
||||
case 'class':
|
||||
case 'className':
|
||||
nativeProp = 'class'
|
||||
// prevent class names managed by React Native from being replaced
|
||||
const className = node.getAttribute(nativeProp) + ' ' + value
|
||||
node.setAttribute(nativeProp, className)
|
||||
break;
|
||||
case 'text':
|
||||
case 'value':
|
||||
// native platforms use `text` prop to replace text input value
|
||||
node.value = value
|
||||
break;
|
||||
default:
|
||||
node.setAttribute(prop, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user