Prettier React Native Libraries
Reviewed By: sahrens Differential Revision: D7961488 fbshipit-source-id: 05f9b8b0b91ae77f9040a5321ccc18f7c3c1ce9a
This commit is contained in:
parent
1e2de71290
commit
d01ab66b47
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// TODO: Move this into an ART mode called "serialized" or something
|
// TODO: Move this into an ART mode called "serialized" or something
|
||||||
|
@ -19,7 +21,6 @@ const CURVE_TO = 3;
|
||||||
const ARC = 4;
|
const ARC = 4;
|
||||||
|
|
||||||
const SerializablePath = Class(Path, {
|
const SerializablePath = Class(Path, {
|
||||||
|
|
||||||
initialize: function(path) {
|
initialize: function(path) {
|
||||||
this.reset();
|
this.reset();
|
||||||
if (path instanceof SerializablePath) {
|
if (path instanceof SerializablePath) {
|
||||||
|
@ -54,7 +55,18 @@ const SerializablePath = Class(Path, {
|
||||||
onArc: function(sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation) {
|
onArc: function(sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation) {
|
||||||
if (rx !== ry || rotation) {
|
if (rx !== ry || rotation) {
|
||||||
return this._arcToBezier(
|
return this._arcToBezier(
|
||||||
sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation
|
sx,
|
||||||
|
sy,
|
||||||
|
ex,
|
||||||
|
ey,
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
rx,
|
||||||
|
ry,
|
||||||
|
sa,
|
||||||
|
ea,
|
||||||
|
ccw,
|
||||||
|
rotation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.path.push(ARC, cx, cy, rx, sa, ea, ccw ? 0 : 1);
|
this.path.push(ARC, cx, cy, rx, sa, ea, ccw ? 0 : 1);
|
||||||
|
@ -66,8 +78,7 @@ const SerializablePath = Class(Path, {
|
||||||
|
|
||||||
toJSON: function() {
|
toJSON: function() {
|
||||||
return this.path;
|
return this.path;
|
||||||
}
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = SerializablePath;
|
module.exports = SerializablePath;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Color = require('art/core/color');
|
const Color = require('art/core/color');
|
||||||
|
@ -69,58 +71,57 @@ const SurfaceViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||||
});
|
});
|
||||||
|
|
||||||
const NodeAttributes = {
|
const NodeAttributes = {
|
||||||
transform: { diff: arrayDiffer },
|
transform: {diff: arrayDiffer},
|
||||||
opacity: true,
|
opacity: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const GroupAttributes = merge(NodeAttributes, {
|
const GroupAttributes = merge(NodeAttributes, {
|
||||||
clipping: { diff: arrayDiffer }
|
clipping: {diff: arrayDiffer},
|
||||||
});
|
});
|
||||||
|
|
||||||
const RenderableAttributes = merge(NodeAttributes, {
|
const RenderableAttributes = merge(NodeAttributes, {
|
||||||
fill: { diff: arrayDiffer },
|
fill: {diff: arrayDiffer},
|
||||||
stroke: { diff: arrayDiffer },
|
stroke: {diff: arrayDiffer},
|
||||||
strokeWidth: true,
|
strokeWidth: true,
|
||||||
strokeCap: true,
|
strokeCap: true,
|
||||||
strokeJoin: true,
|
strokeJoin: true,
|
||||||
strokeDash: { diff: arrayDiffer },
|
strokeDash: {diff: arrayDiffer},
|
||||||
});
|
});
|
||||||
|
|
||||||
const ShapeAttributes = merge(RenderableAttributes, {
|
const ShapeAttributes = merge(RenderableAttributes, {
|
||||||
d: { diff: arrayDiffer },
|
d: {diff: arrayDiffer},
|
||||||
});
|
});
|
||||||
|
|
||||||
const TextAttributes = merge(RenderableAttributes, {
|
const TextAttributes = merge(RenderableAttributes, {
|
||||||
alignment: true,
|
alignment: true,
|
||||||
frame: { diff: fontAndLinesDiffer },
|
frame: {diff: fontAndLinesDiffer},
|
||||||
path: { diff: arrayDiffer }
|
path: {diff: arrayDiffer},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Native Components
|
// Native Components
|
||||||
|
|
||||||
const NativeSurfaceView = createReactNativeComponentClass('ARTSurfaceView',
|
const NativeSurfaceView = createReactNativeComponentClass(
|
||||||
|
'ARTSurfaceView',
|
||||||
() => ({
|
() => ({
|
||||||
validAttributes: SurfaceViewAttributes,
|
validAttributes: SurfaceViewAttributes,
|
||||||
uiViewClassName: 'ARTSurfaceView',
|
uiViewClassName: 'ARTSurfaceView',
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const NativeGroup = createReactNativeComponentClass('ARTGroup',
|
const NativeGroup = createReactNativeComponentClass('ARTGroup', () => ({
|
||||||
() => ({
|
validAttributes: GroupAttributes,
|
||||||
validAttributes: GroupAttributes,
|
uiViewClassName: 'ARTGroup',
|
||||||
uiViewClassName: 'ARTGroup',
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
const NativeShape = createReactNativeComponentClass('ARTShape',
|
const NativeShape = createReactNativeComponentClass('ARTShape', () => ({
|
||||||
() => ({
|
validAttributes: ShapeAttributes,
|
||||||
validAttributes: ShapeAttributes,
|
uiViewClassName: 'ARTShape',
|
||||||
uiViewClassName: 'ARTShape',
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
const NativeText = createReactNativeComponentClass('ARTText',
|
const NativeText = createReactNativeComponentClass('ARTText', () => ({
|
||||||
() => ({
|
validAttributes: TextAttributes,
|
||||||
validAttributes: TextAttributes,
|
uiViewClassName: 'ARTText',
|
||||||
uiViewClassName: 'ARTText',
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ class Surface extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
getChildContext() {
|
getChildContext() {
|
||||||
return { isInSurface: true };
|
return {isInSurface: true};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -153,7 +154,7 @@ class Surface extends React.Component {
|
||||||
const w = extractNumber(props.width, 0);
|
const w = extractNumber(props.width, 0);
|
||||||
const h = extractNumber(props.height, 0);
|
const h = extractNumber(props.height, 0);
|
||||||
return (
|
return (
|
||||||
<NativeSurfaceView style={[props.style, { width: w, height: h }]}>
|
<NativeSurfaceView style={[props.style, {width: w, height: h}]}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</NativeSurfaceView>
|
</NativeSurfaceView>
|
||||||
);
|
);
|
||||||
|
@ -175,10 +176,10 @@ function extractNumber(value, defaultValue) {
|
||||||
const pooledTransform = new Transform();
|
const pooledTransform = new Transform();
|
||||||
|
|
||||||
function extractTransform(props) {
|
function extractTransform(props) {
|
||||||
const scaleX = props.scaleX != null ? props.scaleX :
|
const scaleX =
|
||||||
props.scale != null ? props.scale : 1;
|
props.scaleX != null ? props.scaleX : props.scale != null ? props.scale : 1;
|
||||||
const scaleY = props.scaleY != null ? props.scaleY :
|
const scaleY =
|
||||||
props.scale != null ? props.scale : 1;
|
props.scaleY != null ? props.scaleY : props.scale != null ? props.scale : 1;
|
||||||
|
|
||||||
pooledTransform
|
pooledTransform
|
||||||
.transformTo(1, 0, 0, 1, 0, 0)
|
.transformTo(1, 0, 0, 1, 0, 0)
|
||||||
|
@ -191,9 +192,12 @@ function extractTransform(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
pooledTransform.xx, pooledTransform.yx,
|
pooledTransform.xx,
|
||||||
pooledTransform.xy, pooledTransform.yy,
|
pooledTransform.yx,
|
||||||
pooledTransform.x, pooledTransform.y,
|
pooledTransform.xy,
|
||||||
|
pooledTransform.yy,
|
||||||
|
pooledTransform.x,
|
||||||
|
pooledTransform.y,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +226,7 @@ class Group extends React.Component {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
invariant(
|
invariant(
|
||||||
this.context.isInSurface,
|
this.context.isInSurface,
|
||||||
'ART: <Group /> must be a child of a <Surface />'
|
'ART: <Group /> must be a child of a <Surface />',
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<NativeGroup
|
<NativeGroup
|
||||||
|
@ -299,7 +303,7 @@ function insertOffsetsIntoArray(stops, targetArray, atIndex, multi, reverse) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const offsetString in stops) {
|
for (const offsetString in stops) {
|
||||||
offsetNumber = (+offsetString) * multi;
|
offsetNumber = +offsetString * multi;
|
||||||
targetArray[atIndex + i] = reverse ? 1 - offsetNumber : offsetNumber;
|
targetArray[atIndex + i] = reverse ? 1 - offsetNumber : offsetNumber;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -370,17 +374,23 @@ function extractColor(color) {
|
||||||
|
|
||||||
function extractStrokeCap(strokeCap) {
|
function extractStrokeCap(strokeCap) {
|
||||||
switch (strokeCap) {
|
switch (strokeCap) {
|
||||||
case 'butt': return 0;
|
case 'butt':
|
||||||
case 'square': return 2;
|
return 0;
|
||||||
default: return 1; // round
|
case 'square':
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1; // round
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractStrokeJoin(strokeJoin) {
|
function extractStrokeJoin(strokeJoin) {
|
||||||
switch (strokeJoin) {
|
switch (strokeJoin) {
|
||||||
case 'miter': return 0;
|
case 'miter':
|
||||||
case 'bevel': return 2;
|
return 0;
|
||||||
default: return 1; // round
|
case 'bevel':
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1; // round
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +414,6 @@ class Shape extends React.Component {
|
||||||
strokeJoin={extractStrokeJoin(props.strokeJoin)}
|
strokeJoin={extractStrokeJoin(props.strokeJoin)}
|
||||||
strokeWidth={extractNumber(props.strokeWidth, 1)}
|
strokeWidth={extractNumber(props.strokeWidth, 1)}
|
||||||
transform={extractTransform(props)}
|
transform={extractTransform(props)}
|
||||||
|
|
||||||
d={d}
|
d={d}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -422,9 +431,10 @@ function extractSingleFontFamily(fontFamilyString) {
|
||||||
// ART on the web allows for multiple font-families to be specified.
|
// ART on the web allows for multiple font-families to be specified.
|
||||||
// For compatibility, we extract the first font-family, hoping
|
// For compatibility, we extract the first font-family, hoping
|
||||||
// we'll get a match.
|
// we'll get a match.
|
||||||
return fontFamilyString.split(',')[0]
|
return fontFamilyString
|
||||||
.replace(fontFamilyPrefix, '')
|
.split(',')[0]
|
||||||
.replace(fontFamilySuffix, '');
|
.replace(fontFamilyPrefix, '')
|
||||||
|
.replace(fontFamilySuffix, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFontString(font) {
|
function parseFontString(font) {
|
||||||
|
@ -458,7 +468,8 @@ function extractFont(font) {
|
||||||
}
|
}
|
||||||
const fontFamily = extractSingleFontFamily(font.fontFamily);
|
const fontFamily = extractSingleFontFamily(font.fontFamily);
|
||||||
const fontSize = +font.fontSize || 12;
|
const fontSize = +font.fontSize || 12;
|
||||||
const fontWeight = font.fontWeight != null ? font.fontWeight.toString() : '400';
|
const fontWeight =
|
||||||
|
font.fontWeight != null ? font.fontWeight.toString() : '400';
|
||||||
return {
|
return {
|
||||||
// Normalize
|
// Normalize
|
||||||
fontFamily: fontFamily,
|
fontFamily: fontFamily,
|
||||||
|
@ -470,7 +481,7 @@ function extractFont(font) {
|
||||||
|
|
||||||
const newLine = /\n/g;
|
const newLine = /\n/g;
|
||||||
function extractFontAndLines(font, text) {
|
function extractFontAndLines(font, text) {
|
||||||
return { font: extractFont(font), lines: text.split(newLine) };
|
return {font: extractFont(font), lines: text.split(newLine)};
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractAlignment(alignment) {
|
function extractAlignment(alignment) {
|
||||||
|
@ -488,10 +499,12 @@ class Text extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
const path = props.path;
|
const path = props.path;
|
||||||
const textPath = path ? (path instanceof Path ? path : new Path(path)).toJSON() : null;
|
const textPath = path
|
||||||
|
? (path instanceof Path ? path : new Path(path)).toJSON()
|
||||||
|
: null;
|
||||||
const textFrame = extractFontAndLines(
|
const textFrame = extractFontAndLines(
|
||||||
props.font,
|
props.font,
|
||||||
childrenAsString(props.children)
|
childrenAsString(props.children),
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<NativeText
|
<NativeText
|
||||||
|
@ -503,7 +516,6 @@ class Text extends React.Component {
|
||||||
strokeJoin={extractStrokeJoin(props.strokeJoin)}
|
strokeJoin={extractStrokeJoin(props.strokeJoin)}
|
||||||
strokeWidth={extractNumber(props.strokeWidth, 1)}
|
strokeWidth={extractNumber(props.strokeWidth, 1)}
|
||||||
transform={extractTransform(props)}
|
transform={extractTransform(props)}
|
||||||
|
|
||||||
alignment={extractAlignment(props.alignment)}
|
alignment={extractAlignment(props.alignment)}
|
||||||
frame={textFrame}
|
frame={textFrame}
|
||||||
path={textPath}
|
path={textPath}
|
||||||
|
@ -518,13 +530,14 @@ function LinearGradient(stops, x1, y1, x2, y2) {
|
||||||
const type = LINEAR_GRADIENT;
|
const type = LINEAR_GRADIENT;
|
||||||
|
|
||||||
if (arguments.length < 5) {
|
if (arguments.length < 5) {
|
||||||
const angle = ((x1 == null) ? 270 : x1) * Math.PI / 180;
|
const angle = (x1 == null ? 270 : x1) * Math.PI / 180;
|
||||||
|
|
||||||
let x = Math.cos(angle);
|
let x = Math.cos(angle);
|
||||||
let y = -Math.sin(angle);
|
let y = -Math.sin(angle);
|
||||||
const l = (Math.abs(x) + Math.abs(y)) / 2;
|
const l = (Math.abs(x) + Math.abs(y)) / 2;
|
||||||
|
|
||||||
x *= l; y *= l;
|
x *= l;
|
||||||
|
y *= l;
|
||||||
|
|
||||||
x1 = 0.5 - x;
|
x1 = 0.5 - x;
|
||||||
x2 = 0.5 + x;
|
x2 = 0.5 + x;
|
||||||
|
|
|
@ -4,15 +4,17 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const AlertIOS = require('AlertIOS');
|
const AlertIOS = require('AlertIOS');
|
||||||
const NativeModules = require('NativeModules');
|
const NativeModules = require('NativeModules');
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
|
|
||||||
import type { AlertType, AlertButtonStyle } from 'AlertIOS';
|
import type {AlertType, AlertButtonStyle} from 'AlertIOS';
|
||||||
|
|
||||||
export type Buttons = Array<{
|
export type Buttons = Array<{
|
||||||
text?: string,
|
text?: string,
|
||||||
|
@ -31,7 +33,6 @@ type Options = {
|
||||||
* See http://facebook.github.io/react-native/docs/alert.html
|
* See http://facebook.github.io/react-native/docs/alert.html
|
||||||
*/
|
*/
|
||||||
class Alert {
|
class Alert {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches an alert dialog with the specified title and message.
|
* Launches an alert dialog with the specified title and message.
|
||||||
*
|
*
|
||||||
|
@ -46,7 +47,9 @@ class Alert {
|
||||||
): void {
|
): void {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
if (typeof type !== 'undefined') {
|
if (typeof type !== 'undefined') {
|
||||||
console.warn('Alert.alert() with a 5th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.');
|
console.warn(
|
||||||
|
'Alert.alert() with a 5th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.',
|
||||||
|
);
|
||||||
AlertIOS.alert(title, message, buttons, type);
|
AlertIOS.alert(title, message, buttons, type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +64,6 @@ class Alert {
|
||||||
* Wrapper around the Android native module.
|
* Wrapper around the Android native module.
|
||||||
*/
|
*/
|
||||||
class AlertAndroid {
|
class AlertAndroid {
|
||||||
|
|
||||||
static alert(
|
static alert(
|
||||||
title: ?string,
|
title: ?string,
|
||||||
message?: ?string,
|
message?: ?string,
|
||||||
|
@ -78,35 +80,41 @@ class AlertAndroid {
|
||||||
}
|
}
|
||||||
// At most three buttons (neutral, negative, positive). Ignore rest.
|
// At most three buttons (neutral, negative, positive). Ignore rest.
|
||||||
// The text 'OK' should be probably localized. iOS Alert does that in native.
|
// The text 'OK' should be probably localized. iOS Alert does that in native.
|
||||||
const validButtons: Buttons = buttons ? buttons.slice(0, 3) : [{text: 'OK'}];
|
const validButtons: Buttons = buttons
|
||||||
|
? buttons.slice(0, 3)
|
||||||
|
: [{text: 'OK'}];
|
||||||
const buttonPositive = validButtons.pop();
|
const buttonPositive = validButtons.pop();
|
||||||
const buttonNegative = validButtons.pop();
|
const buttonNegative = validButtons.pop();
|
||||||
const buttonNeutral = validButtons.pop();
|
const buttonNeutral = validButtons.pop();
|
||||||
if (buttonNeutral) {
|
if (buttonNeutral) {
|
||||||
config = {...config, buttonNeutral: buttonNeutral.text || '' };
|
config = {...config, buttonNeutral: buttonNeutral.text || ''};
|
||||||
}
|
}
|
||||||
if (buttonNegative) {
|
if (buttonNegative) {
|
||||||
config = {...config, buttonNegative: buttonNegative.text || '' };
|
config = {...config, buttonNegative: buttonNegative.text || ''};
|
||||||
}
|
}
|
||||||
if (buttonPositive) {
|
if (buttonPositive) {
|
||||||
config = {...config, buttonPositive: buttonPositive.text || '' };
|
config = {...config, buttonPositive: buttonPositive.text || ''};
|
||||||
}
|
}
|
||||||
NativeModules.DialogManagerAndroid.showAlert(
|
NativeModules.DialogManagerAndroid.showAlert(
|
||||||
config,
|
config,
|
||||||
(errorMessage) => console.warn(errorMessage),
|
errorMessage => console.warn(errorMessage),
|
||||||
(action, buttonKey) => {
|
(action, buttonKey) => {
|
||||||
if (action === NativeModules.DialogManagerAndroid.buttonClicked) {
|
if (action === NativeModules.DialogManagerAndroid.buttonClicked) {
|
||||||
if (buttonKey === NativeModules.DialogManagerAndroid.buttonNeutral) {
|
if (buttonKey === NativeModules.DialogManagerAndroid.buttonNeutral) {
|
||||||
buttonNeutral.onPress && buttonNeutral.onPress();
|
buttonNeutral.onPress && buttonNeutral.onPress();
|
||||||
} else if (buttonKey === NativeModules.DialogManagerAndroid.buttonNegative) {
|
} else if (
|
||||||
|
buttonKey === NativeModules.DialogManagerAndroid.buttonNegative
|
||||||
|
) {
|
||||||
buttonNegative.onPress && buttonNegative.onPress();
|
buttonNegative.onPress && buttonNegative.onPress();
|
||||||
} else if (buttonKey === NativeModules.DialogManagerAndroid.buttonPositive) {
|
} else if (
|
||||||
|
buttonKey === NativeModules.DialogManagerAndroid.buttonPositive
|
||||||
|
) {
|
||||||
buttonPositive.onPress && buttonPositive.onPress();
|
buttonPositive.onPress && buttonPositive.onPress();
|
||||||
}
|
}
|
||||||
} else if (action === NativeModules.DialogManagerAndroid.dismissed) {
|
} else if (action === NativeModules.DialogManagerAndroid.dismissed) {
|
||||||
options && options.onDismiss && options.onDismiss();
|
options && options.onDismiss && options.onDismiss();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
* @jsdoc
|
* @jsdoc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const RCTAlertManager = require('NativeModules').AlertManager;
|
const RCTAlertManager = require('NativeModules').AlertManager;
|
||||||
|
@ -18,7 +20,7 @@ export type AlertType = $Enum<{
|
||||||
/**
|
/**
|
||||||
* Default alert with no inputs
|
* Default alert with no inputs
|
||||||
*/
|
*/
|
||||||
'default': string,
|
default: string,
|
||||||
/**
|
/**
|
||||||
* Plain text input alert
|
* Plain text input alert
|
||||||
*/
|
*/
|
||||||
|
@ -40,15 +42,15 @@ export type AlertButtonStyle = $Enum<{
|
||||||
/**
|
/**
|
||||||
* Default button style
|
* Default button style
|
||||||
*/
|
*/
|
||||||
'default': string,
|
default: string,
|
||||||
/**
|
/**
|
||||||
* Cancel button style
|
* Cancel button style
|
||||||
*/
|
*/
|
||||||
'cancel': string,
|
cancel: string,
|
||||||
/**
|
/**
|
||||||
* Destructive button style
|
* Destructive button style
|
||||||
*/
|
*/
|
||||||
'destructive': string,
|
destructive: string,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,11 +89,13 @@ class AlertIOS {
|
||||||
static alert(
|
static alert(
|
||||||
title: ?string,
|
title: ?string,
|
||||||
message?: ?string,
|
message?: ?string,
|
||||||
callbackOrButtons?: ?(() => void) | ButtonsArray,
|
callbackOrButtons?: ?((() => void) | ButtonsArray),
|
||||||
type?: AlertType,
|
type?: AlertType,
|
||||||
): void {
|
): void {
|
||||||
if (typeof type !== 'undefined') {
|
if (typeof type !== 'undefined') {
|
||||||
console.warn('AlertIOS.alert() with a 4th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.');
|
console.warn(
|
||||||
|
'AlertIOS.alert() with a 4th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.',
|
||||||
|
);
|
||||||
this.prompt(title, message, callbackOrButtons, type);
|
this.prompt(title, message, callbackOrButtons, type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,26 +110,30 @@ class AlertIOS {
|
||||||
static prompt(
|
static prompt(
|
||||||
title: ?string,
|
title: ?string,
|
||||||
message?: ?string,
|
message?: ?string,
|
||||||
callbackOrButtons?: ?((text: string) => void) | ButtonsArray,
|
callbackOrButtons?: ?(((text: string) => void) | ButtonsArray),
|
||||||
type?: ?AlertType = 'plain-text',
|
type?: ?AlertType = 'plain-text',
|
||||||
defaultValue?: string,
|
defaultValue?: string,
|
||||||
keyboardType?: string
|
keyboardType?: string,
|
||||||
): void {
|
): void {
|
||||||
if (typeof type === 'function') {
|
if (typeof type === 'function') {
|
||||||
console.warn(
|
console.warn(
|
||||||
'You passed a callback function as the "type" argument to AlertIOS.prompt(). React Native is ' +
|
'You passed a callback function as the "type" argument to AlertIOS.prompt(). React Native is ' +
|
||||||
'assuming you want to use the deprecated AlertIOS.prompt(title, defaultValue, buttons, callback) ' +
|
'assuming you want to use the deprecated AlertIOS.prompt(title, defaultValue, buttons, callback) ' +
|
||||||
'signature. The current signature is AlertIOS.prompt(title, message, callbackOrButtons, type, defaultValue, ' +
|
'signature. The current signature is AlertIOS.prompt(title, message, callbackOrButtons, type, defaultValue, ' +
|
||||||
'keyboardType) and the old syntax will be removed in a future version.');
|
'keyboardType) and the old syntax will be removed in a future version.',
|
||||||
|
);
|
||||||
|
|
||||||
const callback = type;
|
const callback = type;
|
||||||
RCTAlertManager.alertWithArgs({
|
RCTAlertManager.alertWithArgs(
|
||||||
title: title || '',
|
{
|
||||||
type: 'plain-text',
|
title: title || '',
|
||||||
defaultValue: message,
|
type: 'plain-text',
|
||||||
}, (id, value) => {
|
defaultValue: message,
|
||||||
callback(value);
|
},
|
||||||
});
|
(id, value) => {
|
||||||
|
callback(value);
|
||||||
|
},
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +143,7 @@ class AlertIOS {
|
||||||
let destructiveButtonKey;
|
let destructiveButtonKey;
|
||||||
if (typeof callbackOrButtons === 'function') {
|
if (typeof callbackOrButtons === 'function') {
|
||||||
callbacks = [callbackOrButtons];
|
callbacks = [callbackOrButtons];
|
||||||
}
|
} else if (callbackOrButtons instanceof Array) {
|
||||||
else if (callbackOrButtons instanceof Array) {
|
|
||||||
callbackOrButtons.forEach((btn, index) => {
|
callbackOrButtons.forEach((btn, index) => {
|
||||||
callbacks[index] = btn.onPress;
|
callbacks[index] = btn.onPress;
|
||||||
if (btn.style === 'cancel') {
|
if (btn.style === 'cancel') {
|
||||||
|
@ -152,19 +159,22 @@ class AlertIOS {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RCTAlertManager.alertWithArgs({
|
RCTAlertManager.alertWithArgs(
|
||||||
title: title || '',
|
{
|
||||||
message: message || undefined,
|
title: title || '',
|
||||||
buttons,
|
message: message || undefined,
|
||||||
type: type || undefined,
|
buttons,
|
||||||
defaultValue,
|
type: type || undefined,
|
||||||
cancelButtonKey,
|
defaultValue,
|
||||||
destructiveButtonKey,
|
cancelButtonKey,
|
||||||
keyboardType,
|
destructiveButtonKey,
|
||||||
}, (id, value) => {
|
keyboardType,
|
||||||
const cb = callbacks[id];
|
},
|
||||||
cb && cb(value);
|
(id, value) => {
|
||||||
});
|
const cb = callbacks[id];
|
||||||
|
cb && cb(value);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
*/
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeModules = require('NativeModules');
|
const NativeModules = require('NativeModules');
|
||||||
|
@ -15,8 +17,9 @@ module.exports = {
|
||||||
alertWithArgs: function(args, callback) {
|
alertWithArgs: function(args, callback) {
|
||||||
// TODO(5998984): Polyfill it correctly with DialogManagerAndroid
|
// TODO(5998984): Polyfill it correctly with DialogManagerAndroid
|
||||||
NativeModules.DialogManagerAndroid.showAlert(
|
NativeModules.DialogManagerAndroid.showAlert(
|
||||||
args,
|
args,
|
||||||
emptyCallback,
|
emptyCallback,
|
||||||
callback || emptyCallback);
|
callback || emptyCallback,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const RCTAlertManager = require('NativeModules').AlertManager;
|
const RCTAlertManager = require('NativeModules').AlertManager;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -20,58 +22,52 @@ var objectAssign = require('object-assign');
|
||||||
var runSequence = require('run-sequence');
|
var runSequence = require('run-sequence');
|
||||||
var webpackStream = require('webpack-stream');
|
var webpackStream = require('webpack-stream');
|
||||||
|
|
||||||
var DEVELOPMENT_HEADER = [
|
var DEVELOPMENT_HEADER =
|
||||||
'/**',
|
['/**', ' * Animated v<%= version %>', ' */'].join('\n') + '\n';
|
||||||
' * Animated v<%= version %>',
|
var PRODUCTION_HEADER =
|
||||||
' */'
|
[
|
||||||
].join('\n') + '\n';
|
'/**',
|
||||||
var PRODUCTION_HEADER = [
|
' * Animated v<%= version %>',
|
||||||
'/**',
|
' *',
|
||||||
' * Animated v<%= version %>',
|
' * Copyright (c) 2013-present, Facebook, Inc.',
|
||||||
' *',
|
' *',
|
||||||
' * Copyright (c) 2013-present, Facebook, Inc.',
|
' * This source code is licensed under the MIT license found in the',
|
||||||
' *',
|
' * LICENSE file in the root directory of this source tree.',
|
||||||
' * This source code is licensed under the MIT license found in the',
|
' */',
|
||||||
' * LICENSE file in the root directory of this source tree.',
|
].join('\n') + '\n';
|
||||||
' */'
|
|
||||||
].join('\n') + '\n';
|
|
||||||
|
|
||||||
var babelOpts = {
|
var babelOpts = {
|
||||||
nonStandard: true,
|
nonStandard: true,
|
||||||
loose: [
|
loose: ['es6.classes'],
|
||||||
'es6.classes'
|
|
||||||
],
|
|
||||||
stage: 1,
|
stage: 1,
|
||||||
plugins: [babelPluginDEV, babelPluginModules],
|
plugins: [babelPluginDEV, babelPluginModules],
|
||||||
_moduleMap: objectAssign({}, require('fbjs/module-map'), {
|
_moduleMap: objectAssign({}, require('fbjs/module-map'), {
|
||||||
'React': 'react',
|
React: 'react',
|
||||||
})
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
var buildDist = function(opts) {
|
var buildDist = function(opts) {
|
||||||
var webpackOpts = {
|
var webpackOpts = {
|
||||||
debug: opts.debug,
|
debug: opts.debug,
|
||||||
externals: {
|
externals: {
|
||||||
'react': 'React',
|
react: 'React',
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [{test: /\.js$/, loader: 'babel'}],
|
||||||
{test: /\.js$/, loader: 'babel'}
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
filename: opts.output,
|
filename: opts.output,
|
||||||
library: 'Animated'
|
library: 'Animated',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpackStream.webpack.DefinePlugin({
|
new webpackStream.webpack.DefinePlugin({
|
||||||
'process.env.NODE_ENV': JSON.stringify(
|
'process.env.NODE_ENV': JSON.stringify(
|
||||||
opts.debug ? 'development' : 'production'
|
opts.debug ? 'development' : 'production',
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
new webpackStream.webpack.optimize.OccurenceOrderPlugin(),
|
new webpackStream.webpack.optimize.OccurenceOrderPlugin(),
|
||||||
new webpackStream.webpack.optimize.DedupePlugin()
|
new webpackStream.webpack.optimize.DedupePlugin(),
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
if (!opts.debug) {
|
if (!opts.debug) {
|
||||||
webpackOpts.plugins.push(
|
webpackOpts.plugins.push(
|
||||||
|
@ -79,9 +75,9 @@ var buildDist = function(opts) {
|
||||||
compress: {
|
compress: {
|
||||||
hoist_vars: true,
|
hoist_vars: true,
|
||||||
screw_ie8: true,
|
screw_ie8: true,
|
||||||
warnings: false
|
warnings: false,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return webpackStream(webpackOpts, null, function(err, stats) {
|
return webpackStream(webpackOpts, null, function(err, stats) {
|
||||||
|
@ -101,7 +97,7 @@ var paths = {
|
||||||
src: [
|
src: [
|
||||||
'*src/**/*.js',
|
'*src/**/*.js',
|
||||||
'!src/**/__tests__/**/*.js',
|
'!src/**/__tests__/**/*.js',
|
||||||
'!src/**/__mocks__/**/*.js'
|
'!src/**/__mocks__/**/*.js',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,32 +113,36 @@ gulp.task('modules', function() {
|
||||||
.pipe(gulp.dest(paths.lib));
|
.pipe(gulp.dest(paths.lib));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('dist', ['modules'], function () {
|
gulp.task('dist', ['modules'], function() {
|
||||||
var distOpts = {
|
var distOpts = {
|
||||||
debug: true,
|
debug: true,
|
||||||
output: 'animated.js'
|
output: 'animated.js',
|
||||||
};
|
};
|
||||||
return gulp
|
return gulp
|
||||||
.src(paths.entry)
|
.src(paths.entry)
|
||||||
.pipe(buildDist(distOpts))
|
.pipe(buildDist(distOpts))
|
||||||
.pipe(derequire())
|
.pipe(derequire())
|
||||||
.pipe(header(DEVELOPMENT_HEADER, {
|
.pipe(
|
||||||
version: process.env.npm_package_version
|
header(DEVELOPMENT_HEADER, {
|
||||||
}))
|
version: process.env.npm_package_version,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.pipe(gulp.dest(paths.dist));
|
.pipe(gulp.dest(paths.dist));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('dist:min', ['modules'], function () {
|
gulp.task('dist:min', ['modules'], function() {
|
||||||
var distOpts = {
|
var distOpts = {
|
||||||
debug: false,
|
debug: false,
|
||||||
output: 'animated.min.js'
|
output: 'animated.min.js',
|
||||||
};
|
};
|
||||||
return gulp
|
return gulp
|
||||||
.src(paths.entry)
|
.src(paths.entry)
|
||||||
.pipe(buildDist(distOpts))
|
.pipe(buildDist(distOpts))
|
||||||
.pipe(header(PRODUCTION_HEADER, {
|
.pipe(
|
||||||
version: process.env.npm_package_version
|
header(PRODUCTION_HEADER, {
|
||||||
}))
|
version: process.env.npm_package_version,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.pipe(gulp.dest(paths.dist));
|
.pipe(gulp.dest(paths.dist));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const AnimatedImplementation = require('AnimatedImplementation');
|
const AnimatedImplementation = require('AnimatedImplementation');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let ease;
|
let ease;
|
||||||
|
@ -162,7 +164,7 @@ class Easing {
|
||||||
*/
|
*/
|
||||||
static elastic(bounciness: number = 1): (t: number) => number {
|
static elastic(bounciness: number = 1): (t: number) => number {
|
||||||
const p = bounciness * Math.PI;
|
const p = bounciness * Math.PI;
|
||||||
return (t) => 1 - Math.pow(Math.cos(t * Math.PI / 2), 3) * Math.cos(t * p);
|
return t => 1 - Math.pow(Math.cos(t * Math.PI / 2), 3) * Math.cos(t * p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,7 +179,7 @@ class Easing {
|
||||||
if (s === undefined) {
|
if (s === undefined) {
|
||||||
s = 1.70158;
|
s = 1.70158;
|
||||||
}
|
}
|
||||||
return (t) => t * t * ((s + 1) * t - s);
|
return t => t * t * ((s + 1) * t - s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -215,7 +217,7 @@ class Easing {
|
||||||
x1: number,
|
x1: number,
|
||||||
y1: number,
|
y1: number,
|
||||||
x2: number,
|
x2: number,
|
||||||
y2: number
|
y2: number,
|
||||||
): (t: number) => number {
|
): (t: number) => number {
|
||||||
const _bezier = require('bezier');
|
const _bezier = require('bezier');
|
||||||
return _bezier(x1, y1, x2, y2);
|
return _bezier(x1, y1, x2, y2);
|
||||||
|
@ -224,19 +226,15 @@ class Easing {
|
||||||
/**
|
/**
|
||||||
* Runs an easing function forwards.
|
* Runs an easing function forwards.
|
||||||
*/
|
*/
|
||||||
static in(
|
static in(easing: (t: number) => number): (t: number) => number {
|
||||||
easing: (t: number) => number,
|
|
||||||
): (t: number) => number {
|
|
||||||
return easing;
|
return easing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs an easing function backwards.
|
* Runs an easing function backwards.
|
||||||
*/
|
*/
|
||||||
static out(
|
static out(easing: (t: number) => number): (t: number) => number {
|
||||||
easing: (t: number) => number,
|
return t => 1 - easing(1 - t);
|
||||||
): (t: number) => number {
|
|
||||||
return (t) => 1 - easing(1 - t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,10 +242,8 @@ class Easing {
|
||||||
* forwards for half of the duration, then backwards for the rest of the
|
* forwards for half of the duration, then backwards for the rest of the
|
||||||
* duration.
|
* duration.
|
||||||
*/
|
*/
|
||||||
static inOut(
|
static inOut(easing: (t: number) => number): (t: number) => number {
|
||||||
easing: (t: number) => number,
|
return t => {
|
||||||
): (t: number) => number {
|
|
||||||
return (t) => {
|
|
||||||
if (t < 0.5) {
|
if (t < 0.5) {
|
||||||
return easing(t * 2) / 2;
|
return easing(t * 2) / 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ function fromBouncinessAndSpeed(
|
||||||
}
|
}
|
||||||
|
|
||||||
function projectNormal(n, start, end) {
|
function projectNormal(n, start, end) {
|
||||||
return start + (n * (end - start));
|
return start + n * (end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
function linearInterpolation(t, start, end) {
|
function linearInterpolation(t, start, end) {
|
||||||
|
@ -53,18 +54,20 @@ function fromBouncinessAndSpeed(
|
||||||
}
|
}
|
||||||
|
|
||||||
function b3Friction1(x) {
|
function b3Friction1(x) {
|
||||||
return (0.0007 * Math.pow(x, 3)) -
|
return 0.0007 * Math.pow(x, 3) - 0.031 * Math.pow(x, 2) + 0.64 * x + 1.28;
|
||||||
(0.031 * Math.pow(x, 2)) + 0.64 * x + 1.28;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function b3Friction2(x) {
|
function b3Friction2(x) {
|
||||||
return (0.000044 * Math.pow(x, 3)) -
|
return 0.000044 * Math.pow(x, 3) - 0.006 * Math.pow(x, 2) + 0.36 * x + 2;
|
||||||
(0.006 * Math.pow(x, 2)) + 0.36 * x + 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function b3Friction3(x) {
|
function b3Friction3(x) {
|
||||||
return (0.00000045 * Math.pow(x, 3)) -
|
return (
|
||||||
(0.000332 * Math.pow(x, 2)) + 0.1078 * x + 5.84;
|
0.00000045 * Math.pow(x, 3) -
|
||||||
|
0.000332 * Math.pow(x, 2) +
|
||||||
|
0.1078 * x +
|
||||||
|
5.84
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function b3Nobounce(tension) {
|
function b3Nobounce(tension) {
|
||||||
|
@ -84,7 +87,7 @@ function fromBouncinessAndSpeed(
|
||||||
const bouncyFriction = quadraticOutInterpolation(
|
const bouncyFriction = quadraticOutInterpolation(
|
||||||
b,
|
b,
|
||||||
b3Nobounce(bouncyTension),
|
b3Nobounce(bouncyTension),
|
||||||
0.01
|
0.01,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @emails oncall+react_native
|
* @emails oncall+react_native
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let Animated = require('Animated');
|
let Animated = require('Animated');
|
||||||
|
@ -15,29 +17,33 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Animated', () => {
|
describe('Animated', () => {
|
||||||
|
|
||||||
it('works end to end', () => {
|
it('works end to end', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
|
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
|
|
||||||
const node = new Animated.__PropsOnlyForTests({
|
const node = new Animated.__PropsOnlyForTests(
|
||||||
style: {
|
{
|
||||||
backgroundColor: 'red',
|
style: {
|
||||||
opacity: anim,
|
backgroundColor: 'red',
|
||||||
transform: [
|
opacity: anim,
|
||||||
{translateX: anim.interpolate({
|
transform: [
|
||||||
inputRange: [0, 1],
|
{
|
||||||
outputRange: [100, 200],
|
translateX: anim.interpolate({
|
||||||
})},
|
inputRange: [0, 1],
|
||||||
{scale: anim},
|
outputRange: [100, 200],
|
||||||
],
|
}),
|
||||||
shadowOffset: {
|
},
|
||||||
width: anim,
|
{scale: anim},
|
||||||
height: anim,
|
],
|
||||||
|
shadowOffset: {
|
||||||
|
width: anim,
|
||||||
|
height: anim,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}, callback);
|
callback,
|
||||||
|
);
|
||||||
|
|
||||||
expect(anim.__getChildren().length).toBe(3);
|
expect(anim.__getChildren().length).toBe(3);
|
||||||
|
|
||||||
|
@ -45,10 +51,7 @@ describe('Animated tests', () => {
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: 'red',
|
backgroundColor: 'red',
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
transform: [
|
transform: [{translateX: 100}, {scale: 0}],
|
||||||
{translateX: 100},
|
|
||||||
{scale: 0},
|
|
||||||
],
|
|
||||||
shadowOffset: {
|
shadowOffset: {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
|
@ -64,10 +67,7 @@ describe('Animated tests', () => {
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: 'red',
|
backgroundColor: 'red',
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
transform: [
|
transform: [{translateX: 150}, {scale: 0.5}],
|
||||||
{translateX: 150},
|
|
||||||
{scale: 0.5},
|
|
||||||
],
|
|
||||||
shadowOffset: {
|
shadowOffset: {
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
height: 0.5,
|
height: 0.5,
|
||||||
|
@ -107,7 +107,6 @@ describe('Animated tests', () => {
|
||||||
expect(anim.__detach).toBeCalled();
|
expect(anim.__detach).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('stops animation when detached', () => {
|
it('stops animation when detached', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
|
@ -141,7 +140,8 @@ describe('Animated tests', () => {
|
||||||
anim.addListener(listener);
|
anim.addListener(listener);
|
||||||
Animated.spring(anim, {toValue: 15}).start();
|
Animated.spring(anim, {toValue: 15}).start();
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
const lastValue = listener.mock.calls[listener.mock.calls.length - 2][0].value;
|
const lastValue =
|
||||||
|
listener.mock.calls[listener.mock.calls.length - 2][0].value;
|
||||||
expect(lastValue).not.toBe(15);
|
expect(lastValue).not.toBe(15);
|
||||||
expect(lastValue).toBeCloseTo(15);
|
expect(lastValue).toBeCloseTo(15);
|
||||||
expect(anim.__getValue()).toBe(15);
|
expect(anim.__getValue()).toBe(15);
|
||||||
|
@ -151,9 +151,14 @@ describe('Animated tests', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
anim.addListener(listener);
|
anim.addListener(listener);
|
||||||
Animated.spring(anim, {stiffness: 8000, damping: 2000, toValue: 15}).start();
|
Animated.spring(anim, {
|
||||||
|
stiffness: 8000,
|
||||||
|
damping: 2000,
|
||||||
|
toValue: 15,
|
||||||
|
}).start();
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
const lastValue = listener.mock.calls[listener.mock.calls.length - 2][0].value;
|
const lastValue =
|
||||||
|
listener.mock.calls[listener.mock.calls.length - 2][0].value;
|
||||||
expect(lastValue).not.toBe(15);
|
expect(lastValue).not.toBe(15);
|
||||||
expect(lastValue).toBeCloseTo(15);
|
expect(lastValue).toBeCloseTo(15);
|
||||||
expect(anim.__getValue()).toBe(15);
|
expect(anim.__getValue()).toBe(15);
|
||||||
|
@ -164,9 +169,7 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('Animated Sequence', () => {
|
describe('Animated Sequence', () => {
|
||||||
|
|
||||||
it('works with an empty sequence', () => {
|
it('works with an empty sequence', () => {
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
Animated.sequence([]).start(cb);
|
Animated.sequence([]).start(cb);
|
||||||
|
@ -232,9 +235,12 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Animated Loop', () => {
|
describe('Animated Loop', () => {
|
||||||
|
|
||||||
it('loops indefinitely if config not specified', () => {
|
it('loops indefinitely if config not specified', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation);
|
const loop = Animated.loop(animation);
|
||||||
|
@ -261,10 +267,14 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loops indefinitely if iterations is -1', () => {
|
it('loops indefinitely if iterations is -1', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation, { iterations: -1 });
|
const loop = Animated.loop(animation, {iterations: -1});
|
||||||
|
|
||||||
expect(animation.start).not.toBeCalled();
|
expect(animation.start).not.toBeCalled();
|
||||||
|
|
||||||
|
@ -288,10 +298,14 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loops indefinitely if iterations not specified', () => {
|
it('loops indefinitely if iterations not specified', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation, { anotherKey: 'value' });
|
const loop = Animated.loop(animation, {anotherKey: 'value'});
|
||||||
|
|
||||||
expect(animation.start).not.toBeCalled();
|
expect(animation.start).not.toBeCalled();
|
||||||
|
|
||||||
|
@ -315,10 +329,14 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loops three times if iterations is 3', () => {
|
it('loops three times if iterations is 3', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation, { iterations: 3 });
|
const loop = Animated.loop(animation, {iterations: 3});
|
||||||
|
|
||||||
expect(animation.start).not.toBeCalled();
|
expect(animation.start).not.toBeCalled();
|
||||||
|
|
||||||
|
@ -342,10 +360,14 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not loop if iterations is 1', () => {
|
it('does not loop if iterations is 1', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation, { iterations: 1 });
|
const loop = Animated.loop(animation, {iterations: 1});
|
||||||
|
|
||||||
expect(animation.start).not.toBeCalled();
|
expect(animation.start).not.toBeCalled();
|
||||||
|
|
||||||
|
@ -359,10 +381,14 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not animate if iterations is 0', () => {
|
it('does not animate if iterations is 0', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation, { iterations: 0 });
|
const loop = Animated.loop(animation, {iterations: 0});
|
||||||
|
|
||||||
expect(animation.start).not.toBeCalled();
|
expect(animation.start).not.toBeCalled();
|
||||||
|
|
||||||
|
@ -373,7 +399,11 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports interrupting an indefinite loop', () => {
|
it('supports interrupting an indefinite loop', () => {
|
||||||
const animation = {start: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
Animated.loop(animation).start(cb);
|
Animated.loop(animation).start(cb);
|
||||||
|
@ -391,7 +421,12 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports stopping loop', () => {
|
it('supports stopping loop', () => {
|
||||||
const animation = {start: jest.fn(), stop: jest.fn(), reset: jest.fn(), _isUsingNativeDriver: () => false};
|
const animation = {
|
||||||
|
start: jest.fn(),
|
||||||
|
stop: jest.fn(),
|
||||||
|
reset: jest.fn(),
|
||||||
|
_isUsingNativeDriver: () => false,
|
||||||
|
};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
|
|
||||||
const loop = Animated.loop(animation);
|
const loop = Animated.loop(animation);
|
||||||
|
@ -409,7 +444,6 @@ describe('Animated tests', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Animated Parallel', () => {
|
describe('Animated Parallel', () => {
|
||||||
|
|
||||||
it('works with an empty parallel', () => {
|
it('works with an empty parallel', () => {
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
Animated.parallel([]).start(cb);
|
Animated.parallel([]).start(cb);
|
||||||
|
@ -470,7 +504,6 @@ describe('Animated tests', () => {
|
||||||
expect(cb).toBeCalledWith({finished: false});
|
expect(cb).toBeCalledWith({finished: false});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('does not call stop more than once when stopping', () => {
|
it('does not call stop more than once when stopping', () => {
|
||||||
const anim1 = {start: jest.fn(), stop: jest.fn()};
|
const anim1 = {start: jest.fn(), stop: jest.fn()};
|
||||||
const anim2 = {start: jest.fn(), stop: jest.fn()};
|
const anim2 = {start: jest.fn(), stop: jest.fn()};
|
||||||
|
@ -504,10 +537,7 @@ describe('Animated tests', () => {
|
||||||
it('should call anim after delay in sequence', () => {
|
it('should call anim after delay in sequence', () => {
|
||||||
const anim = {start: jest.fn(), stop: jest.fn()};
|
const anim = {start: jest.fn(), stop: jest.fn()};
|
||||||
const cb = jest.fn();
|
const cb = jest.fn();
|
||||||
Animated.sequence([
|
Animated.sequence([Animated.delay(1000), anim]).start(cb);
|
||||||
Animated.delay(1000),
|
|
||||||
anim,
|
|
||||||
]).start(cb);
|
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(anim.start.mock.calls.length).toBe(1);
|
expect(anim.start.mock.calls.length).toBe(1);
|
||||||
expect(cb).not.toBeCalled();
|
expect(cb).not.toBeCalled();
|
||||||
|
@ -529,19 +559,14 @@ describe('Animated tests', () => {
|
||||||
describe('Animated Events', () => {
|
describe('Animated Events', () => {
|
||||||
it('should map events', () => {
|
it('should map events', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
const handler = Animated.event(
|
const handler = Animated.event([null, {state: {foo: value}}]);
|
||||||
[null, {state: {foo: value}}],
|
|
||||||
);
|
|
||||||
handler({bar: 'ignoreBar'}, {state: {baz: 'ignoreBaz', foo: 42}});
|
handler({bar: 'ignoreBar'}, {state: {baz: 'ignoreBaz', foo: 42}});
|
||||||
expect(value.__getValue()).toBe(42);
|
expect(value.__getValue()).toBe(42);
|
||||||
});
|
});
|
||||||
it('should call listeners', () => {
|
it('should call listeners', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
const handler = Animated.event(
|
const handler = Animated.event([{foo: value}], {listener});
|
||||||
[{foo: value}],
|
|
||||||
{listener},
|
|
||||||
);
|
|
||||||
handler({foo: 42});
|
handler({foo: 42});
|
||||||
expect(value.__getValue()).toBe(42);
|
expect(value.__getValue()).toBe(42);
|
||||||
expect(listener.mock.calls.length).toBe(1);
|
expect(listener.mock.calls.length).toBe(1);
|
||||||
|
@ -550,10 +575,7 @@ describe('Animated tests', () => {
|
||||||
it('should call forked event listeners', () => {
|
it('should call forked event listeners', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
const handler = Animated.event(
|
const handler = Animated.event([{foo: value}], {listener});
|
||||||
[{foo: value}],
|
|
||||||
{listener},
|
|
||||||
);
|
|
||||||
const listener2 = jest.fn();
|
const listener2 = jest.fn();
|
||||||
const forkedHandler = Animated.forkEvent(handler, listener2);
|
const forkedHandler = Animated.forkEvent(handler, listener2);
|
||||||
forkedHandler({foo: 42});
|
forkedHandler({foo: 42});
|
||||||
|
@ -577,7 +599,7 @@ describe('Animated tests', () => {
|
||||||
InteractionManager = require('InteractionManager');
|
InteractionManager = require('InteractionManager');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(()=> {
|
afterEach(() => {
|
||||||
jest.unmock('InteractionManager');
|
jest.unmock('InteractionManager');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -633,7 +655,7 @@ describe('Animated tests', () => {
|
||||||
Animated.timing(value2, {
|
Animated.timing(value2, {
|
||||||
toValue: value1.interpolate({
|
toValue: value1.interpolate({
|
||||||
inputRange: [0, 2],
|
inputRange: [0, 2],
|
||||||
outputRange: [0, 1]
|
outputRange: [0, 1],
|
||||||
}),
|
}),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
}).start();
|
}).start();
|
||||||
|
@ -665,24 +687,24 @@ describe('Animated tests', () => {
|
||||||
|
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
|
|
||||||
const node = new Animated.__PropsOnlyForTests({
|
const node = new Animated.__PropsOnlyForTests(
|
||||||
style: {
|
{
|
||||||
opacity: vec.x.interpolate({
|
style: {
|
||||||
inputRange: [0, 42],
|
opacity: vec.x.interpolate({
|
||||||
outputRange: [0.2, 0.8],
|
inputRange: [0, 42],
|
||||||
}),
|
outputRange: [0.2, 0.8],
|
||||||
transform: vec.getTranslateTransform(),
|
}),
|
||||||
...vec.getLayout(),
|
transform: vec.getTranslateTransform(),
|
||||||
}
|
...vec.getLayout(),
|
||||||
}, callback);
|
},
|
||||||
|
},
|
||||||
|
callback,
|
||||||
|
);
|
||||||
|
|
||||||
expect(node.__getValue()).toEqual({
|
expect(node.__getValue()).toEqual({
|
||||||
style: {
|
style: {
|
||||||
opacity: 0.2,
|
opacity: 0.2,
|
||||||
transform: [
|
transform: [{translateX: 0}, {translateY: 0}],
|
||||||
{translateX: 0},
|
|
||||||
{translateY: 0},
|
|
||||||
],
|
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
},
|
},
|
||||||
|
@ -695,10 +717,7 @@ describe('Animated tests', () => {
|
||||||
expect(node.__getValue()).toEqual({
|
expect(node.__getValue()).toEqual({
|
||||||
style: {
|
style: {
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
transform: [
|
transform: [{translateX: 42}, {translateY: 1492}],
|
||||||
{translateX: 42},
|
|
||||||
{translateY: 1492},
|
|
||||||
],
|
|
||||||
left: 42,
|
left: 42,
|
||||||
top: 1492,
|
top: 1492,
|
||||||
},
|
},
|
||||||
|
@ -767,7 +786,7 @@ describe('Animated tests', () => {
|
||||||
it('should removeAll', () => {
|
it('should removeAll', () => {
|
||||||
const value1 = new Animated.Value(0);
|
const value1 = new Animated.Value(0);
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
[1,2,3,4].forEach(() => value1.addListener(listener));
|
[1, 2, 3, 4].forEach(() => value1.addListener(listener));
|
||||||
value1.setValue(42);
|
value1.setValue(42);
|
||||||
expect(listener.mock.calls.length).toBe(4);
|
expect(listener.mock.calls.length).toBe(4);
|
||||||
expect(listener).toBeCalledWith({value: 42});
|
expect(listener).toBeCalledWith({value: 42});
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @emails oncall+react_native
|
* @emails oncall+react_native
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ClassComponentMock = class {};
|
const ClassComponentMock = class {};
|
||||||
|
@ -39,7 +41,6 @@ function createAndMountComponent(ComponentClass, props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Native Animated', () => {
|
describe('Native Animated', () => {
|
||||||
|
|
||||||
const nativeAnimatedModule = require('NativeModules').NativeAnimatedModule;
|
const nativeAnimatedModule = require('NativeModules').NativeAnimatedModule;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -64,7 +65,11 @@ describe('Native Animated', () => {
|
||||||
describe('Animated Value', () => {
|
describe('Animated Value', () => {
|
||||||
it('proxies `setValue` correctly', () => {
|
it('proxies `setValue` correctly', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
Animated.timing(anim, {toValue: 10, duration: 1000, useNativeDriver: true}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 1000,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
|
||||||
const c = createAndMountComponent(Animated.View, {
|
const c = createAndMountComponent(Animated.View, {
|
||||||
style: {
|
style: {
|
||||||
|
@ -82,7 +87,10 @@ describe('Native Animated', () => {
|
||||||
|
|
||||||
anim.setValue(0.5);
|
anim.setValue(0.5);
|
||||||
|
|
||||||
expect(nativeAnimatedModule.setAnimatedNodeValue).toBeCalledWith(expect.any(Number), 0.5);
|
expect(nativeAnimatedModule.setAnimatedNodeValue).toBeCalledWith(
|
||||||
|
expect.any(Number),
|
||||||
|
0.5,
|
||||||
|
);
|
||||||
expect(c.refs.node.setNativeProps).not.toHaveBeenCalled();
|
expect(c.refs.node.setNativeProps).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -101,8 +109,10 @@ describe('Native Animated', () => {
|
||||||
{type: 'value', value: 0, offset: 10},
|
{type: 'value', value: 0, offset: 10},
|
||||||
);
|
);
|
||||||
anim.setOffset(20);
|
anim.setOffset(20);
|
||||||
expect(nativeAnimatedModule.setAnimatedNodeOffset)
|
expect(nativeAnimatedModule.setAnimatedNodeOffset).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number), 20);
|
expect.any(Number),
|
||||||
|
20,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should flatten offset', () => {
|
it('should flatten offset', () => {
|
||||||
|
@ -119,8 +129,9 @@ describe('Native Animated', () => {
|
||||||
{type: 'value', value: 0, offset: 0},
|
{type: 'value', value: 0, offset: 0},
|
||||||
);
|
);
|
||||||
anim.flattenOffset();
|
anim.flattenOffset();
|
||||||
expect(nativeAnimatedModule.flattenAnimatedNodeOffset)
|
expect(nativeAnimatedModule.flattenAnimatedNodeOffset).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number));
|
expect.any(Number),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extract offset', () => {
|
it('should extract offset', () => {
|
||||||
|
@ -137,8 +148,9 @@ describe('Native Animated', () => {
|
||||||
{type: 'value', value: 0, offset: 0},
|
{type: 'value', value: 0, offset: 0},
|
||||||
);
|
);
|
||||||
anim.extractOffset();
|
anim.extractOffset();
|
||||||
expect(nativeAnimatedModule.extractAnimatedNodeOffset)
|
expect(nativeAnimatedModule.extractAnimatedNodeOffset).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number));
|
expect.any(Number),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -148,33 +160,35 @@ describe('Native Animated', () => {
|
||||||
value1.__makeNative();
|
value1.__makeNative();
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
const id = value1.addListener(listener);
|
const id = value1.addListener(listener);
|
||||||
expect(nativeAnimatedModule.startListeningToAnimatedNodeValue)
|
expect(
|
||||||
.toHaveBeenCalledWith(value1.__getNativeTag());
|
nativeAnimatedModule.startListeningToAnimatedNodeValue,
|
||||||
|
).toHaveBeenCalledWith(value1.__getNativeTag());
|
||||||
|
|
||||||
NativeAnimatedHelper.nativeEventEmitter.emit(
|
NativeAnimatedHelper.nativeEventEmitter.emit('onAnimatedValueUpdate', {
|
||||||
'onAnimatedValueUpdate',
|
value: 42,
|
||||||
{value: 42, tag: value1.__getNativeTag()},
|
tag: value1.__getNativeTag(),
|
||||||
);
|
});
|
||||||
expect(listener).toHaveBeenCalledTimes(1);
|
expect(listener).toHaveBeenCalledTimes(1);
|
||||||
expect(listener).toBeCalledWith({value: 42});
|
expect(listener).toBeCalledWith({value: 42});
|
||||||
expect(value1.__getValue()).toBe(42);
|
expect(value1.__getValue()).toBe(42);
|
||||||
|
|
||||||
NativeAnimatedHelper.nativeEventEmitter.emit(
|
NativeAnimatedHelper.nativeEventEmitter.emit('onAnimatedValueUpdate', {
|
||||||
'onAnimatedValueUpdate',
|
value: 7,
|
||||||
{value: 7, tag: value1.__getNativeTag()},
|
tag: value1.__getNativeTag(),
|
||||||
);
|
});
|
||||||
expect(listener).toHaveBeenCalledTimes(2);
|
expect(listener).toHaveBeenCalledTimes(2);
|
||||||
expect(listener).toBeCalledWith({value: 7});
|
expect(listener).toBeCalledWith({value: 7});
|
||||||
expect(value1.__getValue()).toBe(7);
|
expect(value1.__getValue()).toBe(7);
|
||||||
|
|
||||||
value1.removeListener(id);
|
value1.removeListener(id);
|
||||||
expect(nativeAnimatedModule.stopListeningToAnimatedNodeValue)
|
expect(
|
||||||
.toHaveBeenCalledWith(value1.__getNativeTag());
|
nativeAnimatedModule.stopListeningToAnimatedNodeValue,
|
||||||
|
).toHaveBeenCalledWith(value1.__getNativeTag());
|
||||||
|
|
||||||
NativeAnimatedHelper.nativeEventEmitter.emit(
|
NativeAnimatedHelper.nativeEventEmitter.emit('onAnimatedValueUpdate', {
|
||||||
'onAnimatedValueUpdate',
|
value: 1492,
|
||||||
{value: 1492, tag: value1.__getNativeTag()},
|
tag: value1.__getNativeTag(),
|
||||||
);
|
});
|
||||||
expect(listener).toHaveBeenCalledTimes(2);
|
expect(listener).toHaveBeenCalledTimes(2);
|
||||||
expect(value1.__getValue()).toBe(7);
|
expect(value1.__getValue()).toBe(7);
|
||||||
});
|
});
|
||||||
|
@ -183,25 +197,27 @@ describe('Native Animated', () => {
|
||||||
const value1 = new Animated.Value(0);
|
const value1 = new Animated.Value(0);
|
||||||
value1.__makeNative();
|
value1.__makeNative();
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
[1,2,3,4].forEach(() => value1.addListener(listener));
|
[1, 2, 3, 4].forEach(() => value1.addListener(listener));
|
||||||
expect(nativeAnimatedModule.startListeningToAnimatedNodeValue)
|
expect(
|
||||||
.toHaveBeenCalledWith(value1.__getNativeTag());
|
nativeAnimatedModule.startListeningToAnimatedNodeValue,
|
||||||
|
).toHaveBeenCalledWith(value1.__getNativeTag());
|
||||||
|
|
||||||
NativeAnimatedHelper.nativeEventEmitter.emit(
|
NativeAnimatedHelper.nativeEventEmitter.emit('onAnimatedValueUpdate', {
|
||||||
'onAnimatedValueUpdate',
|
value: 42,
|
||||||
{value: 42, tag: value1.__getNativeTag()},
|
tag: value1.__getNativeTag(),
|
||||||
);
|
});
|
||||||
expect(listener).toHaveBeenCalledTimes(4);
|
expect(listener).toHaveBeenCalledTimes(4);
|
||||||
expect(listener).toBeCalledWith({value: 42});
|
expect(listener).toBeCalledWith({value: 42});
|
||||||
|
|
||||||
value1.removeAllListeners();
|
value1.removeAllListeners();
|
||||||
expect(nativeAnimatedModule.stopListeningToAnimatedNodeValue)
|
expect(
|
||||||
.toHaveBeenCalledWith(value1.__getNativeTag());
|
nativeAnimatedModule.stopListeningToAnimatedNodeValue,
|
||||||
|
).toHaveBeenCalledWith(value1.__getNativeTag());
|
||||||
|
|
||||||
NativeAnimatedHelper.nativeEventEmitter.emit(
|
NativeAnimatedHelper.nativeEventEmitter.emit('onAnimatedValueUpdate', {
|
||||||
'onAnimatedValueUpdate',
|
value: 7,
|
||||||
{value: 7, tag: value1.__getNativeTag()},
|
tag: value1.__getNativeTag(),
|
||||||
);
|
});
|
||||||
expect(listener).toHaveBeenCalledTimes(4);
|
expect(listener).toHaveBeenCalledTimes(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -210,15 +226,17 @@ describe('Native Animated', () => {
|
||||||
it('should map events', () => {
|
it('should map events', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
value.__makeNative();
|
value.__makeNative();
|
||||||
const event = Animated.event(
|
const event = Animated.event([{nativeEvent: {state: {foo: value}}}], {
|
||||||
[{nativeEvent: {state: {foo: value}}}],
|
useNativeDriver: true,
|
||||||
{useNativeDriver: true},
|
});
|
||||||
);
|
|
||||||
const c = createAndMountComponent(Animated.View, {onTouchMove: event});
|
const c = createAndMountComponent(Animated.View, {onTouchMove: event});
|
||||||
expect(nativeAnimatedModule.addAnimatedEventToView).toBeCalledWith(
|
expect(nativeAnimatedModule.addAnimatedEventToView).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
'onTouchMove',
|
'onTouchMove',
|
||||||
{nativeEventPath: ['state', 'foo'], animatedValueTag: value.__getNativeTag()},
|
{
|
||||||
|
nativeEventPath: ['state', 'foo'],
|
||||||
|
animatedValueTag: value.__getNativeTag(),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
c.componentWillUnmount();
|
c.componentWillUnmount();
|
||||||
|
@ -232,12 +250,12 @@ describe('Native Animated', () => {
|
||||||
it('should throw on invalid event path', () => {
|
it('should throw on invalid event path', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
value.__makeNative();
|
value.__makeNative();
|
||||||
const event = Animated.event(
|
const event = Animated.event([{notNativeEvent: {foo: value}}], {
|
||||||
[{notNativeEvent: {foo: value}}],
|
useNativeDriver: true,
|
||||||
{useNativeDriver: true},
|
});
|
||||||
);
|
expect(() =>
|
||||||
expect(() => createAndMountComponent(Animated.View, {onTouchMove: event}))
|
createAndMountComponent(Animated.View, {onTouchMove: event}),
|
||||||
.toThrowError(/nativeEvent/);
|
).toThrowError(/nativeEvent/);
|
||||||
expect(nativeAnimatedModule.addAnimatedEventToView).not.toBeCalled();
|
expect(nativeAnimatedModule.addAnimatedEventToView).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -245,10 +263,10 @@ describe('Native Animated', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
value.__makeNative();
|
value.__makeNative();
|
||||||
const listener = jest.fn();
|
const listener = jest.fn();
|
||||||
const event = Animated.event(
|
const event = Animated.event([{nativeEvent: {foo: value}}], {
|
||||||
[{nativeEvent: {foo: value}}],
|
useNativeDriver: true,
|
||||||
{useNativeDriver: true, listener},
|
listener,
|
||||||
);
|
});
|
||||||
const handler = event.__getHandler();
|
const handler = event.__getHandler();
|
||||||
handler({foo: 42});
|
handler({foo: 42});
|
||||||
expect(listener).toHaveBeenCalledTimes(1);
|
expect(listener).toHaveBeenCalledTimes(1);
|
||||||
|
@ -265,21 +283,34 @@ describe('Native Animated', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Animated.timing(anim, {toValue: 10, duration: 1000, useNativeDriver: true}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 1000,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
|
||||||
c.componentWillUnmount();
|
c.componentWillUnmount();
|
||||||
|
|
||||||
expect(nativeAnimatedModule.createAnimatedNode).toHaveBeenCalledTimes(3);
|
expect(nativeAnimatedModule.createAnimatedNode).toHaveBeenCalledTimes(3);
|
||||||
expect(nativeAnimatedModule.connectAnimatedNodes).toHaveBeenCalledTimes(2);
|
expect(nativeAnimatedModule.connectAnimatedNodes).toHaveBeenCalledTimes(
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{type: 'frames', frames: expect.any(Array), toValue: expect.any(Number), iterations: 1},
|
{
|
||||||
expect.any(Function)
|
type: 'frames',
|
||||||
|
frames: expect.any(Array),
|
||||||
|
toValue: expect.any(Number),
|
||||||
|
iterations: 1,
|
||||||
|
},
|
||||||
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(nativeAnimatedModule.disconnectAnimatedNodes).toHaveBeenCalledTimes(2);
|
expect(
|
||||||
|
nativeAnimatedModule.disconnectAnimatedNodes,
|
||||||
|
).toHaveBeenCalledTimes(2);
|
||||||
expect(nativeAnimatedModule.dropAnimatedNode).toHaveBeenCalledTimes(3);
|
expect(nativeAnimatedModule.dropAnimatedNode).toHaveBeenCalledTimes(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -291,14 +322,24 @@ describe('Native Animated', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Animated.timing(anim, {toValue: 10, duration: 1000, useNativeDriver: true}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 1000,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number), {type: 'value', value: 0, offset: 0});
|
expect.any(Number),
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
{type: 'value', value: 0, offset: 0},
|
||||||
.toBeCalledWith(expect.any(Number), {type: 'style', style: {opacity: expect.any(Number)}});
|
);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number), {type: 'props', props: {style: expect.any(Number)}});
|
expect.any(Number),
|
||||||
|
{type: 'style', style: {opacity: expect.any(Number)}},
|
||||||
|
);
|
||||||
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
|
expect.any(Number),
|
||||||
|
{type: 'props', props: {style: expect.any(Number)}},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for Animated.add nodes', () => {
|
it('sends a valid graph description for Animated.add nodes', () => {
|
||||||
|
@ -318,19 +359,23 @@ describe('Native Animated', () => {
|
||||||
{type: 'addition', input: expect.any(Array)},
|
{type: 'addition', input: expect.any(Array)},
|
||||||
);
|
);
|
||||||
const additionCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
const additionCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
||||||
(call) => call[1].type === 'addition'
|
call => call[1].type === 'addition',
|
||||||
);
|
);
|
||||||
expect(additionCalls.length).toBe(1);
|
expect(additionCalls.length).toBe(1);
|
||||||
const additionCall = additionCalls[0];
|
const additionCall = additionCalls[0];
|
||||||
const additionNodeTag = additionCall[0];
|
const additionNodeTag = additionCall[0];
|
||||||
const additionConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
const additionConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
||||||
(call) => call[1] === additionNodeTag
|
call => call[1] === additionNodeTag,
|
||||||
);
|
);
|
||||||
expect(additionConnectionCalls.length).toBe(2);
|
expect(additionConnectionCalls.length).toBe(2);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(additionCall[1].input[0], {type: 'value', value: 1, offset: 0});
|
additionCall[1].input[0],
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
{type: 'value', value: 1, offset: 0},
|
||||||
.toBeCalledWith(additionCall[1].input[1], {type: 'value', value: 2, offset: 0});
|
);
|
||||||
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
|
additionCall[1].input[1],
|
||||||
|
{type: 'value', value: 2, offset: 0},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for Animated.subtract nodes', () => {
|
it('sends a valid graph description for Animated.subtract nodes', () => {
|
||||||
|
@ -350,19 +395,23 @@ describe('Native Animated', () => {
|
||||||
{type: 'subtraction', input: expect.any(Array)},
|
{type: 'subtraction', input: expect.any(Array)},
|
||||||
);
|
);
|
||||||
const subtractionCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
const subtractionCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
||||||
(call) => call[1].type === 'subtraction'
|
call => call[1].type === 'subtraction',
|
||||||
);
|
);
|
||||||
expect(subtractionCalls.length).toBe(1);
|
expect(subtractionCalls.length).toBe(1);
|
||||||
const subtractionCall = subtractionCalls[0];
|
const subtractionCall = subtractionCalls[0];
|
||||||
const subtractionNodeTag = subtractionCall[0];
|
const subtractionNodeTag = subtractionCall[0];
|
||||||
const subtractionConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
const subtractionConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
||||||
(call) => call[1] === subtractionNodeTag
|
call => call[1] === subtractionNodeTag,
|
||||||
);
|
);
|
||||||
expect(subtractionConnectionCalls.length).toBe(2);
|
expect(subtractionConnectionCalls.length).toBe(2);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(subtractionCall[1].input[0], {type: 'value', value: 2, offset: 0});
|
subtractionCall[1].input[0],
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
{type: 'value', value: 2, offset: 0},
|
||||||
.toBeCalledWith(subtractionCall[1].input[1], {type: 'value', value: 1, offset: 0});
|
);
|
||||||
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
|
subtractionCall[1].input[1],
|
||||||
|
{type: 'value', value: 1, offset: 0},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for Animated.multiply nodes', () => {
|
it('sends a valid graph description for Animated.multiply nodes', () => {
|
||||||
|
@ -382,19 +431,23 @@ describe('Native Animated', () => {
|
||||||
{type: 'multiplication', input: expect.any(Array)},
|
{type: 'multiplication', input: expect.any(Array)},
|
||||||
);
|
);
|
||||||
const multiplicationCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
const multiplicationCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
||||||
(call) => call[1].type === 'multiplication'
|
call => call[1].type === 'multiplication',
|
||||||
);
|
);
|
||||||
expect(multiplicationCalls.length).toBe(1);
|
expect(multiplicationCalls.length).toBe(1);
|
||||||
const multiplicationCall = multiplicationCalls[0];
|
const multiplicationCall = multiplicationCalls[0];
|
||||||
const multiplicationNodeTag = multiplicationCall[0];
|
const multiplicationNodeTag = multiplicationCall[0];
|
||||||
const multiplicationConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
const multiplicationConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
||||||
(call) => call[1] === multiplicationNodeTag
|
call => call[1] === multiplicationNodeTag,
|
||||||
);
|
);
|
||||||
expect(multiplicationConnectionCalls.length).toBe(2);
|
expect(multiplicationConnectionCalls.length).toBe(2);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(multiplicationCall[1].input[0], {type: 'value', value: 2, offset: 0});
|
multiplicationCall[1].input[0],
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
{type: 'value', value: 2, offset: 0},
|
||||||
.toBeCalledWith(multiplicationCall[1].input[1], {type: 'value', value: 1, offset: 0});
|
);
|
||||||
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
|
multiplicationCall[1].input[1],
|
||||||
|
{type: 'value', value: 1, offset: 0},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for Animated.divide nodes', () => {
|
it('sends a valid graph description for Animated.divide nodes', () => {
|
||||||
|
@ -409,22 +462,28 @@ describe('Native Animated', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number), {type: 'division', input: expect.any(Array)});
|
expect.any(Number),
|
||||||
|
{type: 'division', input: expect.any(Array)},
|
||||||
|
);
|
||||||
const divisionCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
const divisionCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
||||||
(call) => call[1].type === 'division'
|
call => call[1].type === 'division',
|
||||||
);
|
);
|
||||||
expect(divisionCalls.length).toBe(1);
|
expect(divisionCalls.length).toBe(1);
|
||||||
const divisionCall = divisionCalls[0];
|
const divisionCall = divisionCalls[0];
|
||||||
const divisionNodeTag = divisionCall[0];
|
const divisionNodeTag = divisionCall[0];
|
||||||
const divisionConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
const divisionConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
||||||
(call) => call[1] === divisionNodeTag
|
call => call[1] === divisionNodeTag,
|
||||||
);
|
);
|
||||||
expect(divisionConnectionCalls.length).toBe(2);
|
expect(divisionConnectionCalls.length).toBe(2);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(divisionCall[1].input[0], {type: 'value', value: 4, offset: 0});
|
divisionCall[1].input[0],
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
{type: 'value', value: 4, offset: 0},
|
||||||
.toBeCalledWith(divisionCall[1].input[1], {type: 'value', value: 2, offset: 0});
|
);
|
||||||
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
|
divisionCall[1].input[1],
|
||||||
|
{type: 'value', value: 2, offset: 0},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for Animated.modulo nodes', () => {
|
it('sends a valid graph description for Animated.modulo nodes', () => {
|
||||||
|
@ -442,17 +501,19 @@ describe('Native Animated', () => {
|
||||||
{type: 'modulus', modulus: 4, input: expect.any(Number)},
|
{type: 'modulus', modulus: 4, input: expect.any(Number)},
|
||||||
);
|
);
|
||||||
const moduloCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
const moduloCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
||||||
(call) => call[1].type === 'modulus'
|
call => call[1].type === 'modulus',
|
||||||
);
|
);
|
||||||
expect(moduloCalls.length).toBe(1);
|
expect(moduloCalls.length).toBe(1);
|
||||||
const moduloCall = moduloCalls[0];
|
const moduloCall = moduloCalls[0];
|
||||||
const moduloNodeTag = moduloCall[0];
|
const moduloNodeTag = moduloCall[0];
|
||||||
const moduloConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
const moduloConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
||||||
(call) => call[1] === moduloNodeTag
|
call => call[1] === moduloNodeTag,
|
||||||
);
|
);
|
||||||
expect(moduloConnectionCalls.length).toBe(1);
|
expect(moduloConnectionCalls.length).toBe(1);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(moduloCall[1].input, {type: 'value', value: 4, offset: 0});
|
moduloCall[1].input,
|
||||||
|
{type: 'value', value: 4, offset: 0},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for interpolate() nodes', () => {
|
it('sends a valid graph description for interpolate() nodes', () => {
|
||||||
|
@ -470,23 +531,28 @@ describe('Native Animated', () => {
|
||||||
|
|
||||||
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{type: 'value', value: 10, offset: 0}
|
{type: 'value', value: 10, offset: 0},
|
||||||
);
|
);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number), {
|
expect.any(Number),
|
||||||
|
{
|
||||||
type: 'interpolation',
|
type: 'interpolation',
|
||||||
inputRange: [10, 20],
|
inputRange: [10, 20],
|
||||||
outputRange: [0, 1],
|
outputRange: [0, 1],
|
||||||
extrapolateLeft: 'extend',
|
extrapolateLeft: 'extend',
|
||||||
extrapolateRight: 'extend',
|
extrapolateRight: 'extend',
|
||||||
});
|
},
|
||||||
|
);
|
||||||
const interpolationNodeTag = nativeAnimatedModule.createAnimatedNode.mock.calls.find(
|
const interpolationNodeTag = nativeAnimatedModule.createAnimatedNode.mock.calls.find(
|
||||||
(call) => call[1].type === 'interpolation'
|
call => call[1].type === 'interpolation',
|
||||||
)[0];
|
)[0];
|
||||||
const valueNodeTag = nativeAnimatedModule.createAnimatedNode.mock.calls.find(
|
const valueNodeTag = nativeAnimatedModule.createAnimatedNode.mock.calls.find(
|
||||||
(call) => call[1].type === 'value'
|
call => call[1].type === 'value',
|
||||||
)[0];
|
)[0];
|
||||||
expect(nativeAnimatedModule.connectAnimatedNodes).toBeCalledWith(valueNodeTag, interpolationNodeTag);
|
expect(nativeAnimatedModule.connectAnimatedNodes).toBeCalledWith(
|
||||||
|
valueNodeTag,
|
||||||
|
interpolationNodeTag,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid graph description for transform nodes', () => {
|
it('sends a valid graph description for transform nodes', () => {
|
||||||
|
@ -503,15 +569,18 @@ describe('Native Animated', () => {
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{
|
{
|
||||||
type: 'transform',
|
type: 'transform',
|
||||||
transforms: [{
|
transforms: [
|
||||||
nodeTag: expect.any(Number),
|
{
|
||||||
property: 'translateX',
|
nodeTag: expect.any(Number),
|
||||||
type: 'animated',
|
property: 'translateX',
|
||||||
}, {
|
type: 'animated',
|
||||||
value: 2,
|
},
|
||||||
property: 'scale',
|
{
|
||||||
type: 'static',
|
value: 2,
|
||||||
}],
|
property: 'scale',
|
||||||
|
type: 'static',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -531,20 +600,22 @@ describe('Native Animated', () => {
|
||||||
{type: 'diffclamp', input: expect.any(Number), max: 20, min: 0},
|
{type: 'diffclamp', input: expect.any(Number), max: 20, min: 0},
|
||||||
);
|
);
|
||||||
const diffClampCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
const diffClampCalls = nativeAnimatedModule.createAnimatedNode.mock.calls.filter(
|
||||||
(call) => call[1].type === 'diffclamp'
|
call => call[1].type === 'diffclamp',
|
||||||
);
|
);
|
||||||
expect(diffClampCalls.length).toBe(1);
|
expect(diffClampCalls.length).toBe(1);
|
||||||
const diffClampCall = diffClampCalls[0];
|
const diffClampCall = diffClampCalls[0];
|
||||||
const diffClampNodeTag = diffClampCall[0];
|
const diffClampNodeTag = diffClampCall[0];
|
||||||
const diffClampConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
const diffClampConnectionCalls = nativeAnimatedModule.connectAnimatedNodes.mock.calls.filter(
|
||||||
(call) => call[1] === diffClampNodeTag
|
call => call[1] === diffClampNodeTag,
|
||||||
);
|
);
|
||||||
expect(diffClampConnectionCalls.length).toBe(1);
|
expect(diffClampConnectionCalls.length).toBe(1);
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(diffClampCall[1].input, {type: 'value', value: 2, offset: 0});
|
diffClampCall[1].input,
|
||||||
|
{type: 'value', value: 2, offset: 0},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('doesn\'t call into native API if useNativeDriver is set to false', () => {
|
it("doesn't call into native API if useNativeDriver is set to false", () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
|
|
||||||
const c = createAndMountComponent(Animated.View, {
|
const c = createAndMountComponent(Animated.View, {
|
||||||
|
@ -553,7 +624,11 @@ describe('Native Animated', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Animated.timing(anim, {toValue: 10, duration: 1000, useNativeDriver: false}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 1000,
|
||||||
|
useNativeDriver: false,
|
||||||
|
}).start();
|
||||||
|
|
||||||
c.componentWillUnmount();
|
c.componentWillUnmount();
|
||||||
|
|
||||||
|
@ -569,10 +644,18 @@ describe('Native Animated', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Animated.timing(anim, {toValue: 10, duration: 50, useNativeDriver: true}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 50,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
|
|
||||||
Animated.timing(anim, {toValue: 4, duration: 500, useNativeDriver: false}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 4,
|
||||||
|
duration: 500,
|
||||||
|
useNativeDriver: false,
|
||||||
|
}).start();
|
||||||
expect(jest.runAllTimers).toThrow();
|
expect(jest.runAllTimers).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -585,7 +668,11 @@ describe('Native Animated', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const animation = Animated.timing(anim, {toValue: 10, duration: 50, useNativeDriver: true});
|
const animation = Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 50,
|
||||||
|
useNativeDriver: true,
|
||||||
|
});
|
||||||
expect(animation.start).toThrowError(/left/);
|
expect(animation.start).toThrowError(/left/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -603,29 +690,47 @@ describe('Native Animated', () => {
|
||||||
removeClippedSubviews: true,
|
removeClippedSubviews: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
.toBeCalledWith(expect.any(Number), { type: 'style', style: { opacity: expect.any(Number) }});
|
expect.any(Number),
|
||||||
expect(nativeAnimatedModule.createAnimatedNode)
|
{type: 'style', style: {opacity: expect.any(Number)}},
|
||||||
.toBeCalledWith(expect.any(Number), { type: 'props', props: { style: expect.any(Number) }});
|
);
|
||||||
|
expect(nativeAnimatedModule.createAnimatedNode).toBeCalledWith(
|
||||||
|
expect.any(Number),
|
||||||
|
{type: 'props', props: {style: expect.any(Number)}},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Animations', () => {
|
describe('Animations', () => {
|
||||||
it('sends a valid timing animation description', () => {
|
it('sends a valid timing animation description', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
Animated.timing(anim, {toValue: 10, duration: 1000, useNativeDriver: true}).start();
|
Animated.timing(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 1000,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{type: 'frames', frames: expect.any(Array), toValue: expect.any(Number), iterations: 1},
|
{
|
||||||
expect.any(Function)
|
type: 'frames',
|
||||||
|
frames: expect.any(Array),
|
||||||
|
toValue: expect.any(Number),
|
||||||
|
iterations: 1,
|
||||||
|
},
|
||||||
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid spring animation description', () => {
|
it('sends a valid spring animation description', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
Animated.spring(anim, {toValue: 10, friction: 5, tension: 164, useNativeDriver: true}).start();
|
Animated.spring(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
friction: 5,
|
||||||
|
tension: 164,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
|
@ -641,7 +746,7 @@ describe('Native Animated', () => {
|
||||||
toValue: 10,
|
toValue: 10,
|
||||||
iterations: 1,
|
iterations: 1,
|
||||||
},
|
},
|
||||||
expect.any(Function)
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
|
|
||||||
Animated.spring(anim, {
|
Animated.spring(anim, {
|
||||||
|
@ -649,7 +754,7 @@ describe('Native Animated', () => {
|
||||||
stiffness: 1000,
|
stiffness: 1000,
|
||||||
damping: 500,
|
damping: 500,
|
||||||
mass: 3,
|
mass: 3,
|
||||||
useNativeDriver: true
|
useNativeDriver: true,
|
||||||
}).start();
|
}).start();
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
|
@ -666,10 +771,15 @@ describe('Native Animated', () => {
|
||||||
toValue: 10,
|
toValue: 10,
|
||||||
iterations: 1,
|
iterations: 1,
|
||||||
},
|
},
|
||||||
expect.any(Function)
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
|
|
||||||
Animated.spring(anim, {toValue: 10, bounciness: 8, speed: 10, useNativeDriver: true}).start();
|
Animated.spring(anim, {
|
||||||
|
toValue: 10,
|
||||||
|
bounciness: 8,
|
||||||
|
speed: 10,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
|
@ -685,49 +795,67 @@ describe('Native Animated', () => {
|
||||||
toValue: 10,
|
toValue: 10,
|
||||||
iterations: 1,
|
iterations: 1,
|
||||||
},
|
},
|
||||||
expect.any(Function)
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a valid decay animation description', () => {
|
it('sends a valid decay animation description', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
Animated.decay(anim, {velocity: 10, deceleration: 0.1, useNativeDriver: true}).start();
|
Animated.decay(anim, {
|
||||||
|
velocity: 10,
|
||||||
|
deceleration: 0.1,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{type: 'decay', deceleration: 0.1, velocity: 10, iterations: 1},
|
{type: 'decay', deceleration: 0.1, velocity: 10, iterations: 1},
|
||||||
expect.any(Function)
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works with Animated.loop', () => {
|
it('works with Animated.loop', () => {
|
||||||
const anim = new Animated.Value(0);
|
const anim = new Animated.Value(0);
|
||||||
Animated.loop(
|
Animated.loop(
|
||||||
Animated.decay(anim, {velocity: 10, deceleration: 0.1, useNativeDriver: true}),
|
Animated.decay(anim, {
|
||||||
{ iterations: 10 },
|
velocity: 10,
|
||||||
|
deceleration: 0.1,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}),
|
||||||
|
{iterations: 10},
|
||||||
).start();
|
).start();
|
||||||
|
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{type: 'decay', deceleration: 0.1, velocity: 10, iterations: 10},
|
{type: 'decay', deceleration: 0.1, velocity: 10, iterations: 10},
|
||||||
expect.any(Function)
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends stopAnimation command to native', () => {
|
it('sends stopAnimation command to native', () => {
|
||||||
const value = new Animated.Value(0);
|
const value = new Animated.Value(0);
|
||||||
const animation = Animated.timing(value, {toValue: 10, duration: 50, useNativeDriver: true});
|
const animation = Animated.timing(value, {
|
||||||
|
toValue: 10,
|
||||||
|
duration: 50,
|
||||||
|
useNativeDriver: true,
|
||||||
|
});
|
||||||
|
|
||||||
animation.start();
|
animation.start();
|
||||||
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
expect(nativeAnimatedModule.startAnimatingNode).toBeCalledWith(
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
expect.any(Number),
|
expect.any(Number),
|
||||||
{type: 'frames', frames: expect.any(Array), toValue: expect.any(Number), iterations: 1},
|
{
|
||||||
expect.any(Function)
|
type: 'frames',
|
||||||
|
frames: expect.any(Array),
|
||||||
|
toValue: expect.any(Number),
|
||||||
|
iterations: 1,
|
||||||
|
},
|
||||||
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
const animationId = nativeAnimatedModule.startAnimatingNode.mock.calls[0][0];
|
const animationId =
|
||||||
|
nativeAnimatedModule.startAnimatingNode.mock.calls[0][0];
|
||||||
|
|
||||||
animation.stop();
|
animation.stop();
|
||||||
expect(nativeAnimatedModule.stopAnimation).toBeCalledWith(animationId);
|
expect(nativeAnimatedModule.stopAnimation).toBeCalledWith(animationId);
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @emails oncall+react_native
|
* @emails oncall+react_native
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Easing = require('Easing');
|
const Easing = require('Easing');
|
||||||
|
@ -88,23 +90,363 @@ describe('Easing', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Samples = {
|
const Samples = {
|
||||||
in_quad: [0,0.0030864197530864196,0.012345679012345678,0.027777777777777776,0.04938271604938271,0.0771604938271605,0.1111111111111111,0.15123456790123457,0.19753086419753085,0.25,0.308641975308642,0.37345679012345684,0.4444444444444444,0.5216049382716049,0.6049382716049383,0.6944444444444445,0.7901234567901234,0.8919753086419753,1],
|
in_quad: [
|
||||||
out_quad: [0,0.10802469135802469,0.20987654320987653,0.3055555555555555,0.3950617283950617,0.47839506172839513,0.5555555555555556,0.6265432098765432,0.691358024691358,0.75,0.8024691358024691,0.8487654320987654,0.888888888888889,0.9228395061728394,0.9506172839506174,0.9722222222222221,0.9876543209876543,0.9969135802469136,1],
|
0,
|
||||||
inOut_quad: [0,0.006172839506172839,0.024691358024691357,0.05555555555555555,0.09876543209876543,0.154320987654321,0.2222222222222222,0.30246913580246915,0.3950617283950617,0.5,0.6049382716049383,0.697530864197531,0.7777777777777777,0.845679012345679,0.9012345679012346,0.9444444444444444,0.9753086419753086,0.9938271604938271,1],
|
0.0030864197530864196,
|
||||||
in_cubic: [0,0.00017146776406035664,0.0013717421124828531,0.004629629629629629,0.010973936899862825,0.021433470507544586,0.037037037037037035,0.05881344307270234,0.0877914951989026,0.125,0.1714677640603567,0.22822359396433475,0.2962962962962963,0.37671467764060357,0.4705075445816187,0.5787037037037038,0.7023319615912208,0.8424211248285322,1],
|
0.012345679012345678,
|
||||||
out_cubic: [0,0.15757887517146785,0.2976680384087792,0.42129629629629617,0.5294924554183813,0.6232853223593964,0.7037037037037036,0.7717764060356652,0.8285322359396433,0.875,0.9122085048010974,0.9411865569272977,0.9629629629629629,0.9785665294924554,0.9890260631001372,0.9953703703703703,0.9986282578875172,0.9998285322359396,1],
|
0.027777777777777776,
|
||||||
inOut_cubic: [0,0.0006858710562414266,0.0054869684499314125,0.018518518518518517,0.0438957475994513,0.08573388203017834,0.14814814814814814,0.23525377229080935,0.3511659807956104,0.5,0.6488340192043895,0.7647462277091908,0.8518518518518519,0.9142661179698217,0.9561042524005487,0.9814814814814815,0.9945130315500685,0.9993141289437586,1],
|
0.04938271604938271,
|
||||||
in_sin: [0,0.003805301908254455,0.01519224698779198,0.03407417371093169,0.06030737921409157,0.09369221296335006,0.1339745962155613,0.1808479557110082,0.233955556881022,0.2928932188134524,0.35721239031346064,0.42642356364895384,0.4999999999999999,0.5773817382593005,0.6579798566743311,0.7411809548974793,0.8263518223330696,0.9128442572523416,0.9999999999999999],
|
0.0771604938271605,
|
||||||
out_sin: [0,0.08715574274765817,0.17364817766693033,0.25881904510252074,0.3420201433256687,0.42261826174069944,0.49999999999999994,0.573576436351046,0.6427876096865393,0.7071067811865475,0.766044443118978,0.8191520442889918,0.8660254037844386,0.9063077870366499,0.9396926207859083,0.9659258262890683,0.984807753012208,0.9961946980917455,1],
|
0.1111111111111111,
|
||||||
inOut_sin: [0,0.00759612349389599,0.030153689607045786,0.06698729810778065,0.116977778440511,0.17860619515673032,0.24999999999999994,0.32898992833716556,0.4131759111665348,0.49999999999999994,0.5868240888334652,0.6710100716628343,0.7499999999999999,0.8213938048432696,0.883022221559489,0.9330127018922194,0.9698463103929542,0.9924038765061041,1],
|
0.15123456790123457,
|
||||||
in_exp: [0,0.0014352875901128893,0.002109491677524035,0.0031003926796253885,0.004556754060844206,0.006697218616039631,0.009843133202303688,0.014466792379488908,0.021262343752724643,0.03125,0.045929202883612456,0.06750373368076916,0.09921256574801243,0.1458161299470146,0.2143109957132682,0.31498026247371835,0.46293735614364506,0.6803950000871883,1],
|
0.19753086419753085,
|
||||||
out_exp: [0,0.31960499991281155,0.5370626438563548,0.6850197375262816,0.7856890042867318,0.8541838700529854,0.9007874342519875,0.9324962663192309,0.9540707971163875,0.96875,0.9787376562472754,0.9855332076205111,0.9901568667976963,0.9933027813839603,0.9954432459391558,0.9968996073203746,0.9978905083224759,0.9985647124098871,1],
|
0.25,
|
||||||
inOut_exp: [0,0.0010547458387620175,0.002278377030422103,0.004921566601151844,0.010631171876362321,0.022964601441806228,0.049606282874006216,0.1071554978566341,0.23146867807182253,0.5,0.7685313219281775,0.892844502143366,0.9503937171259937,0.9770353985581938,0.9893688281236377,0.9950784333988482,0.9977216229695779,0.998945254161238,1],
|
0.308641975308642,
|
||||||
in_circle: [0,0.0015444024660317135,0.006192010000093506,0.013986702816730645,0.025003956956430873,0.03935464078941209,0.057190958417936644,0.07871533601238889,0.10419358352238339,0.1339745962155614,0.1685205807169019,0.20845517506805522,0.2546440075000701,0.3083389112228482,0.37146063894529113,0.4472292016074334,0.5418771527091488,0.6713289009389102,1],
|
0.37345679012345684,
|
||||||
out_circle: [0,0.3286710990610898,0.45812284729085123,0.5527707983925666,0.6285393610547089,0.6916610887771518,0.7453559924999298,0.7915448249319448,0.8314794192830981,0.8660254037844386,0.8958064164776166,0.9212846639876111,0.9428090415820634,0.9606453592105879,0.9749960430435691,0.9860132971832694,0.9938079899999065,0.9984555975339683,1],
|
0.4444444444444444,
|
||||||
inOut_circle: [0,0.003096005000046753,0.012501978478215436,0.028595479208968322,0.052096791761191696,0.08426029035845095,0.12732200375003505,0.18573031947264557,0.2709385763545744,0.5,0.7290614236454256,0.8142696805273546,0.8726779962499649,0.915739709641549,0.9479032082388084,0.9714045207910317,0.9874980215217846,0.9969039949999532,1],
|
0.5216049382716049,
|
||||||
in_back_: [0,-0.004788556241426612,-0.017301289437585736,-0.0347587962962963,-0.05438167352537723,-0.07339051783264748,-0.08900592592592595,-0.09844849451303156,-0.0989388203017833,-0.08769750000000004,-0.06194513031550073,-0.018902307956104283,0.044210370370370254,0.13017230795610413,0.2417629080932785,0.3817615740740742,0.5529477091906719,0.7581007167352535,0.9999999999999998],
|
0.6049382716049383,
|
||||||
out_back_: [2.220446049250313e-16,0.24189928326474652,0.44705229080932807,0.6182384259259258,0.7582370919067215,0.8698276920438959,0.9557896296296297,1.0189023079561044,1.0619451303155008,1.0876975,1.0989388203017834,1.0984484945130315,1.089005925925926,1.0733905178326475,1.0543816735253773,1.0347587962962963,1.0173012894375857,1.0047885562414267,1],
|
0.6944444444444445,
|
||||||
|
0.7901234567901234,
|
||||||
|
0.8919753086419753,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
out_quad: [
|
||||||
|
0,
|
||||||
|
0.10802469135802469,
|
||||||
|
0.20987654320987653,
|
||||||
|
0.3055555555555555,
|
||||||
|
0.3950617283950617,
|
||||||
|
0.47839506172839513,
|
||||||
|
0.5555555555555556,
|
||||||
|
0.6265432098765432,
|
||||||
|
0.691358024691358,
|
||||||
|
0.75,
|
||||||
|
0.8024691358024691,
|
||||||
|
0.8487654320987654,
|
||||||
|
0.888888888888889,
|
||||||
|
0.9228395061728394,
|
||||||
|
0.9506172839506174,
|
||||||
|
0.9722222222222221,
|
||||||
|
0.9876543209876543,
|
||||||
|
0.9969135802469136,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
inOut_quad: [
|
||||||
|
0,
|
||||||
|
0.006172839506172839,
|
||||||
|
0.024691358024691357,
|
||||||
|
0.05555555555555555,
|
||||||
|
0.09876543209876543,
|
||||||
|
0.154320987654321,
|
||||||
|
0.2222222222222222,
|
||||||
|
0.30246913580246915,
|
||||||
|
0.3950617283950617,
|
||||||
|
0.5,
|
||||||
|
0.6049382716049383,
|
||||||
|
0.697530864197531,
|
||||||
|
0.7777777777777777,
|
||||||
|
0.845679012345679,
|
||||||
|
0.9012345679012346,
|
||||||
|
0.9444444444444444,
|
||||||
|
0.9753086419753086,
|
||||||
|
0.9938271604938271,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
in_cubic: [
|
||||||
|
0,
|
||||||
|
0.00017146776406035664,
|
||||||
|
0.0013717421124828531,
|
||||||
|
0.004629629629629629,
|
||||||
|
0.010973936899862825,
|
||||||
|
0.021433470507544586,
|
||||||
|
0.037037037037037035,
|
||||||
|
0.05881344307270234,
|
||||||
|
0.0877914951989026,
|
||||||
|
0.125,
|
||||||
|
0.1714677640603567,
|
||||||
|
0.22822359396433475,
|
||||||
|
0.2962962962962963,
|
||||||
|
0.37671467764060357,
|
||||||
|
0.4705075445816187,
|
||||||
|
0.5787037037037038,
|
||||||
|
0.7023319615912208,
|
||||||
|
0.8424211248285322,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
out_cubic: [
|
||||||
|
0,
|
||||||
|
0.15757887517146785,
|
||||||
|
0.2976680384087792,
|
||||||
|
0.42129629629629617,
|
||||||
|
0.5294924554183813,
|
||||||
|
0.6232853223593964,
|
||||||
|
0.7037037037037036,
|
||||||
|
0.7717764060356652,
|
||||||
|
0.8285322359396433,
|
||||||
|
0.875,
|
||||||
|
0.9122085048010974,
|
||||||
|
0.9411865569272977,
|
||||||
|
0.9629629629629629,
|
||||||
|
0.9785665294924554,
|
||||||
|
0.9890260631001372,
|
||||||
|
0.9953703703703703,
|
||||||
|
0.9986282578875172,
|
||||||
|
0.9998285322359396,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
inOut_cubic: [
|
||||||
|
0,
|
||||||
|
0.0006858710562414266,
|
||||||
|
0.0054869684499314125,
|
||||||
|
0.018518518518518517,
|
||||||
|
0.0438957475994513,
|
||||||
|
0.08573388203017834,
|
||||||
|
0.14814814814814814,
|
||||||
|
0.23525377229080935,
|
||||||
|
0.3511659807956104,
|
||||||
|
0.5,
|
||||||
|
0.6488340192043895,
|
||||||
|
0.7647462277091908,
|
||||||
|
0.8518518518518519,
|
||||||
|
0.9142661179698217,
|
||||||
|
0.9561042524005487,
|
||||||
|
0.9814814814814815,
|
||||||
|
0.9945130315500685,
|
||||||
|
0.9993141289437586,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
in_sin: [
|
||||||
|
0,
|
||||||
|
0.003805301908254455,
|
||||||
|
0.01519224698779198,
|
||||||
|
0.03407417371093169,
|
||||||
|
0.06030737921409157,
|
||||||
|
0.09369221296335006,
|
||||||
|
0.1339745962155613,
|
||||||
|
0.1808479557110082,
|
||||||
|
0.233955556881022,
|
||||||
|
0.2928932188134524,
|
||||||
|
0.35721239031346064,
|
||||||
|
0.42642356364895384,
|
||||||
|
0.4999999999999999,
|
||||||
|
0.5773817382593005,
|
||||||
|
0.6579798566743311,
|
||||||
|
0.7411809548974793,
|
||||||
|
0.8263518223330696,
|
||||||
|
0.9128442572523416,
|
||||||
|
0.9999999999999999,
|
||||||
|
],
|
||||||
|
out_sin: [
|
||||||
|
0,
|
||||||
|
0.08715574274765817,
|
||||||
|
0.17364817766693033,
|
||||||
|
0.25881904510252074,
|
||||||
|
0.3420201433256687,
|
||||||
|
0.42261826174069944,
|
||||||
|
0.49999999999999994,
|
||||||
|
0.573576436351046,
|
||||||
|
0.6427876096865393,
|
||||||
|
0.7071067811865475,
|
||||||
|
0.766044443118978,
|
||||||
|
0.8191520442889918,
|
||||||
|
0.8660254037844386,
|
||||||
|
0.9063077870366499,
|
||||||
|
0.9396926207859083,
|
||||||
|
0.9659258262890683,
|
||||||
|
0.984807753012208,
|
||||||
|
0.9961946980917455,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
inOut_sin: [
|
||||||
|
0,
|
||||||
|
0.00759612349389599,
|
||||||
|
0.030153689607045786,
|
||||||
|
0.06698729810778065,
|
||||||
|
0.116977778440511,
|
||||||
|
0.17860619515673032,
|
||||||
|
0.24999999999999994,
|
||||||
|
0.32898992833716556,
|
||||||
|
0.4131759111665348,
|
||||||
|
0.49999999999999994,
|
||||||
|
0.5868240888334652,
|
||||||
|
0.6710100716628343,
|
||||||
|
0.7499999999999999,
|
||||||
|
0.8213938048432696,
|
||||||
|
0.883022221559489,
|
||||||
|
0.9330127018922194,
|
||||||
|
0.9698463103929542,
|
||||||
|
0.9924038765061041,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
in_exp: [
|
||||||
|
0,
|
||||||
|
0.0014352875901128893,
|
||||||
|
0.002109491677524035,
|
||||||
|
0.0031003926796253885,
|
||||||
|
0.004556754060844206,
|
||||||
|
0.006697218616039631,
|
||||||
|
0.009843133202303688,
|
||||||
|
0.014466792379488908,
|
||||||
|
0.021262343752724643,
|
||||||
|
0.03125,
|
||||||
|
0.045929202883612456,
|
||||||
|
0.06750373368076916,
|
||||||
|
0.09921256574801243,
|
||||||
|
0.1458161299470146,
|
||||||
|
0.2143109957132682,
|
||||||
|
0.31498026247371835,
|
||||||
|
0.46293735614364506,
|
||||||
|
0.6803950000871883,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
out_exp: [
|
||||||
|
0,
|
||||||
|
0.31960499991281155,
|
||||||
|
0.5370626438563548,
|
||||||
|
0.6850197375262816,
|
||||||
|
0.7856890042867318,
|
||||||
|
0.8541838700529854,
|
||||||
|
0.9007874342519875,
|
||||||
|
0.9324962663192309,
|
||||||
|
0.9540707971163875,
|
||||||
|
0.96875,
|
||||||
|
0.9787376562472754,
|
||||||
|
0.9855332076205111,
|
||||||
|
0.9901568667976963,
|
||||||
|
0.9933027813839603,
|
||||||
|
0.9954432459391558,
|
||||||
|
0.9968996073203746,
|
||||||
|
0.9978905083224759,
|
||||||
|
0.9985647124098871,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
inOut_exp: [
|
||||||
|
0,
|
||||||
|
0.0010547458387620175,
|
||||||
|
0.002278377030422103,
|
||||||
|
0.004921566601151844,
|
||||||
|
0.010631171876362321,
|
||||||
|
0.022964601441806228,
|
||||||
|
0.049606282874006216,
|
||||||
|
0.1071554978566341,
|
||||||
|
0.23146867807182253,
|
||||||
|
0.5,
|
||||||
|
0.7685313219281775,
|
||||||
|
0.892844502143366,
|
||||||
|
0.9503937171259937,
|
||||||
|
0.9770353985581938,
|
||||||
|
0.9893688281236377,
|
||||||
|
0.9950784333988482,
|
||||||
|
0.9977216229695779,
|
||||||
|
0.998945254161238,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
in_circle: [
|
||||||
|
0,
|
||||||
|
0.0015444024660317135,
|
||||||
|
0.006192010000093506,
|
||||||
|
0.013986702816730645,
|
||||||
|
0.025003956956430873,
|
||||||
|
0.03935464078941209,
|
||||||
|
0.057190958417936644,
|
||||||
|
0.07871533601238889,
|
||||||
|
0.10419358352238339,
|
||||||
|
0.1339745962155614,
|
||||||
|
0.1685205807169019,
|
||||||
|
0.20845517506805522,
|
||||||
|
0.2546440075000701,
|
||||||
|
0.3083389112228482,
|
||||||
|
0.37146063894529113,
|
||||||
|
0.4472292016074334,
|
||||||
|
0.5418771527091488,
|
||||||
|
0.6713289009389102,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
out_circle: [
|
||||||
|
0,
|
||||||
|
0.3286710990610898,
|
||||||
|
0.45812284729085123,
|
||||||
|
0.5527707983925666,
|
||||||
|
0.6285393610547089,
|
||||||
|
0.6916610887771518,
|
||||||
|
0.7453559924999298,
|
||||||
|
0.7915448249319448,
|
||||||
|
0.8314794192830981,
|
||||||
|
0.8660254037844386,
|
||||||
|
0.8958064164776166,
|
||||||
|
0.9212846639876111,
|
||||||
|
0.9428090415820634,
|
||||||
|
0.9606453592105879,
|
||||||
|
0.9749960430435691,
|
||||||
|
0.9860132971832694,
|
||||||
|
0.9938079899999065,
|
||||||
|
0.9984555975339683,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
inOut_circle: [
|
||||||
|
0,
|
||||||
|
0.003096005000046753,
|
||||||
|
0.012501978478215436,
|
||||||
|
0.028595479208968322,
|
||||||
|
0.052096791761191696,
|
||||||
|
0.08426029035845095,
|
||||||
|
0.12732200375003505,
|
||||||
|
0.18573031947264557,
|
||||||
|
0.2709385763545744,
|
||||||
|
0.5,
|
||||||
|
0.7290614236454256,
|
||||||
|
0.8142696805273546,
|
||||||
|
0.8726779962499649,
|
||||||
|
0.915739709641549,
|
||||||
|
0.9479032082388084,
|
||||||
|
0.9714045207910317,
|
||||||
|
0.9874980215217846,
|
||||||
|
0.9969039949999532,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
in_back_: [
|
||||||
|
0,
|
||||||
|
-0.004788556241426612,
|
||||||
|
-0.017301289437585736,
|
||||||
|
-0.0347587962962963,
|
||||||
|
-0.05438167352537723,
|
||||||
|
-0.07339051783264748,
|
||||||
|
-0.08900592592592595,
|
||||||
|
-0.09844849451303156,
|
||||||
|
-0.0989388203017833,
|
||||||
|
-0.08769750000000004,
|
||||||
|
-0.06194513031550073,
|
||||||
|
-0.018902307956104283,
|
||||||
|
0.044210370370370254,
|
||||||
|
0.13017230795610413,
|
||||||
|
0.2417629080932785,
|
||||||
|
0.3817615740740742,
|
||||||
|
0.5529477091906719,
|
||||||
|
0.7581007167352535,
|
||||||
|
0.9999999999999998,
|
||||||
|
],
|
||||||
|
out_back_: [
|
||||||
|
2.220446049250313e-16,
|
||||||
|
0.24189928326474652,
|
||||||
|
0.44705229080932807,
|
||||||
|
0.6182384259259258,
|
||||||
|
0.7582370919067215,
|
||||||
|
0.8698276920438959,
|
||||||
|
0.9557896296296297,
|
||||||
|
1.0189023079561044,
|
||||||
|
1.0619451303155008,
|
||||||
|
1.0876975,
|
||||||
|
1.0989388203017834,
|
||||||
|
1.0984484945130315,
|
||||||
|
1.089005925925926,
|
||||||
|
1.0733905178326475,
|
||||||
|
1.0543816735253773,
|
||||||
|
1.0347587962962963,
|
||||||
|
1.0173012894375857,
|
||||||
|
1.0047885562414267,
|
||||||
|
1,
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(Samples).forEach(function(type) {
|
Object.keys(Samples).forEach(function(type) {
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @emails oncall+react_native
|
* @emails oncall+react_native
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const AnimatedInterpolation = require('../nodes/AnimatedInterpolation');
|
const AnimatedInterpolation = require('../nodes/AnimatedInterpolation');
|
||||||
|
|
|
@ -74,7 +74,10 @@ describe('bezier', function() {
|
||||||
describe('common properties', function() {
|
describe('common properties', function() {
|
||||||
it('should be the right value at extremes', function() {
|
it('should be the right value at extremes', function() {
|
||||||
repeat(10)(function() {
|
repeat(10)(function() {
|
||||||
const a = Math.random(), b = 2 * Math.random() - 0.5, c = Math.random(), d = 2 * Math.random() - 0.5;
|
const a = Math.random(),
|
||||||
|
b = 2 * Math.random() - 0.5,
|
||||||
|
c = Math.random(),
|
||||||
|
d = 2 * Math.random() - 0.5;
|
||||||
const easing = bezier(a, b, c, d);
|
const easing = bezier(a, b, c, d);
|
||||||
expect(easing(0)).toBe(0);
|
expect(easing(0)).toBe(0);
|
||||||
expect(easing(1)).toBe(1);
|
expect(easing(1)).toBe(1);
|
||||||
|
@ -83,7 +86,10 @@ describe('bezier', function() {
|
||||||
|
|
||||||
it('should approach the projected value of its x=y projected curve', function() {
|
it('should approach the projected value of its x=y projected curve', function() {
|
||||||
repeat(10)(function() {
|
repeat(10)(function() {
|
||||||
const a = Math.random(), b = Math.random(), c = Math.random(), d = Math.random();
|
const a = Math.random(),
|
||||||
|
b = Math.random(),
|
||||||
|
c = Math.random(),
|
||||||
|
d = Math.random();
|
||||||
const easing = bezier(a, b, c, d);
|
const easing = bezier(a, b, c, d);
|
||||||
const projected = bezier(b, a, d, c);
|
const projected = bezier(b, a, d, c);
|
||||||
const composed = function(x) {
|
const composed = function(x) {
|
||||||
|
@ -96,7 +102,10 @@ describe('bezier', function() {
|
||||||
describe('two same instances', function() {
|
describe('two same instances', function() {
|
||||||
it('should be strictly equals', function() {
|
it('should be strictly equals', function() {
|
||||||
repeat(10)(function() {
|
repeat(10)(function() {
|
||||||
const a = Math.random(), b = 2 * Math.random() - 0.5, c = Math.random(), d = 2 * Math.random() - 0.5;
|
const a = Math.random(),
|
||||||
|
b = 2 * Math.random() - 0.5,
|
||||||
|
c = Math.random(),
|
||||||
|
d = 2 * Math.random() - 0.5;
|
||||||
allEquals(bezier(a, b, c, d), bezier(a, b, c, d), 100, 0);
|
allEquals(bezier(a, b, c, d), bezier(a, b, c, d), 100, 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -104,14 +113,20 @@ describe('bezier', function() {
|
||||||
describe('symetric curves', function() {
|
describe('symetric curves', function() {
|
||||||
it('should have a central value y~=0.5 at x=0.5', function() {
|
it('should have a central value y~=0.5 at x=0.5', function() {
|
||||||
repeat(10)(function() {
|
repeat(10)(function() {
|
||||||
const a = Math.random(), b = 2 * Math.random() - 0.5, c = 1 - a, d = 1 - b;
|
const a = Math.random(),
|
||||||
|
b = 2 * Math.random() - 0.5,
|
||||||
|
c = 1 - a,
|
||||||
|
d = 1 - b;
|
||||||
const easing = bezier(a, b, c, d);
|
const easing = bezier(a, b, c, d);
|
||||||
assertClose(easing(0.5), 0.5, 2);
|
assertClose(easing(0.5), 0.5, 2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should be symmetrical', function() {
|
it('should be symmetrical', function() {
|
||||||
repeat(10)(function() {
|
repeat(10)(function() {
|
||||||
const a = Math.random(), b = 2 * Math.random() - 0.5, c = 1 - a, d = 1 - b;
|
const a = Math.random(),
|
||||||
|
b = 2 * Math.random() - 0.5,
|
||||||
|
c = 1 - a,
|
||||||
|
d = 1 - b;
|
||||||
const easing = bezier(a, b, c, d);
|
const easing = bezier(a, b, c, d);
|
||||||
const sym = function(x) {
|
const sym = function(x) {
|
||||||
return 1 - easing(1 - x);
|
return 1 - easing(1 - x);
|
||||||
|
|
|
@ -2,47 +2,64 @@
|
||||||
* BezierEasing - use bezier curve for transition easing function
|
* BezierEasing - use bezier curve for transition easing function
|
||||||
* https://github.com/gre/bezier-easing
|
* https://github.com/gre/bezier-easing
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @copyright 2014-2015 Gaëtan Renaudeau. MIT License.
|
* @copyright 2014-2015 Gaëtan Renaudeau. MIT License.
|
||||||
* @noflow
|
* @noflow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// These values are established by empiricism with tests (tradeoff: performance VS precision)
|
// These values are established by empiricism with tests (tradeoff: performance VS precision)
|
||||||
const NEWTON_ITERATIONS = 4;
|
const NEWTON_ITERATIONS = 4;
|
||||||
const NEWTON_MIN_SLOPE = 0.001;
|
const NEWTON_MIN_SLOPE = 0.001;
|
||||||
const SUBDIVISION_PRECISION = 0.0000001;
|
const SUBDIVISION_PRECISION = 0.0000001;
|
||||||
const SUBDIVISION_MAX_ITERATIONS = 10;
|
const SUBDIVISION_MAX_ITERATIONS = 10;
|
||||||
|
|
||||||
const kSplineTableSize = 11;
|
const kSplineTableSize = 11;
|
||||||
const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
|
const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
|
||||||
|
|
||||||
const float32ArraySupported = typeof Float32Array === 'function';
|
const float32ArraySupported = typeof Float32Array === 'function';
|
||||||
|
|
||||||
function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
|
function A(aA1, aA2) {
|
||||||
function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
|
return 1.0 - 3.0 * aA2 + 3.0 * aA1;
|
||||||
function C (aA1) { return 3.0 * aA1; }
|
}
|
||||||
|
function B(aA1, aA2) {
|
||||||
|
return 3.0 * aA2 - 6.0 * aA1;
|
||||||
|
}
|
||||||
|
function C(aA1) {
|
||||||
|
return 3.0 * aA1;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
||||||
function calcBezier (aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; }
|
function calcBezier(aT, aA1, aA2) {
|
||||||
|
return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
|
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
|
||||||
function getSlope (aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); }
|
function getSlope(aT, aA1, aA2) {
|
||||||
|
return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
|
||||||
|
}
|
||||||
|
|
||||||
function binarySubdivide (aX, aA, aB, mX1, mX2) {
|
function binarySubdivide(aX, aA, aB, mX1, mX2) {
|
||||||
let currentX, currentT, i = 0;
|
let currentX,
|
||||||
do {
|
currentT,
|
||||||
currentT = aA + (aB - aA) / 2.0;
|
i = 0;
|
||||||
currentX = calcBezier(currentT, mX1, mX2) - aX;
|
do {
|
||||||
if (currentX > 0.0) {
|
currentT = aA + (aB - aA) / 2.0;
|
||||||
aB = currentT;
|
currentX = calcBezier(currentT, mX1, mX2) - aX;
|
||||||
} else {
|
if (currentX > 0.0) {
|
||||||
aA = currentT;
|
aB = currentT;
|
||||||
}
|
} else {
|
||||||
} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
|
aA = currentT;
|
||||||
return currentT;
|
}
|
||||||
}
|
} while (
|
||||||
|
Math.abs(currentX) > SUBDIVISION_PRECISION &&
|
||||||
|
++i < SUBDIVISION_MAX_ITERATIONS
|
||||||
|
);
|
||||||
|
return currentT;
|
||||||
|
}
|
||||||
|
|
||||||
function newtonRaphsonIterate (aX, aGuessT, mX1, mX2) {
|
function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
|
||||||
for (let i = 0; i < NEWTON_ITERATIONS; ++i) {
|
for (let i = 0; i < NEWTON_ITERATIONS; ++i) {
|
||||||
const currentSlope = getSlope(aGuessT, mX1, mX2);
|
const currentSlope = getSlope(aGuessT, mX1, mX2);
|
||||||
if (currentSlope === 0.0) {
|
if (currentSlope === 0.0) {
|
||||||
|
@ -52,56 +69,71 @@
|
||||||
aGuessT -= currentX / currentSlope;
|
aGuessT -= currentX / currentSlope;
|
||||||
}
|
}
|
||||||
return aGuessT;
|
return aGuessT;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function bezier (mX1, mY1, mX2, mY2) {
|
module.exports = function bezier(mX1, mY1, mX2, mY2) {
|
||||||
if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { // eslint-disable-line yoda
|
if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
|
||||||
throw new Error('bezier x values must be in [0, 1] range');
|
// eslint-disable-line yoda
|
||||||
}
|
throw new Error('bezier x values must be in [0, 1] range');
|
||||||
|
}
|
||||||
|
|
||||||
// Precompute samples table
|
// Precompute samples table
|
||||||
const sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
|
const sampleValues = float32ArraySupported
|
||||||
if (mX1 !== mY1 || mX2 !== mY2) {
|
? new Float32Array(kSplineTableSize)
|
||||||
for (let i = 0; i < kSplineTableSize; ++i) {
|
: new Array(kSplineTableSize);
|
||||||
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
|
if (mX1 !== mY1 || mX2 !== mY2) {
|
||||||
}
|
for (let i = 0; i < kSplineTableSize; ++i) {
|
||||||
}
|
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getTForX (aX) {
|
function getTForX(aX) {
|
||||||
let intervalStart = 0.0;
|
let intervalStart = 0.0;
|
||||||
let currentSample = 1;
|
let currentSample = 1;
|
||||||
const lastSample = kSplineTableSize - 1;
|
const lastSample = kSplineTableSize - 1;
|
||||||
|
|
||||||
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
|
for (
|
||||||
intervalStart += kSampleStepSize;
|
;
|
||||||
}
|
currentSample !== lastSample && sampleValues[currentSample] <= aX;
|
||||||
--currentSample;
|
++currentSample
|
||||||
|
) {
|
||||||
|
intervalStart += kSampleStepSize;
|
||||||
|
}
|
||||||
|
--currentSample;
|
||||||
|
|
||||||
// Interpolate to provide an initial guess for t
|
// Interpolate to provide an initial guess for t
|
||||||
const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
|
const dist =
|
||||||
const guessForT = intervalStart + dist * kSampleStepSize;
|
(aX - sampleValues[currentSample]) /
|
||||||
|
(sampleValues[currentSample + 1] - sampleValues[currentSample]);
|
||||||
|
const guessForT = intervalStart + dist * kSampleStepSize;
|
||||||
|
|
||||||
const initialSlope = getSlope(guessForT, mX1, mX2);
|
const initialSlope = getSlope(guessForT, mX1, mX2);
|
||||||
if (initialSlope >= NEWTON_MIN_SLOPE) {
|
if (initialSlope >= NEWTON_MIN_SLOPE) {
|
||||||
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
|
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
|
||||||
} else if (initialSlope === 0.0) {
|
} else if (initialSlope === 0.0) {
|
||||||
return guessForT;
|
return guessForT;
|
||||||
} else {
|
} else {
|
||||||
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
|
return binarySubdivide(
|
||||||
}
|
aX,
|
||||||
}
|
intervalStart,
|
||||||
|
intervalStart + kSampleStepSize,
|
||||||
|
mX1,
|
||||||
|
mX2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return function BezierEasing (x) {
|
return function BezierEasing(x) {
|
||||||
if (mX1 === mY1 && mX2 === mY2) {
|
if (mX1 === mY1 && mX2 === mY2) {
|
||||||
return x; // linear
|
return x; // linear
|
||||||
}
|
}
|
||||||
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
|
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
|
||||||
if (x === 0) {
|
if (x === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (x === 1) {
|
if (x === 1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return calcBezier(getTForX(x), mY1, mY2);
|
return calcBezier(getTForX(x), mY1, mY2);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createInteractionHandle: function() {},
|
createInteractionHandle: function() {},
|
||||||
clearInteractionHandle: function() {}
|
clearInteractionHandle: function() {},
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
module.exports = function(style) {
|
module.exports = function(style) {
|
||||||
return style;
|
return style;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const MissingNativeEventEmitterShim = require('MissingNativeEventEmitterShim');
|
const MissingNativeEventEmitterShim = require('MissingNativeEventEmitterShim');
|
||||||
|
@ -23,7 +25,6 @@ const invariant = require('fbjs/lib/invariant');
|
||||||
* See http://facebook.github.io/react-native/docs/appstate.html
|
* See http://facebook.github.io/react-native/docs/appstate.html
|
||||||
*/
|
*/
|
||||||
class AppState extends NativeEventEmitter {
|
class AppState extends NativeEventEmitter {
|
||||||
|
|
||||||
_eventHandlers: Object;
|
_eventHandlers: Object;
|
||||||
currentState: ?string;
|
currentState: ?string;
|
||||||
isAvailable: boolean = true;
|
isAvailable: boolean = true;
|
||||||
|
@ -47,27 +48,21 @@ class AppState extends NativeEventEmitter {
|
||||||
// prop is up to date, we have to register an observer that updates it
|
// prop is up to date, we have to register an observer that updates it
|
||||||
// whenever the state changes, even if nobody cares. We should just
|
// whenever the state changes, even if nobody cares. We should just
|
||||||
// deprecate the `currentState` property and get rid of this.
|
// deprecate the `currentState` property and get rid of this.
|
||||||
this.addListener(
|
this.addListener('appStateDidChange', appStateData => {
|
||||||
'appStateDidChange',
|
eventUpdated = true;
|
||||||
(appStateData) => {
|
this.currentState = appStateData.app_state;
|
||||||
eventUpdated = true;
|
});
|
||||||
this.currentState = appStateData.app_state;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: see above - this request just populates the value of `currentState`
|
// TODO: see above - this request just populates the value of `currentState`
|
||||||
// when the module is first initialized. Would be better to get rid of the
|
// when the module is first initialized. Would be better to get rid of the
|
||||||
// prop and expose `getCurrentAppState` method directly.
|
// prop and expose `getCurrentAppState` method directly.
|
||||||
RCTAppState.getCurrentAppState(
|
RCTAppState.getCurrentAppState(appStateData => {
|
||||||
(appStateData) => {
|
// It's possible that the state will have changed here & listeners need to be notified
|
||||||
// It's possible that the state will have changed here & listeners need to be notified
|
if (!eventUpdated && this.currentState !== appStateData.app_state) {
|
||||||
if (!eventUpdated && this.currentState !== appStateData.app_state) {
|
this.currentState = appStateData.app_state;
|
||||||
this.currentState = appStateData.app_state;
|
this.emit('appStateDidChange', appStateData);
|
||||||
this.emit('appStateDidChange', appStateData);
|
}
|
||||||
}
|
}, logError);
|
||||||
},
|
|
||||||
logError
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: now that AppState is a subclass of NativeEventEmitter, we could
|
// TODO: now that AppState is a subclass of NativeEventEmitter, we could
|
||||||
|
@ -75,32 +70,30 @@ class AppState extends NativeEventEmitter {
|
||||||
// addListener` and `listener.remove()` directly. That will be a breaking
|
// addListener` and `listener.remove()` directly. That will be a breaking
|
||||||
// change though, as both the method and event names are different
|
// change though, as both the method and event names are different
|
||||||
// (addListener events are currently required to be globally unique).
|
// (addListener events are currently required to be globally unique).
|
||||||
/**
|
/**
|
||||||
* Add a handler to AppState changes by listening to the `change` event type
|
* Add a handler to AppState changes by listening to the `change` event type
|
||||||
* and providing the handler.
|
* and providing the handler.
|
||||||
*
|
*
|
||||||
* See http://facebook.github.io/react-native/docs/appstate.html#addeventlistener
|
* See http://facebook.github.io/react-native/docs/appstate.html#addeventlistener
|
||||||
*/
|
*/
|
||||||
addEventListener(
|
addEventListener(type: string, handler: Function) {
|
||||||
type: string,
|
|
||||||
handler: Function
|
|
||||||
) {
|
|
||||||
invariant(
|
invariant(
|
||||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
||||||
'Trying to subscribe to unknown event: "%s"', type
|
'Trying to subscribe to unknown event: "%s"',
|
||||||
|
type,
|
||||||
);
|
);
|
||||||
if (type === 'change') {
|
if (type === 'change') {
|
||||||
this._eventHandlers[type].set(handler, this.addListener(
|
this._eventHandlers[type].set(
|
||||||
'appStateDidChange',
|
handler,
|
||||||
(appStateData) => {
|
this.addListener('appStateDidChange', appStateData => {
|
||||||
handler(appStateData.app_state);
|
handler(appStateData.app_state);
|
||||||
}
|
}),
|
||||||
));
|
);
|
||||||
} else if (type === 'memoryWarning') {
|
} else if (type === 'memoryWarning') {
|
||||||
this._eventHandlers[type].set(handler, this.addListener(
|
this._eventHandlers[type].set(
|
||||||
'memoryWarning',
|
handler,
|
||||||
handler
|
this.addListener('memoryWarning', handler),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +102,11 @@ class AppState extends NativeEventEmitter {
|
||||||
*
|
*
|
||||||
* See http://facebook.github.io/react-native/docs/appstate.html#removeeventlistener
|
* See http://facebook.github.io/react-native/docs/appstate.html#removeeventlistener
|
||||||
*/
|
*/
|
||||||
removeEventListener(
|
removeEventListener(type: string, handler: Function) {
|
||||||
type: string,
|
|
||||||
handler: Function
|
|
||||||
) {
|
|
||||||
invariant(
|
invariant(
|
||||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
||||||
'Trying to remove listener for unknown event: "%s"', type
|
'Trying to remove listener for unknown event: "%s"',
|
||||||
|
type,
|
||||||
);
|
);
|
||||||
if (!this._eventHandlers[type].has(handler)) {
|
if (!this._eventHandlers[type].has(handler)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const MessageQueue = require('MessageQueue');
|
const MessageQueue = require('MessageQueue');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BatchedBridge = require('BatchedBridge');
|
const BatchedBridge = require('BatchedBridge');
|
||||||
|
@ -15,53 +17,66 @@ const invariant = require('fbjs/lib/invariant');
|
||||||
import type {ExtendedError} from 'parseErrorStack';
|
import type {ExtendedError} from 'parseErrorStack';
|
||||||
|
|
||||||
type ModuleConfig = [
|
type ModuleConfig = [
|
||||||
string, /* name */
|
string /* name */,
|
||||||
?Object, /* constants */
|
?Object /* constants */,
|
||||||
Array<string>, /* functions */
|
Array<string> /* functions */,
|
||||||
Array<number>, /* promise method IDs */
|
Array<number> /* promise method IDs */,
|
||||||
Array<number>, /* sync method IDs */
|
Array<number> /* sync method IDs */,
|
||||||
];
|
];
|
||||||
|
|
||||||
export type MethodType = 'async' | 'promise' | 'sync';
|
export type MethodType = 'async' | 'promise' | 'sync';
|
||||||
|
|
||||||
function genModule(config: ?ModuleConfig, moduleID: number): ?{name: string, module?: Object} {
|
function genModule(
|
||||||
|
config: ?ModuleConfig,
|
||||||
|
moduleID: number,
|
||||||
|
): ?{name: string, module?: Object} {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [moduleName, constants, methods, promiseMethods, syncMethods] = config;
|
const [moduleName, constants, methods, promiseMethods, syncMethods] = config;
|
||||||
invariant(!moduleName.startsWith('RCT') && !moduleName.startsWith('RK'),
|
invariant(
|
||||||
'Module name prefixes should\'ve been stripped by the native side ' +
|
!moduleName.startsWith('RCT') && !moduleName.startsWith('RK'),
|
||||||
'but wasn\'t for ' + moduleName);
|
"Module name prefixes should've been stripped by the native side " +
|
||||||
|
"but wasn't for " +
|
||||||
|
moduleName,
|
||||||
|
);
|
||||||
|
|
||||||
if (!constants && !methods) {
|
if (!constants && !methods) {
|
||||||
// Module contents will be filled in lazily later
|
// Module contents will be filled in lazily later
|
||||||
return { name: moduleName };
|
return {name: moduleName};
|
||||||
}
|
}
|
||||||
|
|
||||||
const module = {};
|
const module = {};
|
||||||
methods && methods.forEach((methodName, methodID) => {
|
methods &&
|
||||||
const isPromise = promiseMethods && arrayContains(promiseMethods, methodID);
|
methods.forEach((methodName, methodID) => {
|
||||||
const isSync = syncMethods && arrayContains(syncMethods, methodID);
|
const isPromise =
|
||||||
invariant(!isPromise || !isSync, 'Cannot have a method that is both async and a sync hook');
|
promiseMethods && arrayContains(promiseMethods, methodID);
|
||||||
const methodType = isPromise ? 'promise' : isSync ? 'sync' : 'async';
|
const isSync = syncMethods && arrayContains(syncMethods, methodID);
|
||||||
module[methodName] = genMethod(moduleID, methodID, methodType);
|
invariant(
|
||||||
});
|
!isPromise || !isSync,
|
||||||
|
'Cannot have a method that is both async and a sync hook',
|
||||||
|
);
|
||||||
|
const methodType = isPromise ? 'promise' : isSync ? 'sync' : 'async';
|
||||||
|
module[methodName] = genMethod(moduleID, methodID, methodType);
|
||||||
|
});
|
||||||
Object.assign(module, constants);
|
Object.assign(module, constants);
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
BatchedBridge.createDebugLookup(moduleID, moduleName, methods);
|
BatchedBridge.createDebugLookup(moduleID, moduleName, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { name: moduleName, module };
|
return {name: moduleName, module};
|
||||||
}
|
}
|
||||||
|
|
||||||
// export this method as a global so we can call it from native
|
// export this method as a global so we can call it from native
|
||||||
global.__fbGenNativeModule = genModule;
|
global.__fbGenNativeModule = genModule;
|
||||||
|
|
||||||
function loadModule(name: string, moduleID: number): ?Object {
|
function loadModule(name: string, moduleID: number): ?Object {
|
||||||
invariant(global.nativeRequireModuleConfig,
|
invariant(
|
||||||
'Can\'t lazily create module without nativeRequireModuleConfig');
|
global.nativeRequireModuleConfig,
|
||||||
|
"Can't lazily create module without nativeRequireModuleConfig",
|
||||||
|
);
|
||||||
const config = global.nativeRequireModuleConfig(name);
|
const config = global.nativeRequireModuleConfig(name);
|
||||||
const info = genModule(config, moduleID);
|
const info = genModule(config, moduleID);
|
||||||
return info && info.module;
|
return info && info.module;
|
||||||
|
@ -72,18 +87,25 @@ function genMethod(moduleID: number, methodID: number, type: MethodType) {
|
||||||
if (type === 'promise') {
|
if (type === 'promise') {
|
||||||
fn = function(...args: Array<any>) {
|
fn = function(...args: Array<any>) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
BatchedBridge.enqueueNativeCall(moduleID, methodID, args,
|
BatchedBridge.enqueueNativeCall(
|
||||||
(data) => resolve(data),
|
moduleID,
|
||||||
(errorData) => reject(createErrorFromErrorData(errorData)));
|
methodID,
|
||||||
|
args,
|
||||||
|
data => resolve(data),
|
||||||
|
errorData => reject(createErrorFromErrorData(errorData)),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} else if (type === 'sync') {
|
} else if (type === 'sync') {
|
||||||
fn = function(...args: Array<any>) {
|
fn = function(...args: Array<any>) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
invariant(global.nativeCallSyncHook, 'Calling synchronous methods on native ' +
|
invariant(
|
||||||
'modules is not supported in Chrome.\n\n Consider providing alternative ' +
|
global.nativeCallSyncHook,
|
||||||
'methods to expose this method in debug mode, e.g. by exposing constants ' +
|
'Calling synchronous methods on native ' +
|
||||||
'ahead-of-time.');
|
'modules is not supported in Chrome.\n\n Consider providing alternative ' +
|
||||||
|
'methods to expose this method in debug mode, e.g. by exposing constants ' +
|
||||||
|
'ahead-of-time.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return global.nativeCallSyncHook(moduleID, methodID, args);
|
return global.nativeCallSyncHook(moduleID, methodID, args);
|
||||||
};
|
};
|
||||||
|
@ -93,15 +115,22 @@ function genMethod(moduleID: number, methodID: number, type: MethodType) {
|
||||||
const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
|
const secondLastArg = args.length > 1 ? args[args.length - 2] : null;
|
||||||
const hasSuccessCallback = typeof lastArg === 'function';
|
const hasSuccessCallback = typeof lastArg === 'function';
|
||||||
const hasErrorCallback = typeof secondLastArg === 'function';
|
const hasErrorCallback = typeof secondLastArg === 'function';
|
||||||
hasErrorCallback && invariant(
|
hasErrorCallback &&
|
||||||
hasSuccessCallback,
|
invariant(
|
||||||
'Cannot have a non-function arg after a function arg.'
|
hasSuccessCallback,
|
||||||
);
|
'Cannot have a non-function arg after a function arg.',
|
||||||
|
);
|
||||||
const onSuccess = hasSuccessCallback ? lastArg : null;
|
const onSuccess = hasSuccessCallback ? lastArg : null;
|
||||||
const onFail = hasErrorCallback ? secondLastArg : null;
|
const onFail = hasErrorCallback ? secondLastArg : null;
|
||||||
const callbackCount = hasSuccessCallback + hasErrorCallback;
|
const callbackCount = hasSuccessCallback + hasErrorCallback;
|
||||||
args = args.slice(0, args.length - callbackCount);
|
args = args.slice(0, args.length - callbackCount);
|
||||||
BatchedBridge.enqueueNativeCall(moduleID, methodID, args, onFail, onSuccess);
|
BatchedBridge.enqueueNativeCall(
|
||||||
|
moduleID,
|
||||||
|
methodID,
|
||||||
|
args,
|
||||||
|
onFail,
|
||||||
|
onSuccess,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn.type = type;
|
fn.type = type;
|
||||||
|
@ -113,41 +142,43 @@ function arrayContains<T>(array: Array<T>, value: T): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createErrorFromErrorData(errorData: {message: string}): ExtendedError {
|
function createErrorFromErrorData(errorData: {message: string}): ExtendedError {
|
||||||
const {
|
const {message, ...extraErrorInfo} = errorData || {};
|
||||||
message,
|
const error: ExtendedError = new Error(message);
|
||||||
...extraErrorInfo
|
|
||||||
} = errorData || {};
|
|
||||||
const error : ExtendedError = new Error(message);
|
|
||||||
error.framesToPop = 1;
|
error.framesToPop = 1;
|
||||||
return Object.assign(error, extraErrorInfo);
|
return Object.assign(error, extraErrorInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
let NativeModules : {[moduleName: string]: Object} = {};
|
let NativeModules: {[moduleName: string]: Object} = {};
|
||||||
if (global.nativeModuleProxy) {
|
if (global.nativeModuleProxy) {
|
||||||
NativeModules = global.nativeModuleProxy;
|
NativeModules = global.nativeModuleProxy;
|
||||||
} else {
|
} else {
|
||||||
const bridgeConfig = global.__fbBatchedBridgeConfig;
|
const bridgeConfig = global.__fbBatchedBridgeConfig;
|
||||||
invariant(bridgeConfig, '__fbBatchedBridgeConfig is not set, cannot invoke native modules');
|
invariant(
|
||||||
|
bridgeConfig,
|
||||||
|
'__fbBatchedBridgeConfig is not set, cannot invoke native modules',
|
||||||
|
);
|
||||||
|
|
||||||
const defineLazyObjectProperty = require('defineLazyObjectProperty');
|
const defineLazyObjectProperty = require('defineLazyObjectProperty');
|
||||||
(bridgeConfig.remoteModuleConfig || []).forEach((config: ModuleConfig, moduleID: number) => {
|
(bridgeConfig.remoteModuleConfig || []).forEach(
|
||||||
// Initially this config will only contain the module name when running in JSC. The actual
|
(config: ModuleConfig, moduleID: number) => {
|
||||||
// configuration of the module will be lazily loaded.
|
// Initially this config will only contain the module name when running in JSC. The actual
|
||||||
const info = genModule(config, moduleID);
|
// configuration of the module will be lazily loaded.
|
||||||
if (!info) {
|
const info = genModule(config, moduleID);
|
||||||
return;
|
if (!info) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (info.module) {
|
if (info.module) {
|
||||||
NativeModules[info.name] = info.module;
|
NativeModules[info.name] = info.module;
|
||||||
}
|
}
|
||||||
// If there's no module config, define a lazy getter
|
// If there's no module config, define a lazy getter
|
||||||
else {
|
else {
|
||||||
defineLazyObjectProperty(NativeModules, info.name, {
|
defineLazyObjectProperty(NativeModules, info.name, {
|
||||||
get: () => loadModule(info.name, moduleID)
|
get: () => loadModule(info.name, moduleID),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = NativeModules;
|
module.exports = NativeModules;
|
||||||
|
|
|
@ -5,11 +5,14 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
* These don't actually exist anywhere in the code.
|
* These don't actually exist anywhere in the code.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
const remoteModulesConfig = [
|
const remoteModulesConfig = [
|
||||||
['RemoteModule1',null,['remoteMethod','promiseMethod'],[]],
|
['RemoteModule1', null, ['remoteMethod', 'promiseMethod'], []],
|
||||||
['RemoteModule2',null,['remoteMethod','promiseMethod'],[]],
|
['RemoteModule2', null, ['remoteMethod', 'promiseMethod'], []],
|
||||||
];
|
];
|
||||||
|
|
||||||
const MessageQueueTestConfig = {
|
const MessageQueueTestConfig = {
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,10 +15,8 @@
|
||||||
* cases.
|
* cases.
|
||||||
*/
|
*/
|
||||||
const MessageQueueTestModule = {
|
const MessageQueueTestModule = {
|
||||||
testHook1: function() {
|
testHook1: function() {},
|
||||||
},
|
testHook2: function() {},
|
||||||
testHook2: function() {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = MessageQueueTestModule;
|
module.exports = MessageQueueTestModule;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @emails oncall+react_native
|
* @emails oncall+react_native
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
jest
|
jest
|
||||||
|
@ -59,7 +61,12 @@ describe('MessageQueue', function() {
|
||||||
const onSucc = jest.fn();
|
const onSucc = jest.fn();
|
||||||
|
|
||||||
// Perform communication
|
// Perform communication
|
||||||
NativeModules.RemoteModule1.promiseMethod('paloAlto', 'menloPark', onFail, onSucc);
|
NativeModules.RemoteModule1.promiseMethod(
|
||||||
|
'paloAlto',
|
||||||
|
'menloPark',
|
||||||
|
onFail,
|
||||||
|
onSucc,
|
||||||
|
);
|
||||||
NativeModules.RemoteModule2.promiseMethod('mac', 'windows', onFail, onSucc);
|
NativeModules.RemoteModule2.promiseMethod('mac', 'windows', onFail, onSucc);
|
||||||
|
|
||||||
const resultingRemoteInvocations = BatchedBridge.flushedQueue();
|
const resultingRemoteInvocations = BatchedBridge.flushedQueue();
|
||||||
|
@ -73,9 +80,10 @@ describe('MessageQueue', function() {
|
||||||
|
|
||||||
expect(resultingRemoteInvocations[0][0]).toBe(0); // `RemoteModule1`
|
expect(resultingRemoteInvocations[0][0]).toBe(0); // `RemoteModule1`
|
||||||
expect(resultingRemoteInvocations[1][0]).toBe(1); // `promiseMethod`
|
expect(resultingRemoteInvocations[1][0]).toBe(1); // `promiseMethod`
|
||||||
expect([ // the arguments
|
expect([
|
||||||
|
// the arguments
|
||||||
resultingRemoteInvocations[2][0][0],
|
resultingRemoteInvocations[2][0][0],
|
||||||
resultingRemoteInvocations[2][0][1]
|
resultingRemoteInvocations[2][0][1],
|
||||||
]).toEqual(['paloAlto', 'menloPark']);
|
]).toEqual(['paloAlto', 'menloPark']);
|
||||||
// Callbacks ids are tacked onto the end of the remote arguments.
|
// Callbacks ids are tacked onto the end of the remote arguments.
|
||||||
const firstFailCBID = resultingRemoteInvocations[2][0][2];
|
const firstFailCBID = resultingRemoteInvocations[2][0][2];
|
||||||
|
@ -83,9 +91,10 @@ describe('MessageQueue', function() {
|
||||||
|
|
||||||
expect(resultingRemoteInvocations[0][1]).toBe(1); // `RemoteModule2`
|
expect(resultingRemoteInvocations[0][1]).toBe(1); // `RemoteModule2`
|
||||||
expect(resultingRemoteInvocations[1][1]).toBe(1); // `promiseMethod`
|
expect(resultingRemoteInvocations[1][1]).toBe(1); // `promiseMethod`
|
||||||
expect([ // the arguments
|
expect([
|
||||||
|
// the arguments
|
||||||
resultingRemoteInvocations[2][1][0],
|
resultingRemoteInvocations[2][1][0],
|
||||||
resultingRemoteInvocations[2][1][1]
|
resultingRemoteInvocations[2][1][1],
|
||||||
]).toEqual(['mac', 'windows']);
|
]).toEqual(['mac', 'windows']);
|
||||||
const secondFailCBID = resultingRemoteInvocations[2][1][2];
|
const secondFailCBID = resultingRemoteInvocations[2][1][2];
|
||||||
const secondSuccCBID = resultingRemoteInvocations[2][1][3];
|
const secondSuccCBID = resultingRemoteInvocations[2][1][3];
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||||
|
@ -14,12 +16,14 @@ const infoLog = require('infoLog');
|
||||||
|
|
||||||
import type EmitterSubscription from 'EmitterSubscription';
|
import type EmitterSubscription from 'EmitterSubscription';
|
||||||
|
|
||||||
type ExtraData = { [key: string]: string };
|
type ExtraData = {[key: string]: string};
|
||||||
type SourceCallback = () => string;
|
type SourceCallback = () => string;
|
||||||
type DebugData = { extras: ExtraData, files: ExtraData };
|
type DebugData = {extras: ExtraData, files: ExtraData};
|
||||||
|
|
||||||
function defaultExtras() {
|
function defaultExtras() {
|
||||||
BugReporting.addFileSource('react_hierarchy.txt', () => require('dumpReactTree')());
|
BugReporting.addFileSource('react_hierarchy.txt', () =>
|
||||||
|
require('dumpReactTree')(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,14 +40,20 @@ class BugReporting {
|
||||||
|
|
||||||
static _maybeInit() {
|
static _maybeInit() {
|
||||||
if (!BugReporting._subscription) {
|
if (!BugReporting._subscription) {
|
||||||
BugReporting._subscription = RCTDeviceEventEmitter
|
BugReporting._subscription = RCTDeviceEventEmitter.addListener(
|
||||||
.addListener('collectBugExtraData', BugReporting.collectExtraData, null);
|
'collectBugExtraData',
|
||||||
|
BugReporting.collectExtraData,
|
||||||
|
null,
|
||||||
|
);
|
||||||
defaultExtras();
|
defaultExtras();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BugReporting._redboxSubscription) {
|
if (!BugReporting._redboxSubscription) {
|
||||||
BugReporting._redboxSubscription = RCTDeviceEventEmitter
|
BugReporting._redboxSubscription = RCTDeviceEventEmitter.addListener(
|
||||||
.addListener('collectRedBoxExtraData', BugReporting.collectExtraData, null);
|
'collectRedBoxExtraData',
|
||||||
|
BugReporting.collectExtraData,
|
||||||
|
null,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +65,10 @@ class BugReporting {
|
||||||
*
|
*
|
||||||
* Conflicts trample with a warning.
|
* Conflicts trample with a warning.
|
||||||
*/
|
*/
|
||||||
static addSource(key: string, callback: SourceCallback): {remove: () => void} {
|
static addSource(
|
||||||
|
key: string,
|
||||||
|
callback: SourceCallback,
|
||||||
|
): {remove: () => void} {
|
||||||
return this._addSource(key, callback, BugReporting._extraSources);
|
return this._addSource(key, callback, BugReporting._extraSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,17 +80,30 @@ class BugReporting {
|
||||||
*
|
*
|
||||||
* Conflicts trample with a warning.
|
* Conflicts trample with a warning.
|
||||||
*/
|
*/
|
||||||
static addFileSource(key: string, callback: SourceCallback): {remove: () => void} {
|
static addFileSource(
|
||||||
|
key: string,
|
||||||
|
callback: SourceCallback,
|
||||||
|
): {remove: () => void} {
|
||||||
return this._addSource(key, callback, BugReporting._fileSources);
|
return this._addSource(key, callback, BugReporting._fileSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _addSource(key: string, callback: SourceCallback, source: Map<string, SourceCallback>): {remove: () => void} {
|
static _addSource(
|
||||||
|
key: string,
|
||||||
|
callback: SourceCallback,
|
||||||
|
source: Map<string, SourceCallback>,
|
||||||
|
): {remove: () => void} {
|
||||||
BugReporting._maybeInit();
|
BugReporting._maybeInit();
|
||||||
if (source.has(key)) {
|
if (source.has(key)) {
|
||||||
console.warn(`BugReporting.add* called multiple times for same key '${key}'`);
|
console.warn(
|
||||||
|
`BugReporting.add* called multiple times for same key '${key}'`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
source.set(key, callback);
|
source.set(key, callback);
|
||||||
return {remove: () => { source.delete(key); }};
|
return {
|
||||||
|
remove: () => {
|
||||||
|
source.delete(key);
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +132,7 @@ class BugReporting {
|
||||||
RedBoxNativeModule.setExtraData &&
|
RedBoxNativeModule.setExtraData &&
|
||||||
RedBoxNativeModule.setExtraData(extraData, 'From BugReporting.js');
|
RedBoxNativeModule.setExtraData(extraData, 'From BugReporting.js');
|
||||||
|
|
||||||
return { extras: extraData, files: fileData };
|
return {extras: extraData, files: fileData};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -35,7 +37,7 @@ function getReactTree() {
|
||||||
'React tree dumps have been temporarily disabled while React is ' +
|
'React tree dumps have been temporarily disabled while React is ' +
|
||||||
'upgraded to Fiber.'
|
'upgraded to Fiber.'
|
||||||
);
|
);
|
||||||
/*
|
/*
|
||||||
let output = '';
|
let output = '';
|
||||||
const rootIds = Object.getOwnPropertyNames(ReactNativeMount._instancesByContainerID);
|
const rootIds = Object.getOwnPropertyNames(ReactNativeMount._instancesByContainerID);
|
||||||
for (const rootId of rootIds) {
|
for (const rootId of rootIds) {
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +33,10 @@ function getData(element: Object): Object {
|
||||||
if (typeof element !== 'object') {
|
if (typeof element !== 'object') {
|
||||||
nodeType = 'Text';
|
nodeType = 'Text';
|
||||||
text = element + '';
|
text = element + '';
|
||||||
} else if (element._currentElement === null || element._currentElement === false) {
|
} else if (
|
||||||
|
element._currentElement === null ||
|
||||||
|
element._currentElement === false
|
||||||
|
) {
|
||||||
nodeType = 'Empty';
|
nodeType = 'Empty';
|
||||||
} else if (element._renderedComponent) {
|
} else if (element._renderedComponent) {
|
||||||
nodeType = 'NativeWrapper';
|
nodeType = 'NativeWrapper';
|
||||||
|
@ -65,7 +70,11 @@ function getData(element: Object): Object {
|
||||||
name = element.getName();
|
name = element.getName();
|
||||||
// 0.14 top-level wrapper
|
// 0.14 top-level wrapper
|
||||||
// TODO(jared): The backend should just act as if these don't exist.
|
// TODO(jared): The backend should just act as if these don't exist.
|
||||||
if (element._renderedComponent && element._currentElement.props === element._renderedComponent._currentElement) {
|
if (
|
||||||
|
element._renderedComponent &&
|
||||||
|
element._currentElement.props ===
|
||||||
|
element._renderedComponent._currentElement
|
||||||
|
) {
|
||||||
nodeType = 'Wrapper';
|
nodeType = 'Wrapper';
|
||||||
}
|
}
|
||||||
if (name === null) {
|
if (name === null) {
|
||||||
|
@ -133,7 +142,7 @@ function setInContext(inst, path: Array<string | number>, value: any) {
|
||||||
|
|
||||||
function setIn(obj: Object, path: Array<string | number>, value: any) {
|
function setIn(obj: Object, path: Array<string | number>, value: any) {
|
||||||
const last = path.pop();
|
const last = path.pop();
|
||||||
const parent = path.reduce((obj_, attr) => obj_ ? obj_[attr] : null, obj);
|
const parent = path.reduce((obj_, attr) => (obj_ ? obj_[attr] : null), obj);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent[last] = value;
|
parent[last] = value;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +167,11 @@ function copyWithSetImpl(obj, path, idx, value) {
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyWithSet(obj: Object | Array<any>, path: Array<string | number>, value: any): Object | Array<any> {
|
function copyWithSet(
|
||||||
|
obj: Object | Array<any>,
|
||||||
|
path: Array<string | number>,
|
||||||
|
value: any,
|
||||||
|
): Object | Array<any> {
|
||||||
return copyWithSetImpl(obj, path, 0, value);
|
return copyWithSetImpl(obj, path, 0, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const RCTImagePicker = require('NativeModules').ImagePickerIOS;
|
const RCTImagePicker = require('NativeModules').ImagePickerIOS;
|
||||||
|
@ -17,20 +19,36 @@ const ImagePickerIOS = {
|
||||||
canUseCamera: function(callback: Function) {
|
canUseCamera: function(callback: Function) {
|
||||||
return RCTImagePicker.canUseCamera(callback);
|
return RCTImagePicker.canUseCamera(callback);
|
||||||
},
|
},
|
||||||
openCameraDialog: function(config: Object, successCallback: Function, cancelCallback: Function) {
|
openCameraDialog: function(
|
||||||
|
config: Object,
|
||||||
|
successCallback: Function,
|
||||||
|
cancelCallback: Function,
|
||||||
|
) {
|
||||||
config = {
|
config = {
|
||||||
videoMode: false,
|
videoMode: false,
|
||||||
...config,
|
...config,
|
||||||
};
|
};
|
||||||
return RCTImagePicker.openCameraDialog(config, successCallback, cancelCallback);
|
return RCTImagePicker.openCameraDialog(
|
||||||
|
config,
|
||||||
|
successCallback,
|
||||||
|
cancelCallback,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
openSelectDialog: function(config: Object, successCallback: Function, cancelCallback: Function) {
|
openSelectDialog: function(
|
||||||
|
config: Object,
|
||||||
|
successCallback: Function,
|
||||||
|
cancelCallback: Function,
|
||||||
|
) {
|
||||||
config = {
|
config = {
|
||||||
showImages: true,
|
showImages: true,
|
||||||
showVideos: false,
|
showVideos: false,
|
||||||
...config,
|
...config,
|
||||||
};
|
};
|
||||||
return RCTImagePicker.openSelectDialog(config, successCallback, cancelCallback);
|
return RCTImagePicker.openSelectDialog(
|
||||||
|
config,
|
||||||
|
successCallback,
|
||||||
|
cancelCallback,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint no-bitwise: 0 */
|
/* eslint no-bitwise: 0 */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -30,30 +32,39 @@ function normalizeColor(color: string | number): ?number {
|
||||||
|
|
||||||
if ((match = matchers.rgb.exec(color))) {
|
if ((match = matchers.rgb.exec(color))) {
|
||||||
return (
|
return (
|
||||||
(// b
|
// b
|
||||||
(parse255(match[1]) << 24 | // r
|
((parse255(match[1]) << 24) | // r
|
||||||
parse255(match[2]) << 16 | // g
|
(parse255(match[2]) << 16) | // g
|
||||||
parse255(match[3]) << 8 | 0x000000ff)) // a
|
(parse255(match[3]) << 8) |
|
||||||
) >>> 0;
|
0x000000ff) >>> // a
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((match = matchers.rgba.exec(color))) {
|
if ((match = matchers.rgba.exec(color))) {
|
||||||
return (
|
return (
|
||||||
(// b
|
// b
|
||||||
(parse255(match[1]) << 24 | // r
|
((parse255(match[1]) << 24) | // r
|
||||||
parse255(match[2]) << 16 | // g
|
(parse255(match[2]) << 16) | // g
|
||||||
parse255(match[3]) << 8 | parse1(match[4]))) // a
|
(parse255(match[3]) << 8) |
|
||||||
) >>> 0;
|
parse1(match[4])) >>> // a
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((match = matchers.hex3.exec(color))) {
|
if ((match = matchers.hex3.exec(color))) {
|
||||||
return parseInt(
|
return (
|
||||||
match[1] + match[1] + // r
|
parseInt(
|
||||||
match[2] + match[2] + // g
|
match[1] +
|
||||||
match[3] + match[3] + // b
|
match[1] + // r
|
||||||
'ff', // a
|
match[2] +
|
||||||
16
|
match[2] + // g
|
||||||
) >>> 0;
|
match[3] +
|
||||||
|
match[3] + // b
|
||||||
|
'ff', // a
|
||||||
|
16,
|
||||||
|
) >>> 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-color-4/#hex-notation
|
// https://drafts.csswg.org/css-color-4/#hex-notation
|
||||||
|
@ -62,13 +73,19 @@ function normalizeColor(color: string | number): ?number {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((match = matchers.hex4.exec(color))) {
|
if ((match = matchers.hex4.exec(color))) {
|
||||||
return parseInt(
|
return (
|
||||||
match[1] + match[1] + // r
|
parseInt(
|
||||||
match[2] + match[2] + // g
|
match[1] +
|
||||||
match[3] + match[3] + // b
|
match[1] + // r
|
||||||
match[4] + match[4], // a
|
match[2] +
|
||||||
16
|
match[2] + // g
|
||||||
) >>> 0;
|
match[3] +
|
||||||
|
match[3] + // b
|
||||||
|
match[4] +
|
||||||
|
match[4], // a
|
||||||
|
16,
|
||||||
|
) >>> 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((match = matchers.hsl.exec(color))) {
|
if ((match = matchers.hsl.exec(color))) {
|
||||||
|
@ -76,9 +93,11 @@ function normalizeColor(color: string | number): ?number {
|
||||||
(hslToRgb(
|
(hslToRgb(
|
||||||
parse360(match[1]), // h
|
parse360(match[1]), // h
|
||||||
parsePercentage(match[2]), // s
|
parsePercentage(match[2]), // s
|
||||||
parsePercentage(match[3]) // l
|
parsePercentage(match[3]), // l
|
||||||
) | 0x000000ff) // a
|
) |
|
||||||
) >>> 0;
|
0x000000ff) >>> // a
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((match = matchers.hsla.exec(color))) {
|
if ((match = matchers.hsla.exec(color))) {
|
||||||
|
@ -86,9 +105,11 @@ function normalizeColor(color: string | number): ?number {
|
||||||
(hslToRgb(
|
(hslToRgb(
|
||||||
parse360(match[1]), // h
|
parse360(match[1]), // h
|
||||||
parsePercentage(match[2]), // s
|
parsePercentage(match[2]), // s
|
||||||
parsePercentage(match[3]) // l
|
parsePercentage(match[3]), // l
|
||||||
) | parse1(match[4])) // a
|
) |
|
||||||
) >>> 0;
|
parse1(match[4])) >>> // a
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -121,9 +142,9 @@ function hslToRgb(h: number, s: number, l: number): number {
|
||||||
const b = hue2rgb(p, q, h - 1 / 3);
|
const b = hue2rgb(p, q, h - 1 / 3);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Math.round(r * 255) << 24 |
|
(Math.round(r * 255) << 24) |
|
||||||
Math.round(g * 255) << 16 |
|
(Math.round(g * 255) << 16) |
|
||||||
Math.round(b * 255) << 8
|
(Math.round(b * 255) << 8)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +180,7 @@ function parse255(str: string): number {
|
||||||
|
|
||||||
function parse360(str: string): number {
|
function parse360(str: string): number {
|
||||||
const int = parseFloat(str);
|
const int = parseFloat(str);
|
||||||
return (((int % 360) + 360) % 360) / 360;
|
return ((int % 360 + 360) % 360) / 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse1(str: string): number {
|
function parse1(str: string): number {
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeModules = require('NativeModules');
|
const NativeModules = require('NativeModules');
|
||||||
|
@ -32,33 +34,30 @@ const _subscriptions = new Map();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const AccessibilityInfo = {
|
const AccessibilityInfo = {
|
||||||
|
|
||||||
fetch: function(): Promise {
|
fetch: function(): Promise {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
RCTAccessibilityInfo.isTouchExplorationEnabled(
|
RCTAccessibilityInfo.isTouchExplorationEnabled(function(resp) {
|
||||||
function(resp) {
|
resolve(resp);
|
||||||
resolve(resp);
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addEventListener: function (
|
addEventListener: function(
|
||||||
eventName: ChangeEventName,
|
eventName: ChangeEventName,
|
||||||
handler: Function
|
handler: Function,
|
||||||
): void {
|
): void {
|
||||||
const listener = RCTDeviceEventEmitter.addListener(
|
const listener = RCTDeviceEventEmitter.addListener(
|
||||||
TOUCH_EXPLORATION_EVENT,
|
TOUCH_EXPLORATION_EVENT,
|
||||||
(enabled) => {
|
enabled => {
|
||||||
handler(enabled);
|
handler(enabled);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
_subscriptions.set(handler, listener);
|
_subscriptions.set(handler, listener);
|
||||||
},
|
},
|
||||||
|
|
||||||
removeEventListener: function(
|
removeEventListener: function(
|
||||||
eventName: ChangeEventName,
|
eventName: ChangeEventName,
|
||||||
handler: Function
|
handler: Function,
|
||||||
): void {
|
): void {
|
||||||
const listener = _subscriptions.get(handler);
|
const listener = _subscriptions.get(handler);
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
|
@ -67,7 +66,6 @@ const AccessibilityInfo = {
|
||||||
listener.remove();
|
listener.remove();
|
||||||
_subscriptions.delete(handler);
|
_subscriptions.delete(handler);
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = AccessibilityInfo;
|
module.exports = AccessibilityInfo;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeModules = require('NativeModules');
|
const NativeModules = require('NativeModules');
|
||||||
|
@ -19,7 +21,7 @@ const ANNOUNCEMENT_DID_FINISH_EVENT = 'announcementDidFinish';
|
||||||
|
|
||||||
type ChangeEventName = $Enum<{
|
type ChangeEventName = $Enum<{
|
||||||
change: string,
|
change: string,
|
||||||
announcementFinished: string
|
announcementFinished: string,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const _subscriptions = new Map();
|
const _subscriptions = new Map();
|
||||||
|
@ -34,7 +36,6 @@ const _subscriptions = new Map();
|
||||||
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html
|
||||||
*/
|
*/
|
||||||
const AccessibilityInfo = {
|
const AccessibilityInfo = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query whether a screen reader is currently enabled.
|
* Query whether a screen reader is currently enabled.
|
||||||
*
|
*
|
||||||
|
@ -45,10 +46,7 @@ const AccessibilityInfo = {
|
||||||
*/
|
*/
|
||||||
fetch: function(): Promise {
|
fetch: function(): Promise {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
AccessibilityManager.getCurrentVoiceOverState(
|
AccessibilityManager.getCurrentVoiceOverState(resolve, reject);
|
||||||
resolve,
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -67,27 +65,28 @@ const AccessibilityInfo = {
|
||||||
*
|
*
|
||||||
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#addeventlistener
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#addeventlistener
|
||||||
*/
|
*/
|
||||||
addEventListener: function (
|
addEventListener: function(
|
||||||
eventName: ChangeEventName,
|
eventName: ChangeEventName,
|
||||||
handler: Function
|
handler: Function,
|
||||||
): Object {
|
): Object {
|
||||||
let listener;
|
let listener;
|
||||||
|
|
||||||
if (eventName === 'change') {
|
if (eventName === 'change') {
|
||||||
listener = RCTDeviceEventEmitter.addListener(
|
listener = RCTDeviceEventEmitter.addListener(VOICE_OVER_EVENT, handler);
|
||||||
VOICE_OVER_EVENT,
|
|
||||||
handler
|
|
||||||
);
|
|
||||||
} else if (eventName === 'announcementFinished') {
|
} else if (eventName === 'announcementFinished') {
|
||||||
listener = RCTDeviceEventEmitter.addListener(
|
listener = RCTDeviceEventEmitter.addListener(
|
||||||
ANNOUNCEMENT_DID_FINISH_EVENT,
|
ANNOUNCEMENT_DID_FINISH_EVENT,
|
||||||
handler
|
handler,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscriptions.set(handler, listener);
|
_subscriptions.set(handler, listener);
|
||||||
return {
|
return {
|
||||||
remove: AccessibilityInfo.removeEventListener.bind(null, eventName, handler),
|
remove: AccessibilityInfo.removeEventListener.bind(
|
||||||
|
null,
|
||||||
|
eventName,
|
||||||
|
handler,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -98,9 +97,7 @@ const AccessibilityInfo = {
|
||||||
*
|
*
|
||||||
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus
|
||||||
*/
|
*/
|
||||||
setAccessibilityFocus: function(
|
setAccessibilityFocus: function(reactTag: number): void {
|
||||||
reactTag: number
|
|
||||||
): void {
|
|
||||||
AccessibilityManager.setAccessibilityFocus(reactTag);
|
AccessibilityManager.setAccessibilityFocus(reactTag);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -111,9 +108,7 @@ const AccessibilityInfo = {
|
||||||
*
|
*
|
||||||
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility
|
* See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility
|
||||||
*/
|
*/
|
||||||
announceForAccessibility: function(
|
announceForAccessibility: function(announcement: string): void {
|
||||||
announcement: string
|
|
||||||
): void {
|
|
||||||
AccessibilityManager.announceForAccessibility(announcement);
|
AccessibilityManager.announceForAccessibility(announcement);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -124,7 +119,7 @@ const AccessibilityInfo = {
|
||||||
*/
|
*/
|
||||||
removeEventListener: function(
|
removeEventListener: function(
|
||||||
eventName: ChangeEventName,
|
eventName: ChangeEventName,
|
||||||
handler: Function
|
handler: Function,
|
||||||
): void {
|
): void {
|
||||||
const listener = _subscriptions.get(handler);
|
const listener = _subscriptions.get(handler);
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
|
@ -133,7 +128,6 @@ const AccessibilityInfo = {
|
||||||
listener.remove();
|
listener.remove();
|
||||||
_subscriptions.delete(handler);
|
_subscriptions.delete(handler);
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = AccessibilityInfo;
|
module.exports = AccessibilityInfo;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -31,7 +33,7 @@ type DefaultProps = {
|
||||||
color: any,
|
color: any,
|
||||||
hidesWhenStopped: boolean,
|
hidesWhenStopped: boolean,
|
||||||
size: IndicatorSize,
|
size: IndicatorSize,
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a circular loading indicator.
|
* Displays a circular loading indicator.
|
||||||
|
@ -63,7 +65,7 @@ const ActivityIndicator = createReactClass({
|
||||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#size
|
* See http://facebook.github.io/react-native/docs/activityindicator.html#size
|
||||||
*/
|
*/
|
||||||
size: PropTypes.oneOfType([
|
size: PropTypes.oneOfType([
|
||||||
PropTypes.oneOf([ 'small', 'large' ]),
|
PropTypes.oneOf(['small', 'large']),
|
||||||
PropTypes.number,
|
PropTypes.number,
|
||||||
]),
|
]),
|
||||||
/**
|
/**
|
||||||
|
@ -117,14 +119,14 @@ const ActivityIndicator = createReactClass({
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
RCTActivityIndicator = requireNativeComponent(
|
RCTActivityIndicator = requireNativeComponent(
|
||||||
'RCTActivityIndicatorView',
|
'RCTActivityIndicatorView',
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
{ nativeOnly: { activityIndicatorViewStyle: true } }
|
{nativeOnly: {activityIndicatorViewStyle: true}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
const TVNavigationEventEmitter = require('NativeModules').TVNavigationEventEmitter;
|
const TVNavigationEventEmitter = require('NativeModules')
|
||||||
|
.TVNavigationEventEmitter;
|
||||||
const NativeEventEmitter = require('NativeEventEmitter');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
|
|
||||||
function TVEventHandler() {
|
function TVEventHandler() {
|
||||||
|
@ -17,19 +20,24 @@ function TVEventHandler() {
|
||||||
this.__nativeTVNavigationEventEmitter = null;
|
this.__nativeTVNavigationEventEmitter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
TVEventHandler.prototype.enable = function(component: ?any, callback: Function) {
|
TVEventHandler.prototype.enable = function(
|
||||||
|
component: ?any,
|
||||||
|
callback: Function,
|
||||||
|
) {
|
||||||
if (Platform.OS === 'ios' && !TVNavigationEventEmitter) {
|
if (Platform.OS === 'ios' && !TVNavigationEventEmitter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.__nativeTVNavigationEventEmitter = new NativeEventEmitter(TVNavigationEventEmitter);
|
this.__nativeTVNavigationEventEmitter = new NativeEventEmitter(
|
||||||
|
TVNavigationEventEmitter,
|
||||||
|
);
|
||||||
this.__nativeTVNavigationEventListener = this.__nativeTVNavigationEventEmitter.addListener(
|
this.__nativeTVNavigationEventListener = this.__nativeTVNavigationEventEmitter.addListener(
|
||||||
'onHWKeyEvent',
|
'onHWKeyEvent',
|
||||||
(data) => {
|
data => {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(component, data);
|
callback(component, data);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
const PropTypes = require('prop-types');
|
const PropTypes = require('prop-types');
|
||||||
|
|
||||||
|
@ -13,66 +15,65 @@ const PropTypes = require('prop-types');
|
||||||
* Additional View properties for Apple TV
|
* Additional View properties for Apple TV
|
||||||
*/
|
*/
|
||||||
const TVViewPropTypes = {
|
const TVViewPropTypes = {
|
||||||
/**
|
/**
|
||||||
* When set to true, this view will be focusable
|
* When set to true, this view will be focusable
|
||||||
* and navigable using the TV remote.
|
* and navigable using the TV remote.
|
||||||
*/
|
*/
|
||||||
isTVSelectable: PropTypes.bool,
|
isTVSelectable: PropTypes.bool,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* May be set to true to force the TV focus engine to move focus to this view.
|
* May be set to true to force the TV focus engine to move focus to this view.
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus: PropTypes.bool,
|
hasTVPreferredFocus: PropTypes.bool,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *(Apple TV only)* Object with properties to control Apple TV parallax effects.
|
* *(Apple TV only)* Object with properties to control Apple TV parallax effects.
|
||||||
*
|
*
|
||||||
* enabled: If true, parallax effects are enabled. Defaults to true.
|
* enabled: If true, parallax effects are enabled. Defaults to true.
|
||||||
* shiftDistanceX: Defaults to 2.0.
|
* shiftDistanceX: Defaults to 2.0.
|
||||||
* shiftDistanceY: Defaults to 2.0.
|
* shiftDistanceY: Defaults to 2.0.
|
||||||
* tiltAngle: Defaults to 0.05.
|
* tiltAngle: Defaults to 0.05.
|
||||||
* magnification: Defaults to 1.0.
|
* magnification: Defaults to 1.0.
|
||||||
* pressMagnification: Defaults to 1.0.
|
* pressMagnification: Defaults to 1.0.
|
||||||
* pressDuration: Defaults to 0.3.
|
* pressDuration: Defaults to 0.3.
|
||||||
* pressDelay: Defaults to 0.0.
|
* pressDelay: Defaults to 0.0.
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
tvParallaxProperties: PropTypes.object,
|
tvParallaxProperties: PropTypes.object,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0.
|
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0.
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
tvParallaxShiftDistanceX: PropTypes.number,
|
tvParallaxShiftDistanceX: PropTypes.number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0.
|
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0.
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
tvParallaxShiftDistanceY: PropTypes.number,
|
tvParallaxShiftDistanceY: PropTypes.number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 0.05.
|
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 0.05.
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
tvParallaxTiltAngle: PropTypes.number,
|
tvParallaxTiltAngle: PropTypes.number,
|
||||||
|
|
||||||
/**
|
|
||||||
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 1.0.
|
|
||||||
*
|
|
||||||
* @platform ios
|
|
||||||
*/
|
|
||||||
tvParallaxMagnification: PropTypes.number,
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 1.0.
|
||||||
|
*
|
||||||
|
* @platform ios
|
||||||
|
*/
|
||||||
|
tvParallaxMagnification: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TVViewProps = {
|
export type TVViewProps = {
|
||||||
isTVSelectable?: bool,
|
isTVSelectable?: boolean,
|
||||||
hasTVPreferredFocus?: bool,
|
hasTVPreferredFocus?: boolean,
|
||||||
tvParallaxProperties?: Object,
|
tvParallaxProperties?: Object,
|
||||||
tvParallaxShiftDistanceX?: number,
|
tvParallaxShiftDistanceX?: number,
|
||||||
tvParallaxShiftDistanceY?: number,
|
tvParallaxShiftDistanceY?: number,
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -117,8 +119,10 @@ class Button extends React.Component<{
|
||||||
typeof title === 'string',
|
typeof title === 'string',
|
||||||
'The title prop of a Button must be a string',
|
'The title prop of a Button must be a string',
|
||||||
);
|
);
|
||||||
const formattedTitle = Platform.OS === 'android' ? title.toUpperCase() : title;
|
const formattedTitle =
|
||||||
const Touchable = Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;
|
Platform.OS === 'android' ? title.toUpperCase() : title;
|
||||||
|
const Touchable =
|
||||||
|
Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;
|
||||||
return (
|
return (
|
||||||
<Touchable
|
<Touchable
|
||||||
accessibilityComponentType="button"
|
accessibilityComponentType="button"
|
||||||
|
@ -129,7 +133,9 @@ class Button extends React.Component<{
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onPress={onPress}>
|
onPress={onPress}>
|
||||||
<View style={buttonStyles}>
|
<View style={buttonStyles}>
|
||||||
<Text style={textStyles} disabled={disabled}>{formattedTitle}</Text>
|
<Text style={textStyles} disabled={disabled}>
|
||||||
|
{formattedTitle}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</Touchable>
|
</Touchable>
|
||||||
);
|
);
|
||||||
|
@ -166,7 +172,7 @@ const styles = StyleSheet.create({
|
||||||
android: {
|
android: {
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
backgroundColor: '#dfdfdf',
|
backgroundColor: '#dfdfdf',
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
textDisabled: Platform.select({
|
textDisabled: Platform.select({
|
||||||
ios: {
|
ios: {
|
||||||
|
@ -174,7 +180,7 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
android: {
|
android: {
|
||||||
color: '#a1a1a1',
|
color: '#a1a1a1',
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Clipboard = require('NativeModules').Clipboard;
|
const Clipboard = require('NativeModules').Clipboard;
|
||||||
|
@ -36,5 +38,5 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
setString(content: string) {
|
setString(content: string) {
|
||||||
Clipboard.setString(content);
|
Clipboard.setString(content);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -17,7 +18,9 @@ class DummyDatePickerIOS extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.dummyDatePickerIOS, this.props.style]}>
|
<View style={[styles.dummyDatePickerIOS, this.props.style]}>
|
||||||
<Text style={styles.datePickerText}>DatePickerIOS is not supported on this platform!</Text>
|
<Text style={styles.datePickerText}>
|
||||||
|
DatePickerIOS is not supported on this platform!
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +40,7 @@ const styles = StyleSheet.create({
|
||||||
datePickerText: {
|
datePickerText: {
|
||||||
color: '#333333',
|
color: '#333333',
|
||||||
margin: 20,
|
margin: 20,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DummyDatePickerIOS;
|
module.exports = DummyDatePickerIOS;
|
||||||
|
|
|
@ -4,10 +4,13 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
* @flow
|
|
||||||
*
|
*
|
||||||
* This is a controlled component version of RCTDatePickerIOS
|
* This is a controlled component version of RCTDatePickerIOS
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||||
|
@ -125,9 +128,8 @@ const DatePickerIOS = createReactClass({
|
||||||
|
|
||||||
_onChange: function(event: Event) {
|
_onChange: function(event: Event) {
|
||||||
const nativeTimeStamp = event.nativeEvent.timestamp;
|
const nativeTimeStamp = event.nativeEvent.timestamp;
|
||||||
this.props.onDateChange && this.props.onDateChange(
|
this.props.onDateChange &&
|
||||||
new Date(nativeTimeStamp)
|
this.props.onDateChange(new Date(nativeTimeStamp));
|
||||||
);
|
|
||||||
// $FlowFixMe(>=0.41.0)
|
// $FlowFixMe(>=0.41.0)
|
||||||
this.props.onChange && this.props.onChange(event);
|
this.props.onChange && this.props.onChange(event);
|
||||||
},
|
},
|
||||||
|
@ -141,9 +143,17 @@ const DatePickerIOS = createReactClass({
|
||||||
return (
|
return (
|
||||||
<View style={props.style}>
|
<View style={props.style}>
|
||||||
<RCTDatePickerIOS
|
<RCTDatePickerIOS
|
||||||
ref={ picker => { this._picker = picker; } }
|
ref={picker => {
|
||||||
|
this._picker = picker;
|
||||||
|
}}
|
||||||
style={styles.datePickerIOS}
|
style={styles.datePickerIOS}
|
||||||
date={props.date ? props.date.getTime() : props.initialDate ? props.initialDate.getTime() : undefined}
|
date={
|
||||||
|
props.date
|
||||||
|
? props.date.getTime()
|
||||||
|
: props.initialDate
|
||||||
|
? props.initialDate.getTime()
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
locale={props.locale ? props.locale : undefined}
|
locale={props.locale ? props.locale : undefined}
|
||||||
maximumDate={
|
maximumDate={
|
||||||
props.maximumDate ? props.maximumDate.getTime() : undefined
|
props.maximumDate ? props.maximumDate.getTime() : undefined
|
||||||
|
@ -160,7 +170,7 @@ const DatePickerIOS = createReactClass({
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -178,7 +188,7 @@ const RCTDatePickerIOS = requireNativeComponent('RCTDatePicker', {
|
||||||
maximumDate: PropTypes.number,
|
maximumDate: PropTypes.number,
|
||||||
onDateChange: () => null,
|
onDateChange: () => null,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DatePickerIOS;
|
module.exports = DatePickerIOS;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const DatePickerModule = require('NativeModules').DatePickerAndroid;
|
const DatePickerModule = require('NativeModules').DatePickerAndroid;
|
||||||
|
@ -76,11 +78,15 @@ class DatePickerAndroid {
|
||||||
/**
|
/**
|
||||||
* A date has been selected.
|
* A date has been selected.
|
||||||
*/
|
*/
|
||||||
static get dateSetAction() { return 'dateSetAction'; }
|
static get dateSetAction() {
|
||||||
|
return 'dateSetAction';
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* The dialog has been dismissed.
|
* The dialog has been dismissed.
|
||||||
*/
|
*/
|
||||||
static get dismissedAction() { return 'dismissedAction'; }
|
static get dismissedAction() {
|
||||||
|
return 'dismissedAction';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DatePickerAndroid;
|
module.exports = DatePickerAndroid;
|
||||||
|
|
|
@ -4,14 +4,16 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const DatePickerAndroid = {
|
const DatePickerAndroid = {
|
||||||
async open(options: Object): Promise<Object> {
|
async open(options: Object): Promise<Object> {
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
message: 'DatePickerAndroid is not supported on this platform.'
|
message: 'DatePickerAndroid is not supported on this platform.',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -28,11 +30,7 @@ const requireNativeComponent = require('requireNativeComponent');
|
||||||
const RK_DRAWER_REF = 'drawerlayout';
|
const RK_DRAWER_REF = 'drawerlayout';
|
||||||
const INNERVIEW_REF = 'innerView';
|
const INNERVIEW_REF = 'innerView';
|
||||||
|
|
||||||
const DRAWER_STATES = [
|
const DRAWER_STATES = ['Idle', 'Dragging', 'Settling'];
|
||||||
'Idle',
|
|
||||||
'Dragging',
|
|
||||||
'Settling',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React component that wraps the platform `DrawerLayout` (Android only). The
|
* React component that wraps the platform `DrawerLayout` (Android only). The
|
||||||
|
@ -99,7 +97,7 @@ const DrawerLayoutAndroid = createReactClass({
|
||||||
*/
|
*/
|
||||||
drawerPosition: PropTypes.oneOf([
|
drawerPosition: PropTypes.oneOf([
|
||||||
DrawerConsts.DrawerPosition.Left,
|
DrawerConsts.DrawerPosition.Left,
|
||||||
DrawerConsts.DrawerPosition.Right
|
DrawerConsts.DrawerPosition.Right,
|
||||||
]),
|
]),
|
||||||
/**
|
/**
|
||||||
* Specifies the width of the drawer, more precisely the width of the view that be pulled in
|
* Specifies the width of the drawer, more precisely the width of the view that be pulled in
|
||||||
|
@ -116,7 +114,7 @@ const DrawerLayoutAndroid = createReactClass({
|
||||||
drawerLockMode: PropTypes.oneOf([
|
drawerLockMode: PropTypes.oneOf([
|
||||||
'unlocked',
|
'unlocked',
|
||||||
'locked-closed',
|
'locked-closed',
|
||||||
'locked-open'
|
'locked-open',
|
||||||
]),
|
]),
|
||||||
/**
|
/**
|
||||||
* Function called whenever there is an interaction with the navigation view.
|
* Function called whenever there is an interaction with the navigation view.
|
||||||
|
@ -168,31 +166,41 @@ const DrawerLayoutAndroid = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const drawStatusBar = Platform.Version >= 21 && this.props.statusBarBackgroundColor;
|
const drawStatusBar =
|
||||||
const drawerViewWrapper =
|
Platform.Version >= 21 && this.props.statusBarBackgroundColor;
|
||||||
|
const drawerViewWrapper = (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.drawerSubview,
|
styles.drawerSubview,
|
||||||
{width: this.props.drawerWidth, backgroundColor: this.props.drawerBackgroundColor}
|
{
|
||||||
|
width: this.props.drawerWidth,
|
||||||
|
backgroundColor: this.props.drawerBackgroundColor,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
collapsable={false}>
|
collapsable={false}>
|
||||||
{this.props.renderNavigationView()}
|
{this.props.renderNavigationView()}
|
||||||
{drawStatusBar && <View style={styles.drawerStatusBar} />}
|
{drawStatusBar && <View style={styles.drawerStatusBar} />}
|
||||||
</View>;
|
</View>
|
||||||
const childrenWrapper =
|
);
|
||||||
|
const childrenWrapper = (
|
||||||
<View ref={INNERVIEW_REF} style={styles.mainSubview} collapsable={false}>
|
<View ref={INNERVIEW_REF} style={styles.mainSubview} collapsable={false}>
|
||||||
{drawStatusBar &&
|
{drawStatusBar && (
|
||||||
<StatusBar
|
<StatusBar
|
||||||
translucent
|
translucent
|
||||||
backgroundColor={this.props.statusBarBackgroundColor}
|
backgroundColor={this.props.statusBarBackgroundColor}
|
||||||
/>}
|
/>
|
||||||
{drawStatusBar &&
|
)}
|
||||||
<View style={[
|
{drawStatusBar && (
|
||||||
styles.statusBar,
|
<View
|
||||||
{backgroundColor: this.props.statusBarBackgroundColor}
|
style={[
|
||||||
]} />}
|
styles.statusBar,
|
||||||
|
{backgroundColor: this.props.statusBarBackgroundColor},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</View>;
|
</View>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<AndroidDrawerLayout
|
<AndroidDrawerLayout
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
@ -234,7 +242,9 @@ const DrawerLayoutAndroid = createReactClass({
|
||||||
|
|
||||||
_onDrawerStateChanged: function(event) {
|
_onDrawerStateChanged: function(event) {
|
||||||
if (this.props.onDrawerStateChanged) {
|
if (this.props.onDrawerStateChanged) {
|
||||||
this.props.onDrawerStateChanged(DRAWER_STATES[event.nativeEvent.drawerState]);
|
this.props.onDrawerStateChanged(
|
||||||
|
DRAWER_STATES[event.nativeEvent.drawerState],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -245,7 +255,7 @@ const DrawerLayoutAndroid = createReactClass({
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
this._getDrawerLayoutHandle(),
|
this._getDrawerLayoutHandle(),
|
||||||
UIManager.AndroidDrawerLayout.Commands.openDrawer,
|
UIManager.AndroidDrawerLayout.Commands.openDrawer,
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -256,29 +266,28 @@ const DrawerLayoutAndroid = createReactClass({
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
this._getDrawerLayoutHandle(),
|
this._getDrawerLayoutHandle(),
|
||||||
UIManager.AndroidDrawerLayout.Commands.closeDrawer,
|
UIManager.AndroidDrawerLayout.Commands.closeDrawer,
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Closing and opening example
|
* Closing and opening example
|
||||||
* Note: To access the drawer you have to give it a ref. Refs do not work on stateless components
|
* Note: To access the drawer you have to give it a ref. Refs do not work on stateless components
|
||||||
* render () {
|
* render () {
|
||||||
* this.openDrawer = () => {
|
* this.openDrawer = () => {
|
||||||
* this.refs.DRAWER.openDrawer()
|
* this.refs.DRAWER.openDrawer()
|
||||||
* }
|
* }
|
||||||
* this.closeDrawer = () => {
|
* this.closeDrawer = () => {
|
||||||
* this.refs.DRAWER.closeDrawer()
|
* this.refs.DRAWER.closeDrawer()
|
||||||
* }
|
* }
|
||||||
* return (
|
* return (
|
||||||
* <DrawerLayoutAndroid ref={'DRAWER'}>
|
* <DrawerLayoutAndroid ref={'DRAWER'}>
|
||||||
* </DrawerLayoutAndroid>
|
* </DrawerLayoutAndroid>
|
||||||
* )
|
* )
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
_getDrawerLayoutHandle: function() {
|
_getDrawerLayoutHandle: function() {
|
||||||
return ReactNative.findNodeHandle(this.refs[RK_DRAWER_REF]);
|
return ReactNative.findNodeHandle(this.refs[RK_DRAWER_REF]);
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -312,6 +321,9 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
// The View that contains both the actual drawer and the main view
|
// The View that contains both the actual drawer and the main view
|
||||||
const AndroidDrawerLayout = requireNativeComponent('AndroidDrawerLayout', DrawerLayoutAndroid);
|
const AndroidDrawerLayout = requireNativeComponent(
|
||||||
|
'AndroidDrawerLayout',
|
||||||
|
DrawerLayoutAndroid,
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = DrawerLayoutAndroid;
|
module.exports = DrawerLayoutAndroid;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const LayoutAnimation = require('LayoutAnimation');
|
const LayoutAnimation = require('LayoutAnimation');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const createReactClass = require('create-react-class');
|
const createReactClass = require('create-react-class');
|
||||||
|
@ -66,9 +68,9 @@ const KeyboardAvoidingView = createReactClass({
|
||||||
*/
|
*/
|
||||||
keyboardVerticalOffset: PropTypes.number.isRequired,
|
keyboardVerticalOffset: PropTypes.number.isRequired,
|
||||||
/**
|
/**
|
||||||
* This is to allow us to manually control which KAV shuld take effect when
|
* This is to allow us to manually control which KAV shuld take effect when
|
||||||
* having more than one KAV at the same screen
|
* having more than one KAV at the same screen
|
||||||
*/
|
*/
|
||||||
enabled: PropTypes.bool.isRequired,
|
enabled: PropTypes.bool.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -130,10 +132,16 @@ const KeyboardAvoidingView = createReactClass({
|
||||||
this.frame = event.nativeEvent.layout;
|
this.frame = event.nativeEvent.layout;
|
||||||
},
|
},
|
||||||
|
|
||||||
UNSAFE_componentWillUpdate(nextProps: Object, nextState: Object, nextContext?: Object): void {
|
UNSAFE_componentWillUpdate(
|
||||||
if (nextState.bottom === this.state.bottom &&
|
nextProps: Object,
|
||||||
this.props.behavior === 'height' &&
|
nextState: Object,
|
||||||
nextProps.behavior === 'height') {
|
nextContext?: Object,
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
nextState.bottom === this.state.bottom &&
|
||||||
|
this.props.behavior === 'height' &&
|
||||||
|
nextProps.behavior === 'height'
|
||||||
|
) {
|
||||||
// If the component rerenders without an internal state change, e.g.
|
// If the component rerenders without an internal state change, e.g.
|
||||||
// triggered by parent component re-rendering, no need for bottom to change.
|
// triggered by parent component re-rendering, no need for bottom to change.
|
||||||
nextState.bottom = 0;
|
nextState.bottom = 0;
|
||||||
|
@ -154,7 +162,7 @@ const KeyboardAvoidingView = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.subscriptions.forEach((sub) => sub.remove());
|
this.subscriptions.forEach(sub => sub.remove());
|
||||||
},
|
},
|
||||||
|
|
||||||
render(): React.Element<any> {
|
render(): React.Element<any> {
|
||||||
|
@ -172,17 +180,25 @@ const KeyboardAvoidingView = createReactClass({
|
||||||
heightStyle = {height: this.frame.height - bottomHeight, flex: 0};
|
heightStyle = {height: this.frame.height - bottomHeight, flex: 0};
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View ref={viewRef} style={[style, heightStyle]} onLayout={this._onLayout} {...props}>
|
<View
|
||||||
|
ref={viewRef}
|
||||||
|
style={[style, heightStyle]}
|
||||||
|
onLayout={this._onLayout}
|
||||||
|
{...props}>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'position':
|
case 'position':
|
||||||
const positionStyle = {bottom: bottomHeight};
|
const positionStyle = {bottom: bottomHeight};
|
||||||
const { contentContainerStyle } = this.props;
|
const {contentContainerStyle} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View ref={viewRef} style={style} onLayout={this._onLayout} {...props}>
|
<View
|
||||||
|
ref={viewRef}
|
||||||
|
style={style}
|
||||||
|
onLayout={this._onLayout}
|
||||||
|
{...props}>
|
||||||
<View style={[contentContainerStyle, positionStyle]}>
|
<View style={[contentContainerStyle, positionStyle]}>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
|
@ -192,14 +208,22 @@ const KeyboardAvoidingView = createReactClass({
|
||||||
case 'padding':
|
case 'padding':
|
||||||
const paddingStyle = {paddingBottom: bottomHeight};
|
const paddingStyle = {paddingBottom: bottomHeight};
|
||||||
return (
|
return (
|
||||||
<View ref={viewRef} style={[style, paddingStyle]} onLayout={this._onLayout} {...props}>
|
<View
|
||||||
|
ref={viewRef}
|
||||||
|
style={[style, paddingStyle]}
|
||||||
|
onLayout={this._onLayout}
|
||||||
|
{...props}>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<View ref={viewRef} onLayout={this._onLayout} style={style} {...props}>
|
<View
|
||||||
|
ref={viewRef}
|
||||||
|
onLayout={this._onLayout}
|
||||||
|
style={style}
|
||||||
|
{...props}>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('React');
|
const React = require('React');
|
||||||
|
@ -22,14 +24,14 @@ const LazyRenderer = createReactClass({
|
||||||
|
|
||||||
UNSAFE_componentWillMount: function(): void {
|
UNSAFE_componentWillMount: function(): void {
|
||||||
this.setState({
|
this.setState({
|
||||||
_lazyRender : true,
|
_lazyRender: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function(): void {
|
componentDidMount: function(): void {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
_lazyRender : false,
|
_lazyRender: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ const View = require('View');
|
||||||
const ViewPropTypes = require('ViewPropTypes');
|
const ViewPropTypes = require('ViewPropTypes');
|
||||||
const requireNativeComponent = require('requireNativeComponent');
|
const requireNativeComponent = require('requireNativeComponent');
|
||||||
|
|
||||||
import type { ViewProps } from 'ViewPropTypes';
|
import type {ViewProps} from 'ViewPropTypes';
|
||||||
|
|
||||||
type Props = ViewProps & {
|
type Props = ViewProps & {
|
||||||
children: any,
|
children: any,
|
||||||
|
@ -70,13 +71,13 @@ class MaskedViewIOS extends React.Component<Props> {
|
||||||
_hasWarnedInvalidRenderMask = false;
|
_hasWarnedInvalidRenderMask = false;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { maskElement, children, ...otherViewProps } = this.props;
|
const {maskElement, children, ...otherViewProps} = this.props;
|
||||||
|
|
||||||
if (!React.isValidElement(maskElement)) {
|
if (!React.isValidElement(maskElement)) {
|
||||||
if (!this._hasWarnedInvalidRenderMask) {
|
if (!this._hasWarnedInvalidRenderMask) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'MaskedView: Invalid `maskElement` prop was passed to MaskedView. ' +
|
'MaskedView: Invalid `maskElement` prop was passed to MaskedView. ' +
|
||||||
'Expected a React Element. No mask will render.'
|
'Expected a React Element. No mask will render.',
|
||||||
);
|
);
|
||||||
this._hasWarnedInvalidRenderMask = true;
|
this._hasWarnedInvalidRenderMask = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const EventEmitter = require('EventEmitter');
|
const EventEmitter = require('EventEmitter');
|
||||||
|
@ -40,14 +42,12 @@ class NavigatorTransitionerIOS extends React.Component<$FlowFixMeProps> {
|
||||||
requestSchedulingNavigation(cb) {
|
requestSchedulingNavigation(cb) {
|
||||||
RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
|
RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
|
||||||
ReactNative.findNodeHandle(this),
|
ReactNative.findNodeHandle(this),
|
||||||
cb
|
cb,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <RCTNavigator {...this.props} />;
|
||||||
<RCTNavigator {...this.props}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ type State = {
|
||||||
toIndex: number,
|
toIndex: number,
|
||||||
makingNavigatorRequest: boolean,
|
makingNavigatorRequest: boolean,
|
||||||
updatingAllIndicesAtOrBeyond: ?number,
|
updatingAllIndicesAtOrBeyond: ?number,
|
||||||
}
|
};
|
||||||
|
|
||||||
type Event = Object;
|
type Event = Object;
|
||||||
|
|
||||||
|
@ -308,7 +308,6 @@ const NavigatorIOS = createReactClass({
|
||||||
displayName: 'NavigatorIOS',
|
displayName: 'NavigatorIOS',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NavigatorIOS uses `route` objects to identify child views, their props,
|
* NavigatorIOS uses `route` objects to identify child views, their props,
|
||||||
* and navigation bar configuration. Navigation operations such as push
|
* and navigation bar configuration. Navigation operations such as push
|
||||||
|
@ -436,17 +435,16 @@ const NavigatorIOS = createReactClass({
|
||||||
*/
|
*/
|
||||||
barStyle: PropTypes.oneOf(['default', 'black']),
|
barStyle: PropTypes.oneOf(['default', 'black']),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text color of the navigation bar title.
|
* The text color of the navigation bar title.
|
||||||
*/
|
*/
|
||||||
titleTextColor: PropTypes.string,
|
titleTextColor: PropTypes.string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boolean value that indicates whether the navigation bar is
|
* Boolean value that indicates whether the navigation bar is
|
||||||
* translucent.
|
* translucent.
|
||||||
*/
|
*/
|
||||||
translucent: PropTypes.bool,
|
translucent: PropTypes.bool,
|
||||||
|
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -507,7 +505,6 @@ const NavigatorIOS = createReactClass({
|
||||||
* behavior.
|
* behavior.
|
||||||
*/
|
*/
|
||||||
interactivePopGestureEnabled: PropTypes.bool,
|
interactivePopGestureEnabled: PropTypes.bool,
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
navigator: (undefined: ?Object),
|
navigator: (undefined: ?Object),
|
||||||
|
@ -608,7 +605,7 @@ const NavigatorIOS = createReactClass({
|
||||||
|
|
||||||
_tryLockNavigator: function(cb: () => void) {
|
_tryLockNavigator: function(cb: () => void) {
|
||||||
this.refs[TRANSITIONER_REF].requestSchedulingNavigation(
|
this.refs[TRANSITIONER_REF].requestSchedulingNavigation(
|
||||||
(acquiredLock) => acquiredLock && cb()
|
acquiredLock => acquiredLock && cb(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -617,7 +614,9 @@ const NavigatorIOS = createReactClass({
|
||||||
|
|
||||||
invariant(
|
invariant(
|
||||||
newObservedTopOfStack <= this.state.requestedTopOfStack,
|
newObservedTopOfStack <= this.state.requestedTopOfStack,
|
||||||
'No navigator item should be pushed without JS knowing about it %s %s', newObservedTopOfStack, this.state.requestedTopOfStack
|
'No navigator item should be pushed without JS knowing about it %s %s',
|
||||||
|
newObservedTopOfStack,
|
||||||
|
this.state.requestedTopOfStack,
|
||||||
);
|
);
|
||||||
const wasWaitingForConfirmation =
|
const wasWaitingForConfirmation =
|
||||||
this.state.requestedTopOfStack !== this.state.observedTopOfStack;
|
this.state.requestedTopOfStack !== this.state.observedTopOfStack;
|
||||||
|
@ -625,7 +624,7 @@ const NavigatorIOS = createReactClass({
|
||||||
invariant(
|
invariant(
|
||||||
newObservedTopOfStack === this.state.requestedTopOfStack,
|
newObservedTopOfStack === this.state.requestedTopOfStack,
|
||||||
'If waiting for observedTopOfStack to reach requestedTopOfStack, ' +
|
'If waiting for observedTopOfStack to reach requestedTopOfStack, ' +
|
||||||
'the only valid observedTopOfStack should be requestedTopOfStack.'
|
'the only valid observedTopOfStack should be requestedTopOfStack.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Mark the most recent observation regardless of if we can lock the
|
// Mark the most recent observation regardless of if we can lock the
|
||||||
|
@ -653,12 +652,15 @@ const NavigatorIOS = createReactClass({
|
||||||
// even uses the indices in this case, but let's make this describe the
|
// even uses the indices in this case, but let's make this describe the
|
||||||
// truth anyways).
|
// truth anyways).
|
||||||
const updatingAllIndicesAtOrBeyond =
|
const updatingAllIndicesAtOrBeyond =
|
||||||
this.state.routeStack.length > this.state.observedTopOfStack + 1 ?
|
this.state.routeStack.length > this.state.observedTopOfStack + 1
|
||||||
this.state.observedTopOfStack + 1 :
|
? this.state.observedTopOfStack + 1
|
||||||
null;
|
: null;
|
||||||
this.setState({
|
this.setState({
|
||||||
idStack: this.state.idStack.slice(0, this.state.observedTopOfStack + 1),
|
idStack: this.state.idStack.slice(0, this.state.observedTopOfStack + 1),
|
||||||
routeStack: this.state.routeStack.slice(0, this.state.observedTopOfStack + 1),
|
routeStack: this.state.routeStack.slice(
|
||||||
|
0,
|
||||||
|
this.state.observedTopOfStack + 1,
|
||||||
|
),
|
||||||
// Now we rerequest the top of stack that we observed.
|
// Now we rerequest the top of stack that we observed.
|
||||||
requestedTopOfStack: this.state.observedTopOfStack,
|
requestedTopOfStack: this.state.observedTopOfStack,
|
||||||
makingNavigatorRequest: true,
|
makingNavigatorRequest: true,
|
||||||
|
@ -675,7 +677,6 @@ const NavigatorIOS = createReactClass({
|
||||||
// Make sure all previous requests are caught up first. Otherwise reject.
|
// Make sure all previous requests are caught up first. Otherwise reject.
|
||||||
if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
|
if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
|
||||||
this._tryLockNavigator(() => {
|
this._tryLockNavigator(() => {
|
||||||
|
|
||||||
const nextStack = this.state.routeStack.concat([route]);
|
const nextStack = this.state.routeStack.concat([route]);
|
||||||
const nextIDStack = this.state.idStack.concat([getuid()]);
|
const nextIDStack = this.state.idStack.concat([getuid()]);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -752,7 +753,6 @@ const NavigatorIOS = createReactClass({
|
||||||
makingNavigatorRequest: false,
|
makingNavigatorRequest: false,
|
||||||
updatingAllIndicesAtOrBeyond: index,
|
updatingAllIndicesAtOrBeyond: index,
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -787,7 +787,7 @@ const NavigatorIOS = createReactClass({
|
||||||
const indexOfRoute = this.state.routeStack.indexOf(route);
|
const indexOfRoute = this.state.routeStack.indexOf(route);
|
||||||
invariant(
|
invariant(
|
||||||
indexOfRoute !== -1,
|
indexOfRoute !== -1,
|
||||||
'Calling pop to route for a route that doesn\'t exist!'
|
"Calling pop to route for a route that doesn't exist!",
|
||||||
);
|
);
|
||||||
const numToPop = this.state.routeStack.length - indexOfRoute - 1;
|
const numToPop = this.state.routeStack.length - indexOfRoute - 1;
|
||||||
this.popN(numToPop);
|
this.popN(numToPop);
|
||||||
|
@ -851,16 +851,8 @@ const NavigatorIOS = createReactClass({
|
||||||
<RCTNavigatorItem
|
<RCTNavigatorItem
|
||||||
{...props}
|
{...props}
|
||||||
{...route}
|
{...route}
|
||||||
style={[
|
style={[styles.stackItem, itemWrapperStyle, wrapperStyle]}>
|
||||||
styles.stackItem,
|
<Component navigator={this.navigator} route={route} {...passProps} />
|
||||||
itemWrapperStyle,
|
|
||||||
wrapperStyle
|
|
||||||
]}>
|
|
||||||
<Component
|
|
||||||
navigator={this.navigator}
|
|
||||||
route={route}
|
|
||||||
{...passProps}
|
|
||||||
/>
|
|
||||||
</RCTNavigatorItem>
|
</RCTNavigatorItem>
|
||||||
</StaticContainer>
|
</StaticContainer>
|
||||||
);
|
);
|
||||||
|
@ -872,8 +864,9 @@ const NavigatorIOS = createReactClass({
|
||||||
this.state.updatingAllIndicesAtOrBeyond !== null;
|
this.state.updatingAllIndicesAtOrBeyond !== null;
|
||||||
// If not recursing update to navigator at all, may as well avoid
|
// If not recursing update to navigator at all, may as well avoid
|
||||||
// computation of navigator children.
|
// computation of navigator children.
|
||||||
const items = shouldRecurseToNavigator ?
|
const items = shouldRecurseToNavigator
|
||||||
this.state.routeStack.map(this._routeToStackItem) : null;
|
? this.state.routeStack.map(this._routeToStackItem)
|
||||||
|
: null;
|
||||||
return (
|
return (
|
||||||
<StaticContainer shouldUpdate={shouldRecurseToNavigator}>
|
<StaticContainer shouldUpdate={shouldRecurseToNavigator}>
|
||||||
<NavigatorTransitionerIOS
|
<NavigatorTransitionerIOS
|
||||||
|
@ -883,7 +876,9 @@ const NavigatorIOS = createReactClass({
|
||||||
vertical={this.props.vertical}
|
vertical={this.props.vertical}
|
||||||
requestedTopOfStack={this.state.requestedTopOfStack}
|
requestedTopOfStack={this.state.requestedTopOfStack}
|
||||||
onNavigationComplete={this._handleNavigationComplete}
|
onNavigationComplete={this._handleNavigationComplete}
|
||||||
interactivePopGestureEnabled={this.props.interactivePopGestureEnabled}>
|
interactivePopGestureEnabled={
|
||||||
|
this.props.interactivePopGestureEnabled
|
||||||
|
}>
|
||||||
{items}
|
{items}
|
||||||
</NavigatorTransitionerIOS>
|
</NavigatorTransitionerIOS>
|
||||||
</StaticContainer>
|
</StaticContainer>
|
||||||
|
@ -911,9 +906,7 @@ const NavigatorIOS = createReactClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
// $FlowFixMe(>=0.41.0)
|
// $FlowFixMe(>=0.41.0)
|
||||||
<View style={this.props.style}>
|
<View style={this.props.style}>{this._renderNavigationStackItems()}</View>
|
||||||
{this._renderNavigationStackItems()}
|
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -35,36 +36,36 @@ const MODE_DROPDOWN = 'dropdown';
|
||||||
* Individual selectable item in a Picker.
|
* Individual selectable item in a Picker.
|
||||||
*/
|
*/
|
||||||
class PickerItem extends React.Component<{
|
class PickerItem extends React.Component<{
|
||||||
label: string,
|
label: string,
|
||||||
value?: any,
|
value?: any,
|
||||||
color?: ColorPropType,
|
color?: ColorPropType,
|
||||||
testID?: string,
|
testID?: string,
|
||||||
}> {
|
}> {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
/**
|
/**
|
||||||
* Text to display for this item.
|
* Text to display for this item.
|
||||||
*/
|
*/
|
||||||
label: PropTypes.string.isRequired,
|
label: PropTypes.string.isRequired,
|
||||||
/**
|
/**
|
||||||
* The value to be passed to picker's `onValueChange` callback when
|
* The value to be passed to picker's `onValueChange` callback when
|
||||||
* this item is selected. Can be a string or an integer.
|
* this item is selected. Can be a string or an integer.
|
||||||
*/
|
*/
|
||||||
value: PropTypes.any,
|
value: PropTypes.any,
|
||||||
/**
|
/**
|
||||||
* Color of this item's text.
|
* Color of this item's text.
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
color: ColorPropType,
|
color: ColorPropType,
|
||||||
/**
|
/**
|
||||||
* Used to locate the item in end-to-end tests.
|
* Used to locate the item in end-to-end tests.
|
||||||
*/
|
*/
|
||||||
testID: PropTypes.string,
|
testID: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// The items are not rendered directly
|
// The items are not rendered directly
|
||||||
throw null;
|
throw null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,87 +79,89 @@ class PickerItem extends React.Component<{
|
||||||
* </Picker>
|
* </Picker>
|
||||||
*/
|
*/
|
||||||
class Picker extends React.Component<{
|
class Picker extends React.Component<{
|
||||||
style?: $FlowFixMe,
|
style?: $FlowFixMe,
|
||||||
selectedValue?: any,
|
selectedValue?: any,
|
||||||
onValueChange?: Function,
|
onValueChange?: Function,
|
||||||
enabled?: boolean,
|
enabled?: boolean,
|
||||||
mode?: 'dialog' | 'dropdown',
|
mode?: 'dialog' | 'dropdown',
|
||||||
itemStyle?: $FlowFixMe,
|
itemStyle?: $FlowFixMe,
|
||||||
prompt?: string,
|
prompt?: string,
|
||||||
testID?: string,
|
testID?: string,
|
||||||
}> {
|
}> {
|
||||||
/**
|
/**
|
||||||
* On Android, display the options in a dialog.
|
* On Android, display the options in a dialog.
|
||||||
*/
|
*/
|
||||||
static MODE_DIALOG = MODE_DIALOG;
|
static MODE_DIALOG = MODE_DIALOG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On Android, display the options in a dropdown (this is the default).
|
* On Android, display the options in a dropdown (this is the default).
|
||||||
*/
|
*/
|
||||||
static MODE_DROPDOWN = MODE_DROPDOWN;
|
static MODE_DROPDOWN = MODE_DROPDOWN;
|
||||||
|
|
||||||
static Item = PickerItem;
|
static Item = PickerItem;
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
mode: MODE_DIALOG,
|
mode: MODE_DIALOG,
|
||||||
};
|
};
|
||||||
|
|
||||||
// $FlowFixMe(>=0.41.0)
|
// $FlowFixMe(>=0.41.0)
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...ViewPropTypes,
|
...ViewPropTypes,
|
||||||
style: pickerStyleType,
|
style: pickerStyleType,
|
||||||
/**
|
/**
|
||||||
* Value matching value of one of the items. Can be a string or an integer.
|
* Value matching value of one of the items. Can be a string or an integer.
|
||||||
*/
|
*/
|
||||||
selectedValue: PropTypes.any,
|
selectedValue: PropTypes.any,
|
||||||
/**
|
/**
|
||||||
* Callback for when an item is selected. This is called with the following parameters:
|
* Callback for when an item is selected. This is called with the following parameters:
|
||||||
* - `itemValue`: the `value` prop of the item that was selected
|
* - `itemValue`: the `value` prop of the item that was selected
|
||||||
* - `itemPosition`: the index of the selected item in this picker
|
* - `itemPosition`: the index of the selected item in this picker
|
||||||
*/
|
*/
|
||||||
onValueChange: PropTypes.func,
|
onValueChange: PropTypes.func,
|
||||||
/**
|
/**
|
||||||
* If set to false, the picker will be disabled, i.e. the user will not be able to make a
|
* If set to false, the picker will be disabled, i.e. the user will not be able to make a
|
||||||
* selection.
|
* selection.
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
enabled: PropTypes.bool,
|
enabled: PropTypes.bool,
|
||||||
/**
|
/**
|
||||||
* On Android, specifies how to display the selection items when the user taps on the picker:
|
* On Android, specifies how to display the selection items when the user taps on the picker:
|
||||||
*
|
*
|
||||||
* - 'dialog': Show a modal dialog. This is the default.
|
* - 'dialog': Show a modal dialog. This is the default.
|
||||||
* - 'dropdown': Shows a dropdown anchored to the picker view
|
* - 'dropdown': Shows a dropdown anchored to the picker view
|
||||||
*
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
mode: PropTypes.oneOf(['dialog', 'dropdown']),
|
mode: PropTypes.oneOf(['dialog', 'dropdown']),
|
||||||
/**
|
/**
|
||||||
* Style to apply to each of the item labels.
|
* Style to apply to each of the item labels.
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
itemStyle: itemStylePropType,
|
itemStyle: itemStylePropType,
|
||||||
/**
|
/**
|
||||||
* Prompt string for this picker, used on Android in dialog mode as the title of the dialog.
|
* Prompt string for this picker, used on Android in dialog mode as the title of the dialog.
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
prompt: PropTypes.string,
|
prompt: PropTypes.string,
|
||||||
/**
|
/**
|
||||||
* Used to locate this view in end-to-end tests.
|
* Used to locate this view in end-to-end tests.
|
||||||
*/
|
*/
|
||||||
testID: PropTypes.string,
|
testID: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
// $FlowFixMe found when converting React.createClass to ES6
|
// $FlowFixMe found when converting React.createClass to ES6
|
||||||
return <PickerIOS {...this.props}>{this.props.children}</PickerIOS>;
|
return <PickerIOS {...this.props}>{this.props.children}</PickerIOS>;
|
||||||
} else if (Platform.OS === 'android') {
|
} else if (Platform.OS === 'android') {
|
||||||
// $FlowFixMe found when converting React.createClass to ES6
|
return (
|
||||||
return <PickerAndroid {...this.props}>{this.props.children}</PickerAndroid>;
|
// $FlowFixMe found when converting React.createClass to ES6
|
||||||
} else {
|
<PickerAndroid {...this.props}>{this.props.children}</PickerAndroid>
|
||||||
return <UnimplementedView />;
|
);
|
||||||
}
|
} else {
|
||||||
}
|
return <UnimplementedView />;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Picker;
|
module.exports = Picker;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -33,15 +34,18 @@ type Event = Object;
|
||||||
/**
|
/**
|
||||||
* Not exposed as a public API - use <Picker> instead.
|
* Not exposed as a public API - use <Picker> instead.
|
||||||
*/
|
*/
|
||||||
class PickerAndroid extends React.Component<{
|
class PickerAndroid extends React.Component<
|
||||||
style?: $FlowFixMe,
|
{
|
||||||
selectedValue?: any,
|
style?: $FlowFixMe,
|
||||||
enabled?: boolean,
|
selectedValue?: any,
|
||||||
mode?: 'dialog' | 'dropdown',
|
enabled?: boolean,
|
||||||
onValueChange?: Function,
|
mode?: 'dialog' | 'dropdown',
|
||||||
prompt?: string,
|
onValueChange?: Function,
|
||||||
testID?: string,
|
prompt?: string,
|
||||||
}, *> {
|
testID?: string,
|
||||||
|
},
|
||||||
|
*,
|
||||||
|
> {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...ViewPropTypes,
|
...ViewPropTypes,
|
||||||
style: pickerStyleType,
|
style: pickerStyleType,
|
||||||
|
@ -68,7 +72,7 @@ class PickerAndroid extends React.Component<{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate prop and children into stuff that the native picker understands.
|
// Translate prop and children into stuff that the native picker understands.
|
||||||
_stateFromProps = (props) => {
|
_stateFromProps = props => {
|
||||||
let selectedIndex = 0;
|
let selectedIndex = 0;
|
||||||
const items = React.Children.map(props.children, (child, index) => {
|
const items = React.Children.map(props.children, (child, index) => {
|
||||||
if (child.props.value === props.selectedValue) {
|
if (child.props.value === props.selectedValue) {
|
||||||
|
@ -87,7 +91,8 @@ class PickerAndroid extends React.Component<{
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const Picker = this.props.mode === MODE_DROPDOWN ? DropdownPicker : DialogPicker;
|
const Picker =
|
||||||
|
this.props.mode === MODE_DROPDOWN ? DropdownPicker : DialogPicker;
|
||||||
|
|
||||||
const nativeProps = {
|
const nativeProps = {
|
||||||
enabled: this.props.enabled,
|
enabled: this.props.enabled,
|
||||||
|
@ -130,8 +135,13 @@ class PickerAndroid extends React.Component<{
|
||||||
// disallow/undo/mutate the selection of certain values. In other
|
// disallow/undo/mutate the selection of certain values. In other
|
||||||
// words, the embedder of this component should be the source of
|
// words, the embedder of this component should be the source of
|
||||||
// truth, not the native component.
|
// truth, not the native component.
|
||||||
if (this.refs[REF_PICKER] && this.state.selectedIndex !== this._lastNativePosition) {
|
if (
|
||||||
this.refs[REF_PICKER].setNativeProps({selected: this.state.selectedIndex});
|
this.refs[REF_PICKER] &&
|
||||||
|
this.state.selectedIndex !== this._lastNativePosition
|
||||||
|
) {
|
||||||
|
this.refs[REF_PICKER].setNativeProps({
|
||||||
|
selected: this.state.selectedIndex,
|
||||||
|
});
|
||||||
this._lastNativePosition = this.state.selectedIndex;
|
this._lastNativePosition = this.state.selectedIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,10 +162,18 @@ const cfg = {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
items: true,
|
items: true,
|
||||||
selected: true,
|
selected: true,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const DropdownPicker = requireNativeComponent('AndroidDropdownPicker', PickerAndroid, cfg);
|
const DropdownPicker = requireNativeComponent(
|
||||||
const DialogPicker = requireNativeComponent('AndroidDialogPicker', PickerAndroid, cfg);
|
'AndroidDropdownPicker',
|
||||||
|
PickerAndroid,
|
||||||
|
cfg,
|
||||||
|
);
|
||||||
|
const DialogPicker = requireNativeComponent(
|
||||||
|
'AndroidDialogPicker',
|
||||||
|
PickerAndroid,
|
||||||
|
cfg,
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = PickerAndroid;
|
module.exports = PickerAndroid;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This is a controlled component version of RCTPickerIOS
|
* This is a controlled component version of RCTPickerIOS
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This is a controlled component version of RCTPickerIOS
|
* This is a controlled component version of RCTPickerIOS
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||||
|
@ -46,7 +49,7 @@ const PickerIOS = createReactClass({
|
||||||
_stateFromProps: function(props) {
|
_stateFromProps: function(props) {
|
||||||
let selectedIndex = 0;
|
let selectedIndex = 0;
|
||||||
const items = [];
|
const items = [];
|
||||||
React.Children.toArray(props.children).forEach(function (child, index) {
|
React.Children.toArray(props.children).forEach(function(child, index) {
|
||||||
if (child.props.value === props.selectedValue) {
|
if (child.props.value === props.selectedValue) {
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +66,7 @@ const PickerIOS = createReactClass({
|
||||||
return (
|
return (
|
||||||
<View style={this.props.style}>
|
<View style={this.props.style}>
|
||||||
<RCTPickerIOS
|
<RCTPickerIOS
|
||||||
ref={picker => this._picker = picker}
|
ref={picker => (this._picker = picker)}
|
||||||
style={[styles.pickerIOS, this.props.itemStyle]}
|
style={[styles.pickerIOS, this.props.itemStyle]}
|
||||||
items={this.state.items}
|
items={this.state.items}
|
||||||
selectedIndex={this.state.selectedIndex}
|
selectedIndex={this.state.selectedIndex}
|
||||||
|
@ -80,7 +83,10 @@ const PickerIOS = createReactClass({
|
||||||
this.props.onChange(event);
|
this.props.onChange(event);
|
||||||
}
|
}
|
||||||
if (this.props.onValueChange) {
|
if (this.props.onValueChange) {
|
||||||
this.props.onValueChange(event.nativeEvent.newValue, event.nativeEvent.newIndex);
|
this.props.onValueChange(
|
||||||
|
event.nativeEvent.newValue,
|
||||||
|
event.nativeEvent.newIndex,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The picker is a controlled component. This means we expect the
|
// The picker is a controlled component. This means we expect the
|
||||||
|
@ -89,9 +95,12 @@ const PickerIOS = createReactClass({
|
||||||
// disallow/undo/mutate the selection of certain values. In other
|
// disallow/undo/mutate the selection of certain values. In other
|
||||||
// words, the embedder of this component should be the source of
|
// words, the embedder of this component should be the source of
|
||||||
// truth, not the native component.
|
// truth, not the native component.
|
||||||
if (this._picker && this.state.selectedIndex !== event.nativeEvent.newIndex) {
|
if (
|
||||||
|
this._picker &&
|
||||||
|
this.state.selectedIndex !== event.nativeEvent.newIndex
|
||||||
|
) {
|
||||||
this._picker.setNativeProps({
|
this._picker.setNativeProps({
|
||||||
selectedIndex: this.state.selectedIndex
|
selectedIndex: this.state.selectedIndex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -119,16 +128,20 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const RCTPickerIOS = requireNativeComponent('RCTPicker', {
|
const RCTPickerIOS = requireNativeComponent(
|
||||||
propTypes: {
|
'RCTPicker',
|
||||||
style: itemStylePropType,
|
{
|
||||||
|
propTypes: {
|
||||||
|
style: itemStylePropType,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, {
|
{
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
items: true,
|
items: true,
|
||||||
onChange: true,
|
onChange: true,
|
||||||
selectedIndex: true,
|
selectedIndex: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
module.exports = PickerIOS;
|
module.exports = PickerIOS;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2015-present, Facebook, Inc.
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -40,7 +40,7 @@ const styles = StyleSheet.create({
|
||||||
color: '#333333',
|
color: '#333333',
|
||||||
margin: 5,
|
margin: 5,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DummyProgressViewIOS;
|
module.exports = DummyProgressViewIOS;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Image = require('Image');
|
const Image = require('Image');
|
||||||
|
@ -65,7 +67,7 @@ const ProgressViewIOS = createReactClass({
|
||||||
style={[styles.progressView, this.props.style]}
|
style={[styles.progressView, this.props.style]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -76,7 +78,7 @@ const styles = StyleSheet.create({
|
||||||
|
|
||||||
const RCTProgressView = requireNativeComponent(
|
const RCTProgressView = requireNativeComponent(
|
||||||
'RCTProgressView',
|
'RCTProgressView',
|
||||||
ProgressViewIOS
|
ProgressViewIOS,
|
||||||
);
|
);
|
||||||
|
|
||||||
module.exports = ProgressViewIOS;
|
module.exports = ProgressViewIOS;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -19,8 +21,8 @@ const createReactClass = require('create-react-class');
|
||||||
const requireNativeComponent = require('requireNativeComponent');
|
const requireNativeComponent = require('requireNativeComponent');
|
||||||
|
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
const AndroidSwipeRefreshLayout =
|
const AndroidSwipeRefreshLayout = require('UIManager')
|
||||||
require('UIManager').AndroidSwipeRefreshLayout;
|
.AndroidSwipeRefreshLayout;
|
||||||
var RefreshLayoutConsts = AndroidSwipeRefreshLayout
|
var RefreshLayoutConsts = AndroidSwipeRefreshLayout
|
||||||
? AndroidSwipeRefreshLayout.Constants
|
? AndroidSwipeRefreshLayout.Constants
|
||||||
: {SIZE: {}};
|
: {SIZE: {}};
|
||||||
|
@ -125,7 +127,10 @@ const RefreshControl = createReactClass({
|
||||||
* Size of the refresh indicator, see RefreshControl.SIZE.
|
* Size of the refresh indicator, see RefreshControl.SIZE.
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
size: PropTypes.oneOf([RefreshLayoutConsts.SIZE.DEFAULT, RefreshLayoutConsts.SIZE.LARGE]),
|
size: PropTypes.oneOf([
|
||||||
|
RefreshLayoutConsts.SIZE.DEFAULT,
|
||||||
|
RefreshLayoutConsts.SIZE.LARGE,
|
||||||
|
]),
|
||||||
/**
|
/**
|
||||||
* Progress view top offset
|
* Progress view top offset
|
||||||
* @platform android
|
* @platform android
|
||||||
|
@ -156,7 +161,9 @@ const RefreshControl = createReactClass({
|
||||||
return (
|
return (
|
||||||
<NativeRefreshControl
|
<NativeRefreshControl
|
||||||
{...this.props}
|
{...this.props}
|
||||||
ref={ref => {this._nativeRef = ref;}}
|
ref={ref => {
|
||||||
|
this._nativeRef = ref;
|
||||||
|
}}
|
||||||
onRefresh={this._onRefresh}
|
onRefresh={this._onRefresh}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -176,12 +183,12 @@ const RefreshControl = createReactClass({
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
var NativeRefreshControl = requireNativeComponent(
|
var NativeRefreshControl = requireNativeComponent(
|
||||||
'RCTRefreshControl',
|
'RCTRefreshControl',
|
||||||
RefreshControl
|
RefreshControl,
|
||||||
);
|
);
|
||||||
} else if (Platform.OS === 'android') {
|
} else if (Platform.OS === 'android') {
|
||||||
var NativeRefreshControl = requireNativeComponent(
|
var NativeRefreshControl = requireNativeComponent(
|
||||||
'AndroidSwipeRefreshLayout',
|
'AndroidSwipeRefreshLayout',
|
||||||
RefreshControl
|
RefreshControl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('React');
|
const React = require('React');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('View');
|
module.exports = require('View');
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Dimensions = require('Dimensions');
|
const Dimensions = require('Dimensions');
|
||||||
|
@ -21,7 +23,7 @@ const nullthrows = require('fbjs/lib/nullthrows');
|
||||||
const performanceNow = require('fbjs/lib/performanceNow');
|
const performanceNow = require('fbjs/lib/performanceNow');
|
||||||
const warning = require('fbjs/lib/warning');
|
const warning = require('fbjs/lib/warning');
|
||||||
|
|
||||||
const { ScrollViewManager } = require('NativeModules');
|
const {ScrollViewManager} = require('NativeModules');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mixin that can be integrated in order to handle scrolling that plays well
|
* Mixin that can be integrated in order to handle scrolling that plays well
|
||||||
|
@ -104,11 +106,11 @@ const { ScrollViewManager } = require('NativeModules');
|
||||||
const IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16;
|
const IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16;
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
isTouching: boolean,
|
isTouching: boolean,
|
||||||
lastMomentumScrollBeginTime: number,
|
lastMomentumScrollBeginTime: number,
|
||||||
lastMomentumScrollEndTime: number,
|
lastMomentumScrollEndTime: number,
|
||||||
observedScrollSinceBecomingResponder: boolean,
|
observedScrollSinceBecomingResponder: boolean,
|
||||||
becameResponderWhileAnimating: boolean,
|
becameResponderWhileAnimating: boolean,
|
||||||
};
|
};
|
||||||
type Event = Object;
|
type Event = Object;
|
||||||
|
|
||||||
|
@ -165,9 +167,11 @@ const ScrollResponderMixin = {
|
||||||
scrollResponderHandleStartShouldSetResponder: function(e: Event): boolean {
|
scrollResponderHandleStartShouldSetResponder: function(e: Event): boolean {
|
||||||
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||||
|
|
||||||
if (this.props.keyboardShouldPersistTaps === 'handled' &&
|
if (
|
||||||
|
this.props.keyboardShouldPersistTaps === 'handled' &&
|
||||||
currentlyFocusedTextInput != null &&
|
currentlyFocusedTextInput != null &&
|
||||||
e.target !== currentlyFocusedTextInput) {
|
e.target !== currentlyFocusedTextInput
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -184,7 +188,9 @@ const ScrollResponderMixin = {
|
||||||
*
|
*
|
||||||
* Invoke this from an `onStartShouldSetResponderCapture` event.
|
* Invoke this from an `onStartShouldSetResponderCapture` event.
|
||||||
*/
|
*/
|
||||||
scrollResponderHandleStartShouldSetResponderCapture: function(e: Event): boolean {
|
scrollResponderHandleStartShouldSetResponderCapture: function(
|
||||||
|
e: Event,
|
||||||
|
): boolean {
|
||||||
// The scroll view should receive taps instead of its descendants if:
|
// The scroll view should receive taps instead of its descendants if:
|
||||||
// * it is already animating/decelerating
|
// * it is already animating/decelerating
|
||||||
if (this.scrollResponderIsAnimating()) {
|
if (this.scrollResponderIsAnimating()) {
|
||||||
|
@ -197,11 +203,13 @@ const ScrollResponderMixin = {
|
||||||
// then the second tap goes to the actual interior view)
|
// then the second tap goes to the actual interior view)
|
||||||
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||||
const {keyboardShouldPersistTaps} = this.props;
|
const {keyboardShouldPersistTaps} = this.props;
|
||||||
const keyboardNeverPersistTaps = !keyboardShouldPersistTaps ||
|
const keyboardNeverPersistTaps =
|
||||||
keyboardShouldPersistTaps === 'never';
|
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
|
||||||
if (keyboardNeverPersistTaps &&
|
if (
|
||||||
|
keyboardNeverPersistTaps &&
|
||||||
currentlyFocusedTextInput != null
|
currentlyFocusedTextInput != null
|
||||||
/* && !TextInputState.isTextInput(e.target) */) {
|
/* && !TextInputState.isTextInput(e.target) */
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +226,7 @@ const ScrollResponderMixin = {
|
||||||
* altogether. To improve this, find a way to disable the `UIScrollView` after
|
* altogether. To improve this, find a way to disable the `UIScrollView` after
|
||||||
* a touch has already started.
|
* a touch has already started.
|
||||||
*/
|
*/
|
||||||
scrollResponderHandleResponderReject: function() {
|
scrollResponderHandleResponderReject: function() {},
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We will allow the scroll view to give up its lock iff it acquired the lock
|
* We will allow the scroll view to give up its lock iff it acquired the lock
|
||||||
|
@ -270,12 +277,14 @@ const ScrollResponderMixin = {
|
||||||
// By default scroll views will unfocus a textField
|
// By default scroll views will unfocus a textField
|
||||||
// if another touch occurs outside of it
|
// if another touch occurs outside of it
|
||||||
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||||
if (this.props.keyboardShouldPersistTaps !== true &&
|
if (
|
||||||
|
this.props.keyboardShouldPersistTaps !== true &&
|
||||||
this.props.keyboardShouldPersistTaps !== 'always' &&
|
this.props.keyboardShouldPersistTaps !== 'always' &&
|
||||||
currentlyFocusedTextInput != null &&
|
currentlyFocusedTextInput != null &&
|
||||||
e.target !== currentlyFocusedTextInput &&
|
e.target !== currentlyFocusedTextInput &&
|
||||||
!this.state.observedScrollSinceBecomingResponder &&
|
!this.state.observedScrollSinceBecomingResponder &&
|
||||||
!this.state.becameResponderWhileAnimating) {
|
!this.state.becameResponderWhileAnimating
|
||||||
|
) {
|
||||||
this.props.onScrollResponderKeyboardDismissed &&
|
this.props.onScrollResponderKeyboardDismissed &&
|
||||||
this.props.onScrollResponderKeyboardDismissed(e);
|
this.props.onScrollResponderKeyboardDismissed(e);
|
||||||
TextInputState.blurTextInput(currentlyFocusedTextInput);
|
TextInputState.blurTextInput(currentlyFocusedTextInput);
|
||||||
|
@ -318,8 +327,10 @@ const ScrollResponderMixin = {
|
||||||
// - If velocity is non-zero, then the interaction will stop when momentum scroll ends or
|
// - If velocity is non-zero, then the interaction will stop when momentum scroll ends or
|
||||||
// another drag starts and ends.
|
// another drag starts and ends.
|
||||||
// - If we don't get velocity, better to stop the interaction twice than not stop it.
|
// - If we don't get velocity, better to stop the interaction twice than not stop it.
|
||||||
if (!this.scrollResponderIsAnimating() &&
|
if (
|
||||||
(!velocity || velocity.x === 0 && velocity.y === 0)) {
|
!this.scrollResponderIsAnimating() &&
|
||||||
|
(!velocity || (velocity.x === 0 && velocity.y === 0))
|
||||||
|
) {
|
||||||
FrameRateLogger.endScroll();
|
FrameRateLogger.endScroll();
|
||||||
}
|
}
|
||||||
this.props.onScrollEndDrag && this.props.onScrollEndDrag(e);
|
this.props.onScrollEndDrag && this.props.onScrollEndDrag(e);
|
||||||
|
@ -380,9 +391,12 @@ const ScrollResponderMixin = {
|
||||||
*/
|
*/
|
||||||
scrollResponderIsAnimating: function(): boolean {
|
scrollResponderIsAnimating: function(): boolean {
|
||||||
const now = performanceNow();
|
const now = performanceNow();
|
||||||
const timeSinceLastMomentumScrollEnd = now - this.state.lastMomentumScrollEndTime;
|
const timeSinceLastMomentumScrollEnd =
|
||||||
const isAnimating = timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS ||
|
now - this.state.lastMomentumScrollEndTime;
|
||||||
this.state.lastMomentumScrollEndTime < this.state.lastMomentumScrollBeginTime;
|
const isAnimating =
|
||||||
|
timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS ||
|
||||||
|
this.state.lastMomentumScrollEndTime <
|
||||||
|
this.state.lastMomentumScrollBeginTime;
|
||||||
return isAnimating;
|
return isAnimating;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -392,9 +406,9 @@ const ScrollResponderMixin = {
|
||||||
* function otherwise `this` is used.
|
* function otherwise `this` is used.
|
||||||
*/
|
*/
|
||||||
scrollResponderGetScrollableNode: function(): any {
|
scrollResponderGetScrollableNode: function(): any {
|
||||||
return this.getScrollableNode ?
|
return this.getScrollableNode
|
||||||
this.getScrollableNode() :
|
? this.getScrollableNode()
|
||||||
ReactNative.findNodeHandle(this);
|
: ReactNative.findNodeHandle(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -409,12 +423,14 @@ const ScrollResponderMixin = {
|
||||||
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
|
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
|
||||||
*/
|
*/
|
||||||
scrollResponderScrollTo: function(
|
scrollResponderScrollTo: function(
|
||||||
x?: number | { x?: number, y?: number, animated?: boolean },
|
x?: number | {x?: number, y?: number, animated?: boolean},
|
||||||
y?: number,
|
y?: number,
|
||||||
animated?: boolean
|
animated?: boolean,
|
||||||
) {
|
) {
|
||||||
if (typeof x === 'number') {
|
if (typeof x === 'number') {
|
||||||
console.warn('`scrollResponderScrollTo(x, y, animated)` is deprecated. Use `scrollResponderScrollTo({x: 5, y: 5, animated: true})` instead.');
|
console.warn(
|
||||||
|
'`scrollResponderScrollTo(x, y, animated)` is deprecated. Use `scrollResponderScrollTo({x: 5, y: 5, animated: true})` instead.',
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
({x, y, animated} = x || {});
|
({x, y, animated} = x || {});
|
||||||
}
|
}
|
||||||
|
@ -433,9 +449,7 @@ const ScrollResponderMixin = {
|
||||||
*
|
*
|
||||||
* `scrollResponderScrollToEnd({animated: true})`
|
* `scrollResponderScrollToEnd({animated: true})`
|
||||||
*/
|
*/
|
||||||
scrollResponderScrollToEnd: function(
|
scrollResponderScrollToEnd: function(options?: {animated?: boolean}) {
|
||||||
options?: { animated?: boolean },
|
|
||||||
) {
|
|
||||||
// Default to true
|
// Default to true
|
||||||
const animated = (options && options.animated) !== false;
|
const animated = (options && options.animated) !== false;
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
|
@ -448,8 +462,13 @@ const ScrollResponderMixin = {
|
||||||
/**
|
/**
|
||||||
* Deprecated, do not use.
|
* Deprecated, do not use.
|
||||||
*/
|
*/
|
||||||
scrollResponderScrollWithoutAnimationTo: function(offsetX: number, offsetY: number) {
|
scrollResponderScrollWithoutAnimationTo: function(
|
||||||
console.warn('`scrollResponderScrollWithoutAnimationTo` is deprecated. Use `scrollResponderScrollTo` instead');
|
offsetX: number,
|
||||||
|
offsetY: number,
|
||||||
|
) {
|
||||||
|
console.warn(
|
||||||
|
'`scrollResponderScrollWithoutAnimationTo` is deprecated. Use `scrollResponderScrollTo` instead',
|
||||||
|
);
|
||||||
this.scrollResponderScrollTo({x: offsetX, y: offsetY, animated: false});
|
this.scrollResponderScrollTo({x: offsetX, y: offsetY, animated: false});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -460,17 +479,32 @@ const ScrollResponderMixin = {
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
scrollResponderZoomTo: function(
|
scrollResponderZoomTo: function(
|
||||||
rect: {| x: number, y: number, width: number, height: number, animated?: boolean |},
|
rect: {|
|
||||||
animated?: boolean // deprecated, put this inside the rect argument instead
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
animated?: boolean,
|
||||||
|
|},
|
||||||
|
animated?: boolean, // deprecated, put this inside the rect argument instead
|
||||||
) {
|
) {
|
||||||
invariant(ScrollViewManager && ScrollViewManager.zoomToRect, 'zoomToRect is not implemented');
|
invariant(
|
||||||
|
ScrollViewManager && ScrollViewManager.zoomToRect,
|
||||||
|
'zoomToRect is not implemented',
|
||||||
|
);
|
||||||
if ('animated' in rect) {
|
if ('animated' in rect) {
|
||||||
animated = rect.animated;
|
animated = rect.animated;
|
||||||
delete rect.animated;
|
delete rect.animated;
|
||||||
} else if (typeof animated !== 'undefined') {
|
} else if (typeof animated !== 'undefined') {
|
||||||
console.warn('`scrollResponderZoomTo` `animated` argument is deprecated. Use `options.animated` instead');
|
console.warn(
|
||||||
|
'`scrollResponderZoomTo` `animated` argument is deprecated. Use `options.animated` instead',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ScrollViewManager.zoomToRect(this.scrollResponderGetScrollableNode(), rect, animated !== false);
|
ScrollViewManager.zoomToRect(
|
||||||
|
this.scrollResponderGetScrollableNode(),
|
||||||
|
rect,
|
||||||
|
animated !== false,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -480,7 +514,7 @@ const ScrollResponderMixin = {
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
this.scrollResponderGetScrollableNode(),
|
this.scrollResponderGetScrollableNode(),
|
||||||
UIManager.RCTScrollView.Commands.flashScrollIndicators,
|
UIManager.RCTScrollView.Commands.flashScrollIndicators,
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -494,14 +528,18 @@ const ScrollResponderMixin = {
|
||||||
* @param {bool} preventNegativeScrolling Whether to allow pulling the content
|
* @param {bool} preventNegativeScrolling Whether to allow pulling the content
|
||||||
* down to make it meet the keyboard's top. Default is false.
|
* down to make it meet the keyboard's top. Default is false.
|
||||||
*/
|
*/
|
||||||
scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle: any, additionalOffset?: number, preventNegativeScrollOffset?: bool) {
|
scrollResponderScrollNativeHandleToKeyboard: function(
|
||||||
|
nodeHandle: any,
|
||||||
|
additionalOffset?: number,
|
||||||
|
preventNegativeScrollOffset?: boolean,
|
||||||
|
) {
|
||||||
this.additionalScrollOffset = additionalOffset || 0;
|
this.additionalScrollOffset = additionalOffset || 0;
|
||||||
this.preventNegativeScrollOffset = !!preventNegativeScrollOffset;
|
this.preventNegativeScrollOffset = !!preventNegativeScrollOffset;
|
||||||
UIManager.measureLayout(
|
UIManager.measureLayout(
|
||||||
nodeHandle,
|
nodeHandle,
|
||||||
ReactNative.findNodeHandle(this.getInnerViewNode()),
|
ReactNative.findNodeHandle(this.getInnerViewNode()),
|
||||||
this.scrollResponderTextInputFocusError,
|
this.scrollResponderTextInputFocusError,
|
||||||
this.scrollResponderInputMeasureAndScrollToKeyboard
|
this.scrollResponderInputMeasureAndScrollToKeyboard,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -515,12 +553,18 @@ const ScrollResponderMixin = {
|
||||||
* @param {number} width Width of the text input.
|
* @param {number} width Width of the text input.
|
||||||
* @param {number} height Height of the text input.
|
* @param {number} height Height of the text input.
|
||||||
*/
|
*/
|
||||||
scrollResponderInputMeasureAndScrollToKeyboard: function(left: number, top: number, width: number, height: number) {
|
scrollResponderInputMeasureAndScrollToKeyboard: function(
|
||||||
|
left: number,
|
||||||
|
top: number,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
) {
|
||||||
let keyboardScreenY = Dimensions.get('window').height;
|
let keyboardScreenY = Dimensions.get('window').height;
|
||||||
if (this.keyboardWillOpenTo) {
|
if (this.keyboardWillOpenTo) {
|
||||||
keyboardScreenY = this.keyboardWillOpenTo.endCoordinates.screenY;
|
keyboardScreenY = this.keyboardWillOpenTo.endCoordinates.screenY;
|
||||||
}
|
}
|
||||||
let scrollOffsetY = top - keyboardScreenY + height + this.additionalScrollOffset;
|
let scrollOffsetY =
|
||||||
|
top - keyboardScreenY + height + this.additionalScrollOffset;
|
||||||
|
|
||||||
// By default, this can scroll with negative offset, pulling the content
|
// By default, this can scroll with negative offset, pulling the content
|
||||||
// down so that the target component's bottom meets the keyboard's top.
|
// down so that the target component's bottom meets the keyboard's top.
|
||||||
|
@ -549,16 +593,34 @@ const ScrollResponderMixin = {
|
||||||
const {keyboardShouldPersistTaps} = this.props;
|
const {keyboardShouldPersistTaps} = this.props;
|
||||||
warning(
|
warning(
|
||||||
typeof keyboardShouldPersistTaps !== 'boolean',
|
typeof keyboardShouldPersistTaps !== 'boolean',
|
||||||
`'keyboardShouldPersistTaps={${keyboardShouldPersistTaps}}' is deprecated. `
|
`'keyboardShouldPersistTaps={${keyboardShouldPersistTaps}}' is deprecated. ` +
|
||||||
+ `Use 'keyboardShouldPersistTaps="${keyboardShouldPersistTaps ? 'always' : 'never'}"' instead`
|
`Use 'keyboardShouldPersistTaps="${
|
||||||
|
keyboardShouldPersistTaps ? 'always' : 'never'
|
||||||
|
}"' instead`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.keyboardWillOpenTo = null;
|
this.keyboardWillOpenTo = null;
|
||||||
this.additionalScrollOffset = 0;
|
this.additionalScrollOffset = 0;
|
||||||
this.addListenerOn(Keyboard, 'keyboardWillShow', this.scrollResponderKeyboardWillShow);
|
this.addListenerOn(
|
||||||
this.addListenerOn(Keyboard, 'keyboardWillHide', this.scrollResponderKeyboardWillHide);
|
Keyboard,
|
||||||
this.addListenerOn(Keyboard, 'keyboardDidShow', this.scrollResponderKeyboardDidShow);
|
'keyboardWillShow',
|
||||||
this.addListenerOn(Keyboard, 'keyboardDidHide', this.scrollResponderKeyboardDidHide);
|
this.scrollResponderKeyboardWillShow,
|
||||||
|
);
|
||||||
|
this.addListenerOn(
|
||||||
|
Keyboard,
|
||||||
|
'keyboardWillHide',
|
||||||
|
this.scrollResponderKeyboardWillHide,
|
||||||
|
);
|
||||||
|
this.addListenerOn(
|
||||||
|
Keyboard,
|
||||||
|
'keyboardDidShow',
|
||||||
|
this.scrollResponderKeyboardDidShow,
|
||||||
|
);
|
||||||
|
this.addListenerOn(
|
||||||
|
Keyboard,
|
||||||
|
'keyboardDidHide',
|
||||||
|
this.scrollResponderKeyboardDidHide,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -611,8 +673,7 @@ const ScrollResponderMixin = {
|
||||||
scrollResponderKeyboardDidHide: function(e: Event) {
|
scrollResponderKeyboardDidHide: function(e: Event) {
|
||||||
this.keyboardWillOpenTo = null;
|
this.keyboardWillOpenTo = null;
|
||||||
this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e);
|
this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e);
|
||||||
}
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ScrollResponder = {
|
const ScrollResponder = {
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const AnimatedImplementation = require('AnimatedImplementation');
|
const AnimatedImplementation = require('AnimatedImplementation');
|
||||||
|
@ -235,7 +237,13 @@ const ScrollView = createReactClass({
|
||||||
* - `false`, deprecated, use 'never' instead
|
* - `false`, deprecated, use 'never' instead
|
||||||
* - `true`, deprecated, use 'always' instead
|
* - `true`, deprecated, use 'always' instead
|
||||||
*/
|
*/
|
||||||
keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled', false, true]),
|
keyboardShouldPersistTaps: PropTypes.oneOf([
|
||||||
|
'always',
|
||||||
|
'never',
|
||||||
|
'handled',
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
]),
|
||||||
/**
|
/**
|
||||||
* When set, the scroll view will adjust the scroll position so that the first child that is
|
* When set, the scroll view will adjust the scroll position so that the first child that is
|
||||||
* currently visible and at or beyond `minIndexForVisible` will not change position. This is
|
* currently visible and at or beyond `minIndexForVisible` will not change position. This is
|
||||||
|
@ -274,7 +282,7 @@ const ScrollView = createReactClass({
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
minimumZoomScale: PropTypes.number,
|
minimumZoomScale: PropTypes.number,
|
||||||
/**
|
/**
|
||||||
* Enables nested scrolling for Android API level 21+.
|
* Enables nested scrolling for Android API level 21+.
|
||||||
* Nested scrolling is supported by default on iOS
|
* Nested scrolling is supported by default on iOS
|
||||||
* @platform android
|
* @platform android
|
||||||
|
@ -321,10 +329,10 @@ const ScrollView = createReactClass({
|
||||||
*/
|
*/
|
||||||
pagingEnabled: PropTypes.bool,
|
pagingEnabled: PropTypes.bool,
|
||||||
/**
|
/**
|
||||||
* When true, ScrollView allows use of pinch gestures to zoom in and out.
|
* When true, ScrollView allows use of pinch gestures to zoom in and out.
|
||||||
* The default value is true.
|
* The default value is true.
|
||||||
* @platform ios
|
* @platform ios
|
||||||
*/
|
*/
|
||||||
pinchGestureEnabled: PropTypes.bool,
|
pinchGestureEnabled: PropTypes.bool,
|
||||||
/**
|
/**
|
||||||
* When false, the view cannot be scrolled via touch interaction.
|
* When false, the view cannot be scrolled via touch interaction.
|
||||||
|
@ -453,7 +461,7 @@ const ScrollView = createReactClass({
|
||||||
*/
|
*/
|
||||||
scrollPerfTag: PropTypes.string,
|
scrollPerfTag: PropTypes.string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to override default value of overScroll mode.
|
* Used to override default value of overScroll mode.
|
||||||
*
|
*
|
||||||
* Possible values:
|
* Possible values:
|
||||||
|
@ -465,11 +473,7 @@ const ScrollView = createReactClass({
|
||||||
*
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
overScrollMode: PropTypes.oneOf([
|
overScrollMode: PropTypes.oneOf(['auto', 'always', 'never']),
|
||||||
'auto',
|
|
||||||
'always',
|
|
||||||
'never',
|
|
||||||
]),
|
|
||||||
/**
|
/**
|
||||||
* When true, ScrollView will emit updateChildFrames data in scroll events,
|
* When true, ScrollView will emit updateChildFrames data in scroll events,
|
||||||
* otherwise will not compute or emit child frame data. This only exists
|
* otherwise will not compute or emit child frame data. This only exists
|
||||||
|
@ -491,18 +495,20 @@ const ScrollView = createReactClass({
|
||||||
* `import IMAGE from './image.jpg'`.
|
* `import IMAGE from './image.jpg'`.
|
||||||
* @platform vr
|
* @platform vr
|
||||||
*/
|
*/
|
||||||
scrollBarThumbImage: PropTypes.oneOfType([
|
scrollBarThumbImage: PropTypes.oneOfType([
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
uri: PropTypes.string,
|
uri: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
// Opaque type returned by import IMAGE from './image.jpg'
|
// Opaque type returned by import IMAGE from './image.jpg'
|
||||||
PropTypes.number,
|
PropTypes.number,
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [ScrollResponder.Mixin],
|
mixins: [ScrollResponder.Mixin],
|
||||||
|
|
||||||
_scrollAnimatedValue: (new AnimatedImplementation.Value(0): AnimatedImplementation.Value),
|
_scrollAnimatedValue: (new AnimatedImplementation.Value(
|
||||||
|
0,
|
||||||
|
): AnimatedImplementation.Value),
|
||||||
_scrollAnimatedValueAttachment: (null: ?{detach: () => void}),
|
_scrollAnimatedValueAttachment: (null: ?{detach: () => void}),
|
||||||
_stickyHeaderRefs: (new Map(): Map<number, ScrollViewStickyHeader>),
|
_stickyHeaderRefs: (new Map(): Map<number, ScrollViewStickyHeader>),
|
||||||
_headerLayoutYs: (new Map(): Map<string, number>),
|
_headerLayoutYs: (new Map(): Map<string, number>),
|
||||||
|
@ -514,8 +520,12 @@ const ScrollView = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
UNSAFE_componentWillMount: function() {
|
UNSAFE_componentWillMount: function() {
|
||||||
this._scrollAnimatedValue = new AnimatedImplementation.Value(this.props.contentOffset ? this.props.contentOffset.y : 0);
|
this._scrollAnimatedValue = new AnimatedImplementation.Value(
|
||||||
this._scrollAnimatedValue.setOffset(this.props.contentInset ? this.props.contentInset.top : 0);
|
this.props.contentOffset ? this.props.contentOffset.y : 0,
|
||||||
|
);
|
||||||
|
this._scrollAnimatedValue.setOffset(
|
||||||
|
this.props.contentInset ? this.props.contentInset.top : 0,
|
||||||
|
);
|
||||||
this._stickyHeaderRefs = new Map();
|
this._stickyHeaderRefs = new Map();
|
||||||
this._headerLayoutYs = new Map();
|
this._headerLayoutYs = new Map();
|
||||||
},
|
},
|
||||||
|
@ -568,19 +578,23 @@ const ScrollView = createReactClass({
|
||||||
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
|
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
|
||||||
*/
|
*/
|
||||||
scrollTo: function(
|
scrollTo: function(
|
||||||
y?: number | { x?: number, y?: number, animated?: boolean },
|
y?: number | {x?: number, y?: number, animated?: boolean},
|
||||||
x?: number,
|
x?: number,
|
||||||
animated?: boolean
|
animated?: boolean,
|
||||||
) {
|
) {
|
||||||
if (typeof y === 'number') {
|
if (typeof y === 'number') {
|
||||||
console.warn('`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, ' +
|
console.warn(
|
||||||
'animated: true})` instead.');
|
'`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, ' +
|
||||||
|
'animated: true})` instead.',
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
({x, y, animated} = y || {});
|
({x, y, animated} = y || {});
|
||||||
}
|
}
|
||||||
this.getScrollResponder().scrollResponderScrollTo(
|
this.getScrollResponder().scrollResponderScrollTo({
|
||||||
{x: x || 0, y: y || 0, animated: animated !== false}
|
x: x || 0,
|
||||||
);
|
y: y || 0,
|
||||||
|
animated: animated !== false,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -591,9 +605,7 @@ const ScrollView = createReactClass({
|
||||||
* `scrollToEnd({animated: false})` for immediate scrolling.
|
* `scrollToEnd({animated: false})` for immediate scrolling.
|
||||||
* If no options are passed, `animated` defaults to true.
|
* If no options are passed, `animated` defaults to true.
|
||||||
*/
|
*/
|
||||||
scrollToEnd: function(
|
scrollToEnd: function(options?: {animated?: boolean}) {
|
||||||
options?: { animated?: boolean },
|
|
||||||
) {
|
|
||||||
// Default to true
|
// Default to true
|
||||||
const animated = (options && options.animated) !== false;
|
const animated = (options && options.animated) !== false;
|
||||||
this.getScrollResponder().scrollResponderScrollToEnd({
|
this.getScrollResponder().scrollResponderScrollToEnd({
|
||||||
|
@ -605,7 +617,9 @@ const ScrollView = createReactClass({
|
||||||
* Deprecated, use `scrollTo` instead.
|
* Deprecated, use `scrollTo` instead.
|
||||||
*/
|
*/
|
||||||
scrollWithoutAnimationTo: function(y: number = 0, x: number = 0) {
|
scrollWithoutAnimationTo: function(y: number = 0, x: number = 0) {
|
||||||
console.warn('`scrollWithoutAnimationTo` is deprecated. Use `scrollTo` instead');
|
console.warn(
|
||||||
|
'`scrollWithoutAnimationTo` is deprecated. Use `scrollTo` instead',
|
||||||
|
);
|
||||||
this.scrollTo({x, y, animated: false});
|
this.scrollTo({x, y, animated: false});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -627,11 +641,14 @@ const ScrollView = createReactClass({
|
||||||
if (this._scrollAnimatedValueAttachment) {
|
if (this._scrollAnimatedValueAttachment) {
|
||||||
this._scrollAnimatedValueAttachment.detach();
|
this._scrollAnimatedValueAttachment.detach();
|
||||||
}
|
}
|
||||||
if (this.props.stickyHeaderIndices && this.props.stickyHeaderIndices.length > 0) {
|
if (
|
||||||
|
this.props.stickyHeaderIndices &&
|
||||||
|
this.props.stickyHeaderIndices.length > 0
|
||||||
|
) {
|
||||||
this._scrollAnimatedValueAttachment = AnimatedImplementation.attachNativeEvent(
|
this._scrollAnimatedValueAttachment = AnimatedImplementation.attachNativeEvent(
|
||||||
this._scrollViewRef,
|
this._scrollViewRef,
|
||||||
'onScroll',
|
'onScroll',
|
||||||
[{nativeEvent: {contentOffset: {y: this._scrollAnimatedValue}}}]
|
[{nativeEvent: {contentOffset: {y: this._scrollAnimatedValue}}}],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -658,10 +675,12 @@ const ScrollView = createReactClass({
|
||||||
this._headerLayoutYs.set(key, layoutY);
|
this._headerLayoutYs.set(key, layoutY);
|
||||||
|
|
||||||
const indexOfIndex = this.props.stickyHeaderIndices.indexOf(index);
|
const indexOfIndex = this.props.stickyHeaderIndices.indexOf(index);
|
||||||
const previousHeaderIndex = this.props.stickyHeaderIndices[indexOfIndex - 1];
|
const previousHeaderIndex = this.props.stickyHeaderIndices[
|
||||||
|
indexOfIndex - 1
|
||||||
|
];
|
||||||
if (previousHeaderIndex != null) {
|
if (previousHeaderIndex != null) {
|
||||||
const previousHeader = this._stickyHeaderRefs.get(
|
const previousHeader = this._stickyHeaderRefs.get(
|
||||||
this._getKeyForIndex(previousHeaderIndex, childArray)
|
this._getKeyForIndex(previousHeaderIndex, childArray),
|
||||||
);
|
);
|
||||||
previousHeader && previousHeader.setNextHeaderY(layoutY);
|
previousHeader && previousHeader.setNextHeaderY(layoutY);
|
||||||
}
|
}
|
||||||
|
@ -669,18 +688,25 @@ const ScrollView = createReactClass({
|
||||||
|
|
||||||
_handleScroll: function(e: Object) {
|
_handleScroll: function(e: Object) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (this.props.onScroll && this.props.scrollEventThrottle == null && Platform.OS === 'ios') {
|
if (
|
||||||
|
this.props.onScroll &&
|
||||||
|
this.props.scrollEventThrottle == null &&
|
||||||
|
Platform.OS === 'ios'
|
||||||
|
) {
|
||||||
console.log(
|
console.log(
|
||||||
'You specified `onScroll` on a <ScrollView> but not ' +
|
'You specified `onScroll` on a <ScrollView> but not ' +
|
||||||
'`scrollEventThrottle`. You will only receive one event. ' +
|
'`scrollEventThrottle`. You will only receive one event. ' +
|
||||||
'Using `16` you get all the events but be aware that it may ' +
|
'Using `16` you get all the events but be aware that it may ' +
|
||||||
'cause frame drops, use a bigger number if you don\'t need as ' +
|
"cause frame drops, use a bigger number if you don't need as " +
|
||||||
'much precision.'
|
'much precision.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
if (this.props.keyboardDismissMode === 'on-drag' && this.state.isTouching) {
|
if (
|
||||||
|
this.props.keyboardDismissMode === 'on-drag' &&
|
||||||
|
this.state.isTouching
|
||||||
|
) {
|
||||||
dismissKeyboard();
|
dismissKeyboard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -689,7 +715,7 @@ const ScrollView = createReactClass({
|
||||||
|
|
||||||
_handleLayout: function(e: Object) {
|
_handleLayout: function(e: Object) {
|
||||||
if (this.props.invertStickyHeaders) {
|
if (this.props.invertStickyHeaders) {
|
||||||
this.setState({ layoutHeight: e.nativeEvent.layout.height });
|
this.setState({layoutHeight: e.nativeEvent.layout.height});
|
||||||
}
|
}
|
||||||
if (this.props.onLayout) {
|
if (this.props.onLayout) {
|
||||||
this.props.onLayout(e);
|
this.props.onLayout(e);
|
||||||
|
@ -698,7 +724,8 @@ const ScrollView = createReactClass({
|
||||||
|
|
||||||
_handleContentOnLayout: function(e: Object) {
|
_handleContentOnLayout: function(e: Object) {
|
||||||
const {width, height} = e.nativeEvent.layout;
|
const {width, height} = e.nativeEvent.layout;
|
||||||
this.props.onContentSizeChange && this.props.onContentSizeChange(width, height);
|
this.props.onContentSizeChange &&
|
||||||
|
this.props.onContentSizeChange(width, height);
|
||||||
},
|
},
|
||||||
|
|
||||||
_scrollViewRef: (null: ?ScrollView),
|
_scrollViewRef: (null: ?ScrollView),
|
||||||
|
@ -727,18 +754,18 @@ const ScrollView = createReactClass({
|
||||||
ScrollContentContainerViewClass = RCTScrollContentView;
|
ScrollContentContainerViewClass = RCTScrollContentView;
|
||||||
warning(
|
warning(
|
||||||
!this.props.snapToInterval || !this.props.pagingEnabled,
|
!this.props.snapToInterval || !this.props.pagingEnabled,
|
||||||
'snapToInterval is currently ignored when pagingEnabled is true.'
|
'snapToInterval is currently ignored when pagingEnabled is true.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
invariant(
|
invariant(
|
||||||
ScrollViewClass !== undefined,
|
ScrollViewClass !== undefined,
|
||||||
'ScrollViewClass must not be undefined'
|
'ScrollViewClass must not be undefined',
|
||||||
);
|
);
|
||||||
|
|
||||||
invariant(
|
invariant(
|
||||||
ScrollContentContainerViewClass !== undefined,
|
ScrollContentContainerViewClass !== undefined,
|
||||||
'ScrollContentContainerViewClass must not be undefined'
|
'ScrollContentContainerViewClass must not be undefined',
|
||||||
);
|
);
|
||||||
|
|
||||||
const contentContainerStyle = [
|
const contentContainerStyle = [
|
||||||
|
@ -747,12 +774,14 @@ const ScrollView = createReactClass({
|
||||||
];
|
];
|
||||||
if (__DEV__ && this.props.style) {
|
if (__DEV__ && this.props.style) {
|
||||||
const style = flattenStyle(this.props.style);
|
const style = flattenStyle(this.props.style);
|
||||||
const childLayoutProps = ['alignItems', 'justifyContent']
|
const childLayoutProps = ['alignItems', 'justifyContent'].filter(
|
||||||
.filter((prop) => style && style[prop] !== undefined);
|
prop => style && style[prop] !== undefined,
|
||||||
|
);
|
||||||
invariant(
|
invariant(
|
||||||
childLayoutProps.length === 0,
|
childLayoutProps.length === 0,
|
||||||
'ScrollView child layout (' + JSON.stringify(childLayoutProps) +
|
'ScrollView child layout (' +
|
||||||
') must be applied through the contentContainerStyle prop.'
|
JSON.stringify(childLayoutProps) +
|
||||||
|
') must be applied through the contentContainerStyle prop.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,34 +793,38 @@ const ScrollView = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
const {stickyHeaderIndices} = this.props;
|
const {stickyHeaderIndices} = this.props;
|
||||||
const hasStickyHeaders = stickyHeaderIndices && stickyHeaderIndices.length > 0;
|
const hasStickyHeaders =
|
||||||
const childArray = hasStickyHeaders && React.Children.toArray(this.props.children);
|
stickyHeaderIndices && stickyHeaderIndices.length > 0;
|
||||||
const children = hasStickyHeaders ?
|
const childArray =
|
||||||
childArray.map((child, index) => {
|
hasStickyHeaders && React.Children.toArray(this.props.children);
|
||||||
const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1;
|
const children = hasStickyHeaders
|
||||||
if (indexOfIndex > -1) {
|
? childArray.map((child, index) => {
|
||||||
const key = child.key;
|
const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1;
|
||||||
const nextIndex = stickyHeaderIndices[indexOfIndex + 1];
|
if (indexOfIndex > -1) {
|
||||||
return (
|
const key = child.key;
|
||||||
<ScrollViewStickyHeader
|
const nextIndex = stickyHeaderIndices[indexOfIndex + 1];
|
||||||
key={key}
|
return (
|
||||||
ref={(ref) => this._setStickyHeaderRef(key, ref)}
|
<ScrollViewStickyHeader
|
||||||
nextHeaderLayoutY={
|
key={key}
|
||||||
this._headerLayoutYs.get(this._getKeyForIndex(nextIndex, childArray))
|
ref={ref => this._setStickyHeaderRef(key, ref)}
|
||||||
}
|
nextHeaderLayoutY={this._headerLayoutYs.get(
|
||||||
onLayout={(event) => this._onStickyHeaderLayout(index, event, key)}
|
this._getKeyForIndex(nextIndex, childArray),
|
||||||
scrollAnimatedValue={this._scrollAnimatedValue}
|
)}
|
||||||
inverted={this.props.invertStickyHeaders}
|
onLayout={event =>
|
||||||
scrollViewHeight={this.state.layoutHeight}>
|
this._onStickyHeaderLayout(index, event, key)
|
||||||
{child}
|
}
|
||||||
</ScrollViewStickyHeader>
|
scrollAnimatedValue={this._scrollAnimatedValue}
|
||||||
);
|
inverted={this.props.invertStickyHeaders}
|
||||||
} else {
|
scrollViewHeight={this.state.layoutHeight}>
|
||||||
return child;
|
{child}
|
||||||
}
|
</ScrollViewStickyHeader>
|
||||||
}) :
|
);
|
||||||
this.props.children;
|
} else {
|
||||||
const contentContainer =
|
return child;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: this.props.children;
|
||||||
|
const contentContainer = (
|
||||||
<ScrollContentContainerViewClass
|
<ScrollContentContainerViewClass
|
||||||
{...contentSizeChangeProps}
|
{...contentSizeChangeProps}
|
||||||
ref={this._setInnerViewRef}
|
ref={this._setInnerViewRef}
|
||||||
|
@ -799,28 +832,31 @@ const ScrollView = createReactClass({
|
||||||
removeClippedSubviews={
|
removeClippedSubviews={
|
||||||
// Subview clipping causes issues with sticky headers on Android and
|
// Subview clipping causes issues with sticky headers on Android and
|
||||||
// would be hard to fix properly in a performant way.
|
// would be hard to fix properly in a performant way.
|
||||||
Platform.OS === 'android' && hasStickyHeaders ?
|
Platform.OS === 'android' && hasStickyHeaders
|
||||||
false :
|
? false
|
||||||
this.props.removeClippedSubviews
|
: this.props.removeClippedSubviews
|
||||||
}
|
}
|
||||||
collapsable={false}>
|
collapsable={false}>
|
||||||
{children}
|
{children}
|
||||||
</ScrollContentContainerViewClass>;
|
</ScrollContentContainerViewClass>
|
||||||
|
);
|
||||||
|
|
||||||
const alwaysBounceHorizontal =
|
const alwaysBounceHorizontal =
|
||||||
this.props.alwaysBounceHorizontal !== undefined ?
|
this.props.alwaysBounceHorizontal !== undefined
|
||||||
this.props.alwaysBounceHorizontal :
|
? this.props.alwaysBounceHorizontal
|
||||||
this.props.horizontal;
|
: this.props.horizontal;
|
||||||
|
|
||||||
const alwaysBounceVertical =
|
const alwaysBounceVertical =
|
||||||
this.props.alwaysBounceVertical !== undefined ?
|
this.props.alwaysBounceVertical !== undefined
|
||||||
this.props.alwaysBounceVertical :
|
? this.props.alwaysBounceVertical
|
||||||
!this.props.horizontal;
|
: !this.props.horizontal;
|
||||||
|
|
||||||
const DEPRECATED_sendUpdatedChildFrames =
|
const DEPRECATED_sendUpdatedChildFrames = !!this.props
|
||||||
!!this.props.DEPRECATED_sendUpdatedChildFrames;
|
.DEPRECATED_sendUpdatedChildFrames;
|
||||||
|
|
||||||
const baseStyle = this.props.horizontal ? styles.baseHorizontal : styles.baseVertical;
|
const baseStyle = this.props.horizontal
|
||||||
|
? styles.baseHorizontal
|
||||||
|
: styles.baseVertical;
|
||||||
const props = {
|
const props = {
|
||||||
...this.props,
|
...this.props,
|
||||||
alwaysBounceHorizontal,
|
alwaysBounceHorizontal,
|
||||||
|
@ -836,25 +872,33 @@ const ScrollView = createReactClass({
|
||||||
onResponderReject: this.scrollResponderHandleResponderReject,
|
onResponderReject: this.scrollResponderHandleResponderReject,
|
||||||
onResponderRelease: this.scrollResponderHandleResponderRelease,
|
onResponderRelease: this.scrollResponderHandleResponderRelease,
|
||||||
onResponderTerminate: this.scrollResponderHandleTerminate,
|
onResponderTerminate: this.scrollResponderHandleTerminate,
|
||||||
onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest,
|
onResponderTerminationRequest: this
|
||||||
|
.scrollResponderHandleTerminationRequest,
|
||||||
onScroll: this._handleScroll,
|
onScroll: this._handleScroll,
|
||||||
onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
|
onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
|
||||||
onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
|
onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
|
||||||
onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder,
|
onScrollShouldSetResponder: this
|
||||||
onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder,
|
.scrollResponderHandleScrollShouldSetResponder,
|
||||||
onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture,
|
onStartShouldSetResponder: this
|
||||||
|
.scrollResponderHandleStartShouldSetResponder,
|
||||||
|
onStartShouldSetResponderCapture: this
|
||||||
|
.scrollResponderHandleStartShouldSetResponderCapture,
|
||||||
onTouchEnd: this.scrollResponderHandleTouchEnd,
|
onTouchEnd: this.scrollResponderHandleTouchEnd,
|
||||||
onTouchMove: this.scrollResponderHandleTouchMove,
|
onTouchMove: this.scrollResponderHandleTouchMove,
|
||||||
onTouchStart: this.scrollResponderHandleTouchStart,
|
onTouchStart: this.scrollResponderHandleTouchStart,
|
||||||
onTouchCancel: this.scrollResponderHandleTouchCancel,
|
onTouchCancel: this.scrollResponderHandleTouchCancel,
|
||||||
scrollBarThumbImage: resolveAssetSource(this.props.scrollBarThumbImage),
|
scrollBarThumbImage: resolveAssetSource(this.props.scrollBarThumbImage),
|
||||||
scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle,
|
scrollEventThrottle: hasStickyHeaders
|
||||||
sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ?
|
? 1
|
||||||
true : false,
|
: this.props.scrollEventThrottle,
|
||||||
|
sendMomentumEvents:
|
||||||
|
this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
DEPRECATED_sendUpdatedChildFrames,
|
DEPRECATED_sendUpdatedChildFrames,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { decelerationRate } = this.props;
|
const {decelerationRate} = this.props;
|
||||||
if (decelerationRate) {
|
if (decelerationRate) {
|
||||||
props.decelerationRate = processDecelerationRate(decelerationRate);
|
props.decelerationRate = processDecelerationRate(decelerationRate);
|
||||||
}
|
}
|
||||||
|
@ -881,9 +925,12 @@ const ScrollView = createReactClass({
|
||||||
return React.cloneElement(
|
return React.cloneElement(
|
||||||
refreshControl,
|
refreshControl,
|
||||||
{style: props.style},
|
{style: props.style},
|
||||||
<ScrollViewClass {...props} style={baseStyle} ref={this._setScrollViewRef}>
|
<ScrollViewClass
|
||||||
|
{...props}
|
||||||
|
style={baseStyle}
|
||||||
|
ref={this._setScrollViewRef}>
|
||||||
{contentContainer}
|
{contentContainer}
|
||||||
</ScrollViewClass>
|
</ScrollViewClass>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -892,7 +939,7 @@ const ScrollView = createReactClass({
|
||||||
{contentContainer}
|
{contentContainer}
|
||||||
</ScrollViewClass>
|
</ScrollViewClass>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -923,29 +970,29 @@ if (Platform.OS === 'android') {
|
||||||
nativeOnlyProps = {
|
nativeOnlyProps = {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
sendMomentumEvents: true,
|
sendMomentumEvents: true,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
AndroidScrollView = requireNativeComponent(
|
AndroidScrollView = requireNativeComponent(
|
||||||
'RCTScrollView',
|
'RCTScrollView',
|
||||||
(ScrollView: React.ComponentType<any>),
|
(ScrollView: React.ComponentType<any>),
|
||||||
nativeOnlyProps
|
nativeOnlyProps,
|
||||||
);
|
);
|
||||||
AndroidHorizontalScrollView = requireNativeComponent(
|
AndroidHorizontalScrollView = requireNativeComponent(
|
||||||
'AndroidHorizontalScrollView',
|
'AndroidHorizontalScrollView',
|
||||||
(ScrollView: React.ComponentType<any>),
|
(ScrollView: React.ComponentType<any>),
|
||||||
nativeOnlyProps
|
nativeOnlyProps,
|
||||||
);
|
);
|
||||||
AndroidHorizontalScrollContentView = requireNativeComponent(
|
AndroidHorizontalScrollContentView = requireNativeComponent(
|
||||||
'AndroidHorizontalScrollContentView'
|
'AndroidHorizontalScrollContentView',
|
||||||
);
|
);
|
||||||
} else if (Platform.OS === 'ios') {
|
} else if (Platform.OS === 'ios') {
|
||||||
nativeOnlyProps = {
|
nativeOnlyProps = {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
onMomentumScrollBegin: true,
|
onMomentumScrollBegin: true,
|
||||||
onMomentumScrollEnd : true,
|
onMomentumScrollEnd: true,
|
||||||
onScrollBeginDrag: true,
|
onScrollBeginDrag: true,
|
||||||
onScrollEndDrag: true,
|
onScrollEndDrag: true,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
RCTScrollView = requireNativeComponent(
|
RCTScrollView = requireNativeComponent(
|
||||||
'RCTScrollView',
|
'RCTScrollView',
|
||||||
|
@ -955,8 +1002,7 @@ if (Platform.OS === 'android') {
|
||||||
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
|
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
|
||||||
} else {
|
} else {
|
||||||
nativeOnlyProps = {
|
nativeOnlyProps = {
|
||||||
nativeOnly: {
|
nativeOnly: {},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
RCTScrollView = requireNativeComponent(
|
RCTScrollView = requireNativeComponent(
|
||||||
'RCTScrollView',
|
'RCTScrollView',
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -27,9 +28,7 @@ class ScrollViewMock extends ScrollViewComponent {
|
||||||
return (
|
return (
|
||||||
<RCTScrollView {...this.props}>
|
<RCTScrollView {...this.props}>
|
||||||
{this.props.refreshControl}
|
{this.props.refreshControl}
|
||||||
<View>
|
<View>{this.props.children}</View>
|
||||||
{this.props.children}
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
</RCTScrollView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function processDecelerationRate(decelerationRate) {
|
function processDecelerationRate(decelerationRate) {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2015-present, Facebook, Inc.
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -40,7 +40,7 @@ const styles = StyleSheet.create({
|
||||||
color: '#333333',
|
color: '#333333',
|
||||||
margin: 5,
|
margin: 5,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DummySegmentedControlIOS;
|
module.exports = DummySegmentedControlIOS;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||||
|
@ -89,19 +91,20 @@ const SegmentedControlIOS = createReactClass({
|
||||||
* If true, then selecting a segment won't persist visually.
|
* If true, then selecting a segment won't persist visually.
|
||||||
* The `onValueChange` callback will still work as expected.
|
* The `onValueChange` callback will still work as expected.
|
||||||
*/
|
*/
|
||||||
momentary: PropTypes.bool
|
momentary: PropTypes.bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function(): DefaultProps {
|
getDefaultProps: function(): DefaultProps {
|
||||||
return {
|
return {
|
||||||
values: [],
|
values: [],
|
||||||
enabled: true
|
enabled: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
_onChange: function(event: Event) {
|
_onChange: function(event: Event) {
|
||||||
this.props.onChange && this.props.onChange(event);
|
this.props.onChange && this.props.onChange(event);
|
||||||
this.props.onValueChange && this.props.onValueChange(event.nativeEvent.value);
|
this.props.onValueChange &&
|
||||||
|
this.props.onValueChange(event.nativeEvent.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -113,7 +116,7 @@ const SegmentedControlIOS = createReactClass({
|
||||||
onChange={this._onChange}
|
onChange={this._onChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -124,7 +127,7 @@ const styles = StyleSheet.create({
|
||||||
|
|
||||||
const RCTSegmentedControl = requireNativeComponent(
|
const RCTSegmentedControl = requireNativeComponent(
|
||||||
'RCTSegmentedControl',
|
'RCTSegmentedControl',
|
||||||
SegmentedControlIOS
|
SegmentedControlIOS,
|
||||||
);
|
);
|
||||||
|
|
||||||
module.exports = SegmentedControlIOS;
|
module.exports = SegmentedControlIOS;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Image = require('Image');
|
const Image = require('Image');
|
||||||
|
@ -192,13 +194,13 @@ const Slider = createReactClass({
|
||||||
testID: PropTypes.string,
|
testID: PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function() : any {
|
getDefaultProps: function(): any {
|
||||||
return {
|
return {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
value: 0,
|
value: 0,
|
||||||
minimumValue: 0,
|
minimumValue: 0,
|
||||||
maximumValue: 1,
|
maximumValue: 1,
|
||||||
step: 0
|
step: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -206,8 +208,8 @@ const Slider = createReactClass({
|
||||||
uiViewClassName: 'RCTSlider',
|
uiViewClassName: 'RCTSlider',
|
||||||
validAttributes: {
|
validAttributes: {
|
||||||
...ReactNativeViewAttributes.RCTView,
|
...ReactNativeViewAttributes.RCTView,
|
||||||
value: true
|
value: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -220,15 +222,17 @@ const Slider = createReactClass({
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
||||||
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
||||||
* delete this comment and run Flow. */
|
* delete this comment and run Flow. */
|
||||||
props.onValueChange = onValueChange && ((event: Event) => {
|
props.onValueChange =
|
||||||
let userEvent = true;
|
onValueChange &&
|
||||||
if (Platform.OS === 'android') {
|
((event: Event) => {
|
||||||
// On Android there's a special flag telling us the user is
|
let userEvent = true;
|
||||||
// dragging the slider.
|
if (Platform.OS === 'android') {
|
||||||
userEvent = event.nativeEvent.fromUser;
|
// On Android there's a special flag telling us the user is
|
||||||
}
|
// dragging the slider.
|
||||||
onValueChange && userEvent && onValueChange(event.nativeEvent.value);
|
userEvent = event.nativeEvent.fromUser;
|
||||||
});
|
}
|
||||||
|
onValueChange && userEvent && onValueChange(event.nativeEvent.value);
|
||||||
|
});
|
||||||
|
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
||||||
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
||||||
|
@ -238,17 +242,21 @@ const Slider = createReactClass({
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
||||||
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
||||||
* delete this comment and run Flow. */
|
* delete this comment and run Flow. */
|
||||||
props.onSlidingComplete = onSlidingComplete && ((event: Event) => {
|
props.onSlidingComplete =
|
||||||
onSlidingComplete && onSlidingComplete(event.nativeEvent.value);
|
onSlidingComplete &&
|
||||||
});
|
((event: Event) => {
|
||||||
|
onSlidingComplete && onSlidingComplete(event.nativeEvent.value);
|
||||||
|
});
|
||||||
|
|
||||||
return <RCTSlider
|
return (
|
||||||
{...props}
|
<RCTSlider
|
||||||
enabled={!this.props.disabled}
|
{...props}
|
||||||
onStartShouldSetResponder={() => true}
|
enabled={!this.props.disabled}
|
||||||
onResponderTerminationRequest={() => false}
|
onStartShouldSetResponder={() => true}
|
||||||
/>;
|
onResponderTerminationRequest={() => false}
|
||||||
}
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let styles;
|
let styles;
|
||||||
|
@ -269,7 +277,7 @@ if (Platform.OS === 'android') {
|
||||||
options = {
|
options = {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const RCTSlider = requireNativeComponent('RCTSlider', Slider, options);
|
const RCTSlider = requireNativeComponent('RCTSlider', Slider, options);
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('React');
|
const React = require('React');
|
||||||
|
@ -26,18 +28,16 @@ const React = require('React');
|
||||||
* React reconciliation.
|
* React reconciliation.
|
||||||
*/
|
*/
|
||||||
class StaticContainer extends React.Component<Object> {
|
class StaticContainer extends React.Component<Object> {
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: Object): boolean {
|
shouldComponentUpdate(nextProps: Object): boolean {
|
||||||
return !!nextProps.shouldUpdate;
|
return !!nextProps.shouldUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const child = this.props.children;
|
const child = this.props.children;
|
||||||
return (child === null || child === false)
|
return child === null || child === false
|
||||||
? null
|
? null
|
||||||
: React.Children.only(child);
|
: React.Children.only(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = StaticContainer;
|
module.exports = StaticContainer;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('React');
|
const React = require('React');
|
||||||
|
@ -21,7 +23,7 @@ class StaticRenderer extends React.Component<{
|
||||||
render: PropTypes.func.isRequired,
|
render: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: { shouldUpdate: boolean }): boolean {
|
shouldComponentUpdate(nextProps: {shouldUpdate: boolean}): boolean {
|
||||||
return nextProps.shouldUpdate;
|
return nextProps.shouldUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('React');
|
const React = require('React');
|
||||||
|
@ -24,7 +26,7 @@ export type StatusBarStyle = $Enum<{
|
||||||
/**
|
/**
|
||||||
* Default status bar style (dark for iOS, light for Android)
|
* Default status bar style (dark for iOS, light for Android)
|
||||||
*/
|
*/
|
||||||
'default': string,
|
default: string,
|
||||||
/**
|
/**
|
||||||
* Dark background, white texts and icons
|
* Dark background, white texts and icons
|
||||||
*/
|
*/
|
||||||
|
@ -42,15 +44,15 @@ export type StatusBarAnimation = $Enum<{
|
||||||
/**
|
/**
|
||||||
* No animation
|
* No animation
|
||||||
*/
|
*/
|
||||||
'none': string,
|
none: string,
|
||||||
/**
|
/**
|
||||||
* Fade animation
|
* Fade animation
|
||||||
*/
|
*/
|
||||||
'fade': string,
|
fade: string,
|
||||||
/**
|
/**
|
||||||
* Slide animation
|
* Slide animation
|
||||||
*/
|
*/
|
||||||
'slide': string,
|
slide: string,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type DefaultProps = {
|
type DefaultProps = {
|
||||||
|
@ -62,7 +64,7 @@ type DefaultProps = {
|
||||||
*/
|
*/
|
||||||
function mergePropsStack(
|
function mergePropsStack(
|
||||||
propsStack: Array<Object>,
|
propsStack: Array<Object>,
|
||||||
defaultValues: Object
|
defaultValues: Object,
|
||||||
): Object {
|
): Object {
|
||||||
return propsStack.reduce((prev, cur) => {
|
return propsStack.reduce((prev, cur) => {
|
||||||
for (const prop in cur) {
|
for (const prop in cur) {
|
||||||
|
@ -223,7 +225,7 @@ class StatusBar extends React.Component<{
|
||||||
static setNetworkActivityIndicatorVisible(visible: boolean) {
|
static setNetworkActivityIndicatorVisible(visible: boolean) {
|
||||||
if (Platform.OS !== 'ios') {
|
if (Platform.OS !== 'ios') {
|
||||||
console.warn(
|
console.warn(
|
||||||
'`setNetworkActivityIndicatorVisible` is only available on iOS'
|
'`setNetworkActivityIndicatorVisible` is only available on iOS',
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +347,7 @@ class StatusBar extends React.Component<{
|
||||||
const oldProps = StatusBar._currentValues;
|
const oldProps = StatusBar._currentValues;
|
||||||
const mergedProps = mergePropsStack(
|
const mergedProps = mergePropsStack(
|
||||||
StatusBar._propsStack,
|
StatusBar._propsStack,
|
||||||
StatusBar._defaultProps
|
StatusBar._defaultProps,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update the props that have changed using the merged values from the props stack.
|
// Update the props that have changed using the merged values from the props stack.
|
||||||
|
@ -356,13 +358,15 @@ class StatusBar extends React.Component<{
|
||||||
) {
|
) {
|
||||||
StatusBarManager.setStyle(
|
StatusBarManager.setStyle(
|
||||||
mergedProps.barStyle.value,
|
mergedProps.barStyle.value,
|
||||||
mergedProps.barStyle.animated
|
mergedProps.barStyle.animated,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!oldProps || oldProps.hidden.value !== mergedProps.hidden.value) {
|
if (!oldProps || oldProps.hidden.value !== mergedProps.hidden.value) {
|
||||||
StatusBarManager.setHidden(
|
StatusBarManager.setHidden(
|
||||||
mergedProps.hidden.value,
|
mergedProps.hidden.value,
|
||||||
mergedProps.hidden.animated ? mergedProps.hidden.transition : 'none'
|
mergedProps.hidden.animated
|
||||||
|
? mergedProps.hidden.transition
|
||||||
|
: 'none',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +376,7 @@ class StatusBar extends React.Component<{
|
||||||
mergedProps.networkActivityIndicatorVisible
|
mergedProps.networkActivityIndicatorVisible
|
||||||
) {
|
) {
|
||||||
StatusBarManager.setNetworkActivityIndicatorVisible(
|
StatusBarManager.setNetworkActivityIndicatorVisible(
|
||||||
mergedProps.networkActivityIndicatorVisible
|
mergedProps.networkActivityIndicatorVisible,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (Platform.OS === 'android') {
|
} else if (Platform.OS === 'android') {
|
||||||
|
@ -388,7 +392,7 @@ class StatusBar extends React.Component<{
|
||||||
) {
|
) {
|
||||||
StatusBarManager.setColor(
|
StatusBarManager.setColor(
|
||||||
processColor(mergedProps.backgroundColor.value),
|
processColor(mergedProps.backgroundColor.value),
|
||||||
mergedProps.backgroundColor.animated
|
mergedProps.backgroundColor.animated,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!oldProps || oldProps.hidden.value !== mergedProps.hidden.value) {
|
if (!oldProps || oldProps.hidden.value !== mergedProps.hidden.value) {
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeEventEmitter = require('NativeEventEmitter');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeEventEmitter = require('NativeEventEmitter');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
const { StatusBarManager } = require('NativeModules');
|
const {StatusBarManager} = require('NativeModules');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use `StatusBar` for mutating the status bar.
|
* Use `StatusBar` for mutating the status bar.
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import type EventEmitter from 'EventEmitter';
|
import type EventEmitter from 'EventEmitter';
|
||||||
|
@ -21,7 +23,6 @@ import type EventEmitter from 'EventEmitter';
|
||||||
const Subscribable = {};
|
const Subscribable = {};
|
||||||
|
|
||||||
Subscribable.Mixin = {
|
Subscribable.Mixin = {
|
||||||
|
|
||||||
UNSAFE_componentWillMount: function() {
|
UNSAFE_componentWillMount: function() {
|
||||||
this._subscribableSubscriptions = [];
|
this._subscribableSubscriptions = [];
|
||||||
},
|
},
|
||||||
|
@ -29,9 +30,10 @@ Subscribable.Mixin = {
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
// This null check is a fix for a broken version of uglify-es. Should be deleted eventually
|
// This null check is a fix for a broken version of uglify-es. Should be deleted eventually
|
||||||
// https://github.com/facebook/react-native/issues/17348
|
// https://github.com/facebook/react-native/issues/17348
|
||||||
this._subscribableSubscriptions && this._subscribableSubscriptions.forEach(
|
this._subscribableSubscriptions &&
|
||||||
(subscription) => subscription.remove()
|
this._subscribableSubscriptions.forEach(subscription =>
|
||||||
);
|
subscription.remove(),
|
||||||
|
);
|
||||||
this._subscribableSubscriptions = null;
|
this._subscribableSubscriptions = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -52,12 +54,12 @@ Subscribable.Mixin = {
|
||||||
eventEmitter: EventEmitter,
|
eventEmitter: EventEmitter,
|
||||||
eventType: string,
|
eventType: string,
|
||||||
listener: Function,
|
listener: Function,
|
||||||
context: Object
|
context: Object,
|
||||||
) {
|
) {
|
||||||
this._subscribableSubscriptions.push(
|
this._subscribableSubscriptions.push(
|
||||||
eventEmitter.addListener(eventType, listener, context)
|
eventEmitter.addListener(eventType, listener, context),
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Subscribable;
|
module.exports = Subscribable;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -93,7 +95,8 @@ const Switch = createReactClass({
|
||||||
* suppresses an error when upgrading Flow's support for React. To see the
|
* suppresses an error when upgrading Flow's support for React. To see the
|
||||||
* error delete this comment and run Flow. */
|
* error delete this comment and run Flow. */
|
||||||
this.props.onChange && this.props.onChange(event);
|
this.props.onChange && this.props.onChange(event);
|
||||||
this.props.onValueChange && this.props.onValueChange(event.nativeEvent.value);
|
this.props.onValueChange &&
|
||||||
|
this.props.onValueChange(event.nativeEvent.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -113,17 +116,21 @@ const Switch = createReactClass({
|
||||||
/* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an
|
/* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an
|
||||||
* error found when Flow v0.70 was deployed. To see the error delete
|
* error found when Flow v0.70 was deployed. To see the error delete
|
||||||
* this comment and run Flow. */
|
* this comment and run Flow. */
|
||||||
props.trackTintColor = this.props.value ? this.props.onTintColor : this.props.tintColor;
|
props.trackTintColor = this.props.value
|
||||||
|
? this.props.onTintColor
|
||||||
|
: this.props.tintColor;
|
||||||
} else if (Platform.OS === 'ios') {
|
} else if (Platform.OS === 'ios') {
|
||||||
props.style = [styles.rctSwitchIOS, this.props.style];
|
props.style = [styles.rctSwitchIOS, this.props.style];
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<RCTSwitch
|
<RCTSwitch
|
||||||
{...props}
|
{...props}
|
||||||
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
|
ref={ref => {
|
||||||
* comment suppresses an error when upgrading Flow's support for React.
|
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
|
||||||
* To see the error delete this comment and run Flow. */
|
* comment suppresses an error when upgrading Flow's support for React.
|
||||||
ref={(ref) => { this._rctSwitch = ref; }}
|
* To see the error delete this comment and run Flow. */
|
||||||
|
this._rctSwitch = ref;
|
||||||
|
}}
|
||||||
onChange={this._onChange}
|
onChange={this._onChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -134,7 +141,7 @@ const styles = StyleSheet.create({
|
||||||
rctSwitchIOS: {
|
rctSwitchIOS: {
|
||||||
height: 31,
|
height: 31,
|
||||||
width: 51,
|
width: 51,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
|
@ -144,13 +151,13 @@ if (Platform.OS === 'android') {
|
||||||
on: true,
|
on: true,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
trackTintColor: true,
|
trackTintColor: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, {
|
var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
onChange: true
|
onChange: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ class DummyTabBarIOS extends React.Component<$FlowFixMeProps> {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
tabGroup: {
|
tabGroup: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DummyTabBarIOS;
|
module.exports = DummyTabBarIOS;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -20,17 +22,19 @@ const requireNativeComponent = require('requireNativeComponent');
|
||||||
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet';
|
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet';
|
||||||
import type {ViewProps} from 'ViewPropTypes';
|
import type {ViewProps} from 'ViewPropTypes';
|
||||||
|
|
||||||
class TabBarIOS extends React.Component<ViewProps & {
|
class TabBarIOS extends React.Component<
|
||||||
style?: DangerouslyImpreciseStyleProp,
|
ViewProps & {
|
||||||
unselectedTintColor?: string,
|
style?: DangerouslyImpreciseStyleProp,
|
||||||
tintColor?: string,
|
unselectedTintColor?: string,
|
||||||
unselectedItemTintColor?: string,
|
tintColor?: string,
|
||||||
barTintColor?: string,
|
unselectedItemTintColor?: string,
|
||||||
barStyle?: 'default' | 'black',
|
barTintColor?: string,
|
||||||
translucent?: boolean,
|
barStyle?: 'default' | 'black',
|
||||||
itemPositioning?: 'fill' | 'center' | 'auto',
|
translucent?: boolean,
|
||||||
children: React.Node,
|
itemPositioning?: 'fill' | 'center' | 'auto',
|
||||||
}> {
|
children: React.Node,
|
||||||
|
},
|
||||||
|
> {
|
||||||
static Item = TabBarItemIOS;
|
static Item = TabBarItemIOS;
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -94,7 +98,7 @@ class TabBarIOS extends React.Component<ViewProps & {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
tabGroup: {
|
tabGroup: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const RCTTabBar = requireNativeComponent('RCTTabBar', TabBarIOS);
|
const RCTTabBar = requireNativeComponent('RCTTabBar', TabBarIOS);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -18,9 +19,7 @@ class DummyTab extends React.Component {
|
||||||
return <View />;
|
return <View />;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={[this.props.style, styles.tab]}>
|
<View style={[this.props.style, styles.tab]}>{this.props.children}</View>
|
||||||
{this.props.children}
|
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +34,7 @@ const styles = StyleSheet.create({
|
||||||
left: 0,
|
left: 0,
|
||||||
borderColor: 'red',
|
borderColor: 'red',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DummyTab;
|
module.exports = DummyTab;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @noflow
|
* @noflow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ColorPropType = require('ColorPropType');
|
const ColorPropType = require('ColorPropType');
|
||||||
|
@ -26,10 +28,7 @@ class TabBarItemIOS extends React.Component {
|
||||||
/**
|
/**
|
||||||
* Little red bubble that sits at the top right of the icon.
|
* Little red bubble that sits at the top right of the icon.
|
||||||
*/
|
*/
|
||||||
badge: PropTypes.oneOfType([
|
badge: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
PropTypes.string,
|
|
||||||
PropTypes.number,
|
|
||||||
]),
|
|
||||||
/**
|
/**
|
||||||
* Background color for the badge. Available since iOS 10.
|
* Background color for the badge. Available since iOS 10.
|
||||||
*/
|
*/
|
||||||
|
@ -105,7 +104,7 @@ class TabBarItemIOS extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps: { selected?: boolean }) {
|
UNSAFE_componentWillReceiveProps(nextProps: {selected?: boolean}) {
|
||||||
if (this.state.hasBeenSelected || nextProps.selected) {
|
if (this.state.hasBeenSelected || nextProps.selected) {
|
||||||
this.setState({hasBeenSelected: true});
|
this.setState({hasBeenSelected: true});
|
||||||
}
|
}
|
||||||
|
@ -117,18 +116,17 @@ class TabBarItemIOS extends React.Component {
|
||||||
// if the tab has already been shown once, always continue to show it so we
|
// if the tab has already been shown once, always continue to show it so we
|
||||||
// preserve state between tab transitions
|
// preserve state between tab transitions
|
||||||
if (this.state.hasBeenSelected) {
|
if (this.state.hasBeenSelected) {
|
||||||
var tabContents =
|
var tabContents = (
|
||||||
<StaticContainer shouldUpdate={this.props.selected}>
|
<StaticContainer shouldUpdate={this.props.selected}>
|
||||||
{children}
|
{children}
|
||||||
</StaticContainer>;
|
</StaticContainer>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
var tabContents = <View />;
|
var tabContents = <View />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RCTTabBarItem
|
<RCTTabBarItem {...props} style={[styles.tab, style]}>
|
||||||
{...props}
|
|
||||||
style={[styles.tab, style]}>
|
|
||||||
{tabContents}
|
{tabContents}
|
||||||
</RCTTabBarItem>
|
</RCTTabBarItem>
|
||||||
);
|
);
|
||||||
|
@ -142,7 +140,7 @@ const styles = StyleSheet.create({
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const RCTTabBarItem = requireNativeComponent('RCTTabBarItem', TabBarItemIOS);
|
const RCTTabBarItem = requireNativeComponent('RCTTabBarItem', TabBarItemIOS);
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
* @flow
|
|
||||||
*
|
*
|
||||||
* This class is responsible for coordinating the "focused"
|
* This class is responsible for coordinating the "focused"
|
||||||
* state for TextInputs. All calls relating to the keyboard
|
* state for TextInputs. All calls relating to the keyboard
|
||||||
* should be funneled through here
|
* should be funneled through here
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
|
@ -18,7 +21,7 @@ const UIManager = require('UIManager');
|
||||||
const inputs = new Set();
|
const inputs = new Set();
|
||||||
|
|
||||||
const TextInputState = {
|
const TextInputState = {
|
||||||
/**
|
/**
|
||||||
* Internal state
|
* Internal state
|
||||||
*/
|
*/
|
||||||
_currentlyFocusedID: (null: ?number),
|
_currentlyFocusedID: (null: ?number),
|
||||||
|
@ -45,7 +48,7 @@ const TextInputState = {
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
textFieldID,
|
textFieldID,
|
||||||
UIManager.AndroidTextInput.Commands.focusTextInput,
|
UIManager.AndroidTextInput.Commands.focusTextInput,
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +68,7 @@ const TextInputState = {
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
textFieldID,
|
textFieldID,
|
||||||
UIManager.AndroidTextInput.Commands.blurTextInput,
|
UIManager.AndroidTextInput.Commands.blurTextInput,
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const TimePickerModule = require('NativeModules').TimePickerAndroid;
|
const TimePickerModule = require('NativeModules').TimePickerAndroid;
|
||||||
|
@ -31,7 +33,6 @@ const TimePickerModule = require('NativeModules').TimePickerAndroid;
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class TimePickerAndroid {
|
class TimePickerAndroid {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the standard Android time picker dialog.
|
* Opens the standard Android time picker dialog.
|
||||||
*
|
*
|
||||||
|
@ -58,11 +59,15 @@ class TimePickerAndroid {
|
||||||
/**
|
/**
|
||||||
* A time has been selected.
|
* A time has been selected.
|
||||||
*/
|
*/
|
||||||
static get timeSetAction() { return 'timeSetAction'; }
|
static get timeSetAction() {
|
||||||
|
return 'timeSetAction';
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* The dialog has been dismissed.
|
* The dialog has been dismissed.
|
||||||
*/
|
*/
|
||||||
static get dismissedAction() { return 'dismissedAction'; }
|
static get dismissedAction() {
|
||||||
|
return 'dismissedAction';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TimePickerAndroid;
|
module.exports = TimePickerAndroid;
|
||||||
|
|
|
@ -4,14 +4,16 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const TimePickerAndroid = {
|
const TimePickerAndroid = {
|
||||||
async open(options: Object): Promise<Object> {
|
async open(options: Object): Promise<Object> {
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
message: 'TimePickerAndroid is not supported on this platform.'
|
message: 'TimePickerAndroid is not supported on this platform.',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -33,7 +34,6 @@ const RCTToastAndroid = require('NativeModules').ToastAndroid;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const ToastAndroid = {
|
const ToastAndroid = {
|
||||||
|
|
||||||
// Toast duration constants
|
// Toast duration constants
|
||||||
SHORT: RCTToastAndroid.SHORT,
|
SHORT: RCTToastAndroid.SHORT,
|
||||||
LONG: RCTToastAndroid.LONG,
|
LONG: RCTToastAndroid.LONG,
|
||||||
|
@ -43,14 +43,11 @@ const ToastAndroid = {
|
||||||
BOTTOM: RCTToastAndroid.BOTTOM,
|
BOTTOM: RCTToastAndroid.BOTTOM,
|
||||||
CENTER: RCTToastAndroid.CENTER,
|
CENTER: RCTToastAndroid.CENTER,
|
||||||
|
|
||||||
show: function (
|
show: function(message: string, duration: number): void {
|
||||||
message: string,
|
|
||||||
duration: number
|
|
||||||
): void {
|
|
||||||
RCTToastAndroid.show(message, duration);
|
RCTToastAndroid.show(message, duration);
|
||||||
},
|
},
|
||||||
|
|
||||||
showWithGravity: function (
|
showWithGravity: function(
|
||||||
message: string,
|
message: string,
|
||||||
duration: number,
|
duration: number,
|
||||||
gravity: number,
|
gravity: number,
|
||||||
|
@ -58,14 +55,20 @@ const ToastAndroid = {
|
||||||
RCTToastAndroid.showWithGravity(message, duration, gravity);
|
RCTToastAndroid.showWithGravity(message, duration, gravity);
|
||||||
},
|
},
|
||||||
|
|
||||||
showWithGravityAndOffset: function (
|
showWithGravityAndOffset: function(
|
||||||
message: string,
|
message: string,
|
||||||
duration: number,
|
duration: number,
|
||||||
gravity: number,
|
gravity: number,
|
||||||
xOffset: number,
|
xOffset: number,
|
||||||
yOffset: number,
|
yOffset: number,
|
||||||
): void {
|
): void {
|
||||||
RCTToastAndroid.showWithGravityAndOffset(message, duration, gravity, xOffset, yOffset);
|
RCTToastAndroid.showWithGravityAndOffset(
|
||||||
|
message,
|
||||||
|
duration,
|
||||||
|
gravity,
|
||||||
|
xOffset,
|
||||||
|
yOffset,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,21 +4,18 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @noflow
|
* @noflow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const warning = require('fbjs/lib/warning');
|
const warning = require('fbjs/lib/warning');
|
||||||
|
|
||||||
const ToastAndroid = {
|
const ToastAndroid = {
|
||||||
|
show: function(message: string, duration: number): void {
|
||||||
show: function (
|
|
||||||
message: string,
|
|
||||||
duration: number
|
|
||||||
): void {
|
|
||||||
warning(false, 'ToastAndroid is not supported on this platform.');
|
warning(false, 'ToastAndroid is not supported on this platform.');
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = ToastAndroid;
|
module.exports = ToastAndroid;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -82,12 +83,14 @@ const ToolbarAndroid = createReactClass({
|
||||||
* `ifRoom` or `never`
|
* `ifRoom` or `never`
|
||||||
* * `showWithText`: boolean, whether to show text alongside the icon or not
|
* * `showWithText`: boolean, whether to show text alongside the icon or not
|
||||||
*/
|
*/
|
||||||
actions: PropTypes.arrayOf(PropTypes.shape({
|
actions: PropTypes.arrayOf(
|
||||||
title: PropTypes.string.isRequired,
|
PropTypes.shape({
|
||||||
icon: optionalImageSource,
|
title: PropTypes.string.isRequired,
|
||||||
show: PropTypes.oneOf(['always', 'ifRoom', 'never']),
|
icon: optionalImageSource,
|
||||||
showWithText: PropTypes.bool
|
show: PropTypes.oneOf(['always', 'ifRoom', 'never']),
|
||||||
})),
|
showWithText: PropTypes.bool,
|
||||||
|
}),
|
||||||
|
),
|
||||||
/**
|
/**
|
||||||
* Sets the toolbar logo.
|
* Sets the toolbar logo.
|
||||||
*/
|
*/
|
||||||
|
@ -183,7 +186,8 @@ const ToolbarAndroid = createReactClass({
|
||||||
action.icon = resolveAssetSource(action.icon);
|
action.icon = resolveAssetSource(action.icon);
|
||||||
}
|
}
|
||||||
if (action.show) {
|
if (action.show) {
|
||||||
action.show = UIManager.ToolbarAndroid.Constants.ShowAsAction[action.show];
|
action.show =
|
||||||
|
UIManager.ToolbarAndroid.Constants.ShowAsAction[action.show];
|
||||||
}
|
}
|
||||||
nativeActions.push(action);
|
nativeActions.push(action);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +210,7 @@ const ToolbarAndroid = createReactClass({
|
||||||
const NativeToolbar = requireNativeComponent('ToolbarAndroid', ToolbarAndroid, {
|
const NativeToolbar = requireNativeComponent('ToolbarAndroid', ToolbarAndroid, {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
nativeActions: true,
|
nativeActions: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = ToolbarAndroid;
|
module.exports = ToolbarAndroid;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('UnimplementedView');
|
module.exports = require('UnimplementedView');
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -36,7 +37,7 @@ BoundingDimensions.prototype.destructor = function() {
|
||||||
BoundingDimensions.getPooledFromElement = function(element) {
|
BoundingDimensions.getPooledFromElement = function(element) {
|
||||||
return BoundingDimensions.getPooled(
|
return BoundingDimensions.getPooled(
|
||||||
element.offsetWidth,
|
element.offsetWidth,
|
||||||
element.offsetHeight
|
element.offsetHeight,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -110,14 +111,14 @@ const normalizeColor = require('normalizeColor');
|
||||||
* Touchable states.
|
* Touchable states.
|
||||||
*/
|
*/
|
||||||
const States = keyMirror({
|
const States = keyMirror({
|
||||||
NOT_RESPONDER: null, // Not the responder
|
NOT_RESPONDER: null, // Not the responder
|
||||||
RESPONDER_INACTIVE_PRESS_IN: null, // Responder, inactive, in the `PressRect`
|
RESPONDER_INACTIVE_PRESS_IN: null, // Responder, inactive, in the `PressRect`
|
||||||
RESPONDER_INACTIVE_PRESS_OUT: null, // Responder, inactive, out of `PressRect`
|
RESPONDER_INACTIVE_PRESS_OUT: null, // Responder, inactive, out of `PressRect`
|
||||||
RESPONDER_ACTIVE_PRESS_IN: null, // Responder, active, in the `PressRect`
|
RESPONDER_ACTIVE_PRESS_IN: null, // Responder, active, in the `PressRect`
|
||||||
RESPONDER_ACTIVE_PRESS_OUT: null, // Responder, active, out of `PressRect`
|
RESPONDER_ACTIVE_PRESS_OUT: null, // Responder, active, out of `PressRect`
|
||||||
RESPONDER_ACTIVE_LONG_PRESS_IN: null, // Responder, active, in the `PressRect`, after long press threshold
|
RESPONDER_ACTIVE_LONG_PRESS_IN: null, // Responder, active, in the `PressRect`, after long press threshold
|
||||||
RESPONDER_ACTIVE_LONG_PRESS_OUT: null, // Responder, active, out of `PressRect`, after long press threshold
|
RESPONDER_ACTIVE_LONG_PRESS_OUT: null, // Responder, active, out of `PressRect`, after long press threshold
|
||||||
ERROR: null
|
ERROR: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,7 +126,7 @@ const States = keyMirror({
|
||||||
*/
|
*/
|
||||||
const IsActive = {
|
const IsActive = {
|
||||||
RESPONDER_ACTIVE_PRESS_OUT: true,
|
RESPONDER_ACTIVE_PRESS_OUT: true,
|
||||||
RESPONDER_ACTIVE_PRESS_IN: true
|
RESPONDER_ACTIVE_PRESS_IN: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -230,7 +231,7 @@ const Transitions = {
|
||||||
ENTER_PRESS_RECT: States.NOT_RESPONDER,
|
ENTER_PRESS_RECT: States.NOT_RESPONDER,
|
||||||
LEAVE_PRESS_RECT: States.NOT_RESPONDER,
|
LEAVE_PRESS_RECT: States.NOT_RESPONDER,
|
||||||
LONG_PRESS_DETECTED: States.NOT_RESPONDER,
|
LONG_PRESS_DETECTED: States.NOT_RESPONDER,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// ==== Typical Constants for integrating into UI components ====
|
// ==== Typical Constants for integrating into UI components ====
|
||||||
|
@ -324,11 +325,15 @@ const TouchableMixin = {
|
||||||
evt.dispatchConfig = {};
|
evt.dispatchConfig = {};
|
||||||
if (myTag === evt.tag) {
|
if (myTag === evt.tag) {
|
||||||
if (evt.eventType === 'focus') {
|
if (evt.eventType === 'focus') {
|
||||||
cmp.touchableHandleActivePressIn && cmp.touchableHandleActivePressIn(evt);
|
cmp.touchableHandleActivePressIn &&
|
||||||
|
cmp.touchableHandleActivePressIn(evt);
|
||||||
} else if (evt.eventType === 'blur') {
|
} else if (evt.eventType === 'blur') {
|
||||||
cmp.touchableHandleActivePressOut && cmp.touchableHandleActivePressOut(evt);
|
cmp.touchableHandleActivePressOut &&
|
||||||
|
cmp.touchableHandleActivePressOut(evt);
|
||||||
} else if (evt.eventType === 'select') {
|
} else if (evt.eventType === 'select') {
|
||||||
cmp.touchableHandlePress && !cmp.props.disabled && cmp.touchableHandlePress(evt);
|
cmp.touchableHandlePress &&
|
||||||
|
!cmp.props.disabled &&
|
||||||
|
cmp.touchableHandlePress(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -356,7 +361,7 @@ const TouchableMixin = {
|
||||||
*/
|
*/
|
||||||
touchableGetInitialState: function() {
|
touchableGetInitialState: function() {
|
||||||
return {
|
return {
|
||||||
touchable: {touchState: undefined, responderID: null}
|
touchable: {touchState: undefined, responderID: null},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -378,7 +383,7 @@ const TouchableMixin = {
|
||||||
/**
|
/**
|
||||||
* Return true to cancel press on long press.
|
* Return true to cancel press on long press.
|
||||||
*/
|
*/
|
||||||
touchableLongPressCancelsPress: function () {
|
touchableLongPressCancelsPress: function() {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -401,25 +406,27 @@ const TouchableMixin = {
|
||||||
this.state.touchable.responderID = dispatchID;
|
this.state.touchable.responderID = dispatchID;
|
||||||
this._receiveSignal(Signals.RESPONDER_GRANT, e);
|
this._receiveSignal(Signals.RESPONDER_GRANT, e);
|
||||||
let delayMS =
|
let delayMS =
|
||||||
this.touchableGetHighlightDelayMS !== undefined ?
|
this.touchableGetHighlightDelayMS !== undefined
|
||||||
Math.max(this.touchableGetHighlightDelayMS(), 0) : HIGHLIGHT_DELAY_MS;
|
? Math.max(this.touchableGetHighlightDelayMS(), 0)
|
||||||
|
: HIGHLIGHT_DELAY_MS;
|
||||||
delayMS = isNaN(delayMS) ? HIGHLIGHT_DELAY_MS : delayMS;
|
delayMS = isNaN(delayMS) ? HIGHLIGHT_DELAY_MS : delayMS;
|
||||||
if (delayMS !== 0) {
|
if (delayMS !== 0) {
|
||||||
this.touchableDelayTimeout = setTimeout(
|
this.touchableDelayTimeout = setTimeout(
|
||||||
this._handleDelay.bind(this, e),
|
this._handleDelay.bind(this, e),
|
||||||
delayMS
|
delayMS,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this._handleDelay(e);
|
this._handleDelay(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
let longDelayMS =
|
let longDelayMS =
|
||||||
this.touchableGetLongPressDelayMS !== undefined ?
|
this.touchableGetLongPressDelayMS !== undefined
|
||||||
Math.max(this.touchableGetLongPressDelayMS(), 10) : LONG_PRESS_DELAY_MS;
|
? Math.max(this.touchableGetLongPressDelayMS(), 10)
|
||||||
|
: LONG_PRESS_DELAY_MS;
|
||||||
longDelayMS = isNaN(longDelayMS) ? LONG_PRESS_DELAY_MS : longDelayMS;
|
longDelayMS = isNaN(longDelayMS) ? LONG_PRESS_DELAY_MS : longDelayMS;
|
||||||
this.longPressDelayTimeout = setTimeout(
|
this.longPressDelayTimeout = setTimeout(
|
||||||
this._handleLongDelay.bind(this, e),
|
this._handleLongDelay.bind(this, e),
|
||||||
longDelayMS + delayMS
|
longDelayMS + delayMS,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -443,7 +450,9 @@ const TouchableMixin = {
|
||||||
touchableHandleResponderMove: function(e) {
|
touchableHandleResponderMove: function(e) {
|
||||||
// Not enough time elapsed yet, wait for highlight -
|
// Not enough time elapsed yet, wait for highlight -
|
||||||
// this is just a perf optimization.
|
// this is just a perf optimization.
|
||||||
if (this.state.touchable.touchState === States.RESPONDER_INACTIVE_PRESS_IN) {
|
if (
|
||||||
|
this.state.touchable.touchState === States.RESPONDER_INACTIVE_PRESS_IN
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,21 +463,23 @@ const TouchableMixin = {
|
||||||
|
|
||||||
const positionOnActivate = this.state.touchable.positionOnActivate;
|
const positionOnActivate = this.state.touchable.positionOnActivate;
|
||||||
const dimensionsOnActivate = this.state.touchable.dimensionsOnActivate;
|
const dimensionsOnActivate = this.state.touchable.dimensionsOnActivate;
|
||||||
const pressRectOffset = this.touchableGetPressRectOffset ?
|
const pressRectOffset = this.touchableGetPressRectOffset
|
||||||
this.touchableGetPressRectOffset() : {
|
? this.touchableGetPressRectOffset()
|
||||||
left: PRESS_EXPAND_PX,
|
: {
|
||||||
right: PRESS_EXPAND_PX,
|
left: PRESS_EXPAND_PX,
|
||||||
top: PRESS_EXPAND_PX,
|
right: PRESS_EXPAND_PX,
|
||||||
bottom: PRESS_EXPAND_PX
|
top: PRESS_EXPAND_PX,
|
||||||
};
|
bottom: PRESS_EXPAND_PX,
|
||||||
|
};
|
||||||
|
|
||||||
let pressExpandLeft = pressRectOffset.left;
|
let pressExpandLeft = pressRectOffset.left;
|
||||||
let pressExpandTop = pressRectOffset.top;
|
let pressExpandTop = pressRectOffset.top;
|
||||||
let pressExpandRight = pressRectOffset.right;
|
let pressExpandRight = pressRectOffset.right;
|
||||||
let pressExpandBottom = pressRectOffset.bottom;
|
let pressExpandBottom = pressRectOffset.bottom;
|
||||||
|
|
||||||
const hitSlop = this.touchableGetHitSlop ?
|
const hitSlop = this.touchableGetHitSlop
|
||||||
this.touchableGetHitSlop() : null;
|
? this.touchableGetHitSlop()
|
||||||
|
: null;
|
||||||
|
|
||||||
if (hitSlop) {
|
if (hitSlop) {
|
||||||
pressExpandLeft += hitSlop.left;
|
pressExpandLeft += hitSlop.left;
|
||||||
|
@ -482,21 +493,26 @@ const TouchableMixin = {
|
||||||
const pageY = touch && touch.pageY;
|
const pageY = touch && touch.pageY;
|
||||||
|
|
||||||
if (this.pressInLocation) {
|
if (this.pressInLocation) {
|
||||||
const movedDistance = this._getDistanceBetweenPoints(pageX, pageY, this.pressInLocation.pageX, this.pressInLocation.pageY);
|
const movedDistance = this._getDistanceBetweenPoints(
|
||||||
|
pageX,
|
||||||
|
pageY,
|
||||||
|
this.pressInLocation.pageX,
|
||||||
|
this.pressInLocation.pageY,
|
||||||
|
);
|
||||||
if (movedDistance > LONG_PRESS_ALLOWED_MOVEMENT) {
|
if (movedDistance > LONG_PRESS_ALLOWED_MOVEMENT) {
|
||||||
this._cancelLongPressDelayTimeout();
|
this._cancelLongPressDelayTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isTouchWithinActive =
|
const isTouchWithinActive =
|
||||||
pageX > positionOnActivate.left - pressExpandLeft &&
|
pageX > positionOnActivate.left - pressExpandLeft &&
|
||||||
pageY > positionOnActivate.top - pressExpandTop &&
|
pageY > positionOnActivate.top - pressExpandTop &&
|
||||||
pageX <
|
pageX <
|
||||||
positionOnActivate.left +
|
positionOnActivate.left +
|
||||||
dimensionsOnActivate.width +
|
dimensionsOnActivate.width +
|
||||||
pressExpandRight &&
|
pressExpandRight &&
|
||||||
pageY <
|
pageY <
|
||||||
positionOnActivate.top +
|
positionOnActivate.top +
|
||||||
dimensionsOnActivate.height +
|
dimensionsOnActivate.height +
|
||||||
pressExpandBottom;
|
pressExpandBottom;
|
||||||
if (isTouchWithinActive) {
|
if (isTouchWithinActive) {
|
||||||
|
@ -574,8 +590,6 @@ const TouchableMixin = {
|
||||||
* touchableGetPressRectOffset: function
|
* touchableGetPressRectOffset: function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ==== Internal Logic ====
|
// ==== Internal Logic ====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -608,8 +622,14 @@ const TouchableMixin = {
|
||||||
Position.release(this.state.touchable.positionOnActivate);
|
Position.release(this.state.touchable.positionOnActivate);
|
||||||
this.state.touchable.dimensionsOnActivate &&
|
this.state.touchable.dimensionsOnActivate &&
|
||||||
BoundingDimensions.release(this.state.touchable.dimensionsOnActivate);
|
BoundingDimensions.release(this.state.touchable.dimensionsOnActivate);
|
||||||
this.state.touchable.positionOnActivate = Position.getPooled(globalX, globalY);
|
this.state.touchable.positionOnActivate = Position.getPooled(
|
||||||
this.state.touchable.dimensionsOnActivate = BoundingDimensions.getPooled(w, h);
|
globalX,
|
||||||
|
globalY,
|
||||||
|
);
|
||||||
|
this.state.touchable.dimensionsOnActivate = BoundingDimensions.getPooled(
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleDelay: function(e) {
|
_handleDelay: function(e) {
|
||||||
|
@ -620,11 +640,18 @@ const TouchableMixin = {
|
||||||
_handleLongDelay: function(e) {
|
_handleLongDelay: function(e) {
|
||||||
this.longPressDelayTimeout = null;
|
this.longPressDelayTimeout = null;
|
||||||
const curState = this.state.touchable.touchState;
|
const curState = this.state.touchable.touchState;
|
||||||
if (curState !== States.RESPONDER_ACTIVE_PRESS_IN &&
|
if (
|
||||||
curState !== States.RESPONDER_ACTIVE_LONG_PRESS_IN) {
|
curState !== States.RESPONDER_ACTIVE_PRESS_IN &&
|
||||||
console.error('Attempted to transition from state `' + curState + '` to `' +
|
curState !== States.RESPONDER_ACTIVE_LONG_PRESS_IN
|
||||||
States.RESPONDER_ACTIVE_LONG_PRESS_IN + '`, which is not supported. This is ' +
|
) {
|
||||||
'most likely due to `Touchable.longPressDelayTimeout` not being cancelled.');
|
console.error(
|
||||||
|
'Attempted to transition from state `' +
|
||||||
|
curState +
|
||||||
|
'` to `' +
|
||||||
|
States.RESPONDER_ACTIVE_LONG_PRESS_IN +
|
||||||
|
'`, which is not supported. This is ' +
|
||||||
|
'most likely due to `Touchable.longPressDelayTimeout` not being cancelled.',
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this._receiveSignal(Signals.LONG_PRESS_DETECTED, e);
|
this._receiveSignal(Signals.LONG_PRESS_DETECTED, e);
|
||||||
}
|
}
|
||||||
|
@ -647,14 +674,24 @@ const TouchableMixin = {
|
||||||
}
|
}
|
||||||
if (!nextState) {
|
if (!nextState) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Unrecognized signal `' + signal + '` or state `' + curState +
|
'Unrecognized signal `' +
|
||||||
'` for Touchable responder `' + responderID + '`'
|
signal +
|
||||||
|
'` or state `' +
|
||||||
|
curState +
|
||||||
|
'` for Touchable responder `' +
|
||||||
|
responderID +
|
||||||
|
'`',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (nextState === States.ERROR) {
|
if (nextState === States.ERROR) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Touchable cannot transition from `' + curState + '` to `' + signal +
|
'Touchable cannot transition from `' +
|
||||||
'` for responder `' + responderID + '`'
|
curState +
|
||||||
|
'` to `' +
|
||||||
|
signal +
|
||||||
|
'` for responder `' +
|
||||||
|
responderID +
|
||||||
|
'`',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (curState !== nextState) {
|
if (curState !== nextState) {
|
||||||
|
@ -663,14 +700,16 @@ const TouchableMixin = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_cancelLongPressDelayTimeout: function () {
|
_cancelLongPressDelayTimeout: function() {
|
||||||
this.longPressDelayTimeout && clearTimeout(this.longPressDelayTimeout);
|
this.longPressDelayTimeout && clearTimeout(this.longPressDelayTimeout);
|
||||||
this.longPressDelayTimeout = null;
|
this.longPressDelayTimeout = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
_isHighlight: function (state) {
|
_isHighlight: function(state) {
|
||||||
return state === States.RESPONDER_ACTIVE_PRESS_IN ||
|
return (
|
||||||
state === States.RESPONDER_ACTIVE_LONG_PRESS_IN;
|
state === States.RESPONDER_ACTIVE_PRESS_IN ||
|
||||||
|
state === States.RESPONDER_ACTIVE_LONG_PRESS_IN
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
_savePressInLocation: function(e) {
|
_savePressInLocation: function(e) {
|
||||||
|
@ -682,7 +721,7 @@ const TouchableMixin = {
|
||||||
this.pressInLocation = {pageX, pageY, locationX, locationY};
|
this.pressInLocation = {pageX, pageY, locationX, locationY};
|
||||||
},
|
},
|
||||||
|
|
||||||
_getDistanceBetweenPoints: function (aX, aY, bX, bY) {
|
_getDistanceBetweenPoints: function(aX, aY, bX, bY) {
|
||||||
const deltaX = aX - bX;
|
const deltaX = aX - bX;
|
||||||
const deltaY = aY - bY;
|
const deltaY = aY - bY;
|
||||||
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||||
|
@ -728,12 +767,11 @@ const TouchableMixin = {
|
||||||
if (IsPressingIn[curState] && signal === Signals.RESPONDER_RELEASE) {
|
if (IsPressingIn[curState] && signal === Signals.RESPONDER_RELEASE) {
|
||||||
const hasLongPressHandler = !!this.props.onLongPress;
|
const hasLongPressHandler = !!this.props.onLongPress;
|
||||||
const pressIsLongButStillCallOnPress =
|
const pressIsLongButStillCallOnPress =
|
||||||
IsLongPressingIn[curState] && ( // We *are* long pressing..
|
IsLongPressingIn[curState] && // We *are* long pressing.. // But either has no long handler
|
||||||
(// But either has no long handler
|
(!hasLongPressHandler || !this.touchableLongPressCancelsPress()); // or we're told to ignore it.
|
||||||
!hasLongPressHandler || !this.touchableLongPressCancelsPress()) // or we're told to ignore it.
|
|
||||||
);
|
|
||||||
|
|
||||||
const shouldInvokePress = !IsLongPressingIn[curState] || pressIsLongButStillCallOnPress;
|
const shouldInvokePress =
|
||||||
|
!IsLongPressingIn[curState] || pressIsLongButStillCallOnPress;
|
||||||
if (shouldInvokePress && this.touchableHandlePress) {
|
if (shouldInvokePress && this.touchableHandlePress) {
|
||||||
if (!newIsHighlight && !curIsHighlight) {
|
if (!newIsHighlight && !curIsHighlight) {
|
||||||
// we never highlighted because of delay, but we should highlight now
|
// we never highlighted because of delay, but we should highlight now
|
||||||
|
@ -750,11 +788,11 @@ const TouchableMixin = {
|
||||||
this.touchableDelayTimeout && clearTimeout(this.touchableDelayTimeout);
|
this.touchableDelayTimeout && clearTimeout(this.touchableDelayTimeout);
|
||||||
this.touchableDelayTimeout = null;
|
this.touchableDelayTimeout = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
_playTouchSound: function() {
|
_playTouchSound: function() {
|
||||||
UIManager.playTouchSound();
|
UIManager.playTouchSound();
|
||||||
},
|
},
|
||||||
|
|
||||||
_startHighlight: function(e) {
|
_startHighlight: function(e) {
|
||||||
this._savePressInLocation(e);
|
this._savePressInLocation(e);
|
||||||
this.touchableHandleActivePressIn && this.touchableHandleActivePressIn(e);
|
this.touchableHandleActivePressIn && this.touchableHandleActivePressIn(e);
|
||||||
|
@ -762,7 +800,10 @@ const TouchableMixin = {
|
||||||
|
|
||||||
_endHighlight: function(e) {
|
_endHighlight: function(e) {
|
||||||
if (this.touchableHandleActivePressOut) {
|
if (this.touchableHandleActivePressOut) {
|
||||||
if (this.touchableGetPressOutDelayMS && this.touchableGetPressOutDelayMS()) {
|
if (
|
||||||
|
this.touchableGetPressOutDelayMS &&
|
||||||
|
this.touchableGetPressOutDelayMS()
|
||||||
|
) {
|
||||||
this.pressOutDelayTimeout = setTimeout(() => {
|
this.pressOutDelayTimeout = setTimeout(() => {
|
||||||
this.touchableHandleActivePressOut(e);
|
this.touchableHandleActivePressOut(e);
|
||||||
}, this.touchableGetPressOutDelayMS());
|
}, this.touchableGetPressOutDelayMS());
|
||||||
|
@ -771,7 +812,6 @@ const TouchableMixin = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Touchable = {
|
const Touchable = {
|
||||||
|
@ -785,14 +825,17 @@ const Touchable = {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!__DEV__) {
|
if (!__DEV__) {
|
||||||
throw Error('Touchable.TOUCH_TARGET_DEBUG should not be enabled in prod!');
|
throw Error(
|
||||||
|
'Touchable.TOUCH_TARGET_DEBUG should not be enabled in prod!',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const debugHitSlopStyle = {};
|
const debugHitSlopStyle = {};
|
||||||
hitSlop = hitSlop || {top: 0, bottom: 0, left: 0, right: 0};
|
hitSlop = hitSlop || {top: 0, bottom: 0, left: 0, right: 0};
|
||||||
for (const key in hitSlop) {
|
for (const key in hitSlop) {
|
||||||
debugHitSlopStyle[key] = -hitSlop[key];
|
debugHitSlopStyle[key] = -hitSlop[key];
|
||||||
}
|
}
|
||||||
const hexColor = '#' + ('00000000' + normalizeColor(color).toString(16)).substr(-8);
|
const hexColor =
|
||||||
|
'#' + ('00000000' + normalizeColor(color).toString(16)).substr(-8);
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
|
@ -802,11 +845,11 @@ const Touchable = {
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderStyle: 'dashed',
|
borderStyle: 'dashed',
|
||||||
backgroundColor: hexColor.slice(0, -2) + '0F', // Less opaque
|
backgroundColor: hexColor.slice(0, -2) + '0F', // Less opaque
|
||||||
...debugHitSlopStyle
|
...debugHitSlopStyle,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Touchable;
|
module.exports = Touchable;
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
|
@ -112,7 +114,10 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
* Available on android API level 21+.
|
* Available on android API level 21+.
|
||||||
*/
|
*/
|
||||||
SelectableBackgroundBorderless: function() {
|
SelectableBackgroundBorderless: function() {
|
||||||
return {type: 'ThemeAttrAndroid', attribute: 'selectableItemBackgroundBorderless'};
|
return {
|
||||||
|
type: 'ThemeAttrAndroid',
|
||||||
|
attribute: 'selectableItemBackgroundBorderless',
|
||||||
|
};
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Creates an object that represents ripple drawable with specified color (as a
|
* Creates an object that represents ripple drawable with specified color (as a
|
||||||
|
@ -125,12 +130,16 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
* @param borderless If the ripple can render outside it's bounds
|
* @param borderless If the ripple can render outside it's bounds
|
||||||
*/
|
*/
|
||||||
Ripple: function(color: string, borderless: boolean) {
|
Ripple: function(color: string, borderless: boolean) {
|
||||||
return {type: 'RippleAndroid', color: processColor(color), borderless: borderless};
|
return {
|
||||||
|
type: 'RippleAndroid',
|
||||||
|
color: processColor(color),
|
||||||
|
borderless: borderless,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
canUseNativeForeground: function() {
|
canUseNativeForeground: function() {
|
||||||
return Platform.OS === 'android' && Platform.Version >= 23;
|
return Platform.OS === 'android' && Platform.Version >= 23;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [Touchable.Mixin],
|
mixins: [Touchable.Mixin],
|
||||||
|
@ -161,7 +170,10 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
this.props.onPressIn && this.props.onPressIn(e);
|
this.props.onPressIn && this.props.onPressIn(e);
|
||||||
this._dispatchPressedStateChange(true);
|
this._dispatchPressedStateChange(true);
|
||||||
if (this.pressInLocation) {
|
if (this.pressInLocation) {
|
||||||
this._dispatchHotspotUpdate(this.pressInLocation.locationX, this.pressInLocation.locationY);
|
this._dispatchHotspotUpdate(
|
||||||
|
this.pressInLocation.locationX,
|
||||||
|
this.pressInLocation.locationY,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -201,14 +213,17 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
|
|
||||||
_handleResponderMove: function(e) {
|
_handleResponderMove: function(e) {
|
||||||
this.touchableHandleResponderMove(e);
|
this.touchableHandleResponderMove(e);
|
||||||
this._dispatchHotspotUpdate(e.nativeEvent.locationX, e.nativeEvent.locationY);
|
this._dispatchHotspotUpdate(
|
||||||
|
e.nativeEvent.locationX,
|
||||||
|
e.nativeEvent.locationY,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
_dispatchHotspotUpdate: function(destX, destY) {
|
_dispatchHotspotUpdate: function(destX, destY) {
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
ReactNative.findNodeHandle(this),
|
ReactNative.findNodeHandle(this),
|
||||||
UIManager.RCTView.Commands.hotspotUpdate,
|
UIManager.RCTView.Commands.hotspotUpdate,
|
||||||
[destX || 0, destY || 0]
|
[destX || 0, destY || 0],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -216,7 +231,7 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
UIManager.dispatchViewManagerCommand(
|
UIManager.dispatchViewManagerCommand(
|
||||||
ReactNative.findNodeHandle(this),
|
ReactNative.findNodeHandle(this),
|
||||||
UIManager.RCTView.Commands.setPressed,
|
UIManager.RCTView.Commands.setPressed,
|
||||||
[pressed]
|
[pressed],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -227,16 +242,26 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
if (!Array.isArray(children)) {
|
if (!Array.isArray(children)) {
|
||||||
children = [children];
|
children = [children];
|
||||||
}
|
}
|
||||||
children.push(Touchable.renderDebugView({color: 'brown', hitSlop: this.props.hitSlop}));
|
children.push(
|
||||||
|
Touchable.renderDebugView({
|
||||||
|
color: 'brown',
|
||||||
|
hitSlop: this.props.hitSlop,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (this.props.useForeground && !TouchableNativeFeedback.canUseNativeForeground()) {
|
if (
|
||||||
|
this.props.useForeground &&
|
||||||
|
!TouchableNativeFeedback.canUseNativeForeground()
|
||||||
|
) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'Requested foreground ripple, but it is not available on this version of Android. ' +
|
'Requested foreground ripple, but it is not available on this version of Android. ' +
|
||||||
'Consider calling TouchableNativeFeedback.canUseNativeForeground() and using a different ' +
|
'Consider calling TouchableNativeFeedback.canUseNativeForeground() and using a different ' +
|
||||||
'Touchable if the result is false.');
|
'Touchable if the result is false.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const drawableProp =
|
const drawableProp =
|
||||||
this.props.useForeground && TouchableNativeFeedback.canUseNativeForeground()
|
this.props.useForeground &&
|
||||||
|
TouchableNativeFeedback.canUseNativeForeground()
|
||||||
? 'nativeForegroundAndroid'
|
? 'nativeForegroundAndroid'
|
||||||
: 'nativeBackgroundAndroid';
|
: 'nativeBackgroundAndroid';
|
||||||
const childProps = {
|
const childProps = {
|
||||||
|
@ -253,7 +278,8 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
isTVSelectable: true,
|
isTVSelectable: true,
|
||||||
hasTVPreferredFocus: this.props.hasTVPreferredFocus,
|
hasTVPreferredFocus: this.props.hasTVPreferredFocus,
|
||||||
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
|
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
|
||||||
onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest,
|
onResponderTerminationRequest: this
|
||||||
|
.touchableHandleResponderTerminationRequest,
|
||||||
onResponderGrant: this.touchableHandleResponderGrant,
|
onResponderGrant: this.touchableHandleResponderGrant,
|
||||||
onResponderMove: this._handleResponderMove,
|
onResponderMove: this._handleResponderMove,
|
||||||
onResponderRelease: this.touchableHandleResponderRelease,
|
onResponderRelease: this.touchableHandleResponderRelease,
|
||||||
|
@ -263,11 +289,8 @@ const TouchableNativeFeedback = createReactClass({
|
||||||
// We need to clone the actual element so that the ripple background drawable
|
// We need to clone the actual element so that the ripple background drawable
|
||||||
// can be applied directly to the background of this element rather than to
|
// can be applied directly to the background of this element rather than to
|
||||||
// a wrapper view as done in other Touchable*
|
// a wrapper view as done in other Touchable*
|
||||||
return React.cloneElement(
|
return React.cloneElement(child, childProps);
|
||||||
child,
|
},
|
||||||
childProps
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = TouchableNativeFeedback;
|
module.exports = TouchableNativeFeedback;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -22,7 +23,9 @@ class DummyTouchableNativeFeedback extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, this.props.style]}>
|
<View style={[styles.container, this.props.style]}>
|
||||||
<Text style={styles.info}>TouchableNativeFeedback is not supported on this platform!</Text>
|
<Text style={styles.info}>
|
||||||
|
TouchableNativeFeedback is not supported on this platform!
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +45,7 @@ const styles = StyleSheet.create({
|
||||||
info: {
|
info: {
|
||||||
color: '#333333',
|
color: '#333333',
|
||||||
margin: 20,
|
margin: 20,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = DummyTouchableNativeFeedback;
|
module.exports = DummyTouchableNativeFeedback;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @noflow
|
* @noflow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Note (avik): add @flow when Flow supports spread properties in propTypes
|
// Note (avik): add @flow when Flow supports spread properties in propTypes
|
||||||
|
@ -167,15 +169,12 @@ const TouchableOpacity = createReactClass({
|
||||||
* Animate the touchable to a new opacity.
|
* Animate the touchable to a new opacity.
|
||||||
*/
|
*/
|
||||||
setOpacityTo: function(value: number, duration: number) {
|
setOpacityTo: function(value: number, duration: number) {
|
||||||
Animated.timing(
|
Animated.timing(this.state.anim, {
|
||||||
this.state.anim,
|
toValue: value,
|
||||||
{
|
duration: duration,
|
||||||
toValue: value,
|
easing: Easing.inOut(Easing.quad),
|
||||||
duration: duration,
|
useNativeDriver: true,
|
||||||
easing: Easing.inOut(Easing.quad),
|
}).start();
|
||||||
useNativeDriver: true,
|
|
||||||
}
|
|
||||||
).start();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,8 +216,9 @@ const TouchableOpacity = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableGetLongPressDelayMS: function() {
|
touchableGetLongPressDelayMS: function() {
|
||||||
return this.props.delayLongPress === 0 ? 0 :
|
return this.props.delayLongPress === 0
|
||||||
this.props.delayLongPress || 500;
|
? 0
|
||||||
|
: this.props.delayLongPress || 500;
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableGetPressOutDelayMS: function() {
|
touchableGetPressOutDelayMS: function() {
|
||||||
|
@ -230,16 +230,13 @@ const TouchableOpacity = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_opacityInactive: function(duration: number) {
|
_opacityInactive: function(duration: number) {
|
||||||
this.setOpacityTo(
|
this.setOpacityTo(this._getChildStyleOpacityWithDefault(), duration);
|
||||||
this._getChildStyleOpacityWithDefault(),
|
|
||||||
duration
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_getChildStyleOpacityWithDefault: function() {
|
_getChildStyleOpacityWithDefault: function() {
|
||||||
const childStyle = flattenStyle(this.props.style) || {};
|
const childStyle = flattenStyle(this.props.style) || {};
|
||||||
return childStyle.opacity == undefined ? 1 : childStyle.opacity;
|
return childStyle.opacity == undefined ? 1 : childStyle.opacity;
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
|
@ -257,13 +254,18 @@ const TouchableOpacity = createReactClass({
|
||||||
tvParallaxProperties={this.props.tvParallaxProperties}
|
tvParallaxProperties={this.props.tvParallaxProperties}
|
||||||
hitSlop={this.props.hitSlop}
|
hitSlop={this.props.hitSlop}
|
||||||
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
|
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
|
||||||
onResponderTerminationRequest={this.touchableHandleResponderTerminationRequest}
|
onResponderTerminationRequest={
|
||||||
|
this.touchableHandleResponderTerminationRequest
|
||||||
|
}
|
||||||
onResponderGrant={this.touchableHandleResponderGrant}
|
onResponderGrant={this.touchableHandleResponderGrant}
|
||||||
onResponderMove={this.touchableHandleResponderMove}
|
onResponderMove={this.touchableHandleResponderMove}
|
||||||
onResponderRelease={this.touchableHandleResponderRelease}
|
onResponderRelease={this.touchableHandleResponderRelease}
|
||||||
onResponderTerminate={this.touchableHandleResponderTerminate}>
|
onResponderTerminate={this.touchableHandleResponderTerminate}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
{Touchable.renderDebugView({color: 'cyan', hitSlop: this.props.hitSlop})}
|
{Touchable.renderDebugView({
|
||||||
|
color: 'cyan',
|
||||||
|
hitSlop: this.props.hitSlop,
|
||||||
|
})}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const EdgeInsetsPropType = require('EdgeInsetsPropType');
|
const EdgeInsetsPropType = require('EdgeInsetsPropType');
|
||||||
|
@ -46,9 +48,7 @@ const TouchableWithoutFeedback = createReactClass({
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
accessible: PropTypes.bool,
|
accessible: PropTypes.bool,
|
||||||
accessibilityComponentType: PropTypes.oneOf(
|
accessibilityComponentType: PropTypes.oneOf(AccessibilityComponentTypes),
|
||||||
AccessibilityComponentTypes
|
|
||||||
),
|
|
||||||
accessibilityTraits: PropTypes.oneOfType([
|
accessibilityTraits: PropTypes.oneOfType([
|
||||||
PropTypes.oneOf(AccessibilityTraits),
|
PropTypes.oneOf(AccessibilityTraits),
|
||||||
PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)),
|
PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)),
|
||||||
|
@ -63,14 +63,14 @@ const TouchableWithoutFeedback = createReactClass({
|
||||||
*/
|
*/
|
||||||
onPress: PropTypes.func,
|
onPress: PropTypes.func,
|
||||||
/**
|
/**
|
||||||
* Called as soon as the touchable element is pressed and invoked even before onPress.
|
* Called as soon as the touchable element is pressed and invoked even before onPress.
|
||||||
* This can be useful when making network requests.
|
* This can be useful when making network requests.
|
||||||
*/
|
*/
|
||||||
onPressIn: PropTypes.func,
|
onPressIn: PropTypes.func,
|
||||||
/**
|
/**
|
||||||
* Called as soon as the touch is released even before onPress.
|
* Called as soon as the touch is released even before onPress.
|
||||||
*/
|
*/
|
||||||
onPressOut: PropTypes.func,
|
onPressOut: PropTypes.func,
|
||||||
/**
|
/**
|
||||||
* Invoked on mount and layout changes with
|
* Invoked on mount and layout changes with
|
||||||
*
|
*
|
||||||
|
@ -156,8 +156,9 @@ const TouchableWithoutFeedback = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableGetLongPressDelayMS: function(): number {
|
touchableGetLongPressDelayMS: function(): number {
|
||||||
return this.props.delayLongPress === 0 ? 0 :
|
return this.props.delayLongPress === 0
|
||||||
this.props.delayLongPress || 500;
|
? 0
|
||||||
|
: this.props.delayLongPress || 500;
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableGetPressOutDelayMS: function(): number {
|
touchableGetPressOutDelayMS: function(): number {
|
||||||
|
@ -172,15 +173,25 @@ const TouchableWithoutFeedback = createReactClass({
|
||||||
warning(
|
warning(
|
||||||
!child.type || child.type.displayName !== 'Text',
|
!child.type || child.type.displayName !== 'Text',
|
||||||
'TouchableWithoutFeedback does not work well with Text children. Wrap children in a View instead. See ' +
|
'TouchableWithoutFeedback does not work well with Text children. Wrap children in a View instead. See ' +
|
||||||
((child._owner && child._owner.getName && child._owner.getName()) || '<unknown>')
|
((child._owner && child._owner.getName && child._owner.getName()) ||
|
||||||
|
'<unknown>'),
|
||||||
);
|
);
|
||||||
if (Touchable.TOUCH_TARGET_DEBUG && child.type && child.type.displayName === 'View') {
|
if (
|
||||||
|
Touchable.TOUCH_TARGET_DEBUG &&
|
||||||
|
child.type &&
|
||||||
|
child.type.displayName === 'View'
|
||||||
|
) {
|
||||||
children = React.Children.toArray(children);
|
children = React.Children.toArray(children);
|
||||||
children.push(Touchable.renderDebugView({color: 'red', hitSlop: this.props.hitSlop}));
|
children.push(
|
||||||
|
Touchable.renderDebugView({color: 'red', hitSlop: this.props.hitSlop}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const style = (Touchable.TOUCH_TARGET_DEBUG && child.type && child.type.displayName === 'Text') ?
|
const style =
|
||||||
[child.props.style, {color: 'red'}] :
|
Touchable.TOUCH_TARGET_DEBUG &&
|
||||||
child.props.style;
|
child.type &&
|
||||||
|
child.type.displayName === 'Text'
|
||||||
|
? [child.props.style, {color: 'red'}]
|
||||||
|
: child.props.style;
|
||||||
return (React: any).cloneElement(child, {
|
return (React: any).cloneElement(child, {
|
||||||
accessible: this.props.accessible !== false,
|
accessible: this.props.accessible !== false,
|
||||||
accessibilityLabel: this.props.accessibilityLabel,
|
accessibilityLabel: this.props.accessibilityLabel,
|
||||||
|
@ -191,7 +202,8 @@ const TouchableWithoutFeedback = createReactClass({
|
||||||
onLayout: this.props.onLayout,
|
onLayout: this.props.onLayout,
|
||||||
hitSlop: this.props.hitSlop,
|
hitSlop: this.props.hitSlop,
|
||||||
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
|
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
|
||||||
onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest,
|
onResponderTerminationRequest: this
|
||||||
|
.touchableHandleResponderTerminationRequest,
|
||||||
onResponderGrant: this.touchableHandleResponderGrant,
|
onResponderGrant: this.touchableHandleResponderGrant,
|
||||||
onResponderMove: this.touchableHandleResponderMove,
|
onResponderMove: this.touchableHandleResponderMove,
|
||||||
onResponderRelease: this.touchableHandleResponderRelease,
|
onResponderRelease: this.touchableHandleResponderRelease,
|
||||||
|
@ -199,7 +211,7 @@ const TouchableWithoutFeedback = createReactClass({
|
||||||
style,
|
style,
|
||||||
children,
|
children,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = TouchableWithoutFeedback;
|
module.exports = TouchableWithoutFeedback;
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = () => true;
|
module.exports = () => true;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @emails oncall+react_native
|
* @emails oncall+react_native
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('React');
|
const React = require('React');
|
||||||
|
@ -18,7 +20,7 @@ describe('TouchableHighlight', () => {
|
||||||
const instance = ReactTestRenderer.create(
|
const instance = ReactTestRenderer.create(
|
||||||
<TouchableHighlight style={{}}>
|
<TouchableHighlight style={{}}>
|
||||||
<Text>Touchable</Text>
|
<Text>Touchable</Text>
|
||||||
</TouchableHighlight>
|
</TouchableHighlight>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(instance.toJSON()).toMatchSnapshot();
|
expect(instance.toJSON()).toMatchSnapshot();
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
|
@ -14,7 +16,7 @@ const ensureComponentIsNative = function(component: any) {
|
||||||
invariant(
|
invariant(
|
||||||
component && typeof component.setNativeProps === 'function',
|
component && typeof component.setNativeProps === 'function',
|
||||||
'Touchable child must either be native or forward setNativeProps to a ' +
|
'Touchable child must either be native or forward setNativeProps to a ' +
|
||||||
'native component'
|
'native component',
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,22 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
|
|
||||||
const ensurePositiveDelayProps = function(props: any) {
|
const ensurePositiveDelayProps = function(props: any) {
|
||||||
invariant(
|
invariant(
|
||||||
!(props.delayPressIn < 0 || props.delayPressOut < 0 ||
|
!(
|
||||||
props.delayLongPress < 0),
|
props.delayPressIn < 0 ||
|
||||||
'Touchable components cannot have negative delay properties'
|
props.delayPressOut < 0 ||
|
||||||
|
props.delayLongPress < 0
|
||||||
|
),
|
||||||
|
'Touchable components cannot have negative delay properties',
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @format
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -27,10 +28,10 @@ const ReactNativeStyleAttributes = {
|
||||||
...keyMirror(ImageStylePropTypes),
|
...keyMirror(ImageStylePropTypes),
|
||||||
};
|
};
|
||||||
|
|
||||||
ReactNativeStyleAttributes.transform = { process: processTransform };
|
ReactNativeStyleAttributes.transform = {process: processTransform};
|
||||||
ReactNativeStyleAttributes.shadowOffset = { diff: sizesDiffer };
|
ReactNativeStyleAttributes.shadowOffset = {diff: sizesDiffer};
|
||||||
|
|
||||||
const colorAttributes = { process: processColor };
|
const colorAttributes = {process: processColor};
|
||||||
ReactNativeStyleAttributes.backgroundColor = colorAttributes;
|
ReactNativeStyleAttributes.backgroundColor = colorAttributes;
|
||||||
ReactNativeStyleAttributes.borderBottomColor = colorAttributes;
|
ReactNativeStyleAttributes.borderBottomColor = colorAttributes;
|
||||||
ReactNativeStyleAttributes.borderColor = colorAttributes;
|
ReactNativeStyleAttributes.borderColor = colorAttributes;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue