fixed cell width issue

This commit is contained in:
Asad Karimov 2025-03-10 14:48:15 -04:00
parent 214467ac82
commit 363f1fe39d
7 changed files with 98 additions and 121 deletions

@ -1,6 +1,6 @@
/* sheetjs (C) SheetJS -- https://sheetjs.com */
import { useState, useCallback } from 'react';
import { StyleSheet, Text, Button, Alert, ScrollView, Image } from 'react-native';
import { StyleSheet, Text, Button, Alert, ScrollView } from 'react-native';
import { Table, Row, Rows, TableWrapper } from 'react-native-tabeller';
import { read, utils, WorkSheet } from 'xlsx';
@ -25,6 +25,7 @@ function SheetJSExample(): JSX.Element {
const [widths, setWidths] = useState<number[]>(
Array.from({ length: 7 }, () => 20)
);
const importFile = useCallback(async () => {
try {
const ab = await (
@ -60,7 +61,7 @@ function SheetJSExample(): JSX.Element {
data={data[0]}
style={styles.thead}
textStyle={styles.text}
widthArr={widths.map((x) => x * 1.2)}
widthArr={widths}
/>
</TableWrapper>
<ScrollView>
@ -69,7 +70,7 @@ function SheetJSExample(): JSX.Element {
data={data.slice(1)}
style={styles.tr}
textStyle={styles.text}
widthArr={widths.map((x) => x * 1.2)}
widthArr={widths}
/>
</TableWrapper>
</ScrollView>
@ -80,7 +81,12 @@ function SheetJSExample(): JSX.Element {
}
const styles = StyleSheet.create({
container: { backgroundColor: '#F5FCFF' },
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: { fontSize: 20, textAlign: 'center', margin: 10 },
bolded: {
textAlign: 'center',
@ -88,8 +94,17 @@ const styles = StyleSheet.create({
marginBottom: 5,
fontWeight: 'bold',
},
thead: { height: 40, backgroundColor: '#f1f8ff' },
tr: { height: 30 },
thead: {
height: 40,
backgroundColor: '#f1f8ff',
borderWidth: 0.5,
justifyContent: 'center',
},
tr: {
height: 30,
borderWidth: 0.5,
justifyContent: 'center',
},
text: { marginLeft: 5 },
table: { width: '100%' },
image: { height: 16, width: 16 },

Binary file not shown.

@ -1,8 +1,7 @@
import { useMemo } from 'react';
import type { FC, PropsWithChildren } from 'react';
import { View, Text, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import { View, Text, StyleSheet, Pressable } from 'react-native';
import type { ViewStyle } from 'react-native';
import type { CellProps } from '../types';
/**
@ -18,7 +17,7 @@ export const Cell: FC<PropsWithChildren<CellProps>> = ({
borderStyle,
children,
onPress,
cellContainerProps = {},
cellContainer = {},
...props
}) => {
const textDom = children ?? (
@ -34,16 +33,27 @@ export const Cell: FC<PropsWithChildren<CellProps>> = ({
const composedStyles = useMemo(() => {
const styles: ViewStyle = {};
if (width) styles.width = width;
if (height) styles.height = height;
if (flex) styles.flex = flex;
if (!width && !flex && !height && !style) styles.flex = 1;
return styles;
}, [width, height, flex, style]);
// determine whether to apply flex: 1 to cell style
const cellStyle = useMemo(() => {
if (width) {
return {};
}
return styles.cell;
}, [width]);
return (
<View
{...cellContainerProps}
{...cellContainer}
style={StyleSheet.flatten([
{
borderTopWidth,
@ -52,16 +62,13 @@ export const Cell: FC<PropsWithChildren<CellProps>> = ({
},
composedStyles,
style,
cellContainerProps.style,
styles.cell,
cellContainer.style,
cellStyle,
])}
>
<TouchableWithoutFeedback
onPress={onPress ? () => onPress(data) : undefined}
disabled={!onPress}
>
<Pressable style={[styles.cell, style]} onPress={() => onPress?.(data)}>
{textDom}
</TouchableWithoutFeedback>
</Pressable>
</View>
);
};

@ -11,12 +11,9 @@ export const Col: FC<ColProps> = ({
heightArr,
flex,
textStyle,
borderStyle,
...props
}) => {
if (!data) return null;
return (
return data ? (
<View
style={StyleSheet.flatten([
{ width: width ?? (flex ? undefined : 1), flex },
@ -32,13 +29,12 @@ export const Col: FC<ColProps> = ({
width={width}
height={height}
textStyle={textStyle}
borderStyle={borderStyle}
{...props}
/>
);
})}
</View>
);
) : null;
};
export const Cols: FC<ColsProps> = ({
@ -48,14 +44,11 @@ export const Cols: FC<ColsProps> = ({
heightArr,
flexArr,
textStyle,
borderStyle,
...props
}) => {
if (!data) return null;
const width = widthArr ? sum(widthArr) : 0;
return (
return data ? (
<View style={StyleSheet.flatten([styles.cols, width ? { width } : {}])}>
{data.map((item, i) => {
const flex = flexArr?.[i];
@ -69,13 +62,12 @@ export const Cols: FC<ColsProps> = ({
flex={flex}
style={style}
textStyle={textStyle}
borderStyle={borderStyle}
{...props}
/>
);
})}
</View>
);
) : null;
};
const styles = StyleSheet.create({

@ -15,43 +15,40 @@ export const Row: FC<RowProps> = ({
height,
flexArr,
textStyle,
borderStyle,
onPress,
cellTextStyle,
...props
}) => {
// calc total width based on width array
const totalWidth = widthArr ? sum(widthArr) : 0;
// calc row styles based on props
const rowStyle = useMemo((): ViewStyle => {
const width = widthArr ? sum(widthArr) : 0;
const composedStyle = useMemo(() => {
const styles: ViewStyle = {};
if (totalWidth) styles.width = totalWidth;
if (height) styles.height = height;
return styles;
}, [totalWidth, height]);
if (width) styles.width = width;
if (!data || !data.length) return null;
if (height) styles.height = height;
return styles;
}, [width, height]);
if (!data) return null;
return (
<View style={[styles.row, rowStyle, style]}>
{data.map((item, index) => {
const cellFlex = flexArr?.[index];
const cellWidth = widthArr?.[index];
const customTextStyle = cellTextStyle
? cellTextStyle(item, index)
: undefined;
<View style={StyleSheet.flatten([composedStyle, styles.row, style])}>
{data.map((item, i) => {
const flex = flexArr?.[i];
const wth = widthArr?.[i];
return (
<Cell
key={index}
key={i}
data={item}
width={cellWidth}
width={wth}
height={height}
flex={cellFlex}
borderStyle={borderStyle}
textStyle={[customTextStyle, textStyle]}
flex={flex}
style={style}
onPress={onPress}
textStyle={StyleSheet.flatten([
cellTextStyle && cellTextStyle(item),
textStyle,
])}
{...props}
/>
);
@ -60,7 +57,6 @@ export const Row: FC<RowProps> = ({
);
};
/** Rows component - Renders multiple rows*/
export const Rows: FC<RowsProps> = ({
data,
style,
@ -68,44 +64,39 @@ export const Rows: FC<RowsProps> = ({
heightArr,
flexArr,
textStyle,
borderStyle,
...props
}) => {
// calc total flex and width
const totalFlex = flexArr ? sum(flexArr) : 0;
const totalWidth = widthArr ? sum(widthArr) : 0;
const flex = flexArr ? sum(flexArr) : 0;
const width = widthArr ? sum(widthArr) : 0;
// calc container styles
const containerStyle = useMemo((): ViewStyle => {
const composedStyle = useMemo(() => {
const styles: ViewStyle = {};
if (totalFlex) styles.flex = totalFlex;
if (totalWidth) styles.width = totalWidth;
if (flex) styles.flex = flex;
if (width) styles.width = width;
return styles;
}, [totalFlex, totalWidth]);
if (!data || !data.length) return null;
return (
<View style={containerStyle}>
{data.map((rowData, index) => {
const rowHeight = heightArr?.[index];
}, [flex, width]);
return data ? (
<View style={composedStyle}>
{data.map((item, i) => {
const height = heightArr?.[i];
return (
<Row
key={index}
data={rowData}
key={i}
data={item}
widthArr={widthArr}
height={rowHeight}
height={height}
flexArr={flexArr}
style={style}
textStyle={textStyle}
borderStyle={borderStyle}
{...props}
/>
);
})}
</View>
);
) : null;
};
const styles = StyleSheet.create({

@ -1,6 +1,6 @@
import type { FC } from 'react';
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { View } from 'react-native';
import type { TableProps, TableWrapperProps } from '../types';
@ -10,35 +10,25 @@ export const Table: FC<TableProps> = ({ style, borderStyle, children }) => {
const borderColor = borderStyle?.borderColor ?? '#000';
const renderChildren = () =>
React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return child;
// check if we should add the border style | skip known type names
const elementType = child.type as any;
const isScrollView =
elementType?.displayName === 'ScrollView' ||
elementType?.name === 'ScrollView';
if (borderStyle && !isScrollView) {
return React.cloneElement(child, {
borderStyle,
...child.props,
});
}
return child;
});
React.Children.map(children, (child: any) =>
React.cloneElement(
child,
borderStyle && child.type.displayName !== 'ScrollView'
? { borderStyle }
: {}
)
);
return (
<View
style={StyleSheet.flatten([
style={[
style,
{
borderLeftWidth,
borderBottomWidth,
borderColor,
},
])}
]}
>
{renderChildren()}
</View>
@ -51,28 +41,9 @@ export const TableWrapper: FC<TableWrapperProps> = ({
children,
}) => {
const renderChildren = () =>
React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return child;
React.Children.map(children, (child: any) =>
React.cloneElement(child, borderStyle ? { borderStyle } : {})
);
if (borderStyle) {
return React.cloneElement(child, {
borderStyle,
...child.props,
});
}
return child;
});
return (
<View style={StyleSheet.flatten([styles.wrapper, style])}>
{renderChildren()}
</View>
);
return <View style={style}>{renderChildren()}</View>;
};
const styles = StyleSheet.create({
wrapper: {
flex: 1,
},
});

@ -28,7 +28,7 @@ export interface CellProps extends BaseTableProps {
/** text style for cell content */
textStyle?: StyleProp<TextStyle>;
/** props passed to the cell container */
cellContainerProps?: ViewProps;
cellContainer?: ViewProps;
/** callback when cell is pressed */
onPress?: (data: any) => void;
/** children to render inside the cell */
@ -48,7 +48,7 @@ export interface RowProps extends BaseTableProps {
/** text style applied to all cell in the row */
textStyle?: StyleProp<TextStyle>;
/** function to generate custom text styles for individual cell */
cellTextStyle?: (item: any, index: number) => StyleProp<TextStyle>;
cellTextStyle?: (item: any) => StyleProp<TextStyle>;
/** callback when a cell is pressed */
onPress?: (item: any) => void;
}
@ -65,6 +65,7 @@ export interface RowsProps extends BaseTableProps {
flexArr?: number[];
/** text style applied to all cells */
textStyle?: StyleProp<TextStyle>;
cellTextStyle?: (item: any) => StyleProp<TextStyle>;
/** callback when a cell is pressed */
onPress?: (item: any) => void;
}