@quidone/react-native-wheel-picker
Version:
Picker is a UI component for selecting an item from a list of options.
202 lines (199 loc) • 7.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useValueIndex = exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _PickerItem = _interopRequireDefault(require("../item/PickerItem"));
var _ScrollContentOffsetContext = require("../contexts/ScrollContentOffsetContext");
var _PickerItemHeightContext = require("../contexts/PickerItemHeightContext");
var _useValueEventsEffect = _interopRequireDefault(require("./hooks/useValueEventsEffect"));
var _useSyncScrollEffect = _interopRequireDefault(require("./hooks/useSyncScrollEffect"));
var _Overlay = _interopRequireDefault(require("../overlay/Overlay"));
var _faces = require("../item/faces");
var _PickerItemContainer = _interopRequireDefault(require("../item/PickerItemContainer"));
var _react2 = require("../../utils/react");
var _reactUsefulHooks = require("@rozhkov/react-useful-hooks");
var _List = _interopRequireDefault(require("../list/List"));
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const defaultKeyExtractor = (_, index) => index.toString();
const defaultRenderItem = ({
item: {
value,
label
},
itemTextStyle
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_PickerItem.default, {
value: value,
label: label,
itemTextStyle: itemTextStyle
});
const defaultRenderItemContainer = ({
key,
...props
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_PickerItemContainer.default, {
...props
}, key);
const defaultRenderOverlay = props => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Overlay.default, {
...props
});
const defaultRenderList = props => {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_List.default, {
...props
});
};
const useValueIndex = (data, value) => {
return (0, _react.useMemo)(() => {
const index = data.findIndex(x => x.value === value);
return index >= 0 ? index : 0;
}, [data, value]);
};
exports.useValueIndex = useValueIndex;
const Picker = ({
data,
value,
extraValues = [],
width = 'auto',
itemHeight = 48,
visibleItemCount = 5,
readOnly = false,
enableScrollByTapOnItem,
testID,
onValueChanged,
onValueChanging,
keyExtractor = defaultKeyExtractor,
renderItem = defaultRenderItem,
renderItemContainer = defaultRenderItemContainer,
renderOverlay = defaultRenderOverlay,
renderList = defaultRenderList,
style,
itemTextStyle,
overlayItemStyle,
contentContainerStyle,
_enableSyncScrollAfterScrollEnd = true,
_onScrollStart,
_onScrollEnd,
...restProps
}) => {
const valueIndex = useValueIndex(data, value);
const initialIndex = (0, _reactUsefulHooks.useInit)(() => valueIndex);
const offsetY = (0, _react.useMemo)(() => new _reactNative.Animated.Value(valueIndex * itemHeight),
// eslint-disable-next-line react-hooks/exhaustive-deps
[readOnly] // when scrollEnabled changes, the events stop coming. Re-creating
);
const listRef = (0, _react.useRef)(null);
const touching = (0, _react2.useBoolean)(false);
const [faces, pickerHeight] = (0, _react.useMemo)(() => {
const items = (0, _faces.createFaces)(itemHeight, visibleItemCount);
const height = (0, _faces.calcPickerHeight)(items, itemHeight);
return [items, height];
}, [itemHeight, visibleItemCount]);
const renderPickerItem = (0, _react.useCallback)(({
item,
index,
key
}) => renderItemContainer({
listRef,
key,
item,
index,
faces,
renderItem,
itemTextStyle,
enableScrollByTapOnItem,
readOnly
}), [enableScrollByTapOnItem, faces, itemTextStyle, readOnly, renderItem, renderItemContainer]);
const {
activeIndexRef,
onScrollEnd: onScrollEndForValueEvents
} = (0, _useValueEventsEffect.default)({
data,
valueIndex,
itemHeight,
offsetYAv: offsetY
}, {
onValueChanging,
onValueChanged
});
const {
onScrollStart: onScrollStartForSyncScroll,
onScrollEnd: onScrollEndForSyncScroll
} = (0, _useSyncScrollEffect.default)({
listRef,
value,
valueIndex,
extraValues,
activeIndexRef,
touching: touching.value,
enableSyncScrollAfterScrollEnd: _enableSyncScrollAfterScrollEnd
});
const onScrollStart = (0, _reactUsefulHooks.useStableCallback)(() => {
onScrollStartForSyncScroll();
_onScrollStart?.();
});
const onScrollEnd = (0, _reactUsefulHooks.useStableCallback)(() => {
// consistency matters
_onScrollEnd?.();
onScrollEndForValueEvents();
onScrollEndForSyncScroll();
});
// iOS can mount the picker list with a wrong initial contentOffset, so re-apply it after mount.
// See https://github.com/quidone/react-native-wheel-picker/issues/67.
(0, _react.useEffect)(() => {
if (_reactNative.Platform.OS === 'ios') {
listRef.current?.scrollToIndex({
index: initialIndex,
animated: false
});
}
}, []); // eslint-disable-line react-hooks/exhaustive-deps
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScrollContentOffsetContext.ScrollContentOffsetContext.Provider, {
value: offsetY,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_PickerItemHeightContext.PickerItemHeightContext.Provider, {
value: itemHeight,
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
testID: testID,
style: [styles.root, style, {
height: pickerHeight,
width
}],
children: [renderList({
...restProps,
ref: listRef,
data,
initialIndex,
itemHeight,
pickerHeight,
visibleItemCount,
readOnly,
keyExtractor,
renderItem: renderPickerItem,
scrollOffset: offsetY,
onTouchStart: touching.setTrue,
onTouchEnd: touching.setFalse,
onTouchCancel: touching.setFalse,
onScrollStart,
onScrollEnd,
contentContainerStyle
}), renderOverlay && renderOverlay({
itemHeight,
pickerWidth: width,
pickerHeight,
overlayItemStyle
})]
})
})
});
};
const styles = _reactNative.StyleSheet.create({
root: {
justifyContent: 'center',
alignItems: 'center'
}
});
var _default = exports.default = Picker;
//# sourceMappingURL=Picker.js.map