@wordpress/block-editor
Version:
351 lines (347 loc) • 13.1 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = BlockList;
var _reactNative = require("react-native");
var _element = require("@wordpress/element");
var _data = require("@wordpress/data");
var _blocks = require("@wordpress/blocks");
var _components = require("@wordpress/components");
var _i18n = require("@wordpress/i18n");
var _style = _interopRequireDefault(require("./style.scss"));
var _blockListAppender = _interopRequireDefault(require("../block-list-appender"));
var _blockListItem = _interopRequireDefault(require("./block-list-item"));
var _blockListItemCell = _interopRequireDefault(require("./block-list-item-cell"));
var _blockListContext = require("./block-list-context");
var _blockDraggable = require("../block-draggable");
var _useEditorWrapperStyles = require("../../hooks/use-editor-wrapper-styles");
var _store = require("../../store");
var _jsxRuntime = require("react/jsx-runtime");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const identity = x => x;
const stylesMemo = {};
const getStyles = (isStackedHorizontally, horizontalAlignment) => {
const styleName = `${isStackedHorizontally}-${horizontalAlignment}`;
if (stylesMemo[styleName]) {
return stylesMemo[styleName];
}
const computedStyles = [isStackedHorizontally && _style.default.horizontal, horizontalAlignment && _style.default[`is-aligned-${horizontalAlignment}`], _style.default.overflowVisible];
stylesMemo[styleName] = computedStyles;
return computedStyles;
};
function BlockList({
blockWidth: initialBlockWidth,
contentResizeMode,
contentStyle,
filterInnerBlocks,
gridProperties,
header,
horizontal,
horizontalAlignment,
marginHorizontal = _style.default.defaultBlock.marginLeft,
marginVertical = _style.default.defaultBlock.marginTop,
onAddBlock,
onDeleteBlock,
orientation,
parentWidth,
renderAppender,
renderFooterAppender,
rootClientId,
withFooter = true
}) {
const {
blockClientIds,
blockCount,
blockInsertionPointIsVisible,
isReadOnly,
isRootList,
isFloatingToolbarVisible,
isStackedHorizontally,
maxWidth,
isRTL
} = (0, _data.useSelect)(select => {
const {
getBlockCount,
getBlockHierarchyRootClientId,
getBlockOrder,
getSelectedBlockClientId,
isBlockInsertionPointVisible,
getSettings
} = select(_store.store);
const selectedBlockClientId = getSelectedBlockClientId();
const rootBlockId = getBlockHierarchyRootClientId(selectedBlockClientId);
let blockOrder = getBlockOrder(rootClientId);
// Display only block which fulfill the condition in passed `filterInnerBlocks` function.
if (filterInnerBlocks) {
blockOrder = filterInnerBlocks(blockOrder);
}
const {
isRTL: isRTLSetting,
maxWidth: maxWidthSetting,
readOnly
} = getSettings();
return {
blockClientIds: blockOrder,
blockCount: getBlockCount(),
blockInsertionPointIsVisible: _reactNative.Platform.OS === 'ios' && isBlockInsertionPointVisible(),
isReadOnly: readOnly,
isRootList: rootClientId === undefined,
isFloatingToolbarVisible: !!selectedBlockClientId && !!getBlockCount(rootBlockId),
isStackedHorizontally: orientation === 'horizontal',
maxWidth: maxWidthSetting,
isRTL: isRTLSetting
};
}, [filterInnerBlocks, orientation, rootClientId]);
const {
insertBlock,
clearSelectedBlock
} = (0, _data.useDispatch)(_store.store);
const extraData = (0, _element.useRef)({
parentWidth,
renderFooterAppender,
renderAppender,
onDeleteBlock,
contentStyle
});
const [blockWidth, setBlockWidth] = (0, _element.useState)(initialBlockWidth || 0);
const addBlockToEndOfPost = newBlock => {
insertBlock(newBlock, blockCount);
};
const scrollRef = (0, _element.useRef)(null);
const shouldFlatListPreventAutomaticScroll = () => blockInsertionPointIsVisible;
const shouldShowInnerBlockAppender = () => renderAppender && blockClientIds.length > 0;
const getExtraData = () => {
if (extraData.current.parentWidth !== parentWidth || extraData.current.renderFooterAppender !== renderFooterAppender || extraData.current.onDeleteBlock !== onDeleteBlock || extraData.current.contentStyle !== contentStyle || extraData.current.renderAppender !== renderAppender || extraData.current.blockWidth !== blockWidth || extraData.current.gridProperties !== gridProperties) {
extraData.current = {
parentWidth,
renderFooterAppender,
onDeleteBlock,
contentStyle,
renderAppender,
blockWidth,
gridProperties
};
}
return extraData.current;
};
const onLayout = ({
nativeEvent
}) => {
const {
layout
} = nativeEvent;
const layoutWidth = Math.floor(layout.width);
if (isRootList && blockWidth !== layoutWidth) {
setBlockWidth(Math.min(layoutWidth, maxWidth));
} else if (!isRootList && !blockWidth) {
setBlockWidth(Math.min(layoutWidth, maxWidth));
}
};
const renderItem = ({
item: clientId,
index
}) => {
// Extracting the grid item properties here to avoid
// re-renders in the blockListItem component.
const isGridItem = !!gridProperties;
const gridItemProps = gridProperties && {
numOfColumns: gridProperties.numColumns,
tileCount: blockClientIds.length,
tileIndex: blockClientIds.indexOf(clientId)
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockListItem.default, {
index: index,
isStackedHorizontally: isStackedHorizontally,
rootClientId: rootClientId,
clientId: clientId,
parentWidth: parentWidth,
contentResizeMode: contentResizeMode,
contentStyle: contentStyle,
onAddBlock: onAddBlock,
marginVertical: marginVertical,
marginHorizontal: marginHorizontal,
onDeleteBlock: onDeleteBlock,
shouldShowInnerBlockAppender: shouldShowInnerBlockAppender,
blockWidth: blockWidth,
isGridItem: isGridItem,
...gridItemProps
});
};
const {
blockToolbar,
floatingToolbar
} = _style.default;
const containerStyle = {
flex: isRootList ? 1 : 0,
// We set negative margin in the parent to remove the edge spacing between parent block and child block in ineer blocks.
marginVertical: isRootList ? 0 : -marginVertical,
marginHorizontal: isRootList ? 0 : -marginHorizontal
};
const isContentStretch = contentResizeMode === 'stretch';
const isMultiBlocks = blockClientIds.length > 1;
const {
isWider
} = _components.alignmentHelpers;
const extraScrollHeight = blockToolbar.height + (isFloatingToolbarVisible ? floatingToolbar.height : 0);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
style: containerStyle,
onAccessibilityEscape: clearSelectedBlock,
onLayout: onLayout,
testID: "block-list-wrapper",
children: [isRootList ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockListContext.BlockListProvider, {
value: {
..._blockListContext.DEFAULT_BLOCK_LIST_CONTEXT,
scrollRef: scrollRef.current
},
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockDraggable.BlockDraggableWrapper, {
isRTL: isRTL,
children: ({
onScroll
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.KeyboardAwareFlatList, {
accessibilityLabel: "block-list",
ref: scrollRef,
extraScrollHeight: extraScrollHeight,
keyboardShouldPersistTaps: "always",
extraData: getExtraData(),
scrollEnabled: isRootList,
contentContainerStyle: [horizontal && _style.default.horizontalContentContainer, isWider(blockWidth, 'medium') && (isContentStretch && isMultiBlocks ? _style.default.horizontalContentContainerStretch : _style.default.horizontalContentContainerCenter)],
data: blockClientIds,
keyExtractor: identity,
renderItem: renderItem,
CellRendererComponent: _blockListItemCell.default,
shouldPreventAutomaticScroll: shouldFlatListPreventAutomaticScroll,
ListHeaderComponent: header,
ListEmptyComponent: !isReadOnly && /*#__PURE__*/(0, _jsxRuntime.jsx)(EmptyList, {
orientation: orientation,
rootClientId: rootClientId,
renderAppender: renderAppender,
renderFooterAppender: renderFooterAppender
}),
ListFooterComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(Footer, {
addBlockToEndOfPost: addBlockToEndOfPost,
isReadOnly: isReadOnly,
renderFooterAppender: renderFooterAppender,
withFooter: withFooter
}),
onScroll: onScroll
})
})
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
children: blockClientIds.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
style: [{
flex: 0
}, _style.default.overflowVisible],
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
style: [...getStyles(isStackedHorizontally, horizontalAlignment), horizontal && _style.default.horizontalContentContainer],
children: [blockClientIds.map((currentClientId, index) => {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
children: renderItem({
item: currentClientId,
index
})
}, currentClientId);
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(Footer, {
addBlockToEndOfPost: addBlockToEndOfPost,
isReadOnly: isReadOnly,
renderFooterAppender: renderFooterAppender,
withFooter: withFooter
})]
})
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(EmptyList, {
orientation: orientation,
rootClientId: rootClientId,
renderAppender: renderAppender,
renderFooterAppender: renderFooterAppender
})
}), shouldShowInnerBlockAppender() && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
style: {
marginHorizontal: marginHorizontal - _style.default.innerAppender.marginLeft
},
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockListAppender.default, {
rootClientId: rootClientId,
renderAppender: renderAppender,
showSeparator: true
})
})]
});
}
function Footer({
addBlockToEndOfPost,
isReadOnly,
renderFooterAppender,
withFooter
}) {
const onAddParagraphBlock = (0, _element.useCallback)(() => {
const paragraphBlock = (0, _blocks.createBlock)('core/paragraph');
addBlockToEndOfPost(paragraphBlock);
}, [addBlockToEndOfPost]);
if (!isReadOnly && withFooter) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
accessibilityLabel: (0, _i18n.__)('Add paragraph block'),
testID: (0, _i18n.__)('Add paragraph block'),
onPress: onAddParagraphBlock,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
style: _style.default.blockListFooter
})
});
} else if (renderFooterAppender) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
children: renderFooterAppender()
});
}
return null;
}
function EmptyList({
orientation,
renderAppender,
renderFooterAppender,
rootClientId
}) {
const {
shouldShowInsertionPoint
} = (0, _data.useSelect)(select => {
const {
getBlockOrder,
getBlockInsertionPoint,
isBlockInsertionPointVisible
} = select(_store.store);
const isStackedHorizontally = orientation === 'horizontal';
const blockClientIds = getBlockOrder(rootClientId);
const insertionPoint = getBlockInsertionPoint();
const blockInsertionPointIsVisible = isBlockInsertionPointVisible();
return {
shouldShowInsertionPoint: !isStackedHorizontally && blockInsertionPointIsVisible && insertionPoint.rootClientId === rootClientId && (
// If list is empty, show the insertion point (via the default appender)
blockClientIds.length === 0 ||
// Or if the insertion point is right before the denoted block.
!blockClientIds[insertionPoint.index])
};
});
const align = renderAppender ? _components.WIDE_ALIGNMENTS.alignments.full : undefined;
const [wrapperStyles] = (0, _useEditorWrapperStyles.useEditorWrapperStyles)({
align
});
if (renderFooterAppender || renderAppender === false) {
return null;
}
const containerStyles = [_style.default.defaultAppender, wrapperStyles];
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
style: containerStyles,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockListAppender.default, {
rootClientId: rootClientId,
renderAppender: renderAppender,
showSeparator: shouldShowInsertionPoint
})
});
}
//# sourceMappingURL=index.native.js.map
;