UNPKG

@gechiui/block-editor

Version:
443 lines (391 loc) 14.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.OnCaretVerticalPositionChange = exports.BlockList = void 0; var _element = require("@gechiui/element"); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _lodash = require("lodash"); var _reactNative = require("react-native"); var _data = require("@gechiui/data"); var _compose = require("@gechiui/compose"); var _blocks = require("@gechiui/blocks"); var _components = require("@gechiui/components"); var _i18n = require("@gechiui/i18n"); var _style = _interopRequireDefault(require("./style.scss")); var _blockListAppender = _interopRequireDefault(require("../block-list-appender")); var _blockListItem = _interopRequireDefault(require("./block-list-item")); var _store = require("../../store"); /** * External dependencies */ /** * GeChiUI dependencies */ /** * Internal dependencies */ const BlockListContext = (0, _element.createContext)(); const OnCaretVerticalPositionChange = (0, _element.createContext)(); exports.OnCaretVerticalPositionChange = OnCaretVerticalPositionChange; const stylesMemo = {}; const getStyles = (isRootList, isStackedHorizontally, horizontalAlignment) => { if (isRootList) { return; } 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; }; class BlockList extends _element.Component { constructor() { super(...arguments); this.extraData = { parentWidth: this.props.parentWidth, renderFooterAppender: this.props.renderFooterAppender, renderAppender: this.props.renderAppender, onDeleteBlock: this.props.onDeleteBlock, contentStyle: this.props.contentStyle }; this.renderItem = this.renderItem.bind(this); this.renderBlockListFooter = this.renderBlockListFooter.bind(this); this.onCaretVerticalPositionChange = this.onCaretVerticalPositionChange.bind(this); this.scrollViewInnerRef = this.scrollViewInnerRef.bind(this); this.addBlockToEndOfPost = this.addBlockToEndOfPost.bind(this); this.shouldFlatListPreventAutomaticScroll = this.shouldFlatListPreventAutomaticScroll.bind(this); this.shouldShowInnerBlockAppender = this.shouldShowInnerBlockAppender.bind(this); this.renderEmptyList = this.renderEmptyList.bind(this); this.getExtraData = this.getExtraData.bind(this); this.onLayout = this.onLayout.bind(this); this.state = { blockWidth: this.props.blockWidth || 0 }; } addBlockToEndOfPost(newBlock) { this.props.insertBlock(newBlock, this.props.blockCount); } onCaretVerticalPositionChange(targetId, caretY, previousCaretY) { _components.KeyboardAwareFlatList.handleCaretVerticalPositionChange(this.scrollViewRef, targetId, caretY, previousCaretY); } scrollViewInnerRef(ref) { this.scrollViewRef = ref; } shouldFlatListPreventAutomaticScroll() { return this.props.isBlockInsertionPointVisible; } shouldShowInnerBlockAppender() { const { blockClientIds, renderAppender } = this.props; return renderAppender && blockClientIds.length > 0; } renderEmptyList() { return (0, _element.createElement)(EmptyListComponentCompose, { rootClientId: this.props.rootClientId, renderAppender: this.props.renderAppender, renderFooterAppender: this.props.renderFooterAppender }); } getExtraData() { const { parentWidth, renderFooterAppender, onDeleteBlock, contentStyle, renderAppender, gridProperties } = this.props; const { blockWidth } = this.state; if (this.extraData.parentWidth !== parentWidth || this.extraData.renderFooterAppender !== renderFooterAppender || this.extraData.onDeleteBlock !== onDeleteBlock || this.extraData.contentStyle !== contentStyle || this.extraData.renderAppender !== renderAppender || this.extraData.blockWidth !== blockWidth || this.extraData.gridProperties !== gridProperties) { this.extraData = { parentWidth, renderFooterAppender, onDeleteBlock, contentStyle, renderAppender, blockWidth, gridProperties }; } return this.extraData; } onLayout(_ref) { let { nativeEvent } = _ref; const { layout } = nativeEvent; const { blockWidth } = this.state; const { isRootList, maxWidth } = this.props; const layoutWidth = Math.floor(layout.width); if (isRootList && blockWidth !== layoutWidth) { this.setState({ blockWidth: Math.min(layoutWidth, maxWidth) }); } else if (!isRootList && !blockWidth) { this.setState({ blockWidth: Math.min(layoutWidth, maxWidth) }); } } render() { const { isRootList } = this.props; // Use of Context to propagate the main scroll ref to its children e.g InnerBlocks const blockList = isRootList ? (0, _element.createElement)(BlockListContext.Provider, { value: this.scrollViewRef }, this.renderList()) : (0, _element.createElement)(BlockListContext.Consumer, null, ref => this.renderList({ parentScrollRef: ref })); return (0, _element.createElement)(OnCaretVerticalPositionChange.Provider, { value: this.onCaretVerticalPositionChange }, blockList); } renderList() { let extraProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; const { clearSelectedBlock, blockClientIds, title, header, isReadOnly, isRootList, horizontal, marginVertical = _style.default.defaultBlock.marginTop, marginHorizontal = _style.default.defaultBlock.marginLeft, isFloatingToolbarVisible, isStackedHorizontally, horizontalAlignment, contentResizeMode, blockWidth } = this.props; const { parentScrollRef } = extraProps; const { blockToolbar, blockBorder, headerToolbar, 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; return (0, _element.createElement)(_reactNative.View, { style: containerStyle, onAccessibilityEscape: clearSelectedBlock, onLayout: this.onLayout, testID: "block-list-wrapper" }, (0, _element.createElement)(_components.KeyboardAwareFlatList, (0, _extends2.default)({}, _reactNative.Platform.OS === 'android' ? { removeClippedSubviews: false } : {}, { // Disable clipping on Android to fix focus losing. See https://github.com/gechiui-mobile/gutenberg-mobile/pull/741#issuecomment-472746541 accessibilityLabel: "block-list", autoScroll: this.props.autoScroll, innerRef: ref => { this.scrollViewInnerRef(parentScrollRef || ref); }, extraScrollHeight: blockToolbar.height + blockBorder.width, inputAccessoryViewHeight: headerToolbar.height + (isFloatingToolbarVisible ? floatingToolbar.height : 0), keyboardShouldPersistTaps: "always", scrollViewStyle: [{ flex: isRootList ? 1 : 0 }, !isRootList && _style.default.overflowVisible], extraData: this.getExtraData(), scrollEnabled: isRootList, contentContainerStyle: [horizontal && _style.default.horizontalContentContainer, isWider(blockWidth, 'medium') && (isContentStretch && isMultiBlocks ? _style.default.horizontalContentContainerStretch : _style.default.horizontalContentContainerCenter)], style: getStyles(isRootList, isStackedHorizontally, horizontalAlignment), data: blockClientIds, keyExtractor: _lodash.identity, renderItem: this.renderItem, shouldPreventAutomaticScroll: this.shouldFlatListPreventAutomaticScroll, title: title, ListHeaderComponent: header, ListEmptyComponent: !isReadOnly && this.renderEmptyList, ListFooterComponent: this.renderBlockListFooter })), this.shouldShowInnerBlockAppender() && (0, _element.createElement)(_reactNative.View, { style: { marginHorizontal: marginHorizontal - _style.default.innerAppender.marginLeft } }, (0, _element.createElement)(_blockListAppender.default, { rootClientId: this.props.rootClientId, renderAppender: this.props.renderAppender, showSeparator: true }))); } renderItem(_ref2) { let { item: clientId } = _ref2; const { contentResizeMode, contentStyle, onAddBlock, onDeleteBlock, rootClientId, isStackedHorizontally, blockClientIds, parentWidth, marginVertical = _style.default.defaultBlock.marginTop, marginHorizontal = _style.default.defaultBlock.marginLeft, gridProperties } = this.props; const { blockWidth } = this.state; return (0, _element.createElement)(_blockListItem.default, { isStackedHorizontally: isStackedHorizontally, rootClientId: rootClientId, clientId: clientId, parentWidth: parentWidth, contentResizeMode: contentResizeMode, contentStyle: contentStyle, onAddBlock: onAddBlock, marginVertical: marginVertical, marginHorizontal: marginHorizontal, onDeleteBlock: onDeleteBlock, shouldShowInnerBlockAppender: this.shouldShowInnerBlockAppender, blockWidth: blockWidth, gridProperties: gridProperties, items: blockClientIds }); } renderBlockListFooter() { const paragraphBlock = (0, _blocks.createBlock)('core/paragraph'); const { isReadOnly, withFooter = true, renderFooterAppender } = this.props; if (!isReadOnly && withFooter) { return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_reactNative.TouchableWithoutFeedback, { accessibilityLabel: (0, _i18n.__)('Add paragraph block'), testID: (0, _i18n.__)('Add paragraph block'), onPress: () => { this.addBlockToEndOfPost(paragraphBlock); } }, (0, _element.createElement)(_reactNative.View, { style: _style.default.blockListFooter }))); } else if (renderFooterAppender) { return renderFooterAppender(); } return null; } } exports.BlockList = BlockList; var _default = (0, _compose.compose)([(0, _data.withSelect)((select, _ref3) => { let { rootClientId, orientation, filterInnerBlocks } = _ref3; const { getBlockCount, getBlockOrder, getSelectedBlockClientId, isBlockInsertionPointVisible, getSettings } = select(_store.store); const isStackedHorizontally = orientation === 'horizontal'; const selectedBlockClientId = getSelectedBlockClientId(); let blockClientIds = getBlockOrder(rootClientId); // Display only block which fulfill the condition in passed `filterInnerBlocks` function if (filterInnerBlocks) { blockClientIds = filterInnerBlocks(blockClientIds); } const { maxWidth } = getSettings(); const isReadOnly = getSettings().readOnly; const blockCount = getBlockCount(); const hasRootInnerBlocks = !!blockCount; const isFloatingToolbarVisible = !!selectedBlockClientId && hasRootInnerBlocks; return { blockClientIds, blockCount, isBlockInsertionPointVisible: _reactNative.Platform.OS === 'ios' && isBlockInsertionPointVisible(), isReadOnly, isRootList: rootClientId === undefined, isFloatingToolbarVisible, isStackedHorizontally, maxWidth }; }), (0, _data.withDispatch)(dispatch => { const { insertBlock, replaceBlock, clearSelectedBlock } = dispatch(_store.store); return { clearSelectedBlock, insertBlock, replaceBlock }; }), _compose.withPreferredColorScheme])(BlockList); exports.default = _default; class EmptyListComponent extends _element.Component { render() { const { shouldShowInsertionPoint, rootClientId, renderAppender, renderFooterAppender } = this.props; if (renderFooterAppender) { return null; } return (0, _element.createElement)(_reactNative.View, { style: _style.default.defaultAppender }, (0, _element.createElement)(_components.ReadableContentView, { align: renderAppender ? _components.WIDE_ALIGNMENTS.alignments.full : undefined }, (0, _element.createElement)(_blockListAppender.default, { rootClientId: rootClientId, renderAppender: renderAppender, showSeparator: shouldShowInsertionPoint }))); } } const EmptyListComponentCompose = (0, _compose.compose)([(0, _data.withSelect)((select, _ref4) => { let { rootClientId, orientation } = _ref4; const { getBlockOrder, getBlockInsertionPoint, isBlockInsertionPointVisible } = select(_store.store); const isStackedHorizontally = orientation === 'horizontal'; const blockClientIds = getBlockOrder(rootClientId); const insertionPoint = getBlockInsertionPoint(); const blockInsertionPointIsVisible = isBlockInsertionPointVisible(); const 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]); return { shouldShowInsertionPoint }; })])(EmptyListComponent); //# sourceMappingURL=index.native.js.map