UNPKG

@gechiui/block-editor

Version:
393 lines (342 loc) 11.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _element = require("@gechiui/element"); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _reactNative = require("react-native"); var _lodash = require("lodash"); var _components = require("@gechiui/components"); var _data = require("@gechiui/data"); var _compose = require("@gechiui/compose"); var _blocks = require("@gechiui/blocks"); var _blockEditor = require("@gechiui/block-editor"); var _block = _interopRequireDefault(require("./block.scss")); var _blockEdit = _interopRequireDefault(require("../block-edit")); var _blockInvalidWarning = _interopRequireDefault(require("./block-invalid-warning")); var _blockMobileToolbar = _interopRequireDefault(require("../block-mobile-toolbar")); var _store = require("../../store"); /** * External dependencies */ /** * GeChiUI dependencies */ /** * Internal dependencies */ const emptyArray = []; function BlockForType(_ref) { let { attributes, clientId, contentStyle, getBlockWidth, insertBlocksAfter, isSelected, mergeBlocks, name, onBlockFocus, onChange, onDeleteBlock, onReplace, parentWidth, wrapperProps, blockWidth, baseGlobalStyles } = _ref; const defaultColors = (0, _blockEditor.useSetting)('color.palette') || emptyArray; const fontSizes = (0, _blockEditor.useSetting)('typography.fontSizes') || emptyArray; const globalStyle = (0, _components.useGlobalStyles)(); const mergedStyle = (0, _element.useMemo)(() => { return (0, _components.getMergedGlobalStyles)(baseGlobalStyles, globalStyle, wrapperProps.style, attributes, defaultColors, name, fontSizes); }, [defaultColors, globalStyle, // I couldn't simply use attributes and wrapperProps.styles as a dependency because they are almost always a new reference. // Thanks to the JSON.stringify we check if the value is the same instead of reference. JSON.stringify(wrapperProps.style), JSON.stringify((0, _lodash.pick)(attributes, _components.GlobalStylesContext.BLOCK_STYLE_ATTRIBUTES))]); return (0, _element.createElement)(_components.GlobalStylesContext.Provider, { value: mergedStyle }, (0, _element.createElement)(_blockEdit.default, { name: name, isSelected: isSelected, attributes: attributes, setAttributes: onChange, onFocus: onBlockFocus, onReplace: onReplace, insertBlocksAfter: insertBlocksAfter, mergeBlocks: mergeBlocks // Block level styles , wrapperProps: wrapperProps // inherited styles merged with block level styles , style: mergedStyle, clientId: clientId, parentWidth: parentWidth, contentStyle: contentStyle, onDeleteBlock: onDeleteBlock, blockWidth: blockWidth }), (0, _element.createElement)(_reactNative.View, { onLayout: getBlockWidth })); } class BlockListBlock extends _element.Component { constructor() { super(...arguments); this.insertBlocksAfter = this.insertBlocksAfter.bind(this); this.onFocus = this.onFocus.bind(this); this.getBlockWidth = this.getBlockWidth.bind(this); this.state = { blockWidth: this.props.blockWidth - 2 * this.props.marginHorizontal }; this.anchorNodeRef = (0, _element.createRef)(); } onFocus() { const { firstToSelectId, isSelected, onSelect } = this.props; if (!isSelected) { onSelect(firstToSelectId); } } insertBlocksAfter(blocks) { this.props.onInsertBlocks(blocks, this.props.order + 1); if (blocks[0]) { // focus on the first block inserted this.props.onSelect(blocks[0].clientId); } } getBlockWidth(_ref2) { let { nativeEvent } = _ref2; const { layout } = nativeEvent; const { blockWidth } = this.state; const layoutWidth = Math.floor(layout.width); if (!blockWidth || !layoutWidth) { return; } if (blockWidth !== layoutWidth) { this.setState({ blockWidth: layoutWidth }); } } getBlockForType() { const { blockWidth } = this.state; return (0, _element.createElement)(BlockForType, (0, _extends2.default)({}, this.props, { onBlockFocus: this.onFocus, insertBlocksAfter: this.insertBlocksAfter, getBlockWidth: this.getBlockWidth, blockWidth: blockWidth })); } renderBlockTitle() { return (0, _element.createElement)(_reactNative.View, { style: _block.default.blockTitle }, (0, _element.createElement)(_reactNative.Text, null, "BlockType: ", this.props.name)); } render() { const { attributes, blockType, clientId, icon, isSelected, isValid, order, title, isDimmed, isTouchable, onDeleteBlock, isStackedHorizontally, isParentSelected, getStylesFromColorScheme, marginVertical, marginHorizontal, isInnerBlockSelected, name } = this.props; if (!attributes || !blockType) { return null; } const { blockWidth } = this.state; const { align } = attributes; const accessibilityLabel = (0, _blocks.__experimentalGetAccessibleBlockLabel)(blockType, attributes, order + 1); const { isFullWidth, isContainerRelated } = _components.alignmentHelpers; const accessible = !(isSelected || isInnerBlockSelected); const screenWidth = Math.floor(_reactNative.Dimensions.get('window').width); const isScreenWidthEqual = blockWidth === screenWidth; const isScreenWidthWider = blockWidth < screenWidth; const isFullWidthToolbar = isFullWidth(align) || isScreenWidthEqual; return (0, _element.createElement)(_reactNative.TouchableWithoutFeedback, { onPress: this.onFocus, accessible: accessible, accessibilityRole: 'button' }, (0, _element.createElement)(_reactNative.View, { style: { flex: 1 }, accessibilityLabel: accessibilityLabel }, (0, _element.createElement)(_reactNative.View, { pointerEvents: isTouchable ? 'auto' : 'box-only', accessibilityLabel: accessibilityLabel, style: [{ marginVertical, marginHorizontal, flex: 1 }, isDimmed && _block.default.dimmed] }, isSelected && (0, _element.createElement)(_reactNative.View, { pointerEvents: "box-none", style: [_block.default.solidBorder, isFullWidth(align) && isScreenWidthWider && _block.default.borderFullWidth, isFullWidth(align) && isContainerRelated(name) && isScreenWidthWider && _block.default.containerBorderFullWidth, getStylesFromColorScheme(_block.default.solidBorderColor, _block.default.solidBorderColorDark)] }), isParentSelected && (0, _element.createElement)(_reactNative.View, { style: [_block.default.dashedBorder, getStylesFromColorScheme(_block.default.dashedBorderColor, _block.default.dashedBorderColorDark)] }), isValid ? this.getBlockForType() : (0, _element.createElement)(_blockInvalidWarning.default, { blockTitle: title, icon: icon }), (0, _element.createElement)(_reactNative.View, { style: _block.default.neutralToolbar, ref: this.anchorNodeRef }, isSelected && (0, _element.createElement)(_blockMobileToolbar.default, { clientId: clientId, onDelete: onDeleteBlock, isStackedHorizontally: isStackedHorizontally, blockWidth: blockWidth, anchorNodeRef: this.anchorNodeRef.current, isFullWidth: isFullWidthToolbar }))))); } } // Helper function to memoize the wrapperProps since getEditWrapperProps always returns a new reference const wrapperPropsCache = new WeakMap(); const emptyObj = {}; function getWrapperProps(value, getWrapperPropsFunction) { if (!getWrapperPropsFunction) { return emptyObj; } const cachedValue = wrapperPropsCache.get(value); if (!cachedValue) { const wrapperProps = getWrapperPropsFunction(value); wrapperPropsCache.set(value, wrapperProps); return wrapperProps; } return cachedValue; } var _default = (0, _compose.compose)([(0, _data.withSelect)((select, _ref3) => { var _getSettings; let { clientId } = _ref3; const { getBlockIndex, getSettings, isBlockSelected, getBlock, getSelectedBlockClientId, getLowestCommonAncestorWithSelectedBlock, getBlockParents, hasSelectedInnerBlock } = select(_store.store); const order = getBlockIndex(clientId); const isSelected = isBlockSelected(clientId); const isInnerBlockSelected = hasSelectedInnerBlock(clientId); const block = getBlock(clientId); const { name, attributes, isValid } = block || {}; const blockType = (0, _blocks.getBlockType)(name || 'core/missing'); const title = blockType === null || blockType === void 0 ? void 0 : blockType.title; const icon = blockType === null || blockType === void 0 ? void 0 : blockType.icon; const parents = getBlockParents(clientId, true); const parentId = parents[0] || ''; const selectedBlockClientId = getSelectedBlockClientId(); const commonAncestor = getLowestCommonAncestorWithSelectedBlock(clientId); const commonAncestorIndex = parents.indexOf(commonAncestor) - 1; const firstToSelectId = commonAncestor ? parents[commonAncestorIndex] : parents[parents.length - 1]; const isParentSelected = // set false as a default value to prevent re-render when it's changed from null to false (selectedBlockClientId || false) && selectedBlockClientId === parentId; const selectedParents = selectedBlockClientId ? getBlockParents(selectedBlockClientId) : []; const isDescendantOfParentSelected = selectedParents.includes(parentId); const isTouchable = isSelected || isDescendantOfParentSelected || isParentSelected || parentId === ''; const baseGlobalStyles = (_getSettings = getSettings()) === null || _getSettings === void 0 ? void 0 : _getSettings.__experimentalGlobalStylesBaseStyles; return { icon, name: name || 'core/missing', order, title, attributes, blockType, isSelected, isInnerBlockSelected, isValid, isParentSelected, firstToSelectId, isTouchable, baseGlobalStyles, wrapperProps: getWrapperProps(attributes, blockType.getEditWrapperProps) }; }), (0, _data.withDispatch)((dispatch, ownProps, _ref4) => { let { select } = _ref4; const { insertBlocks, mergeBlocks, replaceBlocks, selectBlock, updateBlockAttributes } = dispatch(_store.store); return { mergeBlocks(forward) { const { clientId } = ownProps; const { getPreviousBlockClientId, getNextBlockClientId } = select(_store.store); if (forward) { const nextBlockClientId = getNextBlockClientId(clientId); if (nextBlockClientId) { mergeBlocks(clientId, nextBlockClientId); } } else { const previousBlockClientId = getPreviousBlockClientId(clientId); if (previousBlockClientId) { mergeBlocks(previousBlockClientId, clientId); } } }, onInsertBlocks(blocks, index) { insertBlocks(blocks, index, ownProps.rootClientId); }, onSelect() { let clientId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ownProps.clientId; let initialPosition = arguments.length > 1 ? arguments[1] : undefined; selectBlock(clientId, initialPosition); }, onChange: attributes => { updateBlockAttributes(ownProps.clientId, attributes); }, onReplace(blocks, indexToSelect) { replaceBlocks([ownProps.clientId], blocks, indexToSelect); } }; }), _compose.withPreferredColorScheme])(BlockListBlock); exports.default = _default; //# sourceMappingURL=block.native.js.map