@whitemordred/react-native-bootstrap5
Version:
A complete React Native library that replicates Bootstrap 5.3 with 100% feature parity, full theming support, CSS variables, and dark/light mode
231 lines (229 loc) • 9.29 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Dropdown = exports.DropdownItem = exports.DropdownMenu = exports.DropdownToggle = void 0;
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const ThemeProvider_1 = require("../theme/ThemeProvider");
const DropdownToggle = ({ children, onPress, disabled = false, style, variant = 'secondary', size, }) => {
const { theme } = (0, ThemeProvider_1.useTheme)();
const getVariantStyles = () => {
const variantColors = theme.colors[variant];
const backgroundColor = typeof variantColors === 'string'
? variantColors
: (variantColors === null || variantColors === void 0 ? void 0 : variantColors[500]) || theme.colors.secondary;
return {
backgroundColor: disabled ? theme.colors.light : backgroundColor,
borderColor: backgroundColor,
};
};
const getSizeStyles = () => {
switch (size) {
case 'sm':
return { paddingHorizontal: 8, paddingVertical: 4, fontSize: 14 };
case 'lg':
return { paddingHorizontal: 16, paddingVertical: 12, fontSize: 18 };
default:
return { paddingHorizontal: 12, paddingVertical: 8, fontSize: 16 };
}
};
return (<react_native_1.TouchableOpacity onPress={onPress} disabled={disabled} style={[
styles.dropdownToggle,
getVariantStyles(),
getSizeStyles(),
disabled && styles.disabled,
style,
]}>
{typeof children === 'string' ? (<react_native_1.Text style={[styles.toggleText, { color: theme.colors.white }]}>
{children}
</react_native_1.Text>) : (children)}
<react_native_1.Text style={[styles.caret, { color: theme.colors.white }]}>▼</react_native_1.Text>
</react_native_1.TouchableOpacity>);
};
exports.DropdownToggle = DropdownToggle;
const DropdownMenu = ({ children, visible, onRequestClose, style, }) => {
const { theme } = (0, ThemeProvider_1.useTheme)();
return (<react_native_1.Modal visible={visible} transparent animationType="fade" onRequestClose={onRequestClose}>
<react_native_1.TouchableOpacity style={styles.overlay} onPress={onRequestClose}>
<react_native_1.View style={[styles.menu, { backgroundColor: theme.colors.white }, style]}>
{children}
</react_native_1.View>
</react_native_1.TouchableOpacity>
</react_native_1.Modal>);
};
exports.DropdownMenu = DropdownMenu;
const DropdownItem = ({ children, onPress, disabled = false, divider = false, style, textStyle, }) => {
const { theme } = (0, ThemeProvider_1.useTheme)();
if (divider) {
return (<react_native_1.View style={[styles.divider, { borderBottomColor: theme.colors.light }]}/>);
}
return (<react_native_1.TouchableOpacity onPress={onPress} disabled={disabled} style={[
styles.menuItem,
disabled && styles.disabledItem,
style,
]}>
<react_native_1.Text style={[
styles.menuItemText,
{ color: disabled ? theme.colors.gray[500] : theme.colors.dark },
textStyle,
]}>
{children}
</react_native_1.Text>
</react_native_1.TouchableOpacity>);
};
exports.DropdownItem = DropdownItem;
const Dropdown = ({ items, value, placeholder = 'Select an option', onSelect, disabled = false, variant = 'secondary', size, style, dropdownStyle, children, }) => {
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
const { theme } = (0, ThemeProvider_1.useTheme)();
const selectedItem = items.find(item => item.value === value);
const handleToggle = () => {
if (!disabled) {
setIsOpen(!isOpen);
}
};
const handleSelect = (item) => {
if (!item.disabled) {
onSelect === null || onSelect === void 0 ? void 0 : onSelect(item);
setIsOpen(false);
}
};
if (children) {
return (<react_native_1.View style={[styles.dropdown, style]}>
{react_1.default.Children.map(children, child => {
if (react_1.default.isValidElement(child) && child.type === exports.DropdownToggle) {
return react_1.default.cloneElement(child, {
onPress: handleToggle,
disabled,
variant,
size,
});
}
if (react_1.default.isValidElement(child) && child.type === exports.DropdownMenu) {
return react_1.default.cloneElement(child, {
visible: isOpen,
onRequestClose: () => setIsOpen(false),
});
}
return child;
})}
</react_native_1.View>);
}
return (<react_native_1.View style={[styles.dropdown, style]}>
<react_native_1.TouchableOpacity onPress={handleToggle} disabled={disabled} style={[
styles.dropdownToggle,
{
backgroundColor: theme.colors.white,
borderColor: theme.colors.light,
borderWidth: 1,
},
disabled && styles.disabled,
]}>
<react_native_1.Text style={[styles.toggleText, { color: theme.colors.dark }]}>
{selectedItem ? selectedItem.label : placeholder}
</react_native_1.Text>
<react_native_1.Text style={[styles.caret, { color: theme.colors.dark }]}>
{isOpen ? '▲' : '▼'}
</react_native_1.Text>
</react_native_1.TouchableOpacity>
<react_native_1.Modal visible={isOpen} transparent animationType="fade" onRequestClose={() => setIsOpen(false)}>
<react_native_1.TouchableOpacity style={styles.overlay} onPress={() => setIsOpen(false)}>
<react_native_1.View style={[styles.menu, dropdownStyle, { backgroundColor: theme.colors.white }]}>
<react_native_1.FlatList data={items} keyExtractor={(item, index) => `${item.value}-${index}`} renderItem={({ item }) => (<exports.DropdownItem onPress={() => handleSelect(item)} disabled={item.disabled} divider={item.divider} children={item.label}/>)}/>
</react_native_1.View>
</react_native_1.TouchableOpacity>
</react_native_1.Modal>
</react_native_1.View>);
};
exports.Dropdown = Dropdown;
const styles = react_native_1.StyleSheet.create({
dropdown: {
position: 'relative',
},
dropdownToggle: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 12,
paddingVertical: 8,
borderRadius: 4,
minHeight: 40,
},
toggleText: {
fontSize: 16,
flex: 1,
},
caret: {
fontSize: 12,
marginLeft: 8,
},
disabled: {
opacity: 0.6,
},
overlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
menu: {
minWidth: 200,
maxWidth: react_native_1.Dimensions.get('window').width * 0.8,
maxHeight: react_native_1.Dimensions.get('window').height * 0.6,
borderRadius: 4,
elevation: 5,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
},
menuItem: {
paddingHorizontal: 16,
paddingVertical: 12,
borderBottomWidth: react_native_1.StyleSheet.hairlineWidth,
borderBottomColor: '#e9ecef',
},
menuItemText: {
fontSize: 16,
},
disabledItem: {
opacity: 0.6,
},
divider: {
height: 1,
borderBottomWidth: 1,
marginVertical: 4,
},
});
exports.default = exports.Dropdown;