For a long time now, Apple has discouraged using UIWebViews in favor of WKWebView. In iOS 12, which will be released in the upcoming months, UIWebViews will be formally deprecated. React Native's iOS WebView implementation relies heavily on the UIWebView class. Therefore, in light of these developments, we've built a new native iOS backend to the WebView React Native component that uses WKWebView.

The tail end of these changes were landed in this commit, and will become available in the 0.57 release.

To opt into this new implementation, please use the useWebKit prop:

-
<WebView useWebKit={true} source={{url: 'https://www.google.com'}} />
+
<WebView
+  useWebKit={true}
+  source={{ url: 'https://www.google.com' }}
+/>
 

Improvements

UIWebView had no legitimate way to facilitate communication between the JavaScript running in the WebView, and React Native. When messages were sent from the WebView, we relied on a hack to deliver them to React Native. Succinctly, we encoded the message data into a url with a special scheme, and navigated the WebView to it. On the native side, we intercepted and cancelled this navigation, parsed the data from the url, and finally called into React Native. This implementation was error prone and insecure. I'm glad to announce that we've leveraged WKWebView features to completely replace it.

@@ -297,7 +300,7 @@ accessibilityStates={[“selected”]} }, getSourceExts() { return ['ts', 'tsx']; - }, + } };

Migrating to TypeScript

@@ -360,7 +363,7 @@ accessibilityStates={[“selected”]}

Create a components directory and add the following example.

// components/Hello.tsx
 import React from 'react';
-import {Button, StyleSheet, Text, View} from 'react-native';
+import { Button, StyleSheet, Text, View } from 'react-native';
 
 export interface Props {
   name: string;
@@ -376,19 +379,26 @@ export class Hello extends React.Component<Props, State> {
     super(props);
 
     if ((props.enthusiasmLevel || 0) <= 0) {
-      throw new Error('You could be a little more enthusiastic. :D');
+      throw new Error(
+        'You could be a little more enthusiastic. :D'
+      );
     }
 
     this.state = {
-      enthusiasmLevel: props.enthusiasmLevel || 1,
+      enthusiasmLevel: props.enthusiasmLevel || 1
     };
   }
 
   onIncrement = () =>
-    this.setState({enthusiasmLevel: this.state.enthusiasmLevel + 1});
+    this.setState({
+      enthusiasmLevel: this.state.enthusiasmLevel + 1
+    });
   onDecrement = () =>
-    this.setState({enthusiasmLevel: this.state.enthusiasmLevel - 1});
-  getExclamationMarks = (numChars: number) => Array(numChars + 1).join('!');
+    this.setState({
+      enthusiasmLevel: this.state.enthusiasmLevel - 1
+    });
+  getExclamationMarks = (numChars: number) =>
+    Array(numChars + 1).join('!');
 
   render() {
     return (
@@ -427,23 +437,23 @@ export class Hello extends React.Component<Props, State> {
 const styles = StyleSheet.create({
   root: {
     alignItems: 'center',
-    alignSelf: 'center',
+    alignSelf: 'center'
   },
   buttons: {
     flexDirection: 'row',
     minHeight: 70,
     alignItems: 'stretch',
     alignSelf: 'center',
-    borderWidth: 5,
+    borderWidth: 5
   },
   button: {
     flex: 1,
-    paddingVertical: 0,
+    paddingVertical: 0
   },
   greeting: {
     color: '#999',
-    fontWeight: 'bold',
-  },
+    fontWeight: 'bold'
+  }
 });
 

Whoa! That's a lot, but let's break it down:

@@ -461,7 +471,7 @@ const styles = StyleSheet.create({ import React from 'react'; import renderer from 'react-test-renderer'; -import {Hello} from '../Hello'; +import { Hello } from '../Hello'; it('renders correctly with defaults', () => { const button = renderer @@ -568,10 +578,13 @@ it('renders correctly with defaults',

Example Usage

Here's an example which builds a keyboard toolbar button to reset <TextInput> state.

-
class TextInputAccessoryViewExample extends React.Component<{}, *> {
+
class TextInputAccessoryViewExample extends React.Component<
+  {},
+  *
+> {
   constructor(props) {
     super(props);
-    this.state = {text: 'Placeholder Text'};
+    this.state = { text: 'Placeholder Text' };
   }
 
   render() {
@@ -581,13 +594,15 @@ it('renders correctly with defaults', <TextInput
           style={styles.default}
           inputAccessoryViewID={inputAccessoryViewID}
-          onChangeText={(text) => this.setState({text})}
+          onChangeText={(text) => this.setState({ text })}
           value={this.state.text}
         />
         <InputAccessoryView nativeID={inputAccessoryViewID}>
-          <View style={{backgroundColor: 'white'}}>
+          <View style={{ backgroundColor: 'white' }}>
             <Button
-              onPress={() => this.setState({text: 'Placeholder Text'})}
+              onPress={() =>
+                this.setState({ text: 'Placeholder Text' })
+              }
               title="Reset Text"
             />
           </View>
@@ -754,10 +769,10 @@ const client = new AWSAppSyncClient({
 

Now, for the React Native

Alrighty. Now that we know what we are building and how the animation works, we can get down to the code — the reason you are really here.

The main piece of this puzzle is MaskedViewIOS, a core React Native component.

-
import {MaskedViewIOS} from 'react-native';
+
import { MaskedViewIOS } from 'react-native';
 
 <MaskedViewIOS maskElement={<Text>Basic Mask</Text>}>
-  <View style={{backgroundColor: 'blue'}} />
+  <View style={{ backgroundColor: 'blue' }} />
 </MaskedViewIOS>;
 

MaskedViewIOS takes props maskElement and children. The children are masked by the maskElement. Note that the mask doesn’t need to be an image, it can be any arbitrary view. The behavior of the above example would be to render the blue view, but for it to be visible only where the words “Basic Mask” are from the maskElement. We just made complicated blue text.

@@ -766,14 +781,14 @@ const client = new AWSAppSyncClient({ fullScreenBlueLayer; } <MaskedViewIOS - style={{flex: 1}} + style={{ flex: 1 }} maskElement={ <View style={styles.centeredFullScreen}> <Image source={twitterLogo} /> </View> }> {fullScreenWhiteLayer} - <View style={{flex: 1}}> + <View style={{ flex: 1 }}> <MyApp /> </View> </MaskedViewIOS>; @@ -799,14 +814,14 @@ const client = new AWSAppSyncClient({

Since I’m thinking about this animation as steps occurring at different points in time along the complete animation, we will start our Animated.Value at 0, representing 0% complete, and end our value at 100, representing 100% complete.

Our initial component state will be the following.

state = {
-  loadingProgress: new Animated.Value(0),
+  loadingProgress: new Animated.Value(0)
 };
 

When we are ready to begin the animation, we tell Animated to animate this value to 100.

Animated.timing(this.state.loadingProgress, {
   toValue: 100,
   duration: 1000,
-  useNativeDriver: true, // This is important!
+  useNativeDriver: true // This is important!
 }).start();
 

I then try to figure out a rough estimate of the different pieces of the animations and the values I want them to have at different stages of the overall animation. Below is a table of the different pieces of the animation, and what I think their values should be at different points as we progress through time.

@@ -822,9 +837,9 @@ const client = new AWSAppSyncClient({ opacity: loadingProgress.interpolate({ inputRange: [0, 15, 30], outputRange: [0, 0, 1], - extrapolate: 'clamp', + extrapolate: 'clamp' // clamp means when the input is 30-100, output should stay at 1 - }), + }) }; const imageScale = { @@ -832,10 +847,10 @@ const client = new AWSAppSyncClient({ { scale: loadingProgress.interpolate({ inputRange: [0, 10, 100], - outputRange: [1, 0.8, 70], - }), - }, - ], + outputRange: [1, 0.8, 70] + }) + } + ] }; const appScale = { @@ -843,21 +858,25 @@ const client = new AWSAppSyncClient({ { scale: loadingProgress.interpolate({ inputRange: [0, 100], - outputRange: [1.1, 1], - }), - }, - ], + outputRange: [1.1, 1] + }) + } + ] };

Now that we have these style objects, we can use them when rendering the snippet of the view from earlier in the post. Note that only Animated.View, Animated.Text, and Animated.Image are able to use style objects that use Animated.Value.

-
const fullScreenBlueLayer = <View style={styles.fullScreenBlueLayer} />;
-const fullScreenWhiteLayer = <View style={styles.fullScreenWhiteLayer} />;
+
const fullScreenBlueLayer = (
+  <View style={styles.fullScreenBlueLayer} />
+);
+const fullScreenWhiteLayer = (
+  <View style={styles.fullScreenWhiteLayer} />
+);
 
 return (
   <View style={styles.fullScreen}>
     {fullScreenBlueLayer}
     <MaskedViewIOS
-      style={{flex: 1}}
+      style={{ flex: 1 }}
       maskElement={
         <View style={styles.centeredFullScreen}>
           <Animated.Image
@@ -867,7 +886,8 @@ const client = new AWSAppSyncClient({
         </View>
       }>
       {fullScreenWhiteLayer}
-      <Animated.View style={[opacityClearToVisible, appScale, {flex: 1}]}>
+      <Animated.View
+        style={[opacityClearToVisible, appScale, { flex: 1 }]}>
         {this.props.children}
       </Animated.View>
     </MaskedViewIOS>
@@ -880,10 +900,10 @@ const client = new AWSAppSyncClient({
 
Animated.timing(this.state.loadingProgress, {
   toValue: 100,
   duration: 1000,
-  useNativeDriver: true,
+  useNativeDriver: true
 }).start(() => {
   this.setState({
-    animationDone: true,
+    animationDone: true
   });
 });
 
diff --git a/blog/page3/index.html b/blog/page3/index.html index 01216331b19..e8a9559a82b 100644 --- a/blog/page3/index.html +++ b/blog/page3/index.html @@ -540,7 +540,7 @@ $ npm start
  • These components are based on PureComponent which means that they will not re-render if props remains shallow-equal. Make sure that everything your renderItem function depends on directly is passed as a prop that is not === after updates, otherwise your UI may not update on changes. This includes the data prop and parent component state. For example:

    <FlatList
       data={this.state.data}
    -  renderItem={({item}) => (
    +  renderItem={({ item }) => (
         <MyItem
           item={item}
           onPress={() =>
    @@ -548,8 +548,8 @@ $ npm start
               selected: {
                 // New instance breaks `===`
                 ...oldState.selected, // copy old data
    -            [item.key]: !oldState.selected[item.key], // toggle
    -          },
    +            [item.key]: !oldState.selected[item.key] // toggle
    +          }
             }))
           }
           selected={
    diff --git a/blog/page4/index.html b/blog/page4/index.html
    index 403160ec66f..28252c95400 100644
    --- a/blog/page4/index.html
    +++ b/blog/page4/index.html
    @@ -306,12 +306,14 @@ index e98ebb0..2fb6a11 };
     

    Next, register your task in on AppRegistry:

    -
    AppRegistry.registerHeadlessTask('SomeTaskName', () => require('SomeTaskName'));
    +
    AppRegistry.registerHeadlessTask('SomeTaskName', () =>
    +  require('SomeTaskName')
    +);
     

    Using Headless JS does require some native Java code to be written in order to allow you to start up the service when needed. Take a look at our new Headless JS docs to learn more!

    The Keyboard API

    Working with the on-screen keyboard is now easier with Keyboard. You can now listen for native keyboard events and react to them. For example, to dismiss the active keyboard, simply call Keyboard.dismiss():

    -
    import {Keyboard} from 'react-native';
    +
    import { Keyboard } from 'react-native';
     
     // Hide that keyboard!
     Keyboard.dismiss();
    @@ -477,12 +479,12 @@ $ react-native upgrade
     
     _onDirectionChange = () => {
       I18nManager.forceRTL(!this.state.isRTL);
    -  this.setState({isRTL: !this.state.isRTL});
    +  this.setState({ isRTL: !this.state.isRTL });
       Alert.alert(
         'Reload this page',
         'Please reload this page to change the UI direction! ' +
           'All examples in this app will be affected. ' +
    -      'Check them out to see what they look like in RTL layout.',
    +      'Check them out to see what they look like in RTL layout.'
       );
     };
     
    diff --git a/docs/0.10/accessibility.html b/docs/0.10/accessibility.html index af8caf05854..a9f92566713 100644 --- a/docs/0.10/accessibility.html +++ b/docs/0.10/accessibility.html @@ -255,9 +255,9 @@
    <View
       accessible={true}
       accessibilityActions={[
    -    {name: 'cut', label: 'cut'},
    -    {name: 'copy', label: 'copy'},
    -    {name: 'paste', label: 'paste'},
    +    { name: 'cut', label: 'cut' },
    +    { name: 'copy', label: 'copy' },
    +    { name: 'paste', label: 'paste' }
       ]}
       onAccessibilityAction={(event) => {
         switch (event.nativeEvent.actionName) {
    diff --git a/docs/0.10/accessibility/index.html b/docs/0.10/accessibility/index.html
    index af8caf05854..a9f92566713 100644
    --- a/docs/0.10/accessibility/index.html
    +++ b/docs/0.10/accessibility/index.html
    @@ -255,9 +255,9 @@
     
    <View
       accessible={true}
       accessibilityActions={[
    -    {name: 'cut', label: 'cut'},
    -    {name: 'copy', label: 'copy'},
    -    {name: 'paste', label: 'paste'},
    +    { name: 'cut', label: 'cut' },
    +    { name: 'copy', label: 'copy' },
    +    { name: 'paste', label: 'paste' }
       ]}
       onAccessibilityAction={(event) => {
         switch (event.nativeEvent.actionName) {
    diff --git a/docs/0.10/accessibilityinfo.html b/docs/0.10/accessibilityinfo.html
    index 67d0596f055..fefecce92c5 100644
    --- a/docs/0.10/accessibilityinfo.html
    +++ b/docs/0.10/accessibilityinfo.html
    @@ -16,17 +16,17 @@
     

    Here's a small example illustrating how to use AccessibilityInfo:

    class ScreenReaderStatusExample extends React.Component {
       state = {
    -    screenReaderEnabled: false,
    +    screenReaderEnabled: false
       };
     
       componentDidMount() {
         AccessibilityInfo.addEventListener(
           'change',
    -      this._handleScreenReaderToggled,
    +      this._handleScreenReaderToggled
         );
         AccessibilityInfo.fetch().done((isEnabled) => {
           this.setState({
    -        screenReaderEnabled: isEnabled,
    +        screenReaderEnabled: isEnabled
           });
         });
       }
    @@ -34,13 +34,13 @@
       componentWillUnmount() {
         AccessibilityInfo.removeEventListener(
           'change',
    -      this._handleScreenReaderToggled,
    +      this._handleScreenReaderToggled
         );
       }
     
       _handleScreenReaderToggled = (isEnabled) => {
         this.setState({
    -      screenReaderEnabled: isEnabled,
    +      screenReaderEnabled: isEnabled
         });
       };
     
    @@ -49,7 +49,10 @@
           <View>
             <Text>
               The screen reader is{' '}
    -          {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}.
    +          {this.state.screenReaderEnabled
    +            ? 'enabled'
    +            : 'disabled'}
    +          .
             </Text>
           </View>
         );
    diff --git a/docs/0.10/accessibilityinfo/index.html b/docs/0.10/accessibilityinfo/index.html
    index 67d0596f055..fefecce92c5 100644
    --- a/docs/0.10/accessibilityinfo/index.html
    +++ b/docs/0.10/accessibilityinfo/index.html
    @@ -16,17 +16,17 @@
     

    Here's a small example illustrating how to use AccessibilityInfo:

    class ScreenReaderStatusExample extends React.Component {
       state = {
    -    screenReaderEnabled: false,
    +    screenReaderEnabled: false
       };
     
       componentDidMount() {
         AccessibilityInfo.addEventListener(
           'change',
    -      this._handleScreenReaderToggled,
    +      this._handleScreenReaderToggled
         );
         AccessibilityInfo.fetch().done((isEnabled) => {
           this.setState({
    -        screenReaderEnabled: isEnabled,
    +        screenReaderEnabled: isEnabled
           });
         });
       }
    @@ -34,13 +34,13 @@
       componentWillUnmount() {
         AccessibilityInfo.removeEventListener(
           'change',
    -      this._handleScreenReaderToggled,
    +      this._handleScreenReaderToggled
         );
       }
     
       _handleScreenReaderToggled = (isEnabled) => {
         this.setState({
    -      screenReaderEnabled: isEnabled,
    +      screenReaderEnabled: isEnabled
         });
       };
     
    @@ -49,7 +49,10 @@
           <View>
             <Text>
               The screen reader is{' '}
    -          {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}.
    +          {this.state.screenReaderEnabled
    +            ? 'enabled'
    +            : 'disabled'}
    +          .
             </Text>
           </View>
         );
    diff --git a/docs/0.10/alertios.html b/docs/0.10/alertios.html
    index 305f31a6e79..7a74d825292 100644
    --- a/docs/0.10/alertios.html
    +++ b/docs/0.10/alertios.html
    @@ -35,13 +35,13 @@
         {
           text: 'Cancel',
           onPress: () => console.log('Cancel Pressed'),
    -      style: 'cancel',
    +      style: 'cancel'
         },
         {
           text: 'Install',
    -      onPress: () => console.log('Install Pressed'),
    -    },
    -  ],
    +      onPress: () => console.log('Install Pressed')
    +    }
    +  ]
     );
     

    Example with custom buttons:

    @@ -52,14 +52,15 @@ { text: 'Cancel', onPress: () => console.log('Cancel Pressed'), - style: 'cancel', + style: 'cancel' }, { text: 'OK', - onPress: (password) => console.log('OK Pressed, password: ' + password), - }, + onPress: (password) => + console.log('OK Pressed, password: ' + password) + } ], - 'secure-text', + 'secure-text' );

    Example with the default button and a custom callback:

    @@ -68,7 +69,7 @@ null, (text) => console.log('Your username is ' + text), null, - 'default', + 'default' );

    Methods

    @@ -109,7 +110,7 @@ [callbackOrButtons], [type], [defaultValue], - [keyboardType], + [keyboardType] );

    Create and display a prompt to enter some text.

    diff --git a/docs/0.10/alertios/index.html b/docs/0.10/alertios/index.html index 305f31a6e79..7a74d825292 100644 --- a/docs/0.10/alertios/index.html +++ b/docs/0.10/alertios/index.html @@ -35,13 +35,13 @@ { text: 'Cancel', onPress: () => console.log('Cancel Pressed'), - style: 'cancel', + style: 'cancel' }, { text: 'Install', - onPress: () => console.log('Install Pressed'), - }, - ], + onPress: () => console.log('Install Pressed') + } + ] );

    Example with custom buttons:

    @@ -52,14 +52,15 @@ { text: 'Cancel', onPress: () => console.log('Cancel Pressed'), - style: 'cancel', + style: 'cancel' }, { text: 'OK', - onPress: (password) => console.log('OK Pressed, password: ' + password), - }, + onPress: (password) => + console.log('OK Pressed, password: ' + password) + } ], - 'secure-text', + 'secure-text' );

    Example with the default button and a custom callback:

    @@ -68,7 +69,7 @@ null, (text) => console.log('Your username is ' + text), null, - 'default', + 'default' );
  • Methods

    @@ -109,7 +110,7 @@ [callbackOrButtons], [type], [defaultValue], - [keyboardType], + [keyboardType] );

    Create and display a prompt to enter some text.

    diff --git a/docs/0.10/animated.html b/docs/0.10/animated.html index cc6770de528..b8943e03888 100644 --- a/docs/0.10/animated.html +++ b/docs/0.10/animated.html @@ -18,8 +18,8 @@ // Animate value over time this.state.fadeAnim, // The value to drive { - toValue: 1, // Animate to final value of 1 - }, + toValue: 1 // Animate to final value of 1 + } ).start(); // Start the animation

    Refer to the Animations guide to see additional examples of Animated in action.

    @@ -40,7 +40,7 @@

    In most cases, you will be using timing(). By default, it uses a symmetric easeInOut curve that conveys the gradual acceleration of an object to full speed and concludes by gradually decelerating to a stop.

    Working with animations

    Animations are started by calling start() on your animation. start() takes a completion callback that will be called when the animation is done. If the animation finished running normally, the completion callback will be invoked with {finished: true}. If the animation is done because stop() was called on it before it could finish (e.g. because it was interrupted by a gesture or another animation), then it will receive {finished: false}.

    -
    this.animateValue.spring({}).start(({finished}) => {
    +
    this.animateValue.spring({}).start(({ finished }) => {
       if (finished) {
         console.log('Animation was completed');
       } else {
    diff --git a/docs/0.10/animated/index.html b/docs/0.10/animated/index.html
    index cc6770de528..b8943e03888 100644
    --- a/docs/0.10/animated/index.html
    +++ b/docs/0.10/animated/index.html
    @@ -18,8 +18,8 @@
       // Animate value over time
       this.state.fadeAnim, // The value to drive
       {
    -    toValue: 1, // Animate to final value of 1
    -  },
    +    toValue: 1 // Animate to final value of 1
    +  }
     ).start(); // Start the animation
     

    Refer to the Animations guide to see additional examples of Animated in action.

    @@ -40,7 +40,7 @@

    In most cases, you will be using timing(). By default, it uses a symmetric easeInOut curve that conveys the gradual acceleration of an object to full speed and concludes by gradually decelerating to a stop.

    Working with animations

    Animations are started by calling start() on your animation. start() takes a completion callback that will be called when the animation is done. If the animation finished running normally, the completion callback will be invoked with {finished: true}. If the animation is done because stop() was called on it before it could finish (e.g. because it was interrupted by a gesture or another animation), then it will receive {finished: false}.

    -
    this.animateValue.spring({}).start(({finished}) => {
    +
    this.animateValue.spring({}).start(({ finished }) => {
       if (finished) {
         console.log('Animation was completed');
       } else {
    diff --git a/docs/0.10/animatedvaluexy.html b/docs/0.10/animatedvaluexy.html
    index b5d11985947..b761b6f05b0 100644
    --- a/docs/0.10/animatedvaluexy.html
    +++ b/docs/0.10/animatedvaluexy.html
    @@ -19,7 +19,7 @@
       constructor(props) {
         super(props);
         this.state = {
    -      pan: new Animated.ValueXY(), // inits to zero
    +      pan: new Animated.ValueXY() // inits to zero
         };
         this.state.panResponder = PanResponder.create({
           onStartShouldSetPanResponder: () => true,
    @@ -27,15 +27,15 @@
             null,
             {
               dx: this.state.pan.x, // x,y are Animated.Value
    -          dy: this.state.pan.y,
    -        },
    +          dy: this.state.pan.y
    +        }
           ]),
           onPanResponderRelease: () => {
             Animated.spring(
               this.state.pan, // Auto-multiplexed
    -          {toValue: {x: 0, y: 0}}, // Back to zero
    +          { toValue: { x: 0, y: 0 } } // Back to zero
             ).start();
    -      },
    +      }
         });
       }
       render() {
    diff --git a/docs/0.10/animatedvaluexy/index.html b/docs/0.10/animatedvaluexy/index.html
    index b5d11985947..b761b6f05b0 100644
    --- a/docs/0.10/animatedvaluexy/index.html
    +++ b/docs/0.10/animatedvaluexy/index.html
    @@ -19,7 +19,7 @@
       constructor(props) {
         super(props);
         this.state = {
    -      pan: new Animated.ValueXY(), // inits to zero
    +      pan: new Animated.ValueXY() // inits to zero
         };
         this.state.panResponder = PanResponder.create({
           onStartShouldSetPanResponder: () => true,
    @@ -27,15 +27,15 @@
             null,
             {
               dx: this.state.pan.x, // x,y are Animated.Value
    -          dy: this.state.pan.y,
    -        },
    +          dy: this.state.pan.y
    +        }
           ]),
           onPanResponderRelease: () => {
             Animated.spring(
               this.state.pan, // Auto-multiplexed
    -          {toValue: {x: 0, y: 0}}, // Back to zero
    +          { toValue: { x: 0, y: 0 } } // Back to zero
             ).start();
    -      },
    +      }
         });
       }
       render() {
    diff --git a/docs/0.10/animations.html b/docs/0.10/animations.html
    index b09bbfcc50a..e0842bf4c20 100644
    --- a/docs/0.10/animations.html
    +++ b/docs/0.10/animations.html
    @@ -138,7 +138,7 @@
     
    Animated.timing(this.state.xPosition, {
       toValue: 100,
       easing: Easing.back(),
    -  duration: 2000,
    +  duration: 2000
     }).start();
     

    Take a look at the Configuring animations section of the Animated API reference to learn more about all the config parameters supported by the built-in animations.

    @@ -149,19 +149,19 @@ // decay, then spring to start and twirl Animated.decay(position, { // coast to a stop - velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release - deceleration: 0.997, + velocity: { x: gestureState.vx, y: gestureState.vy }, // velocity from gesture release + deceleration: 0.997 }), Animated.parallel([ // after decay, in parallel: Animated.spring(position, { - toValue: {x: 0, y: 0}, // return to start + toValue: { x: 0, y: 0 } // return to start }), Animated.timing(twirl, { // and twirl - toValue: 360, - }), - ]), + toValue: 360 + }) + ]) ]).start(); // start the sequence group

    If one animation is stopped or interrupted, then all other animations in the group are also stopped. Animated.parallel has a stopTogether option that can be set to false to disable this.

    @@ -173,7 +173,7 @@ const b = Animated.divide(1, a); Animated.spring(a, { - toValue: 2, + toValue: 2 }).start();

    Interpolation

    @@ -181,7 +181,7 @@ Animated.spr

    A mapping to convert a 0-1 range to a 0-100 range would be:

    value.interpolate({
       inputRange: [0, 1],
    -  outputRange: [0, 100],
    +  outputRange: [0, 100]
     });
     

    For example, you may want to think about your Animated.Value as going from 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to 1. This can be done by modifying style from the example above like so:

    @@ -198,7 +198,7 @@ Animated.spr

    interpolate() supports multiple range segments as well, which is handy for defining dead zones and other handy tricks. For example, to get a negation relationship at -300 that goes to 0 at -100, then back up to 1 at 0, and then back down to zero at 100 followed by a dead-zone that remains at 0 for everything beyond that, you could do:

    value.interpolate({
       inputRange: [-300, -100, 0, 100, 101],
    -  outputRange: [300, 0, 1, 0, 0],
    +  outputRange: [300, 0, 1, 0, 0]
     });
     

    Which would map like so:

    @@ -218,18 +218,18 @@ Animated.spr

    interpolate() also supports mapping to strings, allowing you to animate colors as well as values with units. For example, if you wanted to animate a rotation you could do:

    value.interpolate({
       inputRange: [0, 360],
    -  outputRange: ['0deg', '360deg'],
    +  outputRange: ['0deg', '360deg']
     });
     

    interpolate() also supports arbitrary easing functions, many of which are already implemented in the Easing module. interpolate() also has configurable behavior for extrapolating the outputRange. You can set the extrapolation by setting the extrapolate, extrapolateLeft, or extrapolateRight options. The default value is extend but you can use clamp to prevent the output value from exceeding outputRange.

    Tracking dynamic values

    Animated values can also track other values. Set the toValue of an animation to another animated value instead of a plain number. For example, a "Chat Heads" animation like the one used by Messenger on Android could be implemented with a spring() pinned on another animated value, or with timing() and a duration of 0 for rigid tracking. They can also be composed with interpolations:

    -
    Animated.spring(follower, {toValue: leader}).start();
    +
    Animated.spring(follower, { toValue: leader }).start();
     Animated.timing(opacity, {
       toValue: pan.x.interpolate({
         inputRange: [0, 300],
    -    outputRange: [1, 0],
    -  }),
    +    outputRange: [1, 0]
    +  })
     }).start();
     

    The leader and follower animated values would be implemented using Animated.ValueXY(). ValueXY is a handy way to deal with 2D interactions, such as panning or dragging. It is a wrapper that contains two Animated.Value instances and some helper functions that call through to them, making ValueXY a drop-in replacement for Value in many cases. It allows us to track both x and y values in the example above.

    @@ -267,7 +267,7 @@ Animated.tim
    Animated.timing(this.state.animatedValue, {
       toValue: 1,
       duration: 500,
    -  useNativeDriver: true, // <-- Add this
    +  useNativeDriver: true // <-- Add this
     }).start();
     

    Animated values are only compatible with one driver so if you use native driver when starting an animation on a value, make sure every animation on that value also uses the native driver.

    @@ -278,11 +278,11 @@ Animated.tim [ { nativeEvent: { - contentOffset: {y: this.state.animatedValue}, - }, - }, + contentOffset: { y: this.state.animatedValue } + } + } ], - {useNativeDriver: true}, // <-- Add this + { useNativeDriver: true } // <-- Add this )}> {content} </Animated.ScrollView> @@ -296,10 +296,10 @@ Animated.tim
    <Animated.View
       style={{
         transform: [
    -      {scale: this.state.scale},
    -      {rotateY: this.state.rotateY},
    -      {perspective: 1000}, // without this line this Animation will not render on Android while working fine on iOS
    -    ],
    +      { scale: this.state.scale },
    +      { rotateY: this.state.rotateY },
    +      { perspective: 1000 } // without this line this Animation will not render on Android while working fine on iOS
    +    ]
       }}
     />
     
    diff --git a/docs/0.10/animations/index.html b/docs/0.10/animations/index.html index b09bbfcc50a..e0842bf4c20 100644 --- a/docs/0.10/animations/index.html +++ b/docs/0.10/animations/index.html @@ -138,7 +138,7 @@
    Animated.timing(this.state.xPosition, {
       toValue: 100,
       easing: Easing.back(),
    -  duration: 2000,
    +  duration: 2000
     }).start();
     

    Take a look at the Configuring animations section of the Animated API reference to learn more about all the config parameters supported by the built-in animations.

    @@ -149,19 +149,19 @@ // decay, then spring to start and twirl Animated.decay(position, { // coast to a stop - velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release - deceleration: 0.997, + velocity: { x: gestureState.vx, y: gestureState.vy }, // velocity from gesture release + deceleration: 0.997 }), Animated.parallel([ // after decay, in parallel: Animated.spring(position, { - toValue: {x: 0, y: 0}, // return to start + toValue: { x: 0, y: 0 } // return to start }), Animated.timing(twirl, { // and twirl - toValue: 360, - }), - ]), + toValue: 360 + }) + ]) ]).start(); // start the sequence group

    If one animation is stopped or interrupted, then all other animations in the group are also stopped. Animated.parallel has a stopTogether option that can be set to false to disable this.

    @@ -173,7 +173,7 @@ const b = Animated.divide(1, a); Animated.spring(a, { - toValue: 2, + toValue: 2 }).start();

    Interpolation

    @@ -181,7 +181,7 @@ Animated.spr

    A mapping to convert a 0-1 range to a 0-100 range would be:

    value.interpolate({
       inputRange: [0, 1],
    -  outputRange: [0, 100],
    +  outputRange: [0, 100]
     });
     

    For example, you may want to think about your Animated.Value as going from 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to 1. This can be done by modifying style from the example above like so:

    @@ -198,7 +198,7 @@ Animated.spr

    interpolate() supports multiple range segments as well, which is handy for defining dead zones and other handy tricks. For example, to get a negation relationship at -300 that goes to 0 at -100, then back up to 1 at 0, and then back down to zero at 100 followed by a dead-zone that remains at 0 for everything beyond that, you could do:

    value.interpolate({
       inputRange: [-300, -100, 0, 100, 101],
    -  outputRange: [300, 0, 1, 0, 0],
    +  outputRange: [300, 0, 1, 0, 0]
     });
     

    Which would map like so:

    @@ -218,18 +218,18 @@ Animated.spr

    interpolate() also supports mapping to strings, allowing you to animate colors as well as values with units. For example, if you wanted to animate a rotation you could do:

    value.interpolate({
       inputRange: [0, 360],
    -  outputRange: ['0deg', '360deg'],
    +  outputRange: ['0deg', '360deg']
     });
     

    interpolate() also supports arbitrary easing functions, many of which are already implemented in the Easing module. interpolate() also has configurable behavior for extrapolating the outputRange. You can set the extrapolation by setting the extrapolate, extrapolateLeft, or extrapolateRight options. The default value is extend but you can use clamp to prevent the output value from exceeding outputRange.

    Tracking dynamic values

    Animated values can also track other values. Set the toValue of an animation to another animated value instead of a plain number. For example, a "Chat Heads" animation like the one used by Messenger on Android could be implemented with a spring() pinned on another animated value, or with timing() and a duration of 0 for rigid tracking. They can also be composed with interpolations:

    -
    Animated.spring(follower, {toValue: leader}).start();
    +
    Animated.spring(follower, { toValue: leader }).start();
     Animated.timing(opacity, {
       toValue: pan.x.interpolate({
         inputRange: [0, 300],
    -    outputRange: [1, 0],
    -  }),
    +    outputRange: [1, 0]
    +  })
     }).start();
     

    The leader and follower animated values would be implemented using Animated.ValueXY(). ValueXY is a handy way to deal with 2D interactions, such as panning or dragging. It is a wrapper that contains two Animated.Value instances and some helper functions that call through to them, making ValueXY a drop-in replacement for Value in many cases. It allows us to track both x and y values in the example above.

    @@ -267,7 +267,7 @@ Animated.tim
    Animated.timing(this.state.animatedValue, {
       toValue: 1,
       duration: 500,
    -  useNativeDriver: true, // <-- Add this
    +  useNativeDriver: true // <-- Add this
     }).start();
     

    Animated values are only compatible with one driver so if you use native driver when starting an animation on a value, make sure every animation on that value also uses the native driver.

    @@ -278,11 +278,11 @@ Animated.tim [ { nativeEvent: { - contentOffset: {y: this.state.animatedValue}, - }, - }, + contentOffset: { y: this.state.animatedValue } + } + } ], - {useNativeDriver: true}, // <-- Add this + { useNativeDriver: true } // <-- Add this )}> {content} </Animated.ScrollView> @@ -296,10 +296,10 @@ Animated.tim
    <Animated.View
       style={{
         transform: [
    -      {scale: this.state.scale},
    -      {rotateY: this.state.rotateY},
    -      {perspective: 1000}, // without this line this Animation will not render on Android while working fine on iOS
    -    ],
    +      { scale: this.state.scale },
    +      { rotateY: this.state.rotateY },
    +      { perspective: 1000 } // without this line this Animation will not render on Android while working fine on iOS
    +    ]
       }}
     />
     
    diff --git a/docs/0.10/appregistry.html b/docs/0.10/appregistry.html index 2b46d484f2d..25cae750b39 100644 --- a/docs/0.10/appregistry.html +++ b/docs/0.10/appregistry.html @@ -43,7 +43,9 @@

    Reference

    Methods

    registerComponent()

    -
    AppRegistry.registerComponent(appKey, componentProvider, [section]);
    +
    AppRegistry.registerComponent(appKey, componentProvider, [
    +  section
    +]);
     

    Registers an app's root component.

    Parameters:

    diff --git a/docs/0.10/appregistry/index.html b/docs/0.10/appregistry/index.html index 2b46d484f2d..25cae750b39 100644 --- a/docs/0.10/appregistry/index.html +++ b/docs/0.10/appregistry/index.html @@ -43,7 +43,9 @@

    Reference

    Methods

    registerComponent()

    -
    AppRegistry.registerComponent(appKey, componentProvider, [section]);
    +
    AppRegistry.registerComponent(appKey, componentProvider, [
    +  section
    +]);
     

    Registers an app's root component.

    Parameters:

    diff --git a/docs/0.10/appstate.html b/docs/0.10/appstate.html index bad23d28015..8bbbb69fbbe 100644 --- a/docs/0.10/appstate.html +++ b/docs/0.10/appstate.html @@ -23,20 +23,26 @@

    For more information, see Apple's documentation.

    Basic Usage

    To see the current state, you can check AppState.currentState, which will be kept up-to-date. However, currentState will be null at launch while AppState retrieves it over the bridge.

    -
    import React, {Component} from 'react';
    -import {AppState, Text} from 'react-native';
    +
    import React, { Component } from 'react';
    +import { AppState, Text } from 'react-native';
     
     class AppStateExample extends Component {
       state = {
    -    appState: AppState.currentState,
    +    appState: AppState.currentState
       };
     
       componentDidMount() {
    -    AppState.addEventListener('change', this._handleAppStateChange);
    +    AppState.addEventListener(
    +      'change',
    +      this._handleAppStateChange
    +    );
       }
     
       componentWillUnmount() {
    -    AppState.removeEventListener('change', this._handleAppStateChange);
    +    AppState.removeEventListener(
    +      'change',
    +      this._handleAppStateChange
    +    );
       }
     
       _handleAppStateChange = (nextAppState) => {
    @@ -46,7 +52,7 @@
         ) {
           console.log('App has come to the foreground!');
         }
    -    this.setState({appState: nextAppState});
    +    this.setState({ appState: nextAppState });
       };
     
       render() {
    diff --git a/docs/0.10/appstate/index.html b/docs/0.10/appstate/index.html
    index bad23d28015..8bbbb69fbbe 100644
    --- a/docs/0.10/appstate/index.html
    +++ b/docs/0.10/appstate/index.html
    @@ -23,20 +23,26 @@
     

    For more information, see Apple's documentation.

    Basic Usage

    To see the current state, you can check AppState.currentState, which will be kept up-to-date. However, currentState will be null at launch while AppState retrieves it over the bridge.

    -
    import React, {Component} from 'react';
    -import {AppState, Text} from 'react-native';
    +
    import React, { Component } from 'react';
    +import { AppState, Text } from 'react-native';
     
     class AppStateExample extends Component {
       state = {
    -    appState: AppState.currentState,
    +    appState: AppState.currentState
       };
     
       componentDidMount() {
    -    AppState.addEventListener('change', this._handleAppStateChange);
    +    AppState.addEventListener(
    +      'change',
    +      this._handleAppStateChange
    +    );
       }
     
       componentWillUnmount() {
    -    AppState.removeEventListener('change', this._handleAppStateChange);
    +    AppState.removeEventListener(
    +      'change',
    +      this._handleAppStateChange
    +    );
       }
     
       _handleAppStateChange = (nextAppState) => {
    @@ -46,7 +52,7 @@
         ) {
           console.log('App has come to the foreground!');
         }
    -    this.setState({appState: nextAppState});
    +    this.setState({ appState: nextAppState });
       };
     
       render() {
    diff --git a/docs/0.10/asyncstorage.html b/docs/0.10/asyncstorage.html
    index f2b0870222c..148877b2b24 100644
    --- a/docs/0.10/asyncstorage.html
    +++ b/docs/0.10/asyncstorage.html
    @@ -18,7 +18,10 @@
     

    The AsyncStorage JavaScript code is a facade that provides a clear JavaScript API, real Error objects, and non-multi functions. Each method in the API returns a Promise object.

    Persisting data:

    try {
    -  await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.');
    +  await AsyncStorage.setItem(
    +    '@MySuperStore:key',
    +    'I like to save it.'
    +  );
     } catch (error) {
       // Error saving data
     }
    @@ -38,21 +41,29 @@
     
    let UID123_object = {
       name: 'Chris',
       age: 30,
    -  traits: {hair: 'brown', eyes: 'brown'},
    +  traits: { hair: 'brown', eyes: 'brown' }
     };
     // You only need to define what will be added or updated
     let UID123_delta = {
       age: 31,
    -  traits: {eyes: 'blue', shoe_size: 10},
    +  traits: { eyes: 'blue', shoe_size: 10 }
     };
     
    -AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => {
    -  AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => {
    -    AsyncStorage.getItem('UID123', (err, result) => {
    -      console.log(result);
    -    });
    -  });
    -});
    +AsyncStorage.setItem(
    +  'UID123',
    +  JSON.stringify(UID123_object),
    +  () => {
    +    AsyncStorage.mergeItem(
    +      'UID123',
    +      JSON.stringify(UID123_delta),
    +      () => {
    +        AsyncStorage.getItem('UID123', (err, result) => {
    +          console.log(result);
    +        });
    +      }
    +    );
    +  }
    +);
     
     // Console log result:
     // => {'name':'Chris','age':31,'traits':
    @@ -63,35 +74,35 @@ AsyncStorage.let UID234_object = {
       name: 'Chris',
       age: 30,
    -  traits: {hair: 'brown', eyes: 'brown'},
    +  traits: { hair: 'brown', eyes: 'brown' }
     };
     
     // first user, delta values
     let UID234_delta = {
       age: 31,
    -  traits: {eyes: 'blue', shoe_size: 10},
    +  traits: { eyes: 'blue', shoe_size: 10 }
     };
     
     // second user, initial values
     let UID345_object = {
       name: 'Marge',
       age: 25,
    -  traits: {hair: 'blonde', eyes: 'blue'},
    +  traits: { hair: 'blonde', eyes: 'blue' }
     };
     
     // second user, delta values
     let UID345_delta = {
       age: 26,
    -  traits: {eyes: 'green', shoe_size: 6},
    +  traits: { eyes: 'green', shoe_size: 6 }
     };
     
     let multi_set_pairs = [
       ['UID234', JSON.stringify(UID234_object)],
    -  ['UID345', JSON.stringify(UID345_object)],
    +  ['UID345', JSON.stringify(UID345_object)]
     ];
     let multi_merge_pairs = [
       ['UID234', JSON.stringify(UID234_delta)],
    -  ['UID345', JSON.stringify(UID345_delta)],
    +  ['UID345', JSON.stringify(UID345_delta)]
     ];
     
     AsyncStorage.multiSet(multi_set_pairs, (err) => {
    diff --git a/docs/0.10/asyncstorage/index.html b/docs/0.10/asyncstorage/index.html
    index f2b0870222c..148877b2b24 100644
    --- a/docs/0.10/asyncstorage/index.html
    +++ b/docs/0.10/asyncstorage/index.html
    @@ -18,7 +18,10 @@
     

    The AsyncStorage JavaScript code is a facade that provides a clear JavaScript API, real Error objects, and non-multi functions. Each method in the API returns a Promise object.

    Persisting data:

    try {
    -  await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.');
    +  await AsyncStorage.setItem(
    +    '@MySuperStore:key',
    +    'I like to save it.'
    +  );
     } catch (error) {
       // Error saving data
     }
    @@ -38,21 +41,29 @@
     
    let UID123_object = {
       name: 'Chris',
       age: 30,
    -  traits: {hair: 'brown', eyes: 'brown'},
    +  traits: { hair: 'brown', eyes: 'brown' }
     };
     // You only need to define what will be added or updated
     let UID123_delta = {
       age: 31,
    -  traits: {eyes: 'blue', shoe_size: 10},
    +  traits: { eyes: 'blue', shoe_size: 10 }
     };
     
    -AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => {
    -  AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => {
    -    AsyncStorage.getItem('UID123', (err, result) => {
    -      console.log(result);
    -    });
    -  });
    -});
    +AsyncStorage.setItem(
    +  'UID123',
    +  JSON.stringify(UID123_object),
    +  () => {
    +    AsyncStorage.mergeItem(
    +      'UID123',
    +      JSON.stringify(UID123_delta),
    +      () => {
    +        AsyncStorage.getItem('UID123', (err, result) => {
    +          console.log(result);
    +        });
    +      }
    +    );
    +  }
    +);
     
     // Console log result:
     // => {'name':'Chris','age':31,'traits':
    @@ -63,35 +74,35 @@ AsyncStorage.let UID234_object = {
       name: 'Chris',
       age: 30,
    -  traits: {hair: 'brown', eyes: 'brown'},
    +  traits: { hair: 'brown', eyes: 'brown' }
     };
     
     // first user, delta values
     let UID234_delta = {
       age: 31,
    -  traits: {eyes: 'blue', shoe_size: 10},
    +  traits: { eyes: 'blue', shoe_size: 10 }
     };
     
     // second user, initial values
     let UID345_object = {
       name: 'Marge',
       age: 25,
    -  traits: {hair: 'blonde', eyes: 'blue'},
    +  traits: { hair: 'blonde', eyes: 'blue' }
     };
     
     // second user, delta values
     let UID345_delta = {
       age: 26,
    -  traits: {eyes: 'green', shoe_size: 6},
    +  traits: { eyes: 'green', shoe_size: 6 }
     };
     
     let multi_set_pairs = [
       ['UID234', JSON.stringify(UID234_object)],
    -  ['UID345', JSON.stringify(UID345_object)],
    +  ['UID345', JSON.stringify(UID345_object)]
     ];
     let multi_merge_pairs = [
       ['UID234', JSON.stringify(UID234_delta)],
    -  ['UID345', JSON.stringify(UID345_delta)],
    +  ['UID345', JSON.stringify(UID345_delta)]
     ];
     
     AsyncStorage.multiSet(multi_set_pairs, (err) => {
    diff --git a/docs/0.10/communication-ios.html b/docs/0.10/communication-ios.html
    index 7b370cf6f91..acb7604422c 100644
    --- a/docs/0.10/communication-ios.html
    +++ b/docs/0.10/communication-ios.html
    @@ -87,11 +87,11 @@ RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                               initialProperties:props];
     
    import React from 'react';
    -import {View, Image} from 'react-native';
    +import { View, Image } from 'react-native';
     
     export default class ImageBrowserApp extends React.Component {
       renderImage(imgURI) {
    -    return <Image source={{uri: imgURI}} />;
    +    return <Image source={{ uri: imgURI }} />;
       }
       render() {
         return <View>{this.props.images.map(this.renderImage)}</View>;
    diff --git a/docs/0.10/communication-ios/index.html b/docs/0.10/communication-ios/index.html
    index 7b370cf6f91..acb7604422c 100644
    --- a/docs/0.10/communication-ios/index.html
    +++ b/docs/0.10/communication-ios/index.html
    @@ -87,11 +87,11 @@ RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                               initialProperties:props];
     
    import React from 'react';
    -import {View, Image} from 'react-native';
    +import { View, Image } from 'react-native';
     
     export default class ImageBrowserApp extends React.Component {
       renderImage(imgURI) {
    -    return <Image source={{uri: imgURI}} />;
    +    return <Image source={{ uri: imgURI }} />;
       }
       render() {
         return <View>{this.props.images.map(this.renderImage)}</View>;
    diff --git a/docs/0.10/custom-webview-android.html b/docs/0.10/custom-webview-android.html
    index 6f29d10273f..6963b4128a1 100644
    --- a/docs/0.10/custom-webview-android.html
    +++ b/docs/0.10/custom-webview-android.html
    @@ -164,15 +164,18 @@
     
  • Return a WebView component with the prop nativeConfig.component set to your native component (see below)
  • To get your native component, you must use requireNativeComponent: the same as for regular custom components. However, you must pass in an extra third argument, WebView.extraNativeComponentConfig. This third argument contains prop types that are only required for native code.

    -
    import React, {Component, PropTypes} from 'react';
    -import {WebView, requireNativeComponent} from 'react-native';
    +
    import React, { Component, PropTypes } from 'react';
    +import { WebView, requireNativeComponent } from 'react-native';
     
     export default class CustomWebView extends Component {
       static propTypes = WebView.propTypes;
     
       render() {
         return (
    -      <WebView {...this.props} nativeConfig={{component: RCTCustomWebView}} />
    +      <WebView
    +        {...this.props}
    +        nativeConfig={{ component: RCTCustomWebView }}
    +      />
         );
       }
     }
    @@ -180,7 +183,7 @@
     const RCTCustomWebView = requireNativeComponent(
       'RCTCustomWebView',
       CustomWebView,
    -  WebView.extraNativeComponentConfig,
    +  WebView.extraNativeComponentConfig
     );
     

    If you want to add custom props to your native component, you can use nativeConfig.props on the web view.

    @@ -190,15 +193,15 @@ static propTypes = { ...WebView.propTypes, finalUrl: PropTypes.string, - onNavigationCompleted: PropTypes.func, + onNavigationCompleted: PropTypes.func }; static defaultProps = { - finalUrl: 'about:blank', + finalUrl: 'about:blank' }; _onNavigationCompleted = (event) => { - const {onNavigationCompleted} = this.props; + const { onNavigationCompleted } = this.props; onNavigationCompleted && onNavigationCompleted(event); }; @@ -210,8 +213,8 @@ component: RCTCustomWebView, props: { finalUrl: this.props.finalUrl, - onNavigationCompleted: this._onNavigationCompleted, - }, + onNavigationCompleted: this._onNavigationCompleted + } }} /> ); @@ -227,9 +230,9 @@ ...WebView.extraNativeComponentConfig, nativeOnly: { ...WebView.extraNativeComponentConfig.nativeOnly, - onScrollToBottom: true, - }, - }, + onScrollToBottom: true + } + } );