@applicaster/zapp-react-native-ui-components
Version:
Applicaster Zapp React Native ui components for the Quick Brick App
232 lines (201 loc) • 5.99 kB
text/typescript
import * as React from "react";
import { BaseFocusable as BaseFocusableInterface } from "./BaseFocusable.interface";
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
type Props = {
initialFocus?: boolean;
id: string;
groupId: string;
preferredFocus?: boolean;
onRegister?: (focusable: FocusManager.TouchableRef) => void;
onUnregister?: (focusable: FocusManager.TouchableRef) => void;
willReceiveFocus?: FocusManager.FocusEventCB;
hasReceivedFocus?: FocusManager.FocusEventCB;
willLoseFocus?: FocusManager.FocusEventCB;
hasLostFocus?: FocusManager.FocusEventCB;
failedLostFocus?: FocusManager.FocusEventCB;
onPress?: (nativeEvent: React.SyntheticEvent) => void;
onFocus?: FocusManager.FocusEventCB;
onBlur?: FocusManager.FocusEventCB;
selected?: boolean;
};
export class BaseFocusable<
T extends Props = Props,
> extends BaseFocusableInterface<T> {
constructor(props) {
super(props);
this._isMounted = false;
this.state = {
focused: false,
boundingRect: {
x: 0,
y: 0,
width: 0,
height: 0,
top: 0,
bottom: 0,
left: 0,
right: 0,
},
};
this.onRegister = this.onRegister.bind(this);
this.onUnregister = this.onUnregister.bind(this);
this.setFocusedState = this.setFocusedState.bind(this);
this.willReceiveFocus = this.willReceiveFocus.bind(this);
this.onFocus = this.onFocus.bind(this);
this.hasReceivedFocus = this.hasReceivedFocus.bind(this);
this.willLoseFocus = this.willLoseFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.hasLostFocus = this.hasLostFocus.bind(this);
this.failedLostFocus = this.failedLostFocus.bind(this);
this.onPress = this.onPress.bind(this);
this.ref = React.createRef();
}
componentDidMount() {
const { id } = this.props;
const component = this;
this.node = this.ref.current;
focusManager.register({
id,
component: component,
});
}
measureView() {
this.ref.current.measure((x, y, width, height, pageX, pageY) => {
const top = pageY;
const bottom = top + height;
const left = pageX;
const right = left + width;
if (this._isMounted) {
this.setState({
boundingRect: {
x,
y,
width,
height,
top,
bottom,
left,
right,
},
});
}
});
}
getId() {
const { id } = this.props;
return id;
}
getRect() {
const { boundingRect } = this.state;
return {
top: boundingRect?.top,
left: boundingRect?.left,
right: boundingRect?.right,
bottom: boundingRect?.bottom,
width: boundingRect?.width,
height: boundingRect?.height,
x: boundingRect?.x,
y: boundingRect?.y,
};
}
componentWillUnmount() {
this._isMounted = false;
const { id } = this.props;
focusManager.unregister(id, { group: this.isGroup || false });
}
onRegister(focusable) {
this._isMounted = true;
const { onRegister = noop } = this.props;
onRegister(focusable);
}
onUnregister(focusable) {
const { onUnregister = noop } = this.props;
onUnregister(focusable);
}
willLoseFocus(focusable, scrollDirection) {
const { willLoseFocus = noop } = this.props;
willLoseFocus(focusable, scrollDirection);
}
willReceiveFocus(focusable, scrollDirection) {
const { willReceiveFocus = noop } = this.props;
willReceiveFocus(focusable, scrollDirection);
}
/**
* will invoke the underlying component's focus method
* @param {Object} focusable - sender
* @param {Object} scrollDirection
* @returns {Promise}
*/
onFocus(focusable, scrollDirection) {
const { onFocus = noop } = this.props;
this.setFocusedState(true);
onFocus(focusable, scrollDirection);
focusManager.invokeHandler?.(
FOCUS_EVENTS.FOCUS,
focusable,
scrollDirection
);
}
/**
* will invoke the underlying component's hasReceivedFocus method
* @param {Object} focusable - sender
* @param {Object} scrollDirection
* @returns {Promise}
*/
hasReceivedFocus(focusable, scrollDirection) {
const { hasReceivedFocus = noop } = this.props;
hasReceivedFocus(focusable, scrollDirection);
}
/**
* will invoke the underlying component's hasLostFocus method
* @param {Object} focusable - sender
* @param {Object} scrollDirection
* @returns {Promise}
*/
hasLostFocus(focusable, scrollDirection) {
const { hasLostFocus = noop } = this.props;
hasLostFocus(focusable, scrollDirection);
}
/**
* will invoke the underlying component's failedLostFocus method
* @param {Object} focusable - sender
* @param {Object} scrollDirection
* @returns {Promise}
*/
failedLostFocus(focusable, scrollDirection) {
const { failedLostFocus = noop } = this.props;
failedLostFocus(focusable, scrollDirection);
}
/**
* will invoke the underlying component's onBlur method
* @param {Object} focusable - sender
* @param {Object} scrollDirection
* @returns {Promise}
*/
onBlur(focusable, scrollDirection) {
const { onBlur = noop } = this.props;
this.setFocusedState(false);
onBlur(focusable, scrollDirection);
}
/**
* will invoke the underlying component's onPress method
* @param {Object} keyEvent
* @returns {Promise}
*/
onPress(keyEvent) {
const { onPress = noop } = this.props;
onPress(keyEvent);
}
isInGroup(group) {
const { groupId } = this.props;
const { id } = group.props;
return id === groupId;
}
setFocusedState(focused) {
if (this._isMounted) {
this.setState({ focused });
}
}
}