diff --git a/package-lock.json b/package-lock.json index 4cfbfe2c250978..cc61e74462e934 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6834,6 +6834,14 @@ "warning": "^3.0.0" } }, + "@react-native-community/blur": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-native-community/blur/-/blur-3.6.0.tgz", + "integrity": "sha512-GtDBhpX2pQcjl4VopOC8FktrVufrEfYRwVeMQ2WWckqKIv2BdwvlvWvj88L1WmEdBr9UNcm3rtgz+d+YXkmirA==", + "requires": { + "prop-types": "^15.5.10" + } + }, "@react-native-community/cli-debugger-ui": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-3.0.0.tgz", @@ -11956,6 +11964,7 @@ "version": "file:packages/react-native-editor", "requires": { "@babel/runtime": "^7.9.2", + "@react-native-community/blur": "3.6.0", "@react-native-community/slider": "git+https://github.com/wordpress-mobile/react-native-slider.git#5ad284d92b8d886e366445bf215be741ed53ddc6", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/block-editor": "file:packages/block-editor", diff --git a/packages/block-editor/src/components/block-list/index.native.js b/packages/block-editor/src/components/block-list/index.native.js index 7799147217ab97..189b261a67eb98 100644 --- a/packages/block-editor/src/components/block-list/index.native.js +++ b/packages/block-editor/src/components/block-list/index.native.js @@ -229,7 +229,6 @@ export class BlockList extends Component { ListEmptyComponent={ ! isReadOnly && this.renderEmptyList } ListFooterComponent={ this.renderBlockListFooter } /> - { this.shouldShowInnerBlockAppender() && ( { const pickerRef = useRef(); const moversOptions = { keys: [ 'icon', 'actionTitle' ] }; const { - icon: { backward: backwardButtonIcon, forward: forwardButtonIcon }, actionTitle: { backward: backwardButtonTitle, forward: forwardButtonTitle, @@ -47,7 +61,6 @@ const BlockActionsMenu = ( { id: 'deleteOption', label: __( 'Remove block' ), value: 'deleteOption', - icon: trash, separated: true, disabled: isEmptyDefaultBlock, }; @@ -56,14 +69,12 @@ const BlockActionsMenu = ( { id: 'settingsOption', label: __( 'Block settings' ), value: 'settingsOption', - icon: cog, }; const backwardButtonOption = { id: 'backwardButtonOption', label: backwardButtonTitle, value: 'backwardButtonOption', - icon: backwardButtonIcon, disabled: isFirst, }; @@ -71,14 +82,41 @@ const BlockActionsMenu = ( { id: 'forwardButtonOption', label: forwardButtonTitle, value: 'forwardButtonOption', - icon: forwardButtonIcon, disabled: isLast, }; + const copyButtonOption = { + id: 'copyButtonOption', + label: __( 'Copy block' ), + value: 'copyButtonOption', + }; + + const cutButtonOption = { + id: 'cutButtonOption', + label: __( 'Cut block' ), + value: 'cutButtonOption', + }; + + const pasteButtonOption = { + id: 'pasteButtonOption', + label: __( 'Paste block' ), + value: 'pasteButtonOption', + }; + + const duplicateButtonOption = { + id: 'duplicateButtonOption', + label: __( 'Duplicate block' ), + value: 'duplicateButtonOption', + }; + const options = compact( [ wrapBlockMover && backwardButtonOption, wrapBlockMover && forwardButtonOption, wrapBlockSettings && settingsOption, + copyButtonOption, + cutButtonOption, + isPasteEnabled && pasteButtonOption, + duplicateButtonOption, deleteOption, ] ); @@ -96,6 +134,37 @@ const BlockActionsMenu = ( { case backwardButtonOption.value: onMoveUp(); break; + case copyButtonOption.value: + const copyBlock = getBlocksByClientId( selectedBlockClientId ); + updateClipboard( serialize( copyBlock ) ); + createInfoNotice( + // translators: displayed right after the block is copied. + __( 'Block copied' ) + ); + break; + case cutButtonOption.value: + const cutBlock = getBlocksByClientId( selectedBlockClientId ); + updateClipboard( serialize( cutBlock ) ); + removeBlocks( selectedBlockClientId ); + createInfoNotice( + // translators: displayed right after the block is cut. + __( 'Block cut' ) + ); + break; + case pasteButtonOption.value: + pasteBlock(); + createInfoNotice( + // translators: displayed right after the block is pasted. + __( 'Block pasted' ) + ); + break; + case duplicateButtonOption.value: + duplicateBlock(); + createInfoNotice( + // translators: displayed right after the block is duplicated. + __( 'Block duplicated' ) + ); + break; } } @@ -131,6 +200,7 @@ const BlockActionsMenu = ( { destructiveButtonIndex={ options.length } disabledButtonIndices={ disabledButtonIndices } hideCancelButton={ Platform.OS !== 'ios' } + leftAlign={ true } anchor={ anchorNodeRef ? findNodeHandle( anchorNodeRef ) : undefined } @@ -149,7 +219,11 @@ export default compose( getBlockOrder, getBlockName, getBlock, + getBlocksByClientId, + getSelectedBlockClientIds, + canInsertBlockType, } = select( 'core/block-editor' ); + const { getClipboard } = select( 'core/editor' ); const normalizedClientIds = castArray( clientIds ); const block = getBlock( normalizedClientIds ); const blockName = getBlockName( normalizedClientIds ); @@ -171,25 +245,82 @@ export default compose( const isEmptyDefaultBlock = isExactlyOneBlock && isDefaultBlock && isEmptyContent; + const clipboard = getClipboard(); + const clipboardBlock = + clipboard && rawHandler( { HTML: clipboard } )[ 0 ]; + const isPasteEnabled = + clipboardBlock && + canInsertBlockType( clipboardBlock.name, rootClientId ); + return { isFirst: firstIndex === 0, isLast: lastIndex === blockOrder.length - 1, rootClientId, blockTitle, isEmptyDefaultBlock, + getBlocksByClientId, + selectedBlockClientId: getSelectedBlockClientIds(), + currentIndex: firstIndex, + isPasteEnabled, + clipboardBlock, }; } ), - withDispatch( ( dispatch, { clientIds, rootClientId } ) => { - const { moveBlocksDown, moveBlocksUp } = dispatch( - 'core/block-editor' - ); - const { openGeneralSidebar } = dispatch( 'core/edit-post' ); + withDispatch( + ( + dispatch, + { clientIds, rootClientId, currentIndex, clipboardBlock }, + { select } + ) => { + const { + moveBlocksDown, + moveBlocksUp, + duplicateBlocks, + removeBlocks, + insertBlock, + replaceBlocks, + } = dispatch( 'core/block-editor' ); + const { openGeneralSidebar } = dispatch( 'core/edit-post' ); + const { updateClipboard, createInfoNotice } = dispatch( + 'core/editor' + ); + const { getBlockSelectionEnd, getBlock } = select( + 'core/block-editor' + ); - return { - onMoveDown: partial( moveBlocksDown, clientIds, rootClientId ), - onMoveUp: partial( moveBlocksUp, clientIds, rootClientId ), - openGeneralSidebar: () => openGeneralSidebar( 'edit-post/block' ), - }; - } ), + return { + onMoveDown: partial( moveBlocksDown, clientIds, rootClientId ), + onMoveUp: partial( moveBlocksUp, clientIds, rootClientId ), + openGeneralSidebar: () => + openGeneralSidebar( 'edit-post/block' ), + updateClipboard, + createInfoNotice, + duplicateBlock() { + return duplicateBlocks( clientIds ); + }, + removeBlocks, + pasteBlock: () => { + const canReplaceBlock = isUnmodifiedDefaultBlock( + getBlock( getBlockSelectionEnd() ) + ); + + if ( ! canReplaceBlock ) { + const insertedBlock = createBlock( + clipboardBlock.name, + clipboardBlock.attributes, + clipboardBlock.innerBlocks + ); + + insertBlock( + insertedBlock, + currentIndex + 1, + rootClientId + ); + } else { + replaceBlocks( clientIds, clipboardBlock ); + } + }, + }; + } + ), withInstanceId )( BlockActionsMenu ); diff --git a/packages/block-editor/src/components/inserter/menu-item.native.js b/packages/block-editor/src/components/inserter/menu-item.native.js new file mode 100644 index 00000000000000..97c3de091b03b5 --- /dev/null +++ b/packages/block-editor/src/components/inserter/menu-item.native.js @@ -0,0 +1,94 @@ +/** + * External dependencies + */ +import { View, TouchableHighlight, Text } from 'react-native'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { Icon } from '@wordpress/components'; +import { withPreferredColorScheme } from '@wordpress/compose'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import styles from './style.scss'; + +class MenuItem extends Component { + constructor() { + super( ...arguments ); + + this.onPress = this.onPress.bind( this ); + } + + onPress() { + const { onSelect, item } = this.props; + onSelect( item ); + } + + render() { + const { + getStylesFromColorScheme, + item, + itemWidth, + maxWidth, + } = this.props; + + const modalIconWrapperStyle = getStylesFromColorScheme( + styles.modalIconWrapper, + styles.modalIconWrapperDark + ); + const modalIconStyle = getStylesFromColorScheme( + styles.modalIcon, + styles.modalIconDark + ); + const modalItemLabelStyle = getStylesFromColorScheme( + styles.modalItemLabel, + styles.modalItemLabelDark + ); + + const clipboardBlockStyles = getStylesFromColorScheme( + styles.clipboardBlock, + styles.clipboardBlockDark + ); + + const isClipboardBlock = item.id === 'clipboard'; + + return ( + + + + + + + + + { isClipboardBlock ? __( 'Copied block' ) : item.title } + + + + ); + } +} + +export default withPreferredColorScheme( MenuItem ); diff --git a/packages/block-editor/src/components/inserter/menu.native.js b/packages/block-editor/src/components/inserter/menu.native.js index 0ecfba8e84e709..43d96a8dafd04a 100644 --- a/packages/block-editor/src/components/inserter/menu.native.js +++ b/packages/block-editor/src/components/inserter/menu.native.js @@ -1,31 +1,23 @@ /** * External dependencies */ -import { - FlatList, - View, - Text, - TouchableHighlight, - Dimensions, -} from 'react-native'; +import { FlatList, View, TouchableHighlight, Dimensions } from 'react-native'; +import { pick } from 'lodash'; /** * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { createBlock } from '@wordpress/blocks'; +import { createBlock, rawHandler } from '@wordpress/blocks'; import { withDispatch, withSelect } from '@wordpress/data'; -import { - withInstanceId, - compose, - withPreferredColorScheme, -} from '@wordpress/compose'; -import { BottomSheet, Icon } from '@wordpress/components'; +import { withInstanceId, compose } from '@wordpress/compose'; +import { BottomSheet } from '@wordpress/components'; /** * Internal dependencies */ import styles from './style.scss'; +import MenuItem from './menu-item.native'; const MIN_COL_NUM = 3; @@ -35,6 +27,7 @@ export class InserterMenu extends Component { this.onClose = this.onClose.bind( this ); this.onLayout = this.onLayout.bind( this ); + this.renderItem = this.renderItem.bind( this ); this.state = { numberOfColumns: MIN_COL_NUM, }; @@ -99,31 +92,34 @@ export class InserterMenu extends Component { } onLayout() { - const columnProperties = this.calculateColumnsProperties(); - const numberOfColumns = columnProperties.numOfColumns; + const { + numOfColumns, + itemWidth, + maxWidth, + } = this.calculateColumnsProperties(); + const numberOfColumns = numOfColumns; + + this.setState( { numberOfColumns, itemWidth, maxWidth } ); + } - this.setState( { numberOfColumns } ); + renderItem( { item } ) { + const { itemWidth, maxWidth } = this.state; + const { onSelect } = this.props; + return ( + + ); } render() { - const { getStylesFromColorScheme, items, onSelect } = this.props; + const { items } = this.props; const { numberOfColumns } = this.state; const bottomPadding = styles.contentBottomPadding; - const modalIconWrapperStyle = getStylesFromColorScheme( - styles.modalIconWrapper, - styles.modalIconWrapperDark - ); - const modalIconStyle = getStylesFromColorScheme( - styles.modalIcon, - styles.modalIconDark - ); - const modalItemLabelStyle = getStylesFromColorScheme( - styles.modalItemLabel, - styles.modalItemLabelDark - ); - - const columnProperties = this.calculateColumnsProperties(); return ( ) } keyExtractor={ ( item ) => item.name } - renderItem={ ( { item } ) => ( - onSelect( item ) } - > - - - - - - - - { item.title } - - - - ) } + renderItem={ this.renderItem } /> @@ -196,8 +156,10 @@ export default compose( getBlockRootClientId, getBlockSelectionEnd, getSettings, + canInsertBlockType, } = select( 'core/block-editor' ); - const { getChildBlockNames } = select( 'core/blocks' ); + const { getChildBlockNames, getBlockType } = select( 'core/blocks' ); + const { getClipboard } = select( 'core/editor' ); let destinationRootClientId = rootClientId; if ( ! destinationRootClientId && ! clientId && ! isAppender ) { @@ -214,10 +176,29 @@ export default compose( const { __experimentalShouldInsertAtTheTop: shouldInsertAtTheTop, } = getSettings(); + const clipboard = getClipboard(); + const clipboardBlock = + clipboard && rawHandler( { HTML: clipboard } )[ 0 ]; + const shouldAddClipboardBlock = + clipboardBlock && + canInsertBlockType( clipboardBlock.name, destinationRootClientId ); return { rootChildBlocks: getChildBlockNames( destinationRootBlockName ), - items: getInserterItems( destinationRootClientId ), + items: shouldAddClipboardBlock + ? [ + { + ...pick( getBlockType( clipboardBlock.name ), [ + 'name', + 'icon', + ] ), + id: 'clipboard', + initialAttributes: clipboardBlock.attributes, + innerBlocks: clipboardBlock.innerBlocks, + }, + ...getInserterItems( destinationRootClientId ), + ] + : getInserterItems( destinationRootClientId ), destinationRootClientId, shouldInsertAtTheTop, }; @@ -262,9 +243,13 @@ export default compose( }, hideInsertionPoint, onSelect( item ) { - const { name, initialAttributes } = item; + const { name, initialAttributes, innerBlocks } = item; - const insertedBlock = createBlock( name, initialAttributes ); + const insertedBlock = createBlock( + name, + initialAttributes, + innerBlocks + ); insertBlock( insertedBlock, @@ -283,6 +268,5 @@ export default compose( }, }; } ), - withInstanceId, - withPreferredColorScheme + withInstanceId )( InserterMenu ); diff --git a/packages/block-editor/src/components/inserter/style.native.scss b/packages/block-editor/src/components/inserter/style.native.scss index bfb45082c8f8f6..4df8eafcc37a44 100644 --- a/packages/block-editor/src/components/inserter/style.native.scss +++ b/packages/block-editor/src/components/inserter/style.native.scss @@ -78,3 +78,13 @@ .columnPadding { padding: $grid-unit-20; } + +.clipboardBlock { + background-color: transparent; + border-width: 1px; + border-color: $light-gray-400; +} + +.clipboardBlockDark { + border-color: $gray-70; +} diff --git a/packages/blocks/src/api/raw-handling/index.native.js b/packages/blocks/src/api/raw-handling/index.native.js index f7e468e3fe3639..b5252e9046c636 100644 --- a/packages/blocks/src/api/raw-handling/index.native.js +++ b/packages/blocks/src/api/raw-handling/index.native.js @@ -1,2 +1,3 @@ export { getPhrasingContentSchema } from './phrasing-content'; export { pasteHandler } from './paste-handler'; +export { rawHandler } from './index.js'; diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index 2938a072788ba5..02913c7aa8541d 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -42,6 +42,8 @@ export { default as ResizableBox } from './resizable-box'; export { default as UnsupportedFooterControl } from './unsupported-footer-control'; export { default as ColorControl } from './color-control'; export { default as QueryControls } from './query-controls'; +export { default as Notice } from './notice'; +export { default as NoticeList } from './notice/list'; export { default as RadioControl } from './radio-control'; // Higher-Order Components diff --git a/packages/components/src/notice/index.native.js b/packages/components/src/notice/index.native.js new file mode 100644 index 00000000000000..6224d9cfd6928d --- /dev/null +++ b/packages/components/src/notice/index.native.js @@ -0,0 +1,121 @@ +/** + * External dependencies + */ +import { + Animated, + Easing, + Text, + TouchableWithoutFeedback, + View, + Dimensions, + Platform, +} from 'react-native'; +import { BlurView } from '@react-native-community/blur'; + +/** + * WordPress dependencies + */ +import { useEffect, useRef, useState } from '@wordpress/element'; +import { usePreferredColorSchemeStyle } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import styles from './style.scss'; + +const Notice = ( { onNoticeHidden, content, id } ) => { + const [ width, setWidth ] = useState( Dimensions.get( 'window' ).width ); + const [ visible, setVisible ] = useState( true ); + + const animationValue = useRef( new Animated.Value( 0 ) ).current; + const timer = useRef( null ); + const isIOS = Platform.OS === 'ios'; + + const onDimensionsChange = () => { + setWidth( Dimensions.get( 'window' ).width ); + }; + + useEffect( () => { + Dimensions.addEventListener( 'change', onDimensionsChange ); + return () => { + Dimensions.removeEventListener( 'change', onDimensionsChange ); + }; + }, [] ); + + useEffect( () => { + startAnimation(); + return () => { + clearTimeout( timer?.current ); + }; + }, [ visible, id ] ); + + const onHide = () => { + setVisible( false ); + }; + + const startAnimation = () => { + Animated.timing( animationValue, { + toValue: visible ? 1 : 0, + duration: visible ? 300 : 150, + useNativeDriver: true, + easing: Easing.out( Easing.quad ), + } ).start( () => { + if ( visible && onNoticeHidden ) { + timer.current = setTimeout( () => { + onHide(); + }, 3000 ); + } + + if ( ! visible && onNoticeHidden ) { + onNoticeHidden( id ); + } + } ); + }; + + const noticeSolidStyles = usePreferredColorSchemeStyle( + styles.noticeSolid, + styles.noticeSolidDark + ); + + const textStyles = usePreferredColorSchemeStyle( + styles.text, + styles.textDark + ); + + return ( + <> + + + + { content } + + + { isIOS && ( + + ) } + + + ); +}; + +export default Notice; diff --git a/packages/components/src/notice/list.native.js b/packages/components/src/notice/list.native.js new file mode 100644 index 00000000000000..b91a21407c6c3f --- /dev/null +++ b/packages/components/src/notice/list.native.js @@ -0,0 +1,76 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { withDispatch, withSelect } from '@wordpress/data'; +import { compose } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import Notice from './'; +import styles from './style.scss'; + +class NoticeList extends Component { + constructor() { + super( ...arguments ); + this.removeNotice = this.removeNotice.bind( this ); + } + + removeNotice( id ) { + const { removeNotice } = this.props; + removeNotice( id ); + } + + render() { + const { notices, shouldStack } = this.props; + + if ( ! notices.length ) { + return null; + } + + return ( + + { shouldStack ? ( + notices + .reverse() + .map( ( notice ) => ( + + ) ) + ) : ( + + ) } + + ); + } +} + +export default compose( [ + withSelect( ( select ) => { + const { getNotices } = select( 'core/editor' ); + + return { + notices: getNotices(), + }; + } ), + withDispatch( ( dispatch ) => { + const { removeNotice, removeAllNotices } = dispatch( 'core/editor' ); + + return { + removeNotice, + removeAllNotices, + }; + } ), +] )( NoticeList ); diff --git a/packages/components/src/notice/style.native.scss b/packages/components/src/notice/style.native.scss new file mode 100644 index 00000000000000..88a9b60b396dbf --- /dev/null +++ b/packages/components/src/notice/style.native.scss @@ -0,0 +1,46 @@ +.text { + color: #212121; + align-self: center; + background-color: transparent; + font-size: 12; +} + +.textDark { + color: $white; +} + +.list { + position: absolute; + margin-left: auto; + margin-right: auto; + top: 0; + flex-direction: column; + z-index: 102; + align-items: center; + align-self: center; +} + +.notice { + height: 24; + justify-content: center; +} + +.noticeContent { + position: absolute; + z-index: 1; + width: 100%; +} + +.noticeSolid { + background-color: #f4f4f4; +} + +.noticeSolidDark { + background-color: #2a2a2a; +} + +.blurBackground { + width: 100%; + height: 100%; + position: absolute; +} diff --git a/packages/edit-post/src/components/layout/index.native.js b/packages/edit-post/src/components/layout/index.native.js index eb989d7d4f32bd..d0548d9696ecee 100644 --- a/packages/edit-post/src/components/layout/index.native.js +++ b/packages/edit-post/src/components/layout/index.native.js @@ -16,7 +16,11 @@ import { FloatingToolbar, } from '@wordpress/block-editor'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; -import { HTMLTextInput, KeyboardAvoidingView } from '@wordpress/components'; +import { + HTMLTextInput, + KeyboardAvoidingView, + NoticeList, +} from '@wordpress/components'; import { AutosaveMonitor } from '@wordpress/editor'; import { sendNativeEditorDidLayout } from '@wordpress/react-native-bridge'; @@ -135,6 +139,7 @@ class Layout extends Component { { ! isHtmlView && Platform.OS === 'android' && ( ) } + notice.id !== action.id ); + } + return state; +} + export default optimist( combineReducers( { postId, @@ -62,5 +99,7 @@ export default optimist( template, isReady, editorSettings, + clipboard, + notices, } ) ); diff --git a/packages/editor/src/store/selectors.native.js b/packages/editor/src/store/selectors.native.js index 2edfc373213fa2..474686799bc73d 100644 --- a/packages/editor/src/store/selectors.native.js +++ b/packages/editor/src/store/selectors.native.js @@ -55,3 +55,25 @@ export const isEditedPostAutosaveable = createRegistrySelector( return false; } ); + +/** + * Returns the current clipboard data. + * + * @param {Object} state Global application state. + * + * @return {Object} Current clipboard data. + */ +export function getClipboard( state ) { + return state.clipboard; +} + +/** + * Returns the current notice data. + * + * @param {Object} state Global application state. + * + * @return {Object} Current notice data. + */ +export function getNotices( state ) { + return state.notices; +} diff --git a/packages/react-native-editor/ios/Podfile.lock b/packages/react-native-editor/ios/Podfile.lock index 19cb2c000b158d..f097969c346f49 100644 --- a/packages/react-native-editor/ios/Podfile.lock +++ b/packages/react-native-editor/ios/Podfile.lock @@ -189,6 +189,8 @@ PODS: - React-cxxreact (= 0.61.5) - React-jsi (= 0.61.5) - React-jsinspector (0.61.5) + - react-native-blur (0.8.0): + - React - react-native-get-random-values (1.4.0): - React - react-native-keyboard-aware-scroll-view (0.8.8): @@ -266,6 +268,7 @@ DEPENDENCIES: - React-jsi (from `../../../node_modules/react-native/ReactCommon/jsi`) - React-jsiexecutor (from `../../../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../../../node_modules/react-native/ReactCommon/jsinspector`) + - "react-native-blur (from `../../../node_modules/@react-native-community/blur`)" - 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`) @@ -325,6 +328,8 @@ EXTERNAL SOURCES: :path: "../../../node_modules/react-native/ReactCommon/jsiexecutor" React-jsinspector: :path: "../../../node_modules/react-native/ReactCommon/jsinspector" + react-native-blur: + :path: "../../../node_modules/@react-native-community/blur" react-native-get-random-values: :path: "../../../node_modules/react-native-get-random-values" react-native-keyboard-aware-scroll-view: @@ -382,6 +387,7 @@ SPEC CHECKSUMS: React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7 React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386 React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0 + react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c react-native-get-random-values: 8940331a943a46c165d3ed05802c09c392f8dd46 react-native-keyboard-aware-scroll-view: ffa9152671fec9a571197ed2d02e0fcb90206e60 react-native-safe-area: e8230b0017d76c00de6b01e2412dcf86b127c6a3 diff --git a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj index 01bb92522a2d0c..81a72bc9af7c83 100644 --- a/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj +++ b/packages/react-native-editor/ios/gutenberg.xcodeproj/project.pbxproj @@ -492,6 +492,7 @@ "${BUILT_PRODUCTS_DIR}/WordPress-Aztec-iOS/Aztec.framework", "${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework", "${BUILT_PRODUCTS_DIR}/glog/glog.framework", + "${BUILT_PRODUCTS_DIR}/react-native-blur/react_native_blur.framework", "${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", @@ -527,6 +528,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Aztec.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_blur.framework", "${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", diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 6900187f18132e..342d8352b505df 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -30,6 +30,7 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "^7.9.2", + "@react-native-community/blur": "3.6.0", "@react-native-community/slider": "git+https://github.com/wordpress-mobile/react-native-slider.git#5ad284d92b8d886e366445bf215be741ed53ddc6", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", diff --git a/test/native/setup.js b/test/native/setup.js index fe5bfe7a05f33c..3f90fe422455c2 100644 --- a/test/native/setup.js +++ b/test/native/setup.js @@ -98,6 +98,10 @@ jest.mock( 'react-native-hsv-color-picker', () => () => 'HsvColorPicker', { virtual: true, } ); +jest.mock( '@react-native-community/blur', () => () => 'BlurView', { + virtual: true, +} ); + // Overwrite some native module mocks from `react-native` jest preset: // https://github.com/facebook/react-native/blob/master/jest/setup.js // to fix issue "TypeError: Cannot read property 'Commands' of undefined"