@wordpress/components
Version:
UI components for WordPress.
283 lines (246 loc) • 9.89 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _reactNative = require("react-native");
var _reactNativeVideo = _interopRequireDefault(require("react-native-video"));
var _lodash = require("lodash");
var _reactNativeBridge = require("@wordpress/react-native-bridge");
var _i18n = require("@wordpress/i18n");
var _components = require("@wordpress/components");
var _compose = require("@wordpress/compose");
var _focalPoint = _interopRequireDefault(require("./focal-point"));
var _tooltip = _interopRequireDefault(require("./tooltip"));
var _style = _interopRequireDefault(require("./style.scss"));
var _utils = require("./utils");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const MIN_POSITION_VALUE = 0;
const MAX_POSITION_VALUE = 100;
const FOCAL_POINT_UNITS = [{
default: '50',
label: '%',
value: '%'
}];
function FocalPointPicker(props) {
var _styles$focalPoint, _styles$focalPoint2;
const {
focalPoint,
onChange,
shouldEnableBottomSheetScroll,
url
} = props;
const isVideo = (0, _utils.isVideoType)(url);
const [containerSize, setContainerSize] = (0, _element.useState)(null);
const [sliderKey, setSliderKey] = (0, _element.useState)(0);
const [displayPlaceholder, setDisplayPlaceholder] = (0, _element.useState)(true);
const [videoNaturalSize, setVideoNaturalSize] = (0, _element.useState)(null);
const [tooltipVisible, setTooltipVisible] = (0, _element.useState)(false);
let locationPageOffsetX = (0, _element.useRef)().current;
let locationPageOffsetY = (0, _element.useRef)().current;
const videoRef = (0, _element.useRef)(null);
(0, _element.useEffect)(() => {
(0, _reactNativeBridge.requestFocalPointPickerTooltipShown)(tooltipShown => {
if (!tooltipShown) {
setTooltipVisible(true);
(0, _reactNativeBridge.setFocalPointPickerTooltipShown)(true);
}
});
}, []); // Animated coordinates for drag handle
const pan = (0, _element.useRef)(new _reactNative.Animated.ValueXY()).current;
/**
* Set drag handle position anytime focal point coordinates change.
* E.g. initial render, dragging range sliders.
*/
(0, _element.useEffect)(() => {
if (containerSize) {
pan.setValue({
x: focalPoint.x * containerSize.width,
y: focalPoint.y * containerSize.height
});
}
}, [focalPoint, containerSize]); // Pan responder to manage drag handle interactivity
const panResponder = (0, _element.useMemo)(() => _reactNative.PanResponder.create({
onStartShouldSetPanResponder: () => true,
onStartShouldSetPanResponderCapture: () => true,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderGrant: event => {
shouldEnableBottomSheetScroll(false);
const {
locationX: x,
locationY: y,
pageX,
pageY
} = event.nativeEvent;
locationPageOffsetX = pageX - x;
locationPageOffsetY = pageY - y;
pan.setValue({
x,
y
}); // Set cursor to tap location
pan.extractOffset(); // Set offset to current value
},
// Move cursor to match delta drag
onPanResponderMove: _reactNative.Animated.event([null, {
dx: pan.x,
dy: pan.y
}]),
onPanResponderRelease: event => {
shouldEnableBottomSheetScroll(true);
pan.flattenOffset(); // Flatten offset into value
const {
pageX,
pageY
} = event.nativeEvent; // Ideally, x and y below are merely locationX and locationY from the
// nativeEvent. However, we are required to compute these relative
// coordinates to workaround a bug affecting Android's PanResponder.
// Specifically, dragging the handle outside the bounds of the image
// results in inaccurate locationX and locationY coordinates to be
// reported. https://git.io/JtWmi
const x = pageX - locationPageOffsetX;
const y = pageY - locationPageOffsetY;
onChange({
x: (0, _lodash.clamp)(x / (containerSize === null || containerSize === void 0 ? void 0 : containerSize.width), 0, 1).toFixed(2),
y: (0, _lodash.clamp)(y / (containerSize === null || containerSize === void 0 ? void 0 : containerSize.height), 0, 1).toFixed(2)
}); // Slider (child of RangeCell) is uncontrolled, so we must increment a
// key to re-mount and sync the pan gesture values to the sliders
// https://git.io/JTe4A
setSliderKey(prevState => prevState + 1);
}
}), [containerSize]);
const mediaBackground = (0, _compose.usePreferredColorSchemeStyle)(_style.default.mediaBackground, _style.default.mediaBackgroundDark);
const imagePreviewStyles = [displayPlaceholder && _style.default.mediaPlaceholder, _style.default.image];
const videoPreviewStyles = [{
aspectRatio: videoNaturalSize && videoNaturalSize.width / videoNaturalSize.height,
// Hide Video component since it has black background while loading the source
opacity: displayPlaceholder ? 0 : 1
}, _style.default.video, displayPlaceholder && _style.default.mediaPlaceholder];
const focalPointGroupStyles = [_style.default.focalPointGroup, {
transform: [{
translateX: pan.x.interpolate({
inputRange: [0, (containerSize === null || containerSize === void 0 ? void 0 : containerSize.width) || 0],
outputRange: [0, (containerSize === null || containerSize === void 0 ? void 0 : containerSize.width) || 0],
extrapolate: 'clamp'
})
}, {
translateY: pan.y.interpolate({
inputRange: [0, (containerSize === null || containerSize === void 0 ? void 0 : containerSize.height) || 0],
outputRange: [0, (containerSize === null || containerSize === void 0 ? void 0 : containerSize.height) || 0],
extrapolate: 'clamp'
})
}]
}];
const FOCAL_POINT_SIZE = 50;
const focalPointStyles = [_style.default.focalPoint, {
height: FOCAL_POINT_SIZE,
marginLeft: -(FOCAL_POINT_SIZE / 2),
marginTop: -(FOCAL_POINT_SIZE / 2),
width: FOCAL_POINT_SIZE
}];
const onTooltipPress = () => setTooltipVisible(false);
const onMediaLayout = event => {
const {
height,
width
} = event.nativeEvent.layout;
if (width !== 0 && height !== 0 && ((containerSize === null || containerSize === void 0 ? void 0 : containerSize.width) !== width || (containerSize === null || containerSize === void 0 ? void 0 : containerSize.height) !== height)) {
setContainerSize({
width,
height
});
}
};
const onImageDataLoad = () => setDisplayPlaceholder(false);
const onVideoLoad = event => {
const {
height,
width
} = event.naturalSize;
setVideoNaturalSize({
height,
width
});
setDisplayPlaceholder(false); // Avoid invisible, paused video on Android, presumably related to
// https://git.io/Jt6Dr
videoRef === null || videoRef === void 0 ? void 0 : videoRef.current.seek(0);
};
const onXCoordinateChange = x => onChange({
x: (x / 100).toFixed(2)
});
const onYCoordinateChange = y => onChange({
y: (y / 100).toFixed(2)
});
return (0, _element.createElement)(_reactNative.View, {
style: _style.default.container
}, (0, _element.createElement)(_tooltip.default, {
onPress: onTooltipPress,
visible: tooltipVisible
}, (0, _element.createElement)(_reactNative.View, {
style: [_style.default.media, mediaBackground]
}, (0, _element.createElement)(_reactNative.View, (0, _extends2.default)({}, panResponder.panHandlers, {
onLayout: onMediaLayout,
style: _style.default.mediaContainer
}), !isVideo && (0, _element.createElement)(_components.Image, {
editButton: false,
highlightSelected: false,
isSelected: !displayPlaceholder,
height: "100%",
url: url,
style: imagePreviewStyles,
onImageDataLoad: onImageDataLoad
}), isVideo && (0, _element.createElement)(_reactNativeVideo.default, {
muted: true,
paused: true,
disableFocus: true,
onLoad: onVideoLoad,
ref: videoRef,
resizeMode: "contain",
source: {
uri: url
},
style: videoPreviewStyles
}), !displayPlaceholder && (0, _element.createElement)(_reactNative.Animated.View, {
pointerEvents: "none",
style: focalPointGroupStyles
}, (0, _element.createElement)(_tooltip.default.Label, {
text: (0, _i18n.__)('Drag to adjust focal point'),
yOffset: -(FOCAL_POINT_SIZE / 2)
}), (0, _element.createElement)(_focalPoint.default, {
height: (_styles$focalPoint = _style.default.focalPoint) === null || _styles$focalPoint === void 0 ? void 0 : _styles$focalPoint.height,
style: focalPointStyles,
width: (_styles$focalPoint2 = _style.default.focalPoint) === null || _styles$focalPoint2 === void 0 ? void 0 : _styles$focalPoint2.width
})))), (0, _element.createElement)(_components.UnitControl, {
key: `xAxis-${sliderKey}`,
label: (0, _i18n.__)('X-Axis Position'),
max: MAX_POSITION_VALUE,
min: MIN_POSITION_VALUE,
onChange: onXCoordinateChange,
unit: "%",
units: FOCAL_POINT_UNITS,
value: Math.round(focalPoint.x * 100)
}), (0, _element.createElement)(_components.UnitControl, {
key: `yAxis-${sliderKey}`,
label: (0, _i18n.__)('Y-Axis Position'),
max: MAX_POSITION_VALUE,
min: MIN_POSITION_VALUE,
onChange: onYCoordinateChange,
unit: "%",
units: FOCAL_POINT_UNITS,
value: Math.round(focalPoint.y * 100)
})));
}
var _default = FocalPointPicker;
exports.default = _default;
//# sourceMappingURL=index.native.js.map