import { forwardRef, useEffect, useMemo } from 'react'; import { View, type ViewProps } from 'react-native'; import { cn } from '@cdx-ui/utils'; import { progressSegmentedVariants, segmentVariants, type ProgressSegmentedVariants, } from './styles'; /* `ProgressSegmentedProps.total` remains in the public API until the next major release. */ /* eslint-disable @typescript-eslint/no-deprecated */ export interface ProgressSegmentedProps extends ViewProps, ProgressSegmentedVariants { /** Current step (1-based index into the segment count) */ readonly step: number; /** * Number of segments in the bar. Matches the Figma `segments` variant (2–6 in the design * system file); the prop accepts any positive integer for backward compatibility. */ readonly segments?: number; /** * @deprecated Use {@link ProgressSegmentedProps.segments} instead. This alias will be removed * in a future major release. */ readonly total?: number; /** When true, the current step segment is marked as complete rather than in-progress */ readonly isStepComplete?: boolean; /** * Returns the accessibility value text announced by screen readers. Receives the clamped * step, segment count, and whether the step is complete. */ readonly getAccessibilityText?: ( step: number, segmentCount: number, isStepComplete: boolean, ) => string; readonly className?: string; } export const ProgressSegmented = forwardRef( ( { step, segments, total, isStepComplete = false, getAccessibilityText, className, accessibilityLabel = 'Progress', ...props }, ref, ) => { const segmentCount = segments ?? total ?? 5; // TODO: Remove this once the `total` prop is removed. useEffect(() => { if (__DEV__ && total !== undefined && segments === undefined) { console.warn( '[ProgressSegmented] The `total` prop is deprecated and will be removed in a future major release. Use `segments` instead.', ); } }, [total, segments]); const clampedStep = Math.max(0, Math.min(step, segmentCount)); const segmentStates = useMemo(() => { return Array.from({ length: segmentCount }, (_, index) => { const segmentIndex = index + 1; let state: 'complete' | 'incomplete' | 'inprogress' = 'incomplete'; if (segmentIndex < clampedStep || (isStepComplete && segmentIndex === clampedStep)) { state = 'complete'; } else if (segmentIndex === clampedStep) { state = 'inprogress'; } return state; }); }, [segmentCount, clampedStep, isStepComplete]); let accessibilityText = `Step ${String(clampedStep)} of ${String(segmentCount)}`; if (getAccessibilityText) { accessibilityText = getAccessibilityText(clampedStep, segmentCount, isStepComplete); } else if (isStepComplete) { accessibilityText = `Step ${String(clampedStep)} of ${String(segmentCount)}, completed`; } return ( {segmentStates.map((state, index) => ( ))} ); }, ); ProgressSegmented.displayName = 'ProgressSegmented'; /* eslint-enable @typescript-eslint/no-deprecated */