Repository: react-native
Issue: side bar is not sticking in rtl on fixed position while working fine in English.
Labels: Needs: Author Feedback,Needs: Repro,Newer Patch Available

### Description

import React, { useState, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Animated, Dimensions, Text, View, StyleSheet } from 'react-native';
import get from 'lodash.get';
import {I18nManager} from 'react-native'
// import { getFormattedCurrency } from '~/utils/units'

const ComparisonTableRow = (props) => {
  const {
    data = [],
    comparing,
    getBestBy,
    fixed,
    cellTextAlign,
    headerCellContent,
    headerCellStyle,
    cellContent,
    cellStyle,
    rowStyle,
    bestCellStyle,
    bestCellTextStyle,
    mergeCells,

    isHighlightBest,
    headerCellWidth,
    cellWidth,
    innerScrollX,
    scrollY
  } = props;

  let bestValueIndices = [];
  // Only sort them if user provide getBestBy order string/comparison function to sort the values
  if (comparing && getBestBy) {
    const valuesOriginal =
      typeof comparing === 'function'
        ? comparing(data)
        : data.map((item) => getComparingValue(item, comparing));

    const valuesSorted = getSortedValues(valuesOriginal, getBestBy);

    // if bestValueIndices is -1, either there is no best or getBestBy is null
    bestValueIndices = getBestValueIndices(valuesOriginal, valuesSorted);
  }

  const isAllValuesEqual = bestValueIndices.length === data.length;

  const mergedBestCellStyle = {
    ...styles.bestCell,
    ...bestCellStyle
  };

  const mergedBestCellTextStyle = {
    ...styles.bestCellText,
    ...bestCellTextStyle
  };

  function getComparingValue(item, comparing) {
    return get(item, comparing);
  }

  function getSortedValues(valuesOriginal, getBestBy) {
    let valuesSorted = [...valuesOriginal];
    if (typeof getBestBy === 'function') {
      valuesSorted.sort(getBestBy);
    } else if (getBestBy === 'asc') {
      valuesSorted.sort((a, b) => a - b);
    } else if (getBestBy === 'desc') {
      valuesSorted.sort((a, b) => b - a);
    }
    return valuesSorted;
  }

  function getBestValueIndices(valuesOriginal, valuesSorted) {
    const [bestValue] = valuesSorted;
    let bestValueIndices = [];
    if (bestValue !== undefined) {
      valuesOriginal.forEach((value, i) => {
        if (value === bestValue) {
          bestValueIndices.push(i);
        }
      });
    } else {
      bestValueIndices = [-1];
    }
    return bestValueIndices;
  }

  function renderHeaderCellContent() {

    return (
      <Animated.View
        style={[
          styles.headerCell,
          { width: headerCellWidth },
          headerCellStyle,
          innerScrollX && {
            transform: [
              {
                translateX: innerScrollX.interpolate({
                  inputRange: [0, I18nManager.isRTL ? 10: 3000],
                  outputRange: [0, I18nManager.isRTL ? 10: 3000],
                  extrapolate: 'clamp'
                })
              }
            ]
          }
        ]}
      >
        {/* {typeof headerCellContent === 'function' ? (
          headerCellContent()
        ) : ( */}
          <Text style={styles.headerCellText}>{headerCellContent}</Text>
        {/* )} */}
      </Animated.View>
    );
  }

  function renderTemplateCellContent(cellContent, item) {
    const comparingValue = getComparingValue(item, comparing);
    if (comparing && !comparingValue) {
      return '-';
    }

    return comparingValue;
  }

  function renderCustomCellContent(
    cellContent,
    index,
    item,
    isBest,
    mergedBestCellTextStyle
  ) {
    let customCellContent = cellContent({
      item,
      index,
      isBest,
      cellTextStyle: styles.cellText,
      bestCellTextStyle: mergedBestCellTextStyle
    });

    if (React.isValidElement(customCellContent)) {
      return customCellContent;
    }

    return (
      <Text
        style={[
          styles.cellText,
          cellTextAlign && { textAlign: cellTextAlign },
          isBest && mergedBestCellTextStyle
        ]}
      >
        {renderTemplateCellContent(customCellContent, item)}
      </Text>
    );
  }

  return (
    <Animated.View
      style={[
        styles.row,
        rowStyle,
        fixed &&
          scrollY && {
            ...styles.fixedRow,
            transform: [
              {
                translateY: scrollY.interpolate({
                  inputRange: [0, 10000],
                  outputRange: [0, 10000],
                  extrapolate: 'clamp'
                })
              }
            ]
          }
      ]}
    >
      {headerCellContent !== undefined && renderHeaderCellContent()}
      {mergeCells ? (
        <Animated.View
          style={[
            styles.mergedCell,
            { width: Dimensions.get('window').width - headerCellWidth },
            cellStyle,
            innerScrollX && {
              transform: [
                {
                  translateX: innerScrollX.interpolate({
                    inputRange: [0, 1000],
                    outputRange: [0, 1000],
                    extrapolate: 'clamp'
                  })
                }
              ]
            }
          ]}
        >
          {cellContent && typeof cellContent === 'function'
            ? cellContent({ data })
            : null}
        </Animated.View>
      ) : (
        data.map((item, index) => {
          const isBest =
            bestValueIndices.includes(index) &&
            isHighlightBest &&
            !isAllValuesEqual;
          return (
            <View
              style={[
                styles.cell,
                cellStyle,
                { width: cellWidth },
                isBest && mergedBestCellStyle
              ]}
              key={index}
            >
              {typeof cellContent === 'function' ? (
                renderCustomCellContent(
                  cellContent,
                  index,
                  item,
                  isBest,
                  mergedBestCellTextStyle
                )
              ) : (
                <Text
                  style={[
                    styles.cellText,
                    cellTextAlign && { textAlign: cellTextAlign },
                    isBest && mergedBestCellTextStyle
                  ]}
                >
                  {renderTemplateCellContent(cellContent, item)}
                </Text>
              )}
            </View>
          );
        })
      )}
    </Animated.View>
  );
};

const styles = StyleSheet.create({
  row: {
    borderTopWidth: 1,
    borderColor: '#E5E5E5',
    flexDirection: 'row'
  },
  fixedRow: {
    position: 'relative',
    zIndex: 100
  },
  headerCell: {
    position: 'relative',
    zIndex: 10,
    backgroundColor: '#F9F9FB',
    paddingVertical: 11,
    paddingHorizontal: 12,
    borderRightWidth: 1,
    borderColor: '#E5E5E5'
  },
  cell: {
    backgroundColor: '#FFF',
    paddingVertical: 10,
    paddingHorizontal: 14,
    borderRightWidth: 1,
    borderColor: '#E5E5E5'
  },
  mergedCell: {
    justifyContent: 'center',
    paddingVertical: 10,
    paddingHorizontal: 12
  },
  headerCellText: {
    fontSize: 20
  },
  cellText: {
    fontSize: 20
  },
  bestCell: {
    backgroundColor: 'rgba(255,236,170,0.2)'
  },
  bestCellText: {
    color: '#F6571A',
    fontWeight: 'bold'
  }
});

ComparisonTableRow.propTypes = {
  data: PropTypes.array,
  comparing: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  getBestBy: PropTypes.oneOfType([
    PropTypes.oneOf(['asc', 'desc']),
    PropTypes.func
  ]),
  headerCellContent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  headerCellStyle: PropTypes.object,
  cellContent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  cellStyle: PropTypes.object,
  rowStyle: PropTypes.object,
  bestCellStyle: PropTypes.object,
  bestCellTextStyle: PropTypes.object,
  isHighlightBest: PropTypes.bool,
  innerScrollX: PropTypes.object
};

ComparisonTableRow.defaultProps = {};

export default ComparisonTableRow;


code responsible for this:
  <Animated.View
        style={[
          styles.headerCell,
          { width: headerCellWidth },
          headerCellStyle,
          innerScrollX && {
            transform: [
              {
                translateX: innerScrollX.interpolate({
                  inputRange: [0, I18nManager.isRTL ? 10: 3000],
                  outputRange: [0, I18nManager.isRTL ? 10: 3000],
                  extrapolate: 'clamp'
                })
              }
            ]
          }
        ]}
      >
       
          <Text style={styles.headerCellText}>{headerCellContent}</Text>
      </Animated.View>

### Steps to reproduce

unable to reproduce

### React Native Version

0.76.5

### Affected Platforms

Runtime - Android, Runtime - iOS

### Output of `npx react-native info`

```text
System:
  OS: macOS 14.6.1
  CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
  Memory: 56.37 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.12.0
    path: ~/.nvm/versions/node/v22.12.0/bin/node
  Yarn:
    version: 1.22.22
    path: /usr/local/bin/yarn
  npm:
    version: 10.9.0
    path: ~/.nvm/versions/node/v22.12.0/bin/npm
  Watchman:
    version: 2024.12.02.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /usr/local/lib/ruby/gems/3.3.0/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.2
      - iOS 18.2
      - macOS 15.2
      - tvOS 18.2
      - visionOS 2.2
      - watchOS 11.2
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.2 AI-242.23339.11.2421.12700392
  Xcode:
    version: 16.2/16C5032a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.13
    path: /usr/bin/javac
  Ruby:
    version: 3.3.6
    path: /usr/local/opt/ruby/bin/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.0.1
    wanted: 15.0.1
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.76.5
    wanted: 0.76.5
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false
```

### Stacktrace or Logs

```text
no lots
```

### Reproducer

no reproducer

### Screenshots and Videos

_No response_