UNPKG

@devrue/rn-select

Version:

Custom typescript only select component for react native

109 lines (108 loc) 4.17 kB
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import React, { useEffect, useMemo, useState } from 'react'; import { Modal, SafeAreaView } from 'react-native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import useStyles from '../hooks/useStyles'; import { View } from 'react-native'; import { Platform } from 'react-native'; import { Pressable } from 'react-native'; import { useWindowDimensions } from 'react-native'; import { MIN_WIDTH } from './common'; export default function ListContainer({ children, style, position, avoidBottom, onOptionsOffet, ...rest }) { const { width, height } = useWindowDimensions(); const [listHeight, setListHeight] = useState(0); // will bleed horizontally const willBleed = ((position === null || position === void 0 ? void 0 : position.x) ?? 0) + MIN_WIDTH > width; const left = willBleed ? undefined : (position === null || position === void 0 ? void 0 : position.x) ?? 0; const right = willBleed ? width - (((position === null || position === void 0 ? void 0 : position.x) ?? 0) + ((position === null || position === void 0 ? void 0 : position.width) ?? 0)) : undefined; const top = useMemo(() => { if (Platform.OS === 'web' && avoidBottom === 'position') { const maxTop = height - listHeight - 80; const preferredTop = (position === null || position === void 0 ? void 0 : position.y) ?? 0; return Math.min(preferredTop, maxTop); } return (position === null || position === void 0 ? void 0 : position.y) ?? 0; }, [height, listHeight, position === null || position === void 0 ? void 0 : position.y, avoidBottom]); const styles = useStyles(({ tokens }) => ({ backdrop: { flex: 1 }, optionsContainer: { flex: 1, backgroundColor: '#ffffff', ...Platform.select({ default: {}, web: { top, left, right, maxHeight: 400, position: 'fixed', // this style is only applied on web paddingVertical: tokens.size.sm, marginTop: tokens.size.xl + tokens.size.sm, gap: tokens.size.sm, backgroundColor: '#ffffff', borderRadius: tokens.size.sm / 2, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84 } }) }, optionsContainerInner: { flex: 1, paddingTop: tokens.size.sm, gap: tokens.size.sm } }), [left, right, top]); const handleListHeight = listContentHeight => { if (Platform.OS === 'web' && avoidBottom === 'height') { onOptionsOffet === null || onOptionsOffet === void 0 || onOptionsOffet(height - listContentHeight - 80); } setListHeight(listContentHeight); }; return /*#__PURE__*/React.createElement(Modal, rest, /*#__PURE__*/React.createElement(Pressable, { style: styles.backdrop, onPress: rest.onRequestClose }, /*#__PURE__*/React.createElement(SafeAreaProvider, null, /*#__PURE__*/React.createElement(ListContent, { style: [styles.optionsContainer, style], onListHeight: handleListHeight }, /*#__PURE__*/React.createElement(View, { style: styles.optionsContainerInner }, children))))); } function ListContent({ onListHeight, ...rest }) { const [containerRef, setContainerRef] = useState(null); useEffect(() => { const onViewLayout = () => { containerRef === null || containerRef === void 0 || containerRef.measure((_x, _y, _w, h, _pageX, _pageY) => { onListHeight === null || onListHeight === void 0 || onListHeight(h); }); }; onViewLayout(); }, [containerRef, onListHeight]); return /*#__PURE__*/React.createElement(SafeAreaView, _extends({ ref: setContainerRef }, rest)); } //# sourceMappingURL=ListContainer.js.map