@gechiui/block-editor
Version:
393 lines (342 loc) • 11.9 kB
JavaScript
;
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