@futurejj/react-native-checkbox
Version:
A papery checkbox for react native
128 lines (124 loc) • 3.99 kB
JavaScript
"use strict";
import { useEffect, useMemo, useRef } from 'react';
import { Animated, StyleSheet, View, TouchableOpacity, Platform } from 'react-native';
import { animationDuration, defaultCheckedColor, defaultDisabledColor, defaultUncheckedColor } from "./constants.js";
import { getStyles } from "./styles.js";
// Import either Expo or React Native Vector Icons based on availability
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
function loadMaterialIcon() {
try {
return require('@expo/vector-icons/MaterialCommunityIcons').default;
} catch (e) {
try {
return require('react-native-vector-icons/MaterialCommunityIcons').default;
} catch (error) {
console.error('No icon library found. Please install either @expo/vector-icons or react-native-vector-icons');
return null;
}
}
}
const MaterialCommunityIcon = loadMaterialIcon();
function Checkbox(props) {
const {
status,
disabled = false,
onPress,
testID,
uncheckedColor = defaultUncheckedColor,
color = defaultCheckedColor,
style,
size = 24,
...rest
} = props;
// Get styles based on size
const styles = useMemo(() => getStyles(size), [size]);
const {
current: scaleAnim
} = useRef(new Animated.Value(1));
const isFirstRendering = useRef(true);
useEffect(() => {
// Do not run animation on very first rendering
if (isFirstRendering.current) {
isFirstRendering.current = false;
return;
}
const checked = status === 'checked';
Animated.sequence([Animated.timing(scaleAnim, {
toValue: 0.85,
duration: checked ? animationDuration : 0,
useNativeDriver: false
}), Animated.timing(scaleAnim, {
toValue: 1,
duration: checked ? animationDuration : animationDuration * 1.75,
useNativeDriver: false
})]).start();
}, [status, scaleAnim]);
const checked = useMemo(() => status === 'checked', [status]);
const indeterminate = useMemo(() => status === 'indeterminate', [status]);
const selectionControlColor = useMemo(() => {
if (disabled) {
return defaultDisabledColor;
}
if (checked) {
return color;
}
return uncheckedColor;
}, [disabled, checked, color, uncheckedColor]);
const borderWidth = scaleAnim.interpolate({
inputRange: [0.8, 1],
outputRange: [7 * (size / 24), 0] // Scale border animation with size
});
const icon = useMemo(() => indeterminate ? 'minus-box' : checked ? 'checkbox-marked' : 'checkbox-blank-outline', [indeterminate, checked]);
// Accessibility props based on platform
const accessibilityProps = useMemo(() => Platform.OS === 'web' ? {
role: 'checkbox',
accessibilityState: {
checked,
disabled
}
// focusable: !disabled,
} : {
accessibilityRole: 'checkbox',
accessibilityState: {
disabled,
checked
},
accessibilityLiveRegion: 'polite'
}, [checked, disabled]);
return /*#__PURE__*/_jsx(TouchableOpacity, {
...rest,
...accessibilityProps,
onPress: disabled ? undefined : onPress,
style: [styles.container, style],
testID: testID,
activeOpacity: 0.7,
children: /*#__PURE__*/_jsxs(Animated.View, {
style: {
transform: [{
scale: scaleAnim
}]
},
children: [MaterialCommunityIcon ? /*#__PURE__*/_jsx(MaterialCommunityIcon, {
allowFontScaling: false,
name: icon,
size: size,
color: selectionControlColor
}) : /*#__PURE__*/_jsx(View, {
style: [styles.fallbackIcon, {
borderColor: selectionControlColor
}]
}), /*#__PURE__*/_jsx(View, {
style: [StyleSheet.absoluteFill, styles.fillContainer],
children: /*#__PURE__*/_jsx(Animated.View, {
style: [styles.fill, {
borderColor: selectionControlColor
}, {
borderWidth
}]
})
})]
})
});
}
export { Checkbox };
//# sourceMappingURL=index.js.map