From 32951dd4bd548f3ab40d8d7f507ae1ec9a1c0249 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrycja=20Kali=C5=84ska?=
<59940332+patrycjakalinska@users.noreply.github.com>
Date: Wed, 17 Jul 2024 12:41:57 +0200
Subject: [PATCH 1/3] fix: docs: Access before initialization on withSpring and
withTiming (#6282)
Before on docs using `withSpring` and `withTiming` playgrounds
(Customising animations, withSpring, withTiming):
After:
## Test plan
1. Run `yarn && yarn build && yarn serve`
2. Check `Customising animations`, `withSpring`, `withTiming`
documentation pages (they are must, but full docs checkup is
recommended)
---
.../InteractivePlayground/useSpringPlayground/Example.tsx | 3 ++-
.../InteractivePlayground/useTimingPlayground/Example.tsx | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/packages/docs-reanimated/src/components/InteractivePlayground/useSpringPlayground/Example.tsx b/packages/docs-reanimated/src/components/InteractivePlayground/useSpringPlayground/Example.tsx
index 48ab2dffc45..7eddedfd99b 100644
--- a/packages/docs-reanimated/src/components/InteractivePlayground/useSpringPlayground/Example.tsx
+++ b/packages/docs-reanimated/src/components/InteractivePlayground/useSpringPlayground/Example.tsx
@@ -23,6 +23,8 @@ export default function App({ width, options }: Props) {
const shouldReduceMotion =
options.reduceMotion === ReduceMotion.Always ||
(options.reduceMotion === ReduceMotion.System && reduceMotion);
+ const [buttonDisabled, setButtonDisabled] = useState(false);
+
const callback = (isFinished) => {
setTimeout(() => {
if (isFinished) {
@@ -31,7 +33,6 @@ export default function App({ width, options }: Props) {
}
}, 1000);
};
- const [buttonDisabled, setButtonDisabled] = useState(false);
const animatedStyles = useAnimatedStyle(() => {
return {
diff --git a/packages/docs-reanimated/src/components/InteractivePlayground/useTimingPlayground/Example.tsx b/packages/docs-reanimated/src/components/InteractivePlayground/useTimingPlayground/Example.tsx
index befc15a9e11..9f9fd22751f 100644
--- a/packages/docs-reanimated/src/components/InteractivePlayground/useTimingPlayground/Example.tsx
+++ b/packages/docs-reanimated/src/components/InteractivePlayground/useTimingPlayground/Example.tsx
@@ -23,6 +23,8 @@ export default function App({ width, options }: Props) {
const shouldReduceMotion =
options.reduceMotion === ReduceMotion.Always ||
(options.reduceMotion === ReduceMotion.System && reduceMotion);
+ const [buttonDisabled, setButtonDisabled] = useState(false);
+
const callback = (isFinished) => {
setTimeout(
() => {
@@ -34,7 +36,6 @@ export default function App({ width, options }: Props) {
shouldReduceMotion ? 1000 : options.duration
);
};
- const [buttonDisabled, setButtonDisabled] = useState(false);
const animatedStyles = useAnimatedStyle(() => {
return {
From a462b8910730779349f6e0c6ca0fb6fbbf48a747 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrycja=20Kali=C5=84ska?=
<59940332+patrycjakalinska@users.noreply.github.com>
Date: Wed, 17 Jul 2024 12:43:35 +0200
Subject: [PATCH 2/3] docs: Rewrite getRelativeCoords documentation page
(#6249)
To be up to date we rewritten
[getRelativeCoords](https://docs.swmansion.com/react-native-reanimated/docs/utilities/getRelativeCoords/)
and implemented InteractiveExample.
-
[#6165](https://github.com/software-mansion/react-native-reanimated/pull/6165)
- needs to be merged before - it bumped `react-native-reanimated` to
latest where `getRelativeCoords` work
Before:
https://github.com/software-mansion/react-native-reanimated/assets/59940332/6372409d-6eb7-4d8c-b339-13ea8090b509
After:
https://github.com/software-mansion/react-native-reanimated/assets/59940332/a4335d87-0dc3-4dab-93da-86f7ffbb9ba0
---
.../docs/utilities/getRelativeCoords.mdx | 89 +++++++++++++------
.../src/examples/RelativeCoords.tsx | 85 ++++++++++++++++++
2 files changed, 148 insertions(+), 26 deletions(-)
create mode 100644 packages/docs-reanimated/src/examples/RelativeCoords.tsx
diff --git a/packages/docs-reanimated/docs/utilities/getRelativeCoords.mdx b/packages/docs-reanimated/docs/utilities/getRelativeCoords.mdx
index fc04d0b2992..6d02fd2367f 100644
--- a/packages/docs-reanimated/docs/utilities/getRelativeCoords.mdx
+++ b/packages/docs-reanimated/docs/utilities/getRelativeCoords.mdx
@@ -4,25 +4,68 @@ sidebar_position: 4
# getRelativeCoords
-import DocsCompatibilityInfo from '../_shared/_docs_compatibility_info.mdx';
+`getRelativeCoords` determines the location on the screen, relative to the given view.
-
+## Reference
-Determines the location on the screen, relative to the given view. It might be useful when there are only absolute coordinates available and you need coordinates relative to the parent.
+```tsx
+import { getRelativeCoords } from 'react-native-reanimated';
+
+const Comp = () => {
+ const animatedRef = useAnimatedRef();
+ // ...
+
+ const gestureHandler = useAnimatedGestureHandler({
+ onEnd: (event) => {
+ const coords = getRelativeCoords(
+ animatedRef,
+ event.absoluteX,
+ event.absoluteY
+ );
+ },
+ });
+
+ return (
+
+
+
+
+
+ );
+};
+```
+
+
+Type definitions
+
+```typescript
+function getRelativeCoords(
+ animatedRef: AnimatedRef,
+ absoluteX: number,
+ absoluteY: number
+): ComponentCoords | null;
+
+interface ComponentCoords {
+ x: number;
+ y: number;
+}
+```
+
+
### Arguments
-#### animatedRef
+#### `animatedRef`
The product of [`useAnimatedRef`](/docs/core/useAnimatedRef) is Reanimated's extension of a standard React ref (delivers the view tag on the UI thread). This ref should be passed as a prop to the view relative to which we want to know coordinates.
-#### x
+#### `absoluteX`
-Absolute `x` coordinate.
+Number which is an absolute `x` coordinate.
-#### y
+#### `absoluteY`
-Absolute `y` coordinate
+Number which is an absolute `y` coordinate.
### Returns
@@ -33,23 +76,17 @@ Object which contains relative coordinates
### Example
-```js
-const Comp = () => {
- const aref = useAnimatedRef();
- // ...
+import RelativeCoords from '@site/src/examples/RelativeCoords';
+import RelativeCoordsSrc from '!!raw-loader!@site/src/examples/RelativeCoords';
- const gestureHandler = useAnimatedGestureHandler({
- onEnd: (event) => {
- getRelativeCoords(aref, event.absoluteX, event.absoluteY);
- },
- });
+
- return (
-
-
-
-
-
- );
-};
-```
+## Platform compatibility
+
+
+
+| Android | iOS | Web |
+| ------- | --- | --- |
+| ✅ | ✅ | ✅ |
+
+
diff --git a/packages/docs-reanimated/src/examples/RelativeCoords.tsx b/packages/docs-reanimated/src/examples/RelativeCoords.tsx
new file mode 100644
index 00000000000..530ee0c2b3b
--- /dev/null
+++ b/packages/docs-reanimated/src/examples/RelativeCoords.tsx
@@ -0,0 +1,85 @@
+import React, { useState } from 'react';
+import { View, Text, StyleSheet } from 'react-native';
+import Animated, {
+ useAnimatedRef,
+ getRelativeCoords,
+} from 'react-native-reanimated';
+import { useColorScheme } from '@mui/material';
+import { Gesture, GestureDetector } from 'react-native-gesture-handler';
+
+const RelativeCoords = () => {
+ const animatedRef = useAnimatedRef();
+ const { colorScheme } = useColorScheme();
+ const [coords, setCoords] = useState({ x: 0, y: 0 });
+
+ const tapGesture = Gesture.Tap().onEnd((event) => {
+ const relativeCoords = getRelativeCoords(
+ animatedRef,
+ event.absoluteX,
+ event.absoluteY
+ );
+ if (relativeCoords) {
+ setCoords(relativeCoords);
+ }
+ });
+
+ const textColor =
+ colorScheme === 'light' ? styles.darkText : styles.lightText;
+
+ return (
+
+
+ Relative coordinates to parent:
+
+
+ x={coords.x.toFixed()} y=
+ {coords.y.toFixed()}
+
+
+
+ Tap anywhere inside.
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ innerView: {
+ width: 300,
+ height: 300,
+ backgroundColor: 'var(--swm-purple-light-80)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderRadius: 40,
+ cursor: 'pointer',
+ },
+ coordsData: {
+ fontSize: 20,
+ fontFamily: 'Aeonik',
+ color: 'var(--swm-navy-light-100)',
+ },
+ coords: {
+ marginBottom: 16,
+ fontWeight: '500',
+ },
+ text: {
+ color: 'var(--swm-off-white)',
+ fontFamily: 'Aeonik',
+ fontSize: 16,
+ fontWeight: 'bold',
+ },
+ lightText: {
+ color: 'var(--swm-off-white)',
+ },
+ darkText: {
+ color: 'var(--swm-navy-light-100)',
+ },
+});
+
+export default RelativeCoords;
From a4633869f1e487c966b3b6e2d4063ea693f2419e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20=C5=BBelawski?=
<40713406+tjzel@users.noreply.github.com>
Date: Wed, 17 Jul 2024 12:49:35 +0200
Subject: [PATCH 3/3] refactor: Improve UX of runtime tests menu (#6283)
## Summary
- Lazy evaluation of imports; it was impossible to uncheck a test suite.
- More explicit UI; it was hard to tell what test suites were enabled.
- QoL information the user has to reload the app to re-run tests.
- Minor code readability improvements.
https://github.com/user-attachments/assets/2a3135ab-a3ce-4433-a8b1-eeb3cf3fde13
---
.../RuntimeTestsRunner.tsx | 263 +++++++++++++-----
.../RuntimeTests/RuntimeTestsExample.tsx | 18 +-
2 files changed, 196 insertions(+), 85 deletions(-)
diff --git a/apps/common-app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsRunner.tsx b/apps/common-app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsRunner.tsx
index 162b810cf75..0a98617e7c8 100644
--- a/apps/common-app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsRunner.tsx
+++ b/apps/common-app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/RuntimeTestsRunner.tsx
@@ -1,16 +1,9 @@
-import { View, TouchableOpacity, StyleSheet, Text } from 'react-native';
+import { View, StyleSheet, Text, Pressable } from 'react-native';
import type { ReactNode } from 'react';
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import { runTests, configure } from './RuntimeTestsApi';
import { RenderLock } from './SyncUIRunner';
-interface ImportButton {
- testSuiteName: string;
- importTest: () => void;
- skipByDefault?: boolean;
-}
-
-let renderLock: RenderLock = new RenderLock();
export class ErrorBoundary extends React.Component<
{ children: React.JSX.Element | Array },
{ hasError: boolean }
@@ -34,77 +27,51 @@ export class ErrorBoundary extends React.Component<
}
}
-function ImportButtons({ importButtons }: { importButtons: Array }) {
- const [importedTests, setImportedTests] = useState>([]);
- const [importedAll, setImportedAll] = useState(false);
-
- const handleImportAllClick = () => {
- setImportedAll(true);
- const newImportedTests = importedTests;
- for (const button of importButtons) {
- if (!button.skipByDefault) {
- button.importTest();
- if (!importedTests.includes(button.testSuiteName)) {
- newImportedTests.push(button.testSuiteName);
- }
- }
- }
- setImportedTests(newImportedTests);
- };
+let renderLock: RenderLock = new RenderLock();
- const handleImportClick = (button: ImportButton) => {
- button.importTest();
- if (!importedTests.includes(button.testSuiteName)) {
- setImportedTests([...importedTests, button.testSuiteName]);
- }
- };
- return (
-
-
- Import all reanimated tests
-
-
-
- {importButtons.map(importButton => {
- const { testSuiteName } = importButton;
- return (
- handleImportClick(importButton)}
- style={[styles.importButton, importedTests.includes(testSuiteName) ? styles.importButtonImported : {}]}>
- {testSuiteName}
-
- );
- })}
-
-
- );
+interface TestData {
+ testSuiteName: string;
+ importTest: () => void;
+ skipByDefault?: boolean;
}
-export default function RuntimeTestsRunner({ importButtons }: { importButtons: Array }) {
+interface RuntimeTestRunnerProps {
+ tests: TestData[];
+}
+
+export default function RuntimeTestsRunner({ tests }: RuntimeTestRunnerProps) {
const [component, setComponent] = useState(null);
const [started, setStarted] = useState(false);
+ const testSelectionCallbacks = useRef void>>(new Set());
useEffect(() => {
if (renderLock) {
renderLock.unlock();
}
}, [component]);
+
+ async function run() {
+ renderLock = configure({ render: setComponent });
+ await runTests();
+ }
+
+ function handleStartClick() {
+ testSelectionCallbacks.current.forEach(callback => callback());
+ setStarted(true);
+ // eslint-disable-next-line no-void
+ void run();
+ }
+
return (
- {started ? null : }
- {started ? null : (
- {
- setStarted(true);
- renderLock = configure({ render: setComponent });
- await runTests();
- }}
- style={styles.button}>
- Run tests
-
+ {started ? (
+ Reload the app to run the tests again
+ ) : (
+ <>
+
+
+ Run tests
+
+ >
)}
{/* Don't render anything if component is undefined to prevent blinking */}
@@ -113,23 +80,142 @@ export default function RuntimeTestsRunner({ importButtons }: { importButtons: A
);
}
+interface TestSelectorProps {
+ tests: Array;
+ testSelectionCallbacks: React.RefObject void>>;
+}
+
+function TestSelector({ tests, testSelectionCallbacks }: TestSelectorProps) {
+ const [selectedTests, setSelectedTests] = useState