Skip to content

Commit

Permalink
[RNMobile] Add Reusable blocks to the inserter menu (#28495)
Browse files Browse the repository at this point in the history
* Add custom header to BottomSheet

* SegmentedControl mobile component exported

* Add Reusable blocks to inserter menu with tabs

* Add native version of inserter-list-item

* Add mobile version of block-types-list component

* Add getWidth to mobile version of inserter-list-item component

* Add blocks-tab mobile version to inserter component

* Add reusable-blocks-tab mobile version to inserter component

* Inserter menu mobile version refactor to use new tabs

* Lint fixes in inserter menu components

* README of block-types-list component updated with mobile changes

* modal prefix removed from inserter-list-item style names

* blocks-tab renamed to block-types-tab in inserter menu

* add block-types-tab UI test

* Add reusable-blocks-tab UI test

* Remove unused import from block types list

* Change key calculation for block types list component

Block name's field was being used which is not unique so it has been changed to id field.

* Fix style format issue in inserter list item

* Add header prop to BottomSheet

* Add header height to max height calculation

* Move inserter search form to bottom sheet header

* Update BlockTypesList to functional component

* Add use clipboard block hook

* Use block types list in search results

* Remove inserter list item native files

* Cleanup inserter native styles

* Update platform specific styles

* Fix styles import

* Update android input

* Replace search icone with Gridicon

* Remove touchable highlight component

It wasn't doing much

* Refactor input form

* Clean up style generation

* Rename input container class

* Fix input container active styling

* Update input button styles

* Fix input button on Android

* Fix iOS active search styles

* Tighten up iOS input buttons

* Align items in icon button

* Use elevation for input shadow

* Updates for dark mode

* Fix icon fill color

* Clean up styles

* Fix key calculation in BlockTypesList

* Add block-editor store definition in ReusableBlocksTab

* Limit the number of lines of block title

* Add inserter tabs component

* Add inserter tabs in inserter menu

* Add search focus to inserter menu

* Unify keyboard listeners in bottom sheet component

Additionally a layout animation has been added to fix potential visual glitches.

* Update useClipboardBlock hook

* Add visual improvements to inserter menu

* Set maximum items per page of reusable blocks

* Add new color scheme hook

* Refactor style generation

* Fix style selectors

* Fix fill color on icons

* Refactor native inserter tabs

The tab animation is now done in the container instead of its children.

* Add layout animations in inserter menu

The layout animations will be triggered when the search value changes (only on iOS because Android this type of animations don't work properly).

* Add layout animation fixes in bottom sheet

* Increase max listeners on iOS to prevent warning

* Add root client id to search results

* Hide tabs when is not main inserter

* Force layout calculation on block types list mount

* Improve inserter menu layout animations for Android

* Add layout animations to bottom sheet component

* Update keyboard layout animation

* Add keyboard show/hide callbacks to bottom sheet

* Remove search form height

This value that was being used for calculating the padding bottom of the search results view is no longer needed.

* Prevent multiple layout animations on Android

* Use keyboard events instead focus for display tabs

* Enable layout animation of empty search for Android

* Update block-types-list README

* Add last scroll events to inserter tabs

The last scroll events are used to notify upstream when the current tab of the inserter menu has changed. This is a workaround for the bottom-sheet component to manage multiple scrollable children.

* Fix block types tab unit test

* Add landscape mode support in inserter tabs

* Revert "Merge branch 'update/inserter-block-search' into rnmobile/add/2575-reusable-blocks-inserter"

This reverts commit 4df39cd, reversing
changes made to 575c58f.

# Conflicts:
#	packages/block-editor/src/components/inserter/search-form.native.js
#	packages/block-editor/src/components/inserter/style.native.scss

* Revert "Add search focus to inserter menu"

This reverts commit cadfaa6.

# Conflicts:
#	packages/block-editor/src/components/inserter/menu.native.js
#	packages/block-editor/src/components/inserter/search-form.native.js

* Revert "Increase max listeners on iOS to prevent warning"

This reverts commit 110a513.

* Limit layout animation to header changes in bottom sheet

* Enable reusable tab when inserting in inner blocks

* Remove hasReusableBlocks from inserter menu

* Apply BEM naming to block types list styles

* Rename block types tab to match web version

* Move tabs container style to a constant

* Rename block types tab function to match web version

* Rename import of block types list in inserter unit tests

* Move bottom-sheet keyboard handlers to constants

* Update inserter tabs to use wrapper width for animations

* Include safe area inset on the block types list

* Update react-native-editor changelog

Co-authored-by: jhnstn <[email protected]>
  • Loading branch information
fluiddot and jhnstn authored May 14, 2021
1 parent 8331d12 commit e148801
Show file tree
Hide file tree
Showing 17 changed files with 679 additions and 199 deletions.
19 changes: 19 additions & 0 deletions packages/block-editor/src/components/block-types-list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ The blocks that will be displayed in the block list.

- Type: `Array<Block>`
- Required: Yes
- Platform: Web | Mobile

#### name

Name of the list to be used as part of component's key.

- Type: `String`
- Required: Yes
- Platform: Mobile

#### listProps

Extra `FlatList` props for customizing the list.

On Mobile usually this component is rendered inside `BottomSheet` component, which already [generates these props](<(https://github.com/WordPress/gutenberg/blob/1ca1fe0c64dfe1a385221399fc94b0fb14f34199/packages/components/src/mobile/bottom-sheet/index.native.js#L355-L372)>) for this component.

- Type: `String`
- Required: No
- Platform: Mobile

## Related components

Expand Down
112 changes: 112 additions & 0 deletions packages/block-editor/src/components/block-types-list/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* External dependencies
*/
import {
Dimensions,
FlatList,
StyleSheet,
TouchableWithoutFeedback,
View,
} from 'react-native';

/**
* WordPress dependencies
*/
import { useState, useEffect } from '@wordpress/element';
import { BottomSheet, InserterButton } from '@wordpress/components';

/**
* Internal dependencies
*/
import styles from './style.scss';

const MIN_COL_NUM = 3;

export default function BlockTypesList( { name, items, onSelect, listProps } ) {
const [ numberOfColumns, setNumberOfColumns ] = useState( MIN_COL_NUM );
const [ itemWidth, setItemWidth ] = useState();
const [ maxWidth, setMaxWidth ] = useState();

useEffect( () => {
Dimensions.addEventListener( 'change', onLayout );
onLayout();
return () => {
Dimensions.removeEventListener( 'change', onLayout );
};
}, [] );

function calculateItemWidth() {
const {
paddingLeft: itemPaddingLeft,
paddingRight: itemPaddingRight,
} = InserterButton.Styles.modalItem;
const { width } = InserterButton.Styles.modalIconWrapper;
return width + itemPaddingLeft + itemPaddingRight;
}

function onLayout() {
const columnStyle = styles[ 'block-types-list__column' ];
const sumLeftRightPadding =
columnStyle.paddingLeft + columnStyle.paddingRight;

const bottomSheetWidth = BottomSheet.getWidth();
const containerTotalWidth = bottomSheetWidth - sumLeftRightPadding;
const itemTotalWidth = calculateItemWidth();

const columnsFitToWidth = Math.floor(
containerTotalWidth / itemTotalWidth
);

const numColumns = Math.max( MIN_COL_NUM, columnsFitToWidth );

setNumberOfColumns( numColumns );
setMaxWidth( containerTotalWidth / numColumns );

if ( columnsFitToWidth < MIN_COL_NUM ) {
const updatedItemWidth =
( bottomSheetWidth - 2 * sumLeftRightPadding ) / MIN_COL_NUM;
setItemWidth( updatedItemWidth );
}
}

const contentContainerStyle = StyleSheet.flatten(
listProps.contentContainerStyle
);

return (
<FlatList
onLayout={ onLayout }
key={ `InserterUI-${ name }-${ numberOfColumns }` } //re-render when numberOfColumns changes
keyboardShouldPersistTaps="always"
numColumns={ numberOfColumns }
data={ items }
initialNumToRender={ 3 }
ItemSeparatorComponent={ () => (
<TouchableWithoutFeedback accessible={ false }>
<View
style={ styles[ 'block-types-list__row-separator' ] }
/>
</TouchableWithoutFeedback>
) }
keyExtractor={ ( item ) => item.id }
renderItem={ ( { item } ) => (
<InserterButton
{ ...{
item,
itemWidth,
maxWidth,
onSelect,
} }
/>
) }
{ ...listProps }
contentContainerStyle={ {
...contentContainerStyle,
paddingBottom: Math.max(
listProps.safeAreaBottomInset,
contentContainerStyle.paddingBottom
),
} }
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.block-types-list__row-separator {
height: 12px;
}

.block-types-list__column {
padding: $grid-unit-20;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import BlockTypesList from '../block-types-list';
import useClipboardBlock from './hooks/use-clipboard-block';
import { store as blockEditorStore } from '../../store';

const NON_BLOCK_CATEGORIES = [ 'reusable' ];

function BlockTypesTab( { onSelect, rootClientId, listProps } ) {
const clipboardBlock = useClipboardBlock( rootClientId );

const { items } = useSelect(
( select ) => {
const { getInserterItems } = select( blockEditorStore );

const allItems = getInserterItems( rootClientId );
const blockItems = allItems.filter(
( { category } ) => ! NON_BLOCK_CATEGORIES.includes( category )
);

return {
items: clipboardBlock
? [ clipboardBlock, ...blockItems ]
: blockItems,
};
},
[ rootClientId ]
);

return (
<BlockTypesList
name="Blocks"
items={ items }
onSelect={ onSelect }
listProps={ listProps }
/>
);
}

export default BlockTypesTab;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { rawHandler, store as blocksStore } from '@wordpress/blocks';
import { getClipboard } from '@wordpress/components';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../../store';

export default function useClipboardBlock( destinationRootClientId ) {
const { canInsertBlockType } = useSelect( blockEditorStore );
const { getBlockType } = useSelect( blocksStore );

const clipboard = getClipboard();
const clipboardBlock = rawHandler( { HTML: clipboard } )[ 0 ];

const canAddClipboardBlock = canInsertBlockType(
clipboardBlock?.name,
destinationRootClientId
);

if ( ! canAddClipboardBlock ) {
return undefined;
}

const { icon, name } = getBlockType( clipboardBlock.name );
const { attributes: initialAttributes, innerBlocks } = clipboardBlock;

return {
id: 'clipboard',
name,
icon,
initialAttributes,
innerBlocks,
};
}
Loading

0 comments on commit e148801

Please sign in to comment.