@wordpress/components
Version:
UI components for WordPress.
233 lines (206 loc) • 8.11 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.DraggableTrigger = void 0;
var _element = require("@wordpress/element");
var _reactNativeGestureHandler = require("react-native-gesture-handler");
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
var _style = _interopRequireDefault(require("./style.scss"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const Context = (0, _element.createContext)({});
const {
Provider
} = Context;
/**
* Draggable component.
*
* @param {Object} props Component props.
* @param {JSX.Element} props.children Children to be rendered.
* @param {Function} [props.onDragEnd] Callback when dragging ends.
* @param {Function} [props.onDragOver] Callback when dragging happens over an element.
* @param {Function} [props.onDragStart] Callback when dragging starts.
* @param {string} [props.testID] Id used for querying the pan gesture in tests.
*
* @return {JSX.Element} The component to be rendered.
*/
const Draggable = _ref => {
let {
children,
onDragEnd,
onDragOver,
onDragStart,
testID
} = _ref;
const isDragging = (0, _reactNativeReanimated.useSharedValue)(false);
const isPanActive = (0, _reactNativeReanimated.useSharedValue)(false);
const draggingId = (0, _reactNativeReanimated.useSharedValue)('');
const panGestureRef = (0, _element.useRef)();
const currentFirstTouchId = (0, _reactNativeReanimated.useSharedValue)(null);
const initialPosition = {
x: (0, _reactNativeReanimated.useSharedValue)(0),
y: (0, _reactNativeReanimated.useSharedValue)(0)
};
const lastPosition = {
x: (0, _reactNativeReanimated.useSharedValue)(0),
y: (0, _reactNativeReanimated.useSharedValue)(0)
};
(0, _reactNativeReanimated.useAnimatedReaction)(() => isDragging.value, (result, previous) => {
if (result === previous || previous === null) {
return;
}
if (result) {
if (onDragStart) {
onDragStart({
x: initialPosition.x.value,
y: initialPosition.y.value,
id: draggingId.value
});
}
} else if (onDragEnd) {
onDragEnd({
x: lastPosition.x.value,
y: lastPosition.y.value,
id: draggingId.value
});
}
});
function getFirstTouchEvent(event) {
'worklet';
return event.allTouches.find(touch => touch.id === currentFirstTouchId.value);
}
const panGesture = _reactNativeGestureHandler.Gesture.Pan().manualActivation(true).onTouchesDown(event => {
if (!currentFirstTouchId.value) {
const firstEvent = event.allTouches[0];
const {
x = 0,
y = 0
} = firstEvent;
currentFirstTouchId.value = firstEvent.id;
initialPosition.x.value = x;
initialPosition.y.value = y;
}
}).onTouchesMove((event, state) => {
if (!isPanActive.value && isDragging.value) {
isPanActive.value = true;
state.activate();
}
if (isPanActive.value && isDragging.value) {
const firstEvent = getFirstTouchEvent(event);
if (!firstEvent) {
state.end();
return;
}
lastPosition.x.value = firstEvent.x;
lastPosition.y.value = firstEvent.y;
if (onDragOver) {
onDragOver(firstEvent);
}
}
}).onTouchesCancelled((_event, state) => {
state.end();
}).onEnd(() => {
currentFirstTouchId.value = null;
isPanActive.value = false;
isDragging.value = false;
}).withRef(panGestureRef).shouldCancelWhenOutside(false).withTestId(testID);
const providerValue = (0, _element.useMemo)(() => {
return {
panGestureRef,
isDragging,
isPanActive,
draggingId
};
}, [// `isDragging`, `isPanActive` and `draggingId` are created using the
// `useSharedValue` hook provided by the `react-native-reanimated`, which in
// theory should guarantee that the value of these variables remains stable.
// ESLint can't pick this up, and that's why they have to be specified as
// dependencies for this hook call.
isDragging, isPanActive, draggingId]);
return (0, _element.createElement)(_reactNativeGestureHandler.GestureDetector, {
gesture: panGesture
}, (0, _element.createElement)(_reactNativeReanimated.default.View, {
style: _style.default.draggable__container
}, (0, _element.createElement)(Provider, {
value: providerValue
}, children)));
};
/**
* Draggable trigger component.
*
* This component acts as the trigger for the dragging functionality.
*
* @param {Object} props Component props.
* @param {JSX.Element} props.children Children to be rendered.
* @param {*} props.id Identifier passed within the event callbacks.
* @param {boolean} [props.enabled] Enables the long-press gesture.
* @param {number} [props.maxDistance] Maximum distance, that defines how far the finger is allowed to travel during a long press gesture.
* @param {number} [props.minDuration] Minimum time, that a finger must remain pressed on the corresponding view.
* @param {Function} [props.onLongPress] Callback when long-press gesture is triggered over an element.
* @param {Function} [props.onLongPressEnd] Callback when long-press gesture ends.
* @param {string} [props.testID] Id used for querying the long-press gesture handler in tests.
*
* @return {JSX.Element} The component to be rendered.
*/
const DraggableTrigger = _ref2 => {
let {
children,
enabled = true,
id,
maxDistance = 1000,
minDuration = 500,
onLongPress,
onLongPressEnd,
testID
} = _ref2;
const {
panGestureRef,
isDragging,
isPanActive,
draggingId
} = (0, _element.useContext)(Context);
const gestureHandler = (0, _reactNativeReanimated.useAnimatedGestureHandler)({
onActive: () => {
if (isDragging.value) {
return;
}
draggingId.value = id;
isDragging.value = true;
if (onLongPress) {
(0, _reactNativeReanimated.runOnJS)(onLongPress)(id);
}
},
onEnd: () => {
if (!isPanActive.value) {
isDragging.value = false;
}
if (onLongPressEnd) {
(0, _reactNativeReanimated.runOnJS)(onLongPressEnd)(id);
}
}
});
return (0, _element.createElement)(_reactNativeGestureHandler.LongPressGestureHandler, {
enabled: enabled,
minDurationMs: minDuration,
maxDist: maxDistance,
simultaneousHandlers: panGestureRef,
shouldCancelWhenOutside: false,
onGestureEvent: gestureHandler,
testID: testID
}, children);
};
exports.DraggableTrigger = DraggableTrigger;
var _default = Draggable;
exports.default = _default;
//# sourceMappingURL=index.native.js.map