UNPKG

react95-native

Version:

Refreshed Windows 95 style UI components for your React Native app

223 lines (199 loc) 9.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _useAsyncReference = _interopRequireDefault(require("../../hooks/useAsyncReference")); var _theming = require("../../core/theming"); var _ = require("../.."); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; } function _extends() { _extends = Object.assign || 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); } // TODO: performance improvements (callbacks, refs ...etc) // TODO: disable scroll buttons when scroll position reached min or max // TODO: add 'scrollIncrement' prop (granularity of scroll buttons) const ScrollView = ({ alwaysShowScrollbars = false, children, horizontal = false, small = false, scrollViewProps = {}, style, theme, ...rest }) => { const scrollViewRef = (0, _react.useRef)(null); const [contentOffset, setContentOffset] = (0, _useAsyncReference.default)(0); const [contentSize, setContentSize] = (0, _useAsyncReference.default)(0); const [scrollViewSize, setScrollViewSize] = (0, _useAsyncReference.default)(0); const scrollbarThickness = small ? 26 : 30; const scrollbarButtonSize = scrollbarThickness; const scrollbarAxis = horizontal ? 'x' : 'y'; const scrollbarLengthDimension = horizontal ? 'width' : 'height'; const scrollbarThicknessDimension = horizontal ? 'height' : 'width'; const contentFullyVisible = contentSize.current <= scrollViewSize.current; const visibleContentRatio = scrollViewSize.current / contentSize.current; const scrolledContentRatio = contentOffset.current / contentSize.current; const thumbPosition = Math.max(0, Math.min(1 - visibleContentRatio, parseFloat(scrolledContentRatio.toFixed(3)))) * 100; // CALLBACKS const scrollTo = (distance, animated = false) => { if (scrollViewRef.current) { scrollViewRef.current.scrollTo({ [scrollbarAxis]: distance, animated }); } }; const handleScrollButtonPress = direction => { scrollTo(contentOffset.current + 24 * direction, true); }; const handleTrackPress = direction => { scrollTo(contentOffset.current + scrollViewSize.current * direction); }; const handleScroll = e => { var _scrollViewProps$onSc; (_scrollViewProps$onSc = scrollViewProps.onScroll) === null || _scrollViewProps$onSc === void 0 ? void 0 : _scrollViewProps$onSc.call(scrollViewProps, e); setContentOffset(e.nativeEvent.contentOffset[scrollbarAxis]); }; const handleContentSizeChange = (width, height) => { var _scrollViewProps$onCo; (_scrollViewProps$onCo = scrollViewProps.onContentSizeChange) === null || _scrollViewProps$onCo === void 0 ? void 0 : _scrollViewProps$onCo.call(scrollViewProps, width, height); setContentSize(horizontal ? width : height); }; const handleLayout = e => { var _scrollViewProps$onLa; (_scrollViewProps$onLa = scrollViewProps.onLayout) === null || _scrollViewProps$onLa === void 0 ? void 0 : _scrollViewProps$onLa.call(scrollViewProps, e); setScrollViewSize(e.nativeEvent.layout[scrollbarLengthDimension]); }; const dragStartScrollPositionRef = (0, _react.useRef)(0); const panResponder = (0, _react.useRef)(_reactNative.PanResponder.create({ onStartShouldSetPanResponder: () => true, onStartShouldSetPanResponderCapture: () => true, onMoveShouldSetPanResponder: () => true, onMoveShouldSetPanResponderCapture: () => true, onPanResponderGrant: () => { dragStartScrollPositionRef.current = contentOffset.current; }, onPanResponderMove: (_evt, gestureState) => { const scrollTrackLength = scrollViewSize.current - 2 * scrollbarButtonSize; const scrollDistanceChange = gestureState[horizontal ? 'dx' : 'dy'] / scrollTrackLength; const translatedDistance = scrollDistanceChange * contentSize.current; scrollTo(dragStartScrollPositionRef.current + translatedDistance); }, onPanResponderTerminationRequest: () => true })).current; return /*#__PURE__*/_react.default.createElement(_reactNative.View, _extends({ style: [styles.wrapper, { flexDirection: horizontal ? 'column' : 'row' }, style] }, rest), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [styles.content] }, /*#__PURE__*/_react.default.createElement(_reactNative.ScrollView, _extends({}, scrollViewProps, { showsVerticalScrollIndicator: false, showsHorizontalScrollIndicator: false, scrollEventThrottle: 10, ref: scrollViewRef, onScroll: handleScroll, onContentSizeChange: handleContentSizeChange, onLayout: handleLayout, horizontal: horizontal }), children)), (!contentFullyVisible || alwaysShowScrollbars) && /*#__PURE__*/_react.default.createElement(_reactNative.View, { accessibilityRole: "scrollbar", style: [{ flexDirection: horizontal ? 'row' : 'column', [scrollbarLengthDimension]: '100%', [scrollbarThicknessDimension]: scrollbarThickness, backgroundColor: theme.material }] }, /*#__PURE__*/_react.default.createElement(_reactNative.ImageBackground, { style: [styles.background], imageStyle: { resizeMode: 'repeat' }, source: { // TODO: create util function for generating checkered background uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAIUlEQVQoU2P8////fwYkwMjIyIjCp4MCZPtAbAwraa8AAEGrH/nfAIhgAAAAAElFTkSuQmCC' } }), /*#__PURE__*/_react.default.createElement(_.Button, { theme: theme, variant: "raised", onPress: () => handleScrollButtonPress(-1), disabled: contentFullyVisible, style: { height: scrollbarButtonSize, width: scrollbarButtonSize, padding: 0 } }, /*#__PURE__*/_react.default.createElement(_.ArrowIcon, { theme: theme, direction: horizontal ? 'left' : 'up', disabled: contentFullyVisible, segments: small ? 3 : 4 })), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [styles.scrollbarTrack] }, !contentFullyVisible && /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { flex: 1, flexDirection: horizontal ? 'row' : 'column' } }, /*#__PURE__*/_react.default.createElement(_reactNative.TouchableWithoutFeedback, { onPressIn: () => handleTrackPress(-1) }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { [scrollbarLengthDimension]: "".concat(thumbPosition, "%") } })), /*#__PURE__*/_react.default.createElement(_.Panel, _extends({ theme: theme, variant: "raised", style: { [scrollbarLengthDimension]: "".concat(visibleContentRatio * 100, "%") } }, panResponder.panHandlers)), /*#__PURE__*/_react.default.createElement(_reactNative.TouchableWithoutFeedback, { onPressIn: () => handleTrackPress(1) }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { flex: 1 } })))), /*#__PURE__*/_react.default.createElement(_.Button, { theme: theme, variant: "raised", onPress: () => handleScrollButtonPress(1), disabled: contentFullyVisible, style: { height: scrollbarButtonSize, width: scrollbarButtonSize, padding: 0 } }, /*#__PURE__*/_react.default.createElement(_.ArrowIcon, { theme: theme, direction: horizontal ? 'right' : 'down', disabled: contentFullyVisible, segments: small ? 3 : 4 })))); }; const styles = _reactNative.StyleSheet.create({ wrapper: { display: 'flex', position: 'relative' }, content: { flexGrow: 1, flexShrink: 1 }, scrollbarTrack: { overflow: 'hidden', flex: 1 }, background: { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0 } }); var _default = (0, _theming.withTheme)(ScrollView); exports.default = _default; //# sourceMappingURL=ScrollView.js.map