diff --git a/docs/manifest.json b/docs/manifest.json
index abcc27569c88e..5ffb21b8e7c86 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -1037,6 +1037,12 @@
"markdown_source": "../packages/components/src/menu-items-choice/README.md",
"parent": "components"
},
+ {
+ "title": "BottomSheetNavigation",
+ "slug": "bottom-sheet-navigation",
+ "markdown_source": "../packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/README.md",
+ "parent": "components"
+ },
{
"title": "Modal",
"slug": "modal",
diff --git a/package-lock.json b/package-lock.json
index 30a0b3d39da0a..1ef619832ba3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1367,6 +1367,14 @@
"minimist": "^1.2.0"
}
},
+ "@egjs/hammerjs": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
+ "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
+ "requires": {
+ "@types/hammerjs": "^2.0.36"
+ }
+ },
"@egoist/vue-to-react": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@egoist/vue-to-react/-/vue-to-react-1.1.0.tgz",
@@ -7092,10 +7100,80 @@
"resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-3.0.0.tgz",
"integrity": "sha512-ng6Tm537E/M42GjE4TRUxQyL8sRfClcL7bQWblOCoxPZzJ2J3bdALsjeG3vDnVCIfI/R0AeFalN9KjMt0+Z/Zg=="
},
+ "@react-native-community/masked-view": {
+ "version": "git+https://github.com/wordpress-mobile/react-native-masked-view.git#098004d0968f853fc7d96c2aa5f96afe7a133c58",
+ "from": "git+https://github.com/wordpress-mobile/react-native-masked-view.git#098004d0968f853fc7d96c2aa5f96afe7a133c58"
+ },
"@react-native-community/slider": {
"version": "git+https://github.com/wordpress-mobile/react-native-slider.git#d263ff16cdd9fb7352b354342522ff030f220f42",
"from": "git+https://github.com/wordpress-mobile/react-native-slider.git#d263ff16cdd9fb7352b354342522ff030f220f42"
},
+ "@react-navigation/core": {
+ "version": "5.12.0",
+ "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-5.12.0.tgz",
+ "integrity": "sha512-CTmYrFXCZwInN40CpEzkPxhrpzujj20qvsUgpH05+oO1flwsnaJsyBfYawIcTS62/1/Z6SAM7iW5PbKk+qw9iQ==",
+ "requires": {
+ "@react-navigation/routers": "^5.4.9",
+ "escape-string-regexp": "^4.0.0",
+ "nanoid": "^3.1.9",
+ "query-string": "^6.13.1",
+ "react-is": "^16.13.0",
+ "use-subscription": "^1.4.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+ },
+ "query-string": {
+ "version": "6.13.1",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.1.tgz",
+ "integrity": "sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA==",
+ "requires": {
+ "decode-uri-component": "^0.2.0",
+ "split-on-first": "^1.0.0",
+ "strict-uri-encode": "^2.0.0"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "strict-uri-encode": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
+ "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
+ }
+ }
+ },
+ "@react-navigation/native": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-5.7.0.tgz",
+ "integrity": "sha512-a2JBOdRB3q20Jdc5hF8shR4Dk+ZmjF2Rr9RviErtARztu08lU+jcb1gK6c31OKL37JDuaS3xexE9Cb7dYeMy3Q==",
+ "requires": {
+ "@react-navigation/core": "^5.12.0",
+ "nanoid": "^3.1.9"
+ }
+ },
+ "@react-navigation/routers": {
+ "version": "5.4.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-5.4.9.tgz",
+ "integrity": "sha512-dYD5qrIKUmuBEp+O98hB0tDYpEsGQgCQFQgMEoFKBmVVhx2JnJJ1zxRjU7xWcCU4VdBA8IOowgHQHJsVNKYyrg==",
+ "requires": {
+ "nanoid": "^3.1.9"
+ }
+ },
+ "@react-navigation/stack": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-5.6.2.tgz",
+ "integrity": "sha512-51Aasxg8j2eKxz4mhA0ajJXrhAyJQkk2iiNE511zcqJ3tlfxv/h70Eej3PetnbbHFMOwNsEwc2GjB3OnfQcxjQ==",
+ "requires": {
+ "color": "^3.1.2",
+ "react-native-iphone-x-helper": "^1.2.1"
+ }
+ },
"@samverschueren/stream-to-observable": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
@@ -10116,6 +10194,11 @@
"@types/node": "*"
}
},
+ "@types/hammerjs": {
+ "version": "2.0.36",
+ "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz",
+ "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ=="
+ },
"@types/history": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.4.tgz",
@@ -11762,7 +11845,10 @@
"requires": {
"@babel/runtime": "^7.9.2",
"@react-native-community/blur": "3.6.0",
+ "@react-native-community/masked-view": "git+https://github.com/wordpress-mobile/react-native-masked-view.git#098004d0968f853fc7d96c2aa5f96afe7a133c58",
"@react-native-community/slider": "git+https://github.com/wordpress-mobile/react-native-slider.git#d263ff16cdd9fb7352b354342522ff030f220f42",
+ "@react-navigation/native": "^5.6.1",
+ "@react-navigation/stack": "5.6.2",
"@wordpress/api-fetch": "file:packages/api-fetch",
"@wordpress/block-editor": "file:packages/block-editor",
"@wordpress/block-library": "file:packages/block-library",
@@ -11784,14 +11870,18 @@
"node-fetch": "^2.6.0",
"react-native": "0.61.5",
"react-native-dark-mode": "git+https://github.com/wordpress-mobile/react-native-dark-mode.git#f09bf1480e7b34536413ab3300f29e4375edb2c6",
+ "react-native-gesture-handler": "git+https://github.com/wordpress-mobile/react-native-gesture-handler.git#b80e959908b383a26d6e35d992d6d529efad0b16",
"react-native-get-random-values": "git+https://github.com/wordpress-mobile/react-native-get-random-values.git#f03f2c16414aff4ea76064dcd00a9e3c6efc838d",
"react-native-hr": "git+https://github.com/Riglerr/react-native-hr.git#2d01a5cf77212d100e8b99e0310cce5234f977b3",
"react-native-hsv-color-picker": "git+https://github.com/wordpress-mobile/react-native-hsv-color-picker.git",
"react-native-keyboard-aware-scroll-view": "git+https://github.com/wordpress-mobile/react-native-keyboard-aware-scroll-view.git#gb-v0.8.8",
"react-native-linear-gradient": "git+https://github.com/wordpress-mobile/react-native-linear-gradient.git#52bf43077171cff8714ce3e0155f3ebb7f55bc37",
"react-native-modal": "^6.5.0",
+ "react-native-reanimated": "git+https://github.com/wordpress-mobile/react-native-reanimated.git#ed48f510fba751cd75da7629e92276166766be91",
"react-native-safe-area": "^0.5.0",
+ "react-native-safe-area-context": "git+https://github.com/wordpress-mobile/react-native-safe-area-context.git#1e3c0d34f31b59fb79f71ec0b4c39c513f684871",
"react-native-sass-transformer": "^1.1.1",
+ "react-native-screens": "git+https://github.com/wordpress-mobile/react-native-screens.git#835843f4c3697bba5c330d05d8fc270d50ca9d2a",
"react-native-svg": "git+https://github.com/wordpress-mobile/react-native-svg.git#a628e92990a2404e30a0086f168bd2b5b7b4ce96",
"react-native-url-polyfill": "^1.1.2",
"react-native-video": "git+https://github.com/wordpress-mobile/react-native-video.git#1b964b107863351ed744fc104d7952bbec3e2d4f"
@@ -22760,6 +22850,15 @@
"object-visit": "^1.0.0"
}
},
+ "color": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz",
+ "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==",
+ "requires": {
+ "color-convert": "^1.9.1",
+ "color-string": "^1.5.2"
+ }
+ },
"color-convert": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
@@ -22773,6 +22872,15 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok="
},
+ "color-string": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
+ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
"color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
@@ -40442,6 +40550,11 @@
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
},
+ "nanoid": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.10.tgz",
+ "integrity": "sha512-iZFMXKeXWkxzlfmMfM91gw7YhN2sdJtixY+eZh9V6QWJWTOiurhpKhBMgr82pfzgSqglQgqYSCowEYsz8D++6w=="
+ },
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -46392,6 +46505,16 @@
}
}
},
+ "react-native-gesture-handler": {
+ "version": "git+https://github.com/wordpress-mobile/react-native-gesture-handler.git#b80e959908b383a26d6e35d992d6d529efad0b16",
+ "from": "git+https://github.com/wordpress-mobile/react-native-gesture-handler.git#b80e959908b383a26d6e35d992d6d529efad0b16",
+ "requires": {
+ "@egjs/hammerjs": "^2.0.17",
+ "hoist-non-react-statics": "^2.3.1",
+ "invariant": "^2.2.4",
+ "prop-types": "^15.7.2"
+ }
+ },
"react-native-get-random-values": {
"version": "git+https://github.com/wordpress-mobile/react-native-get-random-values.git#f03f2c16414aff4ea76064dcd00a9e3c6efc838d",
"from": "git+https://github.com/wordpress-mobile/react-native-get-random-values.git#f03f2c16414aff4ea76064dcd00a9e3c6efc838d",
@@ -46437,6 +46560,35 @@
"react-native-animatable": "^1.2.4"
}
},
+ "react-native-reanimated": {
+ "version": "git+https://github.com/wordpress-mobile/react-native-reanimated.git#ed48f510fba751cd75da7629e92276166766be91",
+ "from": "git+https://github.com/wordpress-mobile/react-native-reanimated.git#ed48f510fba751cd75da7629e92276166766be91",
+ "requires": {
+ "fbjs": "^1.0.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+ "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
+ },
+ "fbjs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz",
+ "integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==",
+ "requires": {
+ "core-js": "^2.4.1",
+ "fbjs-css-vars": "^1.0.0",
+ "isomorphic-fetch": "^2.1.1",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^0.7.18"
+ }
+ }
+ }
+ },
"react-native-safe-area": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/react-native-safe-area/-/react-native-safe-area-0.5.1.tgz",
@@ -46445,6 +46597,10 @@
"@types/react": "^16.8.8"
}
},
+ "react-native-safe-area-context": {
+ "version": "git+https://github.com/wordpress-mobile/react-native-safe-area-context.git#1e3c0d34f31b59fb79f71ec0b4c39c513f684871",
+ "from": "git+https://github.com/wordpress-mobile/react-native-safe-area-context.git#1e3c0d34f31b59fb79f71ec0b4c39c513f684871"
+ },
"react-native-sass-transformer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/react-native-sass-transformer/-/react-native-sass-transformer-1.4.0.tgz",
@@ -46462,6 +46618,10 @@
}
}
},
+ "react-native-screens": {
+ "version": "git+https://github.com/wordpress-mobile/react-native-screens.git#835843f4c3697bba5c330d05d8fc270d50ca9d2a",
+ "from": "git+https://github.com/wordpress-mobile/react-native-screens.git#835843f4c3697bba5c330d05d8fc270d50ca9d2a"
+ },
"react-native-svg": {
"version": "git+https://github.com/wordpress-mobile/react-native-svg.git#a628e92990a2404e30a0086f168bd2b5b7b4ce96",
"from": "git+https://github.com/wordpress-mobile/react-native-svg.git#a628e92990a2404e30a0086f168bd2b5b7b4ce96",
@@ -48896,7 +49056,6 @@
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
- "dev": true,
"requires": {
"is-arrayish": "^0.3.1"
},
@@ -48904,8 +49063,7 @@
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
- "dev": true
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},
@@ -49275,6 +49433,11 @@
"through": "2"
}
},
+ "split-on-first": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
+ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
+ },
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
@@ -52858,6 +53021,14 @@
"tslib": "^1.9.3"
}
},
+ "use-subscription": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.4.1.tgz",
+ "integrity": "sha512-7+IIwDG/4JICrWHL/Q/ZPK5yozEnvRm6vHImu0LKwQlmWGKeiF7mbAenLlK/cTNXrTtXHU/SFASQHzB6+oSJMQ==",
+ "requires": {
+ "object-assign": "^4.1.1"
+ }
+ },
"util": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
diff --git a/packages/block-editor/src/components/block-settings/container.native.js b/packages/block-editor/src/components/block-settings/container.native.js
index 302030563debe..a316b2c86cf5f 100644
--- a/packages/block-editor/src/components/block-settings/container.native.js
+++ b/packages/block-editor/src/components/block-settings/container.native.js
@@ -1,21 +1,20 @@
/**
* WordPress dependencies
*/
-import {
- BottomSheet,
- BottomSheetConsumer,
- ColorSettings,
- colorsUtils,
-} from '@wordpress/components';
-import { withSelect, withDispatch } from '@wordpress/data';
-import { compose } from '@wordpress/compose';
import { InspectorControls } from '@wordpress/block-editor';
-
+import { BottomSheet, ColorSettings } from '@wordpress/components';
+import { compose } from '@wordpress/compose';
+import { withDispatch, withSelect } from '@wordpress/data';
/**
* Internal dependencies
*/
import styles from './container.native.scss';
+export const blockSettingsScreens = {
+ settings: 'Settings',
+ color: 'Color',
+};
+
function BottomSheetSettings( {
editorSidebarOpened,
closeGeneralSidebar,
@@ -30,23 +29,18 @@ function BottomSheetSettings( {
contentStyle={ styles.content }
{ ...props }
>
-
- { ( { currentScreen, extraProps, ...bottomSheetProps } ) => {
- switch ( currentScreen ) {
- case colorsUtils.subsheets.color:
- return (
-
- );
- case colorsUtils.subsheets.settings:
- default:
- return ;
- }
- } }
-
+
+
+
+
+
+
+
+
);
}
diff --git a/packages/block-editor/src/components/block-settings/index.native.js b/packages/block-editor/src/components/block-settings/index.native.js
index f3895a9c69792..9daa470d59798 100644
--- a/packages/block-editor/src/components/block-settings/index.native.js
+++ b/packages/block-editor/src/components/block-settings/index.native.js
@@ -1,2 +1,5 @@
export { default as BlockSettingsButton } from './button';
-export { default as BottomSheetSettings } from './container';
+export {
+ default as BottomSheetSettings,
+ blockSettingsScreens,
+} from './container';
diff --git a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js
index f9e7bd2950dc0..126064cfd3865 100644
--- a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js
+++ b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js
@@ -1,43 +1,47 @@
+/**
+ * External dependencies
+ */
+import { useNavigation } from '@react-navigation/native';
+
/**
* WordPress dependencies
*/
-import {
- ColorControl,
- BottomSheetConsumer,
- PanelBody,
-} from '@wordpress/components';
+import { ColorControl, PanelBody } from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import { blockSettingsScreens } from '../block-settings';
export default function PanelColorGradientSettings( { settings, title } ) {
+ const navigation = useNavigation();
+
return (
-
- { ( { onReplaceSubsheet } ) =>
- settings.map(
- ( {
- onColorChange,
- colorValue,
- onGradientChange,
- gradientValue,
- label,
- } ) => (
- {
- onReplaceSubsheet( 'Color', {
- onColorChange,
- colorValue: gradientValue || colorValue,
- gradientValue,
- onGradientChange,
- label,
- } );
- } }
- key={ `color-setting-${ label }` }
- label={ label }
- color={ gradientValue || colorValue }
- />
- )
- )
- }
-
+ { settings.map(
+ ( {
+ onColorChange,
+ colorValue,
+ onGradientChange,
+ gradientValue,
+ label,
+ } ) => (
+ {
+ navigation.navigate( blockSettingsScreens.color, {
+ onColorChange,
+ colorValue: gradientValue || colorValue,
+ gradientValue,
+ onGradientChange,
+ label,
+ } );
+ } }
+ key={ `color-setting-${ label }` }
+ label={ label }
+ color={ gradientValue || colorValue }
+ />
+ )
+ ) }
);
}
diff --git a/packages/block-editor/src/components/index.native.js b/packages/block-editor/src/components/index.native.js
index 2dff50cea14cb..fffd9854296b3 100644
--- a/packages/block-editor/src/components/index.native.js
+++ b/packages/block-editor/src/components/index.native.js
@@ -35,7 +35,11 @@ export { default as Caption } from './caption';
export { default as PanelColorSettings } from './panel-color-settings';
export { default as __experimentalPanelColorGradientSettings } from './colors-gradients/panel-color-gradient-settings';
-export { BottomSheetSettings, BlockSettingsButton } from './block-settings';
+export {
+ BottomSheetSettings,
+ BlockSettingsButton,
+ blockSettingsScreens,
+} from './block-settings';
export { default as VideoPlayer, VIDEO_ASPECT_RATIO } from './video-player';
// Content Related Components
diff --git a/packages/block-library/src/cover/edit.native.js b/packages/block-library/src/cover/edit.native.js
index d698791df731d..39e6d685b0557 100644
--- a/packages/block-library/src/cover/edit.native.js
+++ b/packages/block-library/src/cover/edit.native.js
@@ -204,8 +204,8 @@ const Cover = ( {
function openColorPicker() {
if ( isParentSelected ) {
- openGeneralSidebar();
setCustomColorPickerShowing( true );
+ openGeneralSidebar();
}
}
@@ -314,25 +314,29 @@ const Cover = ( {
{ ( {
shouldEnableBottomSheetScroll,
- shouldDisableBottomSheetMaxHeight,
- onCloseBottomSheet,
- onHardwareButtonPress,
+ shouldEnableBottomSheetMaxHeight,
+ onHandleClosingBottomSheet,
+ onHandleHardwareButtonPress,
isBottomSheetContentScrolling,
} ) => (
{
setCustomColor( color );
setColor( color );
} }
onNavigationBack={ closeSettingsBottomSheet }
- onCloseBottomSheet={ onCloseBottomSheet }
- onHardwareButtonPress={ onHardwareButtonPress }
+ onHandleClosingBottomSheet={
+ onHandleClosingBottomSheet
+ }
+ onHandleHardwareButtonPress={
+ onHandleHardwareButtonPress
+ }
onBottomSheetClosed={ () => {
setCustomColorPickerShowing( false );
} }
diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js
index 149063b0e7360..cc75a22c67d3c 100644
--- a/packages/components/src/color-palette/index.native.js
+++ b/packages/components/src/color-palette/index.native.js
@@ -24,7 +24,6 @@ import { usePreferredColorSchemeStyle } from '@wordpress/compose';
import styles from './style.scss';
import ColorIndicator from '../color-indicator';
import { colorsUtils } from '../mobile/color-settings/utils';
-import { performLayoutAnimation } from '../mobile/layout-animation';
const ANIMATION_DURATION = 200;
@@ -138,7 +137,6 @@ function ColorPalette( {
contentWidth - scrollPosition - customIndicatorWidth < width;
if ( isCustomGradientColor ) {
- performLayoutAnimation();
if ( ! isIOS ) {
// Scroll position on Android doesn't adjust automatically when removing the last item from the horizontal list.
// https://github.com/facebook/react-native/issues/27504
diff --git a/packages/components/src/color-picker/index.native.js b/packages/components/src/color-picker/index.native.js
index daea6ce175fbd..27682f7ff2542 100644
--- a/packages/components/src/color-picker/index.native.js
+++ b/packages/components/src/color-picker/index.native.js
@@ -2,12 +2,13 @@
* External dependencies
*/
import { View, Text, TouchableWithoutFeedback, Platform } from 'react-native';
+import React from 'react';
import HsvColorPicker from 'react-native-hsv-color-picker';
import tinycolor from 'tinycolor2';
/**
* WordPress dependencies
*/
-import { useState, useEffect } from '@wordpress/element';
+import { useState, useEffect, useRef } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { BottomSheet } from '@wordpress/components';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
@@ -19,23 +20,27 @@ import styles from './style.scss';
function ColorPicker( {
shouldEnableBottomSheetScroll,
- shouldDisableBottomSheetMaxHeight,
+ shouldEnableBottomSheetMaxHeight,
isBottomSheetContentScrolling,
setColor,
activeColor,
isGradientColor,
onNavigationBack,
- onCloseBottomSheet,
+ onHandleClosingBottomSheet,
onBottomSheetClosed,
- onHardwareButtonPress,
+ onHandleHardwareButtonPress,
bottomLabelText,
} ) {
+ const didMount = useRef( false );
const isIOS = Platform.OS === 'ios';
const hitSlop = { top: 22, bottom: 22, left: 22, right: 22 };
-
- const [ hue, setHue ] = useState( 0 );
- const [ sat, setSaturation ] = useState( 0.5 );
- const [ val, setValue ] = useState( 0.5 );
+ const { h: initH, s: initS, v: initV } =
+ ! isGradientColor && activeColor
+ ? tinycolor( activeColor ).toHsv()
+ : { h: 0, s: 0.5, v: 0.5 };
+ const [ hue, setHue ] = useState( initH );
+ const [ sat, setSaturation ] = useState( initS );
+ const [ val, setValue ] = useState( initV );
const [ savedColor ] = useState( activeColor );
const {
@@ -71,32 +76,24 @@ function ColorPicker( {
`hsv ${ hue } ${ sat } ${ val }`
).toHexString();
- function setHSVFromHex( color ) {
- const { h, s, v } = tinycolor( color ).toHsv();
-
- setHue( h );
- setSaturation( s );
- setValue( v );
- }
-
useEffect( () => {
+ if ( ! didMount.current ) {
+ didMount.current = true;
+ return;
+ }
setColor( currentColor );
}, [ currentColor ] );
useEffect( () => {
- if ( ! isGradientColor && activeColor ) {
- setHSVFromHex( activeColor );
- }
- setColor( activeColor );
- shouldDisableBottomSheetMaxHeight( false );
- onCloseBottomSheet( () => {
+ shouldEnableBottomSheetMaxHeight( false );
+ onHandleClosingBottomSheet( () => {
setColor( savedColor );
if ( onBottomSheetClosed ) {
onBottomSheetClosed();
}
} );
- if ( onHardwareButtonPress ) {
- onHardwareButtonPress( onButtonPress );
+ if ( onHandleHardwareButtonPress ) {
+ onHandleHardwareButtonPress( onButtonPress );
}
}, [] );
@@ -111,8 +108,8 @@ function ColorPicker( {
function onButtonPress( action ) {
onNavigationBack();
- onCloseBottomSheet( null );
- shouldDisableBottomSheetMaxHeight( true );
+ onHandleClosingBottomSheet( null );
+ shouldEnableBottomSheetMaxHeight( true );
setColor( action === 'apply' ? currentColor : savedColor );
if ( onBottomSheetClosed ) {
onBottomSheetClosed();
diff --git a/packages/components/src/custom-gradient-picker/index.native.js b/packages/components/src/custom-gradient-picker/index.native.js
index 696078941d5a6..52d662df0a9bb 100644
--- a/packages/components/src/custom-gradient-picker/index.native.js
+++ b/packages/components/src/custom-gradient-picker/index.native.js
@@ -13,7 +13,6 @@ import { useState } from '@wordpress/element';
* Internal dependencies
*/
import { colorsUtils } from '../mobile/color-settings/utils';
-import { performLayoutAnimation } from '../mobile/layout-animation';
import { getGradientParsed } from './utils';
import { serializeGradient } from './serializer';
import {
@@ -22,14 +21,16 @@ import {
} from './constants';
import styles from './style.scss';
-function CustomGradientPicker( { currentValue, setColor, isGradientColor } ) {
+function CustomGradientPicker( { setColor, currentValue, isGradientColor } ) {
const [ gradientOrientation, setGradientOrientation ] = useState(
HORIZONTAL_GRADIENT_ORIENTATION
);
+ const [ currentColor, setCurrentColor ] = useState( currentValue );
+
const { getGradientType, gradients, gradientOptions } = colorsUtils;
- const { gradientAST } = getGradientParsed( currentValue );
- const gradientType = getGradientType( currentValue );
+ const { gradientAST } = getGradientParsed( currentColor );
+ const gradientType = getGradientType( currentColor );
function isLinearGradient( type ) {
return type === gradients.linear;
@@ -62,7 +63,7 @@ function CustomGradientPicker( { currentValue, setColor, isGradientColor } ) {
function onGradientTypeChange( type ) {
const gradientColor = getGradientColor( type );
- performLayoutAnimation();
+ setCurrentColor( gradientColor );
setColor( gradientColor );
}
@@ -75,7 +76,8 @@ function CustomGradientPicker( { currentValue, setColor, isGradientColor } ) {
},
} );
- if ( isGradientColor && gradientColor !== currentValue ) {
+ if ( isGradientColor && gradientColor !== currentColor ) {
+ setCurrentColor( gradientColor );
setColor( gradientColor );
}
}
@@ -87,7 +89,6 @@ function CustomGradientPicker( { currentValue, setColor, isGradientColor } ) {
DEFAULT_LINEAR_GRADIENT_ANGLE
);
}
-
return (
<>
diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js
index fe5a8df75c8f2..18c46804e64ef 100644
--- a/packages/components/src/index.native.js
+++ b/packages/components/src/index.native.js
@@ -59,7 +59,11 @@ export * from './text';
// Mobile Components
export { default as BottomSheet } from './mobile/bottom-sheet';
-export { BottomSheetConsumer } from './mobile/bottom-sheet/bottom-sheet-context';
+export {
+ BottomSheetConsumer,
+ BottomSheetProvider,
+ BottomSheetContext,
+} from './mobile/bottom-sheet/bottom-sheet-context';
export { default as HTMLTextInput } from './mobile/html-text-input';
export { default as KeyboardAvoidingView } from './mobile/keyboard-avoiding-view';
export { default as KeyboardAwareFlatList } from './mobile/keyboard-aware-flat-list';
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-context.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-context.native.js
index 9252e5daf3ac4..ebfc384f53069 100644
--- a/packages/components/src/mobile/bottom-sheet/bottom-sheet-context.native.js
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-context.native.js
@@ -18,26 +18,23 @@ if (
// Context in BottomSheet is necessary for controlling the
// transition flow between subsheets and replacing a content inside them
-export const {
- Provider: BottomSheetProvider,
- Consumer: BottomSheetConsumer,
-} = createContext( {
+export const BottomSheetContext = createContext( {
// Specifies whether content is currently scrolling
isBottomSheetContentScrolling: false,
// Function called to enable scroll within bottom sheet
shouldEnableBottomSheetScroll: () => {},
- // Function called to disable bottom sheet max height.
+ // Function called to enable/disable bottom sheet max height.
// E.g. used to extend bottom sheet on full screen in ColorPicker,
// which is helpful on small devices with set the largest font/display size.
- shouldDisableBottomSheetMaxHeight: () => {},
+ shouldEnableBottomSheetMaxHeight: () => {},
// Callback that is called on closing bottom sheet
- onCloseBottomSheet: () => {},
+ onHandleClosingBottomSheet: () => {},
// Android only: Function called to control android hardware back button functionality
- onHardwareButtonPress: () => {},
- // Function called to navigate to another subsheet
- onReplaceSubsheet: () => {},
- // Object contains extra data passed to the current subsheet
- extraProps: {},
- // Specifies the currently active subsheet name
- currentScreen: undefined,
+ // Return true if the bottom-sheet default close action shouldn't be called
+ onHandleHardwareButtonPress: () => {},
} );
+
+export const {
+ Provider: BottomSheetProvider,
+ Consumer: BottomSheetConsumer,
+} = BottomSheetContext;
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/README.md b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/README.md
new file mode 100644
index 0000000000000..4ad61cc91f66d
--- /dev/null
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/README.md
@@ -0,0 +1,88 @@
+# BottomSheet Navigation
+We use [`react-navigation`](https://reactnavigation.org/) v5 to handle multiple screens inside the bottom-sheet. We have two components that help use it w/o additional settings.
+- BottomSheet.NavigationContainer
+- BottomSheet.NavigationScreen
+
+## BottomSheet.NavigationContainer
+
+`BottomSheet.NavigationContainer` is a React component to render a Stack Navigator with settings prepared for the Bottom-Sheet. This component also handles the height animation of bottom-sheet when back or pushing a new screen.
+
+**NOTE:** Children of the `BottomSheet.NavigationContainer` can be only `BottomSheet.NavigationScreen`
+
+## BottomSheet.NavigationScreen
+
+`BottomSheet.NavigationScreen` is a React component to render a Screen inside the stack that is passed from parent. This component can be rendered only inside the `BottomSheet.NavigationContainer` and is responsible for handling the hardware back button on Android and setting the correct height of the parent (container).
+
+
+## Usage
+
+
+```jsx
+import { BottomSheet } from '@wordpress/components';
+
+
+const BottomSheetWithNavigation = () => (
+
+
+
+
+
+
+
+
+
+
+);
+```
+
+## Props
+
+### BottomSheet.NavigationContainer
+The component accepts the following props.
+
+### animate
+
+This prop determines if the container height should be animated. It should be set to `true` only for the root container in BottomSheet. In nested `BottomSheet.NavigationContainer` set it to `false`.
+
+- Type: `Boolean`
+- Required: No
+- Default: `false`
+
+### main
+
+Since we do not wrap the whole editor inside navigation (yet) we need to determine if the container is the very top one (root one). Set it to `true` in only for NOT nested navigation container.
+
+Note: This prop is needed until we wrap the editor inside the navigation container.
+
+- Type: `Boolean`
+- Required: No
+- Default: `false`
+
+### theme
+
+This prop is to set the theme of navigation containers. Please read: https://reactnavigation.org/docs/themes/
+
+- Type: `Object`
+- Required: No
+
+
+### BottomSheet.NavigationScreen
+The component accepts the following props. Props not included in this set will be applied to the Stack.Screen from `react-navigation`.
+
+### name
+
+This prop is used as a Screen name.
+
+- Type: `String`
+- Required: Yes
+
+### children
+
+The component that should be rendered as content.
+
+- Type: React Element
+- Required: Yes
\ No newline at end of file
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/bottom-sheet-navigation-context.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/bottom-sheet-navigation-context.native.js
new file mode 100644
index 0000000000000..9e89c285b2534
--- /dev/null
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/bottom-sheet-navigation-context.native.js
@@ -0,0 +1,16 @@
+/**
+ * WordPress dependencies
+ */
+import { createContext } from '@wordpress/element';
+
+// Navigation context in BottomSheet is necessary for controlling the
+// height of navigation container.
+export const BottomSheetNavigationContext = createContext( {
+ currentHeight: 1,
+ setHeight: () => {},
+} );
+
+export const {
+ Provider: BottomSheetNavigationProvider,
+ Consumer: BottomSheetNavigationConsumer,
+} = BottomSheetNavigationContext;
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js
new file mode 100644
index 0000000000000..a8b802d6cf2cb
--- /dev/null
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js
@@ -0,0 +1,129 @@
+/**
+ * External dependencies
+ */
+import { View, Easing } from 'react-native';
+import { NavigationContainer, DefaultTheme } from '@react-navigation/native';
+import { createStackNavigator } from '@react-navigation/stack';
+
+/**
+ * WordPress dependencies
+ */
+import {
+ useState,
+ useContext,
+ useMemo,
+ Children,
+ useRef,
+} from '@wordpress/element';
+
+import { usePreferredColorSchemeStyle } from '@wordpress/compose';
+
+/**
+ * Internal dependencies
+ */
+import { performLayoutAnimation } from '../../layout-animation';
+import {
+ BottomSheetNavigationContext,
+ BottomSheetNavigationProvider,
+} from './bottom-sheet-navigation-context';
+
+import styles from './styles.scss';
+
+const AnimationSpec = {
+ animation: 'timing',
+ config: {
+ duration: 200,
+ easing: Easing.ease,
+ },
+};
+
+const fadeConfig = ( { current } ) => {
+ return {
+ cardStyle: {
+ opacity: current.progress,
+ },
+ };
+};
+
+const options = {
+ transitionSpec: {
+ open: AnimationSpec,
+ close: AnimationSpec,
+ },
+ headerShown: false,
+ gestureEnabled: false,
+ cardStyleInterpolator: fadeConfig,
+};
+
+const ANIMATION_DURATION = 190;
+
+function BottomSheetNavigationContainer( { children, animate, main, theme } ) {
+ const Stack = useRef( createStackNavigator() ).current;
+ const context = useContext( BottomSheetNavigationContext );
+ const [ currentHeight, setCurrentHeight ] = useState(
+ context.currentHeight || 1
+ );
+
+ const backgroundStyle = usePreferredColorSchemeStyle(
+ styles.background,
+ styles.backgroundDark
+ );
+
+ const _theme = theme || {
+ ...DefaultTheme,
+ colors: {
+ ...DefaultTheme.colors,
+ background: backgroundStyle.backgroundColor,
+ },
+ };
+
+ const setHeight = ( height, layout ) => {
+ if ( currentHeight !== height && height > 1 ) {
+ if ( animate && layout && currentHeight === 1 ) {
+ setCurrentHeight( height );
+ } else if ( animate ) {
+ performLayoutAnimation( ANIMATION_DURATION );
+ setCurrentHeight( height );
+ } else {
+ setCurrentHeight( height );
+ }
+ }
+ };
+
+ const screens = useMemo( () => {
+ return Children.map( children, ( child ) => {
+ const { name, ...otherProps } = child.props;
+ return (
+ child }
+ />
+ );
+ } );
+ }, [ children ] );
+
+ return useMemo( () => {
+ return (
+
+
+ { main ? (
+
+
+ { screens }
+
+
+ ) : (
+
+ { screens }
+
+ ) }
+
+
+ );
+ }, [ currentHeight ] );
+}
+
+export default BottomSheetNavigationContainer;
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js
new file mode 100644
index 0000000000000..3c13517f1a0d2
--- /dev/null
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js
@@ -0,0 +1,67 @@
+/**
+ * External dependencies
+ */
+import {
+ useFocusEffect,
+ useIsFocused,
+ useNavigation,
+} from '@react-navigation/native';
+import { View } from 'react-native';
+import { debounce } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { BottomSheetContext } from '@wordpress/components';
+
+import { useRef, useCallback, useContext, useMemo } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { BottomSheetNavigationContext } from './bottom-sheet-navigation-context';
+
+const BottomSheetNavigationScreen = ( { children } ) => {
+ const navigation = useNavigation();
+ const heightRef = useRef( { maxHeight: 0 } );
+ const isFocused = useIsFocused();
+ const {
+ onHandleHardwareButtonPress,
+ shouldEnableBottomSheetMaxHeight,
+ } = useContext( BottomSheetContext );
+
+ const { setHeight } = useContext( BottomSheetNavigationContext );
+
+ const setHeightDebounce = useCallback( debounce( setHeight, 10 ), [] );
+
+ useFocusEffect(
+ useCallback( () => {
+ onHandleHardwareButtonPress( () => {
+ if ( navigation.canGoBack() ) {
+ shouldEnableBottomSheetMaxHeight( true );
+ navigation.goBack();
+ return true;
+ }
+ onHandleHardwareButtonPress( null );
+ return false;
+ } );
+ if ( heightRef.current.maxHeight !== 0 ) {
+ setHeight( heightRef.current.maxHeight );
+ }
+ return () => {};
+ }, [] )
+ );
+ const onLayout = ( { nativeEvent } ) => {
+ const { height } = nativeEvent.layout;
+ if ( heightRef.current.maxHeight !== height && isFocused ) {
+ heightRef.current.maxHeight = height;
+ setHeightDebounce( height, true );
+ }
+ };
+
+ return useMemo( () => {
+ return { children };
+ }, [ children, isFocused ] );
+};
+
+export default BottomSheetNavigationScreen;
diff --git a/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/styles.native.scss b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/styles.native.scss
new file mode 100644
index 0000000000000..ebed998355726
--- /dev/null
+++ b/packages/components/src/mobile/bottom-sheet/bottom-sheet-navigation/styles.native.scss
@@ -0,0 +1,7 @@
+.background {
+ background-color: $white;
+}
+
+.backgroundDark {
+ background-color: $background-dark-elevated;
+}
diff --git a/packages/components/src/mobile/bottom-sheet/index.native.js b/packages/components/src/mobile/bottom-sheet/index.native.js
index f617098f2ac35..2a407d34cea61 100644
--- a/packages/components/src/mobile/bottom-sheet/index.native.js
+++ b/packages/components/src/mobile/bottom-sheet/index.native.js
@@ -34,9 +34,10 @@ import SwitchCell from './switch-cell';
import RangeCell from './range-cell';
import ColorCell from './color-cell';
import RadioCell from './radio-cell';
+import NavigationScreen from './bottom-sheet-navigation/navigation-screen';
+import NavigationContainer from './bottom-sheet-navigation/navigation-container';
import KeyboardAvoidingView from './keyboard-avoiding-view';
import { BottomSheetProvider } from './bottom-sheet-context';
-import { performLayoutAnimation } from '../layout-animation';
class BottomSheet extends Component {
constructor() {
@@ -48,6 +49,7 @@ class BottomSheet extends Component {
this.onShouldSetBottomSheetMaxHeight = this.onShouldSetBottomSheetMaxHeight.bind(
this
);
+
this.onDimensionsChange = this.onDimensionsChange.bind( this );
this.onCloseBottomSheet = this.onCloseBottomSheet.bind( this );
this.onHandleClosingBottomSheet = this.onHandleClosingBottomSheet.bind(
@@ -57,7 +59,6 @@ class BottomSheet extends Component {
this.onHandleHardwareButtonPress = this.onHandleHardwareButtonPress.bind(
this
);
- this.onReplaceSubsheet = this.onReplaceSubsheet.bind( this );
this.keyboardWillShow = this.keyboardWillShow.bind( this );
this.keyboardDidHide = this.keyboardDidHide.bind( this );
@@ -68,11 +69,9 @@ class BottomSheet extends Component {
keyboardHeight: 0,
scrollEnabled: true,
isScrolling: false,
- onCloseBottomSheet: null,
- onHardwareButtonPress: null,
+ handleClosingBottomSheet: null,
+ handleHardwareButtonPress: null,
isMaxHeightSet: true,
- currentScreen: '',
- extraProps: {},
};
SafeArea.getSafeAreaInsetsForRootView().then(
@@ -120,6 +119,8 @@ class BottomSheet extends Component {
}
componentWillUnmount() {
+ this.keyboardWillShowListener.remove();
+ this.keyboardDidHideListener.remove();
if ( this.androidModalClosedSubscription ) {
this.androidModalClosedSubscription.remove();
}
@@ -132,16 +133,6 @@ class BottomSheet extends Component {
'safeAreaInsetsForRootViewDidChange',
this.onSafeAreaInsetsUpdate
);
- this.keyboardWillShowListener.remove();
- this.keyboardDidHideListener.remove();
- }
-
- componentDidUpdate( prevProps ) {
- const { isVisible } = this.props;
-
- if ( ! prevProps.isVisible && isVisible ) {
- this.setState( { currentScreen: '' } );
- }
}
onSafeAreaInsetsUpdate( result ) {
@@ -221,29 +212,34 @@ class BottomSheet extends Component {
}
onHandleClosingBottomSheet( action ) {
- this.setState( { onCloseBottomSheet: action } );
+ this.setState( { handleClosingBottomSheet: action } );
}
onHandleHardwareButtonPress( action ) {
- this.setState( { onHardwareButtonPress: action } );
+ this.setState( { handleHardwareButtonPress: action } );
}
onCloseBottomSheet() {
const { onClose } = this.props;
- const { onCloseBottomSheet } = this.state;
- if ( onCloseBottomSheet ) {
- onCloseBottomSheet();
+ const { handleClosingBottomSheet } = this.state;
+ if ( handleClosingBottomSheet ) {
+ handleClosingBottomSheet();
}
- onClose();
+ if ( onClose ) {
+ onClose();
+ }
+ this.onShouldSetBottomSheetMaxHeight( true );
}
onHardwareButtonPress() {
const { onClose } = this.props;
- const { onHardwareButtonPress } = this.state;
- if ( onHardwareButtonPress ) {
- return onHardwareButtonPress();
+ const { handleHardwareButtonPress } = this.state;
+ if ( handleHardwareButtonPress && handleHardwareButtonPress() ) {
+ return;
+ }
+ if ( onClose ) {
+ return onClose();
}
- return onClose();
}
getContentStyle() {
@@ -256,18 +252,6 @@ class BottomSheet extends Component {
};
}
- onReplaceSubsheet( destination, extraProps, callback ) {
- performLayoutAnimation();
-
- this.setState(
- {
- currentScreen: destination,
- extraProps: extraProps || {},
- },
- callback
- );
- }
-
render() {
const {
title = '',
@@ -291,8 +275,6 @@ class BottomSheet extends Component {
isScrolling,
scrollEnabled,
isMaxHeightSet,
- extraProps,
- currentScreen,
} = this.state;
const panResponder = PanResponder.create( {
@@ -362,7 +344,7 @@ class BottomSheet extends Component {
@@ -451,5 +430,7 @@ ThemedBottomSheet.SwitchCell = SwitchCell;
ThemedBottomSheet.RangeCell = RangeCell;
ThemedBottomSheet.ColorCell = ColorCell;
ThemedBottomSheet.RadioCell = RadioCell;
+ThemedBottomSheet.NavigationScreen = NavigationScreen;
+ThemedBottomSheet.NavigationContainer = NavigationContainer;
export default ThemedBottomSheet;
diff --git a/packages/components/src/mobile/bottom-sheet/range-cell.native.js b/packages/components/src/mobile/bottom-sheet/range-cell.native.js
index b34e369aa5079..f42b406b1c0e0 100644
--- a/packages/components/src/mobile/bottom-sheet/range-cell.native.js
+++ b/packages/components/src/mobile/bottom-sheet/range-cell.native.js
@@ -188,9 +188,9 @@ class BottomSheetRangeCell extends Component {
styles.sliderDarkTextInput
);
- const cellRowContainerStyle = [
- styles.cellRowStyles,
- isIOS ? styles.cellRowStylesIOS : styles.cellRowStylesAndroid,
+ const containerStyle = [
+ styles.container,
+ isIOS ? styles.containerIOS : styles.containerAndroid,
];
return (
@@ -200,7 +200,7 @@ class BottomSheetRangeCell extends Component {
styles.cellContainerStyles,
cellContainerStyle,
] }
- cellRowContainerStyle={ cellRowContainerStyle }
+ cellRowContainerStyle={ containerStyle }
accessibilityRole={ 'none' }
value={ '' }
editable={ false }
@@ -213,7 +213,7 @@ class BottomSheetRangeCell extends Component {
__( 'Double tap to change the value using slider' )
}
>
-
+
{ rangePreview }
{
+ const navigation = useNavigation();
+ const route = useRoute();
+ const { setColor, currentValue, isGradientColor } = route.params;
+ return (
+
+
+
+
+ );
+};
+
+export default GradientPickerScreen;
diff --git a/packages/components/src/mobile/color-settings/index.native.js b/packages/components/src/mobile/color-settings/index.native.js
index 79aa0c8a98aec..ec8be2ac573c6 100644
--- a/packages/components/src/mobile/color-settings/index.native.js
+++ b/packages/components/src/mobile/color-settings/index.native.js
@@ -1,240 +1,84 @@
/**
* External dependencies
*/
-import { View, Text } from 'react-native';
+import React from 'react';
+
/**
* WordPress dependencies
*/
-import { __ } from '@wordpress/i18n';
-import { useState, useEffect } from '@wordpress/element';
-import { usePreferredColorSchemeStyle } from '@wordpress/compose';
-import { ColorControl, PanelBody } from '@wordpress/components';
+import { useEffect, useContext } from '@wordpress/element';
+import { BottomSheetContext, BottomSheet } from '@wordpress/components';
+import { useRoute } from '@react-navigation/native';
+
/**
* Internal dependencies
*/
-import ColorPicker from '../../color-picker';
-import ColorPalette from '../../color-palette';
-import ColorIndicator from '../../color-indicator';
-import CustomGradientPicker from '../../custom-gradient-picker';
-import NavigationHeader from '../bottom-sheet/navigation-header';
-import SegmentedControls from '../segmented-control';
-import { colorsUtils } from './utils';
-import { performLayoutAnimation } from '../layout-animation';
-
-import styles from './style.scss';
-
-function ColorSettings( {
- label,
- onColorChange,
- onGradientChange,
- colorValue,
- onReplaceSubsheet,
- shouldEnableBottomSheetScroll,
- shouldDisableBottomSheetMaxHeight,
- isBottomSheetContentScrolling,
- onCloseBottomSheet,
- onHardwareButtonPress,
- defaultSettings,
-} ) {
- const [ currentValue, setCurrentValue ] = useState( colorValue );
- const [ isCustomScreen, setIsCustomScreen ] = useState( false );
- const [ isCustomGradientScreen, setIsCustomGradientScreen ] = useState(
- false
- );
-
- const { segments, subsheets, isGradient } = colorsUtils;
- const isGradientColor = isGradient( currentValue );
- const selectedSegmentIndex = isGradientColor ? 1 : 0;
-
- const [ currentSegment, setCurrentSegment ] = useState(
- segments[ selectedSegmentIndex ]
- );
-
- const isSolidSegment = currentSegment === segments[ 0 ];
- const isCustomGadientShown = ! isSolidSegment && isGradientColor;
-
- const horizontalSeparatorStyle = usePreferredColorSchemeStyle(
- styles.horizontalSeparator,
- styles.horizontalSeparatorDark
- );
-
- useEffect( () => {
- onHardwareButtonPress( () => {
- if ( isCustomScreen ) {
- onCustomScreenToggle( false );
- } else if ( isCustomGradientScreen ) {
- onCustomGradientScreenToggle( false );
- } else {
- onReplaceSubsheet(
- subsheets[ 0 ],
- {},
- afterHardwareButtonPress()
- );
- }
- } );
- }, [ isCustomScreen, isCustomGradientScreen ] );
-
- useEffect( () => {
- performLayoutAnimation();
- }, [ isCustomGadientShown ] );
+import PickerScreen from './picker-screen';
+import GradientPickerScreen from './gradient-picker-screen';
+import PaletteScreen from './palette.screen';
- useEffect( () => {
- setCurrentSegment( segments[ selectedSegmentIndex ] );
- shouldDisableBottomSheetMaxHeight( true );
- onCloseBottomSheet( null );
- }, [] );
-
- function afterHardwareButtonPress() {
- onHardwareButtonPress( null );
- shouldDisableBottomSheetMaxHeight( true );
- }
-
- function onCustomScreenToggle( shouldShow ) {
- performLayoutAnimation();
- setIsCustomScreen( shouldShow );
- }
-
- function onCustomGradientScreenToggle( shouldShow ) {
- performLayoutAnimation();
- setIsCustomGradientScreen( shouldShow );
- }
-
- function onCustomPress() {
- if ( isSolidSegment ) {
- onCustomScreenToggle( true );
- } else {
- onCustomGradientScreenToggle( true );
- }
- }
-
- function setColor( color ) {
- setCurrentValue( color );
- if ( isSolidSegment && onColorChange && onGradientChange ) {
- onColorChange( color );
- onGradientChange( '' );
- } else if ( isSolidSegment && onColorChange ) {
- onColorChange( color );
- } else if ( ! isSolidSegment && onGradientChange ) {
- onGradientChange( color );
- onColorChange( '' );
- }
- }
+import { colorsUtils } from './utils';
- function getFooter() {
- if ( onGradientChange ) {
- return (
-
- )
- }
- />
- );
- }
+const ColorSettingsMemo = React.memo(
+ ( {
+ defaultSettings,
+ onHandleClosingBottomSheet,
+ shouldEnableBottomSheetMaxHeight,
+ onColorChange,
+ colorValue,
+ gradientValue,
+ onGradientChange,
+ label,
+ } ) => {
+ useEffect( () => {
+ shouldEnableBottomSheetMaxHeight( true );
+ onHandleClosingBottomSheet( null );
+ }, [] );
return (
-
-
- { currentValue && (
-
- ) }
-
-
+
- { __( 'Select a color' ) }
-
-
-
+
+
+
+
+
+
+
+
+
);
}
+);
+function ColorSettings( props ) {
+ const route = useRoute();
+ const {
+ onHandleClosingBottomSheet,
+ shouldEnableBottomSheetMaxHeight,
+ } = useContext( BottomSheetContext );
return (
-
- { isCustomScreen && (
-
- onCustomScreenToggle( false ) }
- onCloseBottomSheet={ onCloseBottomSheet }
- isBottomSheetContentScrolling={
- isBottomSheetContentScrolling
- }
- />
-
- ) }
- { ! isCustomScreen && ! isCustomGradientScreen && (
-
-
- onReplaceSubsheet( subsheets[ 0 ] )
- }
- />
-
- { isCustomGadientShown && (
- <>
-
-
-
- onCustomGradientScreenToggle( true )
- }
- withColorIndicator={ false }
- />
-
- >
- ) }
-
- { getFooter() }
-
- ) }
- { isCustomGradientScreen && (
-
-
- onCustomGradientScreenToggle( false )
- }
- />
-
-
- ) }
-
+
);
}
diff --git a/packages/components/src/mobile/color-settings/palette.screen.native.js b/packages/components/src/mobile/color-settings/palette.screen.native.js
new file mode 100644
index 0000000000000..91cd1cc8e7195
--- /dev/null
+++ b/packages/components/src/mobile/color-settings/palette.screen.native.js
@@ -0,0 +1,156 @@
+/**
+ * External dependencies
+ */
+import { View, Text } from 'react-native';
+
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useState, useContext } from '@wordpress/element';
+import { usePreferredColorSchemeStyle } from '@wordpress/compose';
+import {
+ ColorControl,
+ PanelBody,
+ BottomSheetContext,
+} from '@wordpress/components';
+import { useRoute, useNavigation } from '@react-navigation/native';
+/**
+ * Internal dependencies
+ */
+import ColorPalette from '../../color-palette';
+import ColorIndicator from '../../color-indicator';
+import NavigationHeader from '../bottom-sheet/navigation-header';
+import SegmentedControls from '../segmented-control';
+import { colorsUtils } from './utils';
+
+import styles from './style.scss';
+
+const PaletteScreen = () => {
+ const route = useRoute();
+ const navigation = useNavigation();
+ const { shouldEnableBottomSheetScroll } = useContext( BottomSheetContext );
+ const {
+ label,
+ onColorChange,
+ onGradientChange,
+ colorValue,
+ defaultSettings,
+ } = route.params || {};
+ const { segments, isGradient } = colorsUtils;
+ const [ currentValue, setCurrentValue ] = useState( colorValue );
+ const isGradientColor = isGradient( currentValue );
+ const selectedSegmentIndex = isGradientColor ? 1 : 0;
+
+ const [ currentSegment, setCurrentSegment ] = useState(
+ segments[ selectedSegmentIndex ]
+ );
+
+ const horizontalSeparatorStyle = usePreferredColorSchemeStyle(
+ styles.horizontalSeparator,
+ styles.horizontalSeparatorDark
+ );
+
+ const isSolidSegment = currentSegment === segments[ 0 ];
+ const isCustomGadientShown = ! isSolidSegment && isGradientColor;
+
+ const setColor = ( color ) => {
+ setCurrentValue( color );
+ if ( isSolidSegment && onColorChange && onGradientChange ) {
+ onColorChange( color );
+ onGradientChange( '' );
+ } else if ( isSolidSegment && onColorChange ) {
+ onColorChange( color );
+ } else if ( ! isSolidSegment && onGradientChange ) {
+ onGradientChange( color );
+ onColorChange( '' );
+ }
+ };
+
+ function onCustomPress() {
+ if ( isSolidSegment ) {
+ navigation.navigate( colorsUtils.screens.picker, {
+ currentValue,
+ setColor,
+ } );
+ } else {
+ navigation.navigate( colorsUtils.screens.gradientPicker, {
+ setColor,
+ isGradientColor,
+ currentValue,
+ } );
+ }
+ }
+
+ function getFooter() {
+ if ( onGradientChange ) {
+ return (
+
+ )
+ }
+ />
+ );
+ }
+ return (
+
+
+ { currentValue && (
+
+ ) }
+
+
+ { __( 'Select a color' ) }
+
+
+
+ );
+ }
+ return (
+
+
+
+ { isCustomGadientShown && (
+ <>
+
+
+
+
+ >
+ ) }
+
+ { getFooter() }
+
+ );
+};
+
+export default PaletteScreen;
diff --git a/packages/components/src/mobile/color-settings/picker-screen.native.js b/packages/components/src/mobile/color-settings/picker-screen.native.js
new file mode 100644
index 0000000000000..3d11cbae38a82
--- /dev/null
+++ b/packages/components/src/mobile/color-settings/picker-screen.native.js
@@ -0,0 +1,60 @@
+/**
+ * External dependencies
+ */
+import { useRoute, useNavigation } from '@react-navigation/native';
+import React from 'react';
+
+/**
+ * WordPress dependencies
+ */
+import { useContext, useMemo } from '@wordpress/element';
+import { BottomSheetContext } from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import ColorPicker from '../../color-picker';
+
+const PickerScreen = () => {
+ const route = useRoute();
+ const navigation = useNavigation();
+ const {
+ onShouldEnableInnerHandling,
+ shouldEnableBottomSheetMaxHeight,
+ onHandleClosingBottomSheet,
+ isBottomSheetContentScrolling,
+ shouldEnableBottomSheetScroll,
+ onHandleHardwareButtonPress,
+ } = useContext( BottomSheetContext );
+ const { setColor, currentValue, isGradientColor } = route.params;
+ return useMemo( () => {
+ return (
+
+ );
+ }, [
+ setColor,
+ currentValue,
+ isGradientColor,
+ onShouldEnableInnerHandling,
+ shouldEnableBottomSheetMaxHeight,
+ onHandleClosingBottomSheet,
+ isBottomSheetContentScrolling,
+ shouldEnableBottomSheetScroll,
+ onHandleHardwareButtonPress,
+ ] );
+};
+
+export default PickerScreen;
diff --git a/packages/components/src/mobile/color-settings/utils.native.js b/packages/components/src/mobile/color-settings/utils.native.js
index e331f601e4b4c..a49da82b08008 100644
--- a/packages/components/src/mobile/color-settings/utils.native.js
+++ b/packages/components/src/mobile/color-settings/utils.native.js
@@ -18,9 +18,10 @@ const getGradientType = ( color ) => {
};
export const colorsUtils = {
- subsheets: {
- settings: 'Settings',
- color: 'Color',
+ screens: {
+ gradientPicker: 'GradientPicker',
+ picker: 'Picker',
+ palette: 'Palette',
},
segments: [ 'Solid', 'Gradient' ],
gradients,
diff --git a/packages/react-native-bridge/android/build.gradle b/packages/react-native-bridge/android/build.gradle
index 9eb117f9d2754..efc20f008d4f5 100644
--- a/packages/react-native-bridge/android/build.gradle
+++ b/packages/react-native-bridge/android/build.gradle
@@ -155,6 +155,11 @@ dependencies {
implementation project(':react-native-video')
implementation project(':@react-native-community_slider')
implementation project(':react-native-get-random-values')
+ implementation project(':@react-native-community_masked-view')
+ implementation project(':react-native-gesture-handler')
+ implementation project(':react-native-screens')
+ implementation project(':react-native-safe-area-context')
+ implementation project(':react-native-reanimated')
implementation 'com.facebook.react:react-native:+'
} else {
@@ -165,6 +170,11 @@ dependencies {
implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-linear-gradient', readHashedVersion('../../react-native-editor/package.json', 'react-native-linear-gradient', 'dependencies')))
implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-slider', readHashedVersion('../../react-native-editor/package.json', '@react-native-community/slider', 'dependencies')))
implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-get-random-values', readHashedVersion('../../react-native-editor/package.json', 'react-native-get-random-values', 'dependencies')))
+ implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-masked-view', readHashedVersion('../../react-native-editor/package.json', '@react-native-community/masked-view', 'dependencies')))
+ implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-gesture-handler', readHashedVersion('../../react-native-editor/package.json', 'react-native-gesture-handler', 'dependencies')))
+ implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-screens', readHashedVersion('../../react-native-editor/package.json', 'react-native-screens', 'dependencies')))
+ implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-safe-area-context', readHashedVersion('../../react-native-editor/package.json', 'react-native-safe-area-context', 'dependencies')))
+ implementation (waitJitpack('com.github.wordpress-mobile', 'react-native-reanimated', readHashedVersion('../../react-native-editor/package.json', 'react-native-reanimated', 'dependencies')))
// FIXME Temporary fix to get Jitpack builds to green while I work on a solution without hardcoded values.
//def rnVersion = readReactNativeVersion('../package.json', 'peerDependencies')
diff --git a/packages/react-native-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java b/packages/react-native-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java
index 27e59f4cdc05d..7a1d236deae19 100644
--- a/packages/react-native-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java
+++ b/packages/react-native-bridge/android/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java
@@ -37,6 +37,12 @@
import com.BV.LinearGradient.LinearGradientPackage;
import com.reactnativecommunity.slider.ReactSliderPackage;
import org.linusu.RNGetRandomValuesPackage;
+import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
+import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
+import com.swmansion.reanimated.ReanimatedPackage;
+import com.swmansion.rnscreens.RNScreensPackage;
+import com.th3rdwave.safeareacontext.SafeAreaContextPackage;
+import org.reactnative.maskedview.RNCMaskedViewPackage;
import org.wordpress.android.util.AppLog;
import org.wordpress.mobile.ReactNativeAztec.ReactAztecPackage;
@@ -392,6 +398,11 @@ public void requestStarterPageTemplatesTooltipShown(StarterPageTemplatesTooltipS
new ReactVideoPackage(),
new ReactSliderPackage(),
new RNGetRandomValuesPackage(),
+ new RNGestureHandlerPackage(),
+ new RNScreensPackage(),
+ new SafeAreaContextPackage(),
+ new RNCMaskedViewPackage(),
+ new ReanimatedPackage(),
mRnReactNativeGutenbergBridgePackage);
}
@@ -415,7 +426,7 @@ public void onCreateView(Context initContext,
mIsDarkMode = gutenbergProps.isDarkMode();
mExceptionLogger = exceptionLogger;
mBreadcrumbLogger = breadcrumbLogger;
- mReactRootView = new ReactRootView(new MutableContextWrapper(initContext));
+ mReactRootView = new RNGestureHandlerEnabledRootView(new MutableContextWrapper(initContext));
mReactRootView.setBackgroundColor(colorBackground);
ReactInstanceManagerBuilder builder =
diff --git a/packages/react-native-editor/android/app/build.gradle b/packages/react-native-editor/android/app/build.gradle
index 3f150b4c1669d..fc595ce89b2e6 100644
--- a/packages/react-native-editor/android/app/build.gradle
+++ b/packages/react-native-editor/android/app/build.gradle
@@ -166,6 +166,11 @@ dependencies {
implementation project(':react-native-video')
implementation project(':react-native-svg')
implementation project(':react-native-get-random-values')
+ implementation project(':@react-native-community_masked-view')
+ implementation project(':react-native-gesture-handler')
+ implementation project(':react-native-screens')
+ implementation project(':react-native-safe-area-context')
+ implementation project(':react-native-reanimated')
implementation "org.wordpress:utils:$wordpressUtilsVersion"
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation "com.facebook.react:react-native:+" // From node_modules
diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java
index fe21447c9f622..e9dbb45a78915 100644
--- a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java
+++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java
@@ -31,6 +31,11 @@
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
+import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
+import com.swmansion.reanimated.ReanimatedPackage;
+import com.swmansion.rnscreens.RNScreensPackage;
+import com.th3rdwave.safeareacontext.SafeAreaContextPackage;
+import org.reactnative.maskedview.RNCMaskedViewPackage;
import java.util.Arrays;
import java.util.List;
@@ -185,6 +190,11 @@ protected List getPackages() {
new ReactAztecPackage(null, null),
new LinearGradientPackage(),
new RNGetRandomValuesPackage(),
+ new RNCMaskedViewPackage(),
+ new RNGestureHandlerPackage(),
+ new ReanimatedPackage(),
+ new SafeAreaContextPackage(),
+ new RNScreensPackage(),
mRnReactNativeGutenbergBridgePackage);
}
diff --git a/packages/react-native-editor/android/settings.gradle b/packages/react-native-editor/android/settings.gradle
index f7ae4dfa566f5..733c341d7fc5f 100644
--- a/packages/react-native-editor/android/settings.gradle
+++ b/packages/react-native-editor/android/settings.gradle
@@ -14,5 +14,15 @@ include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-linear-gradient/android')
include ':react-native-get-random-values'
project(':react-native-get-random-values').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-get-random-values/android')
+include ':@react-native-community_masked-view'
+project(':@react-native-community_masked-view').projectDir = new File(rootProject.projectDir, '../../../node_modules/@react-native-community/masked-view/android')
+include ':react-native-gesture-handler'
+project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-gesture-handler/android')
+include ':react-native-screens'
+project(':react-native-screens').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-screens/android')
+include ':react-native-safe-area-context'
+project(':react-native-safe-area-context').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-safe-area-context/android')
+include ':react-native-reanimated'
+project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../../../node_modules/react-native-reanimated/android')
include ':app'
diff --git a/packages/react-native-editor/babel.config.js b/packages/react-native-editor/babel.config.js
index 0fd51ac0d1006..868045c19ca90 100644
--- a/packages/react-native-editor/babel.config.js
+++ b/packages/react-native-editor/babel.config.js
@@ -24,7 +24,7 @@ module.exports = function ( api ) {
},
],
],
- exclude: /node_modules\/(react-native|@react-native-community)/,
+ exclude: /node_modules\/(react-native|@react-native-community|@react-navigation)/,
},
{
// Auto-add `import { createElement } from '@wordpress/element';` when JSX is found
@@ -39,7 +39,7 @@ module.exports = function ( api ) {
},
],
],
- exclude: /node_modules\/(react-native|@react-native-community)/,
+ exclude: /node_modules\/(react-native|@react-native-community|@react-navigation)/,
},
],
env: {
diff --git a/packages/react-native-editor/index.js b/packages/react-native-editor/index.js
index 1417cc0322975..b84a0fe9760b6 100644
--- a/packages/react-native-editor/index.js
+++ b/packages/react-native-editor/index.js
@@ -1,3 +1,7 @@
+/**
+ * External dependencies
+ */
+import 'react-native-gesture-handler';
/**
* Internal dependencies
*/
diff --git a/packages/react-native-editor/ios/Podfile.lock b/packages/react-native-editor/ios/Podfile.lock
index 867fce1b1063e..f75fd8c978827 100644
--- a/packages/react-native-editor/ios/Podfile.lock
+++ b/packages/react-native-editor/ios/Podfile.lock
@@ -197,6 +197,8 @@ PODS:
- React
- react-native-safe-area (0.5.1):
- React
+ - react-native-safe-area-context (3.1.1):
+ - React
- react-native-slider (3.0.2):
- React
- react-native-video (5.0.2):
@@ -241,6 +243,14 @@ PODS:
- ReactCommon/jscallinvoker (= 0.61.5)
- ReactNativeDarkMode (0.0.10):
- React
+ - RNCMaskedView (0.1.10):
+ - React
+ - RNGestureHandler (1.6.0):
+ - React
+ - RNReanimated (1.9.0):
+ - React
+ - RNScreens (2.9.0):
+ - React
- RNSVG (9.13.6-gb):
- React
- RNTAztecView (1.34.0):
@@ -272,6 +282,7 @@ DEPENDENCIES:
- react-native-get-random-values (from `../../../node_modules/react-native-get-random-values`)
- react-native-keyboard-aware-scroll-view (from `../../../node_modules/react-native-keyboard-aware-scroll-view`)
- react-native-safe-area (from `../../../node_modules/react-native-safe-area`)
+ - react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`)
- "react-native-slider (from `../../../node_modules/@react-native-community/slider`)"
- react-native-video (from `../../../node_modules/react-native-video`)
- React-RCTActionSheet (from `../../../node_modules/react-native/Libraries/ActionSheetIOS`)
@@ -286,6 +297,10 @@ DEPENDENCIES:
- ReactCommon/jscallinvoker (from `../../../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`)
- ReactNativeDarkMode (from `../../../node_modules/react-native-dark-mode`)
+ - "RNCMaskedView (from `../../../node_modules/@react-native-community/masked-view`)"
+ - RNGestureHandler (from `../../../node_modules/react-native-gesture-handler`)
+ - RNReanimated (from `../../../node_modules/react-native-reanimated`)
+ - RNScreens (from `../../../node_modules/react-native-screens`)
- RNSVG (from `../../../node_modules/react-native-svg`)
- RNTAztecView (from `../../react-native-aztec/RNTAztecView.podspec`)
- Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`)
@@ -336,6 +351,8 @@ EXTERNAL SOURCES:
:path: "../../../node_modules/react-native-keyboard-aware-scroll-view"
react-native-safe-area:
:path: "../../../node_modules/react-native-safe-area"
+ react-native-safe-area-context:
+ :path: "../../../node_modules/react-native-safe-area-context"
react-native-slider:
:path: "../../../node_modules/@react-native-community/slider"
react-native-video:
@@ -362,6 +379,14 @@ EXTERNAL SOURCES:
:path: "../../../node_modules/react-native/ReactCommon"
ReactNativeDarkMode:
:path: "../../../node_modules/react-native-dark-mode"
+ RNCMaskedView:
+ :path: "../../../node_modules/@react-native-community/masked-view"
+ RNGestureHandler:
+ :path: "../../../node_modules/react-native-gesture-handler"
+ RNReanimated:
+ :path: "../../../node_modules/react-native-reanimated"
+ RNScreens:
+ :path: "../../../node_modules/react-native-screens"
RNSVG:
:path: "../../../node_modules/react-native-svg"
RNTAztecView:
@@ -391,8 +416,9 @@ SPEC CHECKSUMS:
react-native-get-random-values: 8940331a943a46c165d3ed05802c09c392f8dd46
react-native-keyboard-aware-scroll-view: ffa9152671fec9a571197ed2d02e0fcb90206e60
react-native-safe-area: e8230b0017d76c00de6b01e2412dcf86b127c6a3
+ react-native-safe-area-context: 4c3249e4840225c61fcd215b136af0a737bccb79
react-native-slider: ecb7f25c14f2348d1c1f629a6f2be7611d22a066
- react-native-video: d01ed7ff1e38fa7dcc6c15c94cf505e661b7bfd0
+ react-native-video: 961749da457e73bf0b5565edfbaffc25abfb8974
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
@@ -404,6 +430,10 @@ SPEC CHECKSUMS:
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
ReactNativeDarkMode: f61376360c5d983907e5c316e8e1c853a8c2f348
+ RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
+ RNGestureHandler: dde546180bf24af0b5f737c8ad04b6f3fa51609a
+ RNReanimated: b5ccb50650ba06f6e749c7c329a1bc3ae0c88b43
+ RNScreens: c526239bbe0e957b988dacc8d75ac94ec9cb19da
RNSVG: 68a534a5db06dcbdaebfd5079349191598caef7b
RNTAztecView: b2a8bbc94328376f6cd7a238e826f5d49b20ae1a
WordPress-Aztec-iOS: b7ac8b30f746992e85d9668453ac87c2cdcecf4f
diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj
index 81a72bc9af7c8..b5cb62934183a 100644
--- a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj
+++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj
@@ -470,7 +470,11 @@
"${BUILT_PRODUCTS_DIR}/Folly/folly.framework",
"${BUILT_PRODUCTS_DIR}/Gutenberg/Gutenberg.framework",
"${BUILT_PRODUCTS_DIR}/RCTTypeSafety/RCTTypeSafety.framework",
+ "${BUILT_PRODUCTS_DIR}/RNCMaskedView/RNCMaskedView.framework",
+ "${BUILT_PRODUCTS_DIR}/RNGestureHandler/RNGestureHandler.framework",
+ "${BUILT_PRODUCTS_DIR}/RNReanimated/RNReanimated.framework",
"${BUILT_PRODUCTS_DIR}/RNSVG/RNSVG.framework",
+ "${BUILT_PRODUCTS_DIR}/RNScreens/RNScreens.framework",
"${BUILT_PRODUCTS_DIR}/RNTAztecView/RNTAztecView.framework",
"${BUILT_PRODUCTS_DIR}/React-Core/React.framework",
"${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework",
@@ -496,6 +500,7 @@
"${BUILT_PRODUCTS_DIR}/react-native-get-random-values/react_native_get_random_values.framework",
"${BUILT_PRODUCTS_DIR}/react-native-keyboard-aware-scroll-view/react_native_keyboard_aware_scroll_view.framework",
"${BUILT_PRODUCTS_DIR}/react-native-safe-area/react_native_safe_area.framework",
+ "${BUILT_PRODUCTS_DIR}/react-native-safe-area-context/react_native_safe_area_context.framework",
"${BUILT_PRODUCTS_DIR}/react-native-slider/react_native_slider.framework",
);
name = "[CP] Embed Pods Frameworks";
@@ -506,7 +511,11 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/folly.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Gutenberg.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTTypeSafety.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNCMaskedView.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNGestureHandler.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNReanimated.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNSVG.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNScreens.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNTAztecView.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework",
@@ -532,6 +541,7 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_get_random_values.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_keyboard_aware_scroll_view.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_safe_area.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_safe_area_context.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_slider.framework",
);
runOnlyForDeploymentPostprocessing = 0;
diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json
index a659008228aa8..9bd566d7a1828 100644
--- a/packages/react-native-editor/package.json
+++ b/packages/react-native-editor/package.json
@@ -31,7 +31,10 @@
"dependencies": {
"@babel/runtime": "^7.9.2",
"@react-native-community/blur": "3.6.0",
+ "@react-native-community/masked-view": "git+https://github.com/wordpress-mobile/react-native-masked-view.git#098004d0968f853fc7d96c2aa5f96afe7a133c58",
"@react-native-community/slider": "git+https://github.com/wordpress-mobile/react-native-slider.git#d263ff16cdd9fb7352b354342522ff030f220f42",
+ "@react-navigation/native": "^5.6.1",
+ "@react-navigation/stack": "5.6.2",
"@wordpress/api-fetch": "file:../api-fetch",
"@wordpress/block-editor": "file:../block-editor",
"@wordpress/block-library": "file:../block-library",
@@ -53,14 +56,18 @@
"node-fetch": "^2.6.0",
"react-native": "0.61.5",
"react-native-dark-mode": "git+https://github.com/wordpress-mobile/react-native-dark-mode.git#f09bf1480e7b34536413ab3300f29e4375edb2c6",
+ "react-native-gesture-handler": "git+https://github.com/wordpress-mobile/react-native-gesture-handler.git#b80e959908b383a26d6e35d992d6d529efad0b16",
"react-native-get-random-values": "git+https://github.com/wordpress-mobile/react-native-get-random-values.git#f03f2c16414aff4ea76064dcd00a9e3c6efc838d",
"react-native-hr": "git+https://github.com/Riglerr/react-native-hr.git#2d01a5cf77212d100e8b99e0310cce5234f977b3",
"react-native-hsv-color-picker": "git+https://github.com/wordpress-mobile/react-native-hsv-color-picker",
"react-native-keyboard-aware-scroll-view": "git+https://github.com/wordpress-mobile/react-native-keyboard-aware-scroll-view.git#gb-v0.8.8",
"react-native-linear-gradient": "git+https://github.com/wordpress-mobile/react-native-linear-gradient.git#52bf43077171cff8714ce3e0155f3ebb7f55bc37",
"react-native-modal": "^6.5.0",
+ "react-native-reanimated": "git+https://github.com/wordpress-mobile/react-native-reanimated.git#ed48f510fba751cd75da7629e92276166766be91",
"react-native-safe-area": "^0.5.0",
+ "react-native-safe-area-context": "git+https://github.com/wordpress-mobile/react-native-safe-area-context.git#1e3c0d34f31b59fb79f71ec0b4c39c513f684871",
"react-native-sass-transformer": "^1.1.1",
+ "react-native-screens": "git+https://github.com/wordpress-mobile/react-native-screens.git#835843f4c3697bba5c330d05d8fc270d50ca9d2a",
"react-native-svg": "git+https://github.com/wordpress-mobile/react-native-svg.git#a628e92990a2404e30a0086f168bd2b5b7b4ce96",
"react-native-url-polyfill": "^1.1.2",
"react-native-video": "git+https://github.com/wordpress-mobile/react-native-video.git#1b964b107863351ed744fc104d7952bbec3e2d4f"
diff --git a/test/native/__mocks__/fileMock.js b/test/native/__mocks__/fileMock.js
new file mode 100644
index 0000000000000..59890f6a201a5
--- /dev/null
+++ b/test/native/__mocks__/fileMock.js
@@ -0,0 +1,3 @@
+// __mocks__/fileMock.js
+
+module.exports = 'test-file-stub';
diff --git a/test/native/jest.config.js b/test/native/jest.config.js
index 18ccbb421ea7f..2443e29ef5f4e 100644
--- a/test/native/jest.config.js
+++ b/test/native/jest.config.js
@@ -49,6 +49,8 @@ module.exports = {
moduleNameMapper: {
// Mock the CSS modules. See https://facebook.github.io/jest/docs/en/webpack.html#handling-static-assets
'\\.(scss)$': '/' + configPath + '/__mocks__/styleMock.js',
+ '\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
+ '/' + configPath + '/__mocks__/fileMock.js',
[ `@wordpress\\/(${ transpiledPackageNames.join(
'|'
) })$` ]: '/packages/$1/src',
diff --git a/test/native/setup.js b/test/native/setup.js
index 3f90fe422455c..9ca6804e56454 100644
--- a/test/native/setup.js
+++ b/test/native/setup.js
@@ -2,6 +2,7 @@
* External dependencies
*/
import { NativeModules } from 'react-native';
+import 'react-native-gesture-handler/jestSetup';
jest.mock( '@wordpress/element', () => {
return {
@@ -122,3 +123,16 @@ Object.keys( mockNativeModules ).forEach( ( module ) => {
} );
}
} );
+
+jest.mock( 'react-native-reanimated', () => {
+ const Reanimated = require( 'react-native-reanimated/mock' );
+
+ // The mock for `call` immediately calls the callback which is incorrect
+ // So we override it with a no-op
+ Reanimated.default.call = () => {};
+
+ return Reanimated;
+} );
+
+// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing
+jest.mock( 'react-native/Libraries/Animated/src/NativeAnimatedHelper' );