Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | 1x 1x 6x 6x 6x 1x 6x 6x 6x 6x 6x 6x 6x 6x 13x 12x 11x 9x 5x 6x 13x 13x 13x 13x 13x 13x 13x 13x 13x 1x 1x | import React, { useEffect } from 'react';
import { View, Text, StyleSheet, Pressable } from 'react-native';
import type { StepperProps } from '../Stepper.types';
import { useTheme } from '../../../Themes/ThemeProvider';
import { colors as coloring } from '@sb/styles/colors';
const SEGMENT_GAP = 4;
const Stepper: React.FC<StepperProps> = ({
id,
steps,
currentStep,
onStepChange,
readonly = false,
header,
extraSpacing = false,
errorColor,
activeColor,
completedColor,
stepSize = 'medium',
forceErrorTest = false,
}) => {
const stepCount = steps.length;
useEffect(() => {
if (stepCount < 1) {
console.warn('Stepper requires at least one step.');
}
}, [stepCount]);
const { theme } = useTheme();
const finalErrorColor = errorColor || coloring[theme].colorStatus_Error;
const finalActiveColor = activeColor || coloring[theme].colorAccent;
const finalCompletedColor = completedColor || coloring[theme].colorAccent;
const thicknessMap: Record<'small' | 'medium' | 'large', number> = {
small: 2,
medium: 4,
large: 6,
};
const segmentThickness = thicknessMap[stepSize];
const spacingMargin = extraSpacing ? 38 : 8;
const getSegmentColor = (i: number): string => {
if (forceErrorTest && i === currentStep) return finalErrorColor;
if (steps[i].status === 'error') return finalErrorColor;
if (i < currentStep) return finalCompletedColor;
if (i === currentStep) return finalActiveColor;
return coloring[theme].colorStepperFallback;
};
return (
<View testID={id} style={[styles.container]}>
<View
accessibilityRole="tablist"
style={[styles.segmentContainer, { marginBottom: spacingMargin }]}
>
{steps.map((_, i) => {
const color = getSegmentColor(i);
const isLast = i === stepCount - 1;
const isFirst = i === 0;
const isSelected = i === currentStep;
let label = `Step ${i + 1}`;
if (isFirst) label += ', First step';
if (isLast) label += ', Final step';
if (isSelected) label += ', Selected';
return (
<Pressable
key={`segment-${i}`}
accessibilityRole="tab"
accessibilityLabel={label}
accessibilityState={{ disabled: readonly, selected: isSelected }}
onPress={() => {
Eif (!readonly && onStepChange) onStepChange(i);
}}
disabled={readonly}
style={[
styles.segment,
{
height: segmentThickness,
backgroundColor: color,
marginRight: isLast ? 0 : SEGMENT_GAP,
},
]}
/>
);
})}
</View>
{header && typeof header === 'string' && header.length ? (
<Text style={[styles.headerText, { color: coloring[theme].colorLoader_Text }]}>
{header}
</Text>
) : (
header
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
flexDirection: 'column',
alignItems: 'flex-start',
},
segmentContainer: {
flexDirection: 'row',
width: '100%',
},
segment: {
flex: 1,
},
headerText: {
fontWeight: 'bold',
textAlign: 'left',
},
});
export default Stepper;
|