@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
222 lines (218 loc) • 8.37 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.Carousel = exports.CarouselControls = exports.CarouselIndicators = exports.CarouselCaption = void 0;
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const ThemeProvider_1 = require("../theme/ThemeProvider");
const CarouselCaption = ({ title, subtitle, style, titleStyle, subtitleStyle, }) => {
const { theme } = (0, ThemeProvider_1.useTheme)();
if (!title && !subtitle)
return null;
return (<react_native_1.View style={[styles.caption, style]}>
{title && (<react_native_1.Text style={[styles.captionTitle, { color: theme.colors.white }, titleStyle]}>
{title}
</react_native_1.Text>)}
{subtitle && (<react_native_1.Text style={[styles.captionSubtitle, { color: theme.colors.white }, subtitleStyle]}>
{subtitle}
</react_native_1.Text>)}
</react_native_1.View>);
};
exports.CarouselCaption = CarouselCaption;
const CarouselIndicators = ({ items, activeIndex, onPress, style, }) => {
const { theme } = (0, ThemeProvider_1.useTheme)();
return (<react_native_1.View style={[styles.indicators, style]}>
{items.map((_, index) => (<react_native_1.TouchableOpacity style={[
styles.indicator,
{
backgroundColor: index === activeIndex
? theme.colors.white
: 'rgba(255, 255, 255, 0.5)',
},
]} onPress={() => onPress(index)}/>))}
</react_native_1.View>);
};
exports.CarouselIndicators = CarouselIndicators;
const CarouselControls = ({ onPrevious, onNext, style, }) => {
const { theme } = (0, ThemeProvider_1.useTheme)();
return (<react_native_1.View style={[styles.controls, style]}>
<react_native_1.TouchableOpacity style={[styles.controlButton, styles.prevButton]} onPress={onPrevious}>
<react_native_1.Text style={[styles.controlText, { color: theme.colors.white }]}>‹</react_native_1.Text>
</react_native_1.TouchableOpacity>
<react_native_1.TouchableOpacity style={[styles.controlButton, styles.nextButton]} onPress={onNext}>
<react_native_1.Text style={[styles.controlText, { color: theme.colors.white }]}>›</react_native_1.Text>
</react_native_1.TouchableOpacity>
</react_native_1.View>);
};
exports.CarouselControls = CarouselControls;
const Carousel = ({ items, autoPlay = false, interval = 5000, indicators = true, controls = true, fade = false, onSlideChange, style, itemStyle, }) => {
const [activeIndex, setActiveIndex] = (0, react_1.useState)(0);
const scrollViewRef = (0, react_1.useRef)(null);
const autoPlayRef = (0, react_1.useRef)();
const { width } = react_native_1.Dimensions.get('window');
(0, react_1.useEffect)(() => {
if (autoPlay) {
startAutoPlay();
}
else {
stopAutoPlay();
}
return () => stopAutoPlay();
}, [autoPlay, activeIndex]);
const startAutoPlay = () => {
stopAutoPlay();
autoPlayRef.current = setTimeout(() => {
const nextIndex = (activeIndex + 1) % items.length;
goToSlide(nextIndex);
}, interval);
};
const stopAutoPlay = () => {
if (autoPlayRef.current) {
clearTimeout(autoPlayRef.current);
}
};
const goToSlide = (index) => {
var _a;
if (index >= 0 && index < items.length) {
setActiveIndex(index);
(_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
x: index * width,
animated: true,
});
onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(index);
}
};
const handleScroll = (event) => {
const contentOffsetX = event.nativeEvent.contentOffset.x;
const newIndex = Math.round(contentOffsetX / width);
if (newIndex !== activeIndex && newIndex >= 0 && newIndex < items.length) {
setActiveIndex(newIndex);
onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(newIndex);
}
};
const goToPrevious = () => {
const prevIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
goToSlide(prevIndex);
};
const goToNext = () => {
const nextIndex = (activeIndex + 1) % items.length;
goToSlide(nextIndex);
};
return (<react_native_1.View style={[styles.carousel, style]}>
<react_native_1.ScrollView horizontal pagingEnabled showsHorizontalScrollIndicator={false} onScroll={handleScroll} scrollEventThrottle={16} onTouchStart={stopAutoPlay} onTouchEnd={() => autoPlay && startAutoPlay()}>
{items.map((item, index) => (<react_native_1.View style={[styles.slide, { width }, itemStyle]}>
{item.content}
{item.caption && (<exports.CarouselCaption title={item.caption.title} subtitle={item.caption.subtitle}/>)}
</react_native_1.View>))}
</react_native_1.ScrollView>
{indicators && (<exports.CarouselIndicators items={items} activeIndex={activeIndex} onPress={goToSlide}/>)}
{controls && (<exports.CarouselControls onPrevious={goToPrevious} onNext={goToNext}/>)}
</react_native_1.View>);
};
exports.Carousel = Carousel;
const styles = react_native_1.StyleSheet.create({
carousel: {
position: 'relative',
backgroundColor: '#000',
},
slide: {
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
},
caption: {
position: 'absolute',
bottom: 20,
left: 20,
right: 20,
padding: 16,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderRadius: 8,
},
captionTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 4,
},
captionSubtitle: {
fontSize: 14,
opacity: 0.9,
},
indicators: {
position: 'absolute',
bottom: 20,
left: 0,
right: 0,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
indicator: {
width: 12,
height: 12,
borderRadius: 6,
marginHorizontal: 4,
},
controls: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
controlButton: {
width: 50,
height: 50,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.3)',
borderRadius: 25,
margin: 10,
},
prevButton: {
marginLeft: 20,
},
nextButton: {
marginRight: 20,
},
controlText: {
fontSize: 24,
fontWeight: 'bold',
},
});
exports.default = exports.Carousel;