@fto-consult/expo-ui 6.24.2 → 6.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/app.config.json +1 -1
  2. package/babel.config.alias.js +2 -1
  3. package/babel.config.js +1 -1
  4. package/electron/utils/env.js +80 -0
  5. package/expo-ui-path.js +2 -2
  6. package/index.js +14 -13
  7. package/is-local-dev.js +5 -0
  8. package/metro.config.js +3 -2
  9. package/package.json +7 -4
  10. package/readChart.txt +4 -1
  11. package/src/App.js +3 -3
  12. package/src/components/Datagrid/Accordion/Row.js +74 -100
  13. package/src/components/Datagrid/Accordion/ToogleRow.js +9 -0
  14. package/src/components/Datagrid/Accordion/index.js +30 -35
  15. package/src/components/Datagrid/Actions/index.js +12 -44
  16. package/src/components/Datagrid/Checkbox.js +4 -7
  17. package/src/components/Datagrid/Common/Common.js +121 -152
  18. package/src/components/Datagrid/Dashboard/index.js +2 -2
  19. package/src/components/Datagrid/IndexComponent.js +8 -13
  20. package/src/components/Datagrid/Table/index.js +53 -51
  21. package/src/components/Datagrid/Test/index.js +10 -3
  22. package/src/components/Datagrid/events/evx.js +7 -0
  23. package/src/components/Datagrid/events/index.js +11 -0
  24. package/src/components/Datagrid/hooks/Provider.js +6 -0
  25. package/src/components/Datagrid/hooks/context.js +5 -0
  26. package/src/components/Datagrid/hooks/index.js +104 -0
  27. package/src/components/Datagrid/utils.js +8 -5
  28. package/src/components/Dialog/Dialog.js +13 -12
  29. package/src/components/Dialog/DialogContent.js +11 -0
  30. package/src/components/KeyboardAvoidingView/index.js +7 -3
  31. package/src/components/Label/index.js +8 -4
  32. package/src/components/List/Common.js +5 -3
  33. package/src/components/List/FlashList.js +13 -13
  34. package/src/components/List/Virtuoso/index.js +68 -10
  35. package/src/components/List/Virtuoso/index.native.js +6 -1
  36. package/src/components/Table/Header/Cell/index.js +10 -0
  37. package/src/components/Table/Header/Cell/index.native.js +7 -0
  38. package/src/components/Table/Header/index.js +34 -0
  39. package/src/components/Table/List/index.js +3 -1
  40. package/src/components/Table/List/index.native.js +2 -1
  41. package/src/components/Table/Row/Cell/Content.js +16 -0
  42. package/src/components/Table/Row/Cell/Content.native.js +15 -0
  43. package/src/components/Table/Row/Cell/index.js +30 -0
  44. package/src/components/Table/Row/RowWrapper.js +7 -0
  45. package/src/components/Table/Row/RowWrapper.native.js +11 -0
  46. package/src/components/Table/Row/index.js +38 -0
  47. package/src/components/Table/RowTemplate/index.js +10 -0
  48. package/src/components/Table/RowTemplate/index.web.js +9 -0
  49. package/src/components/Table/ScrollNative/index.js +7 -0
  50. package/src/components/Table/ScrollNative/index.native.js +8 -0
  51. package/src/components/Table/VirtuosoTable/index.js +5 -0
  52. package/src/components/Table/VirtuosoTable/index.native.js +3 -0
  53. package/src/components/Table/hooks.js +84 -0
  54. package/src/components/Table/index.js +92 -250
  55. package/src/components/Table/styles.js +104 -0
  56. package/src/components/Table/utils.js +1 -0
  57. package/src/context/Provider.js +16 -2
  58. package/src/layouts/AppBar/index.js +11 -10
  59. package/src/layouts/Screen/ScreenWithoutAuthContainer.js +14 -6
  60. package/src/navigation/Drawer/items/index.js +2 -1
  61. package/src/navigation/index.js +11 -3
  62. package/src/screens/Help/About.js +1 -1
  63. package/src/screens/Help/openLibraries.js +1 -1
  64. package/src/test-screens/Home.js +4 -1
  65. package/webpack.config.js +4 -2
  66. package/src/components/Table/Cell.js +0 -24
  67. package/src/components/Table/FiltersOrFooters.js +0 -18
  68. package/src/components/Table/Header.js +0 -25
  69. package/src/components/Table/Row.js +0 -21
@@ -1,19 +1,26 @@
1
1
  import View from "$ecomponents/View";
2
- import {defaultObj,defaultStr,debounce,defaultNumber,defaultVal} from "$cutils";
2
+ import {defaultObj,defaultStr,debounce,defaultNumber,isObj,defaultVal} from "$cutils";
3
3
  import PropTypes from "prop-types";
4
- export const DEFAULT_COLUMN_WIDTH = 60;
5
4
  import React from "$react";
6
- import Label from "$ecomponents/Label";
7
5
  import { StyleSheet,View as RNView,ScrollView,Dimensions} from "react-native";
8
- import { getRowStyle } from "$ecomponents/Datagrid/utils";
9
6
  import {isMobileNative} from "$cplatform";
10
7
  import theme from "$theme";
11
8
  import AbsoluteScrollView from "./AbsoluteScrollView";
12
- import Cell from "./Cell";
13
9
  import Row from "./Row";
14
- import List from "./List";
15
- import FiltersOrFooters from "./FiltersOrFooters";
10
+ import List,{TableRowComponent} from "./List";
11
+ import Header from "./Header";
12
+ import { usePrepareColumns,TableContext,useTable} from "./hooks";
13
+ import styles from "./styles";
14
+ import {useIsRowSelected} from "$ecomponents/Datagrid/hooks";
15
+ import {getRowStyle} from "$ecomponents/Datagrid/utils";
16
+ import ScrollNative from "./ScrollNative";
17
+ import VirtuosoTableComponent from "./VirtuosoTable";
18
+ export {styles};
19
+
16
20
  const isSCrollingRef = React.createRef();
21
+ const isNative = isMobileNative();
22
+
23
+ export * from "./utils";
17
24
  const scrollLists = (opts,refs)=>{
18
25
  refs.map((ref)=>{
19
26
  if(ref && ref.current && ref.current.scrollTo){
@@ -44,99 +51,27 @@ const getOnScrollCb = (refs,pos,cb2)=>{
44
51
  return isMobileNative()? cb : debounce(cb,200);
45
52
  }
46
53
 
47
- const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContainerStyle,onRender,height,progressBar,filter:customFilter,renderListContent,children,renderEmpty,renderItem,isRowSelected,headerScrollViewProps,footerScrollViewProps,scrollViewProps,showFooters,renderFooterCell,footerCellContainerProps,filterCellContainerProps,headerContainerProps,headerCellContainerProps,headerProps,rowProps:customRowProps,renderCell,cellContainerProps,hasFooters,renderHeaderCell,renderFilterCell,columnProps,getRowKey,columnsWidths,colsWidths,footerContainerProps,showHeaders,showFilters,columns,data,testID,...props},tableRef)=>{
54
+ const TableComponent = React.forwardRef(({containerProps,listContainerStyle,onRender,height,progressBar,renderListContent,children,renderEmpty,renderItem,isRowSelected,headerScrollViewProps,footerScrollViewProps,scrollViewProps,showFooters,renderFooterCell,footerCellContainerProps,filterCellContainerProps,headerContainerProps,headerCellContainerProps,headerProps,rowProps:customRowProps,cellContainerProps,hasFooters,renderHeaderCell,renderFilterCell,columnProps,getRowKey,columnsWidths,colsWidths,footerContainerProps,showHeaders,showFilters,columns,...props},tableRef)=>{
48
55
  containerProps = defaultObj(containerProps);
49
- testID = defaultStr(testID,"RN_TableComponent");
50
56
  cellContainerProps = defaultObj(cellContainerProps);
51
57
  scrollViewProps = defaultObj(scrollViewProps);
52
58
  headerScrollViewProps = defaultObj(headerScrollViewProps);
53
59
  footerScrollViewProps = defaultObj(footerScrollViewProps);
54
- renderCell = typeof renderCell ==="function"? renderCell : undefined;
55
- const getRowProps = typeof rowProps ==='function'? rowProps : undefined;
56
- let rowProps = isObj(customRowProps)? customRowProps:{};
57
60
  const listRef = React.useRef(null),scrollViewRef = React.useRef(null),headerScrollViewRef = React.useRef(null);
58
- const emptyData = renderListContent === false ?null : typeof renderEmpty =='function' && !Object.size(data,true)? renderEmpty() : null;
59
- const hasEmptyData = emptyData && React.isValidElement(emptyData);
60
61
  const layoutRef = React.useRef({});
61
-
62
- const preparedColumns = React.useMemo(()=>{
63
- const cols = {},headers = {},footers = {},filters = {},vColumnsMapping = [],visibleColumns = [],columnsNames = [];
64
- let hasFooters = false;
65
- columnProps = defaultObj(columnProps);
66
- let columnIndex = 0;
67
- const widths = defaultObj(columnsWidths,colsWidths);
68
- headerCellContainerProps = defaultObj(headerCellContainerProps);
69
- footerCellContainerProps = defaultObj(footerCellContainerProps);
70
- filterCellContainerProps = defaultObj(filterCellContainerProps);
71
- Object.map(columns,(columnDef,field)=>{
72
- if(!isObj(columnDef)) return;
73
- const columnField = defaultStr(columnDef.field,field);
74
- let {visible,width,type,...colProps} = columnDef;
75
- visible = typeof visible =='boolean'? visible : true;
76
- type = defaultStr(type,"text").toLowerCase().trim();
77
- colProps = defaultObj(colProps);
78
- width = defaultDecimal(widths[columnField],width,DEFAULT_COLUMN_WIDTH);
79
- const style = StyleSheet.flatten([colProps.style,{width}]);
80
- const colArgs = {width,type,style,columnDef,containerProps:{},columnField,index:columnIndex,columnIndex};
81
- const content = typeof renderHeaderCell =='function'? renderHeaderCell(colArgs) : defaultVal(columnDef.text,columnDef.label,columnField);
82
- const hContainerProps = defaultObj(colArgs.containerProps);
83
- if(!React.isValidElement(content,true)){
84
- console.error(content," is not valid element of header ",columnDef," it could not be render on table");
85
- return null;
86
- }
87
- headers[columnField] = <View testID={testID+"_HeaderCell_"+columnField} {...headerCellContainerProps} {...hContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,headerCellContainerProps.style,hContainerProps.style,style]}>
88
- <Label splitText numberOfLines={2} style={[theme.styles.w100,theme.styles.h100,{maxHeight:70}]} textBold primary>{content}</Label>
89
- </View>;
90
- if(typeof renderFilterCell =='function'){
91
- const filterCell = renderFilterCell(colArgs);
92
- filters[columnField] = <View testID={testID+"_Filter_Cell_"+columnField} {...filterCellContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,styles.filterCell,filterCellContainerProps.style,style]}>
93
- {React.isValidElement(filterCell)? filterCell : null}
94
- </View>
95
- }
96
- if(typeof renderFooterCell ==='function') {
97
- const footerProps = {...colArgs,containerProps:{}};
98
- let cellFooter = renderFooterCell(footerProps);
99
- let fContainerProps = {};
100
- if(!React.isValidElement(cellFooter,true) && isObj(cellFooter)){
101
- fContainerProps = isObj(cellFooter.containerProps)? cellFooter.containerProps : {};
102
- cellFooter = React.isValidElement(cellFooter.children)? cellFooter.children : React.isValidElement(cellFooter.content)? cellFooter.content : null;
103
- } else if(isObj(footerProps.containerProps)){
104
- fContainerProps = footerProps.containerProps;
105
- }
106
- cellFooter = React.isValidElement(cellFooter,true)? cellFooter : null;
107
- if(!hasFooters && cellFooter){
108
- hasFooters = true;
109
- }
110
- footers[columnField] = <View testID={testID+"_Footer_Cell_"+columnField} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,footerCellContainerProps.style,style]}>
111
- <Label primary children={cellFooter}/>
112
- </View>
113
- }
114
- vColumnsMapping.push(visible);
115
- if(visible){
116
- visibleColumns.push(columnField);
117
- }
118
- columnsNames.push(columnField);
119
- cols[columnField] = {
120
- ...columnDef,
121
- width,
122
- index : columnIndex,
123
- field : columnField,
124
- visible,
125
- columnField,
126
- };
127
- columnIndex++;
128
- });
129
- return {columns:cols,columnsNames,headers,visibleColumns,vColumnsMapping,hasFooters,footers,filters};
130
- },[columns,sortedColumn,props.footers]);
131
- const {columns:cols,headers,footers,filters,hasFooters:stateHasFooters,columnsNames,vColumnsMapping,visibleColumns} = preparedColumns;
62
+ const {columns:cols,testID,headers,footers,getItem,withDatagridContext,filters,getRowByIndex,itemsChanged,hasFooters:stateHasFooters,visibleColsNames,keyExtractor,items,data} = useTable();
132
63
  headerContainerProps = defaultObj(headerContainerProps);
133
64
  footerContainerProps = defaultObj(footerContainerProps);
134
- const dimensions = Dimensions.get("window");
135
- const maxHWidth = dimensions.width - defaultNumber(layoutRef.current.left,layoutRef.current.x);
65
+ const hasData = !!Object.size(data,true);
66
+ const emptyData = !hasData && renderListContent === false ?null : typeof renderEmpty =='function' ? renderEmpty() : null;
67
+ const hasEmptyData = emptyData && React.isValidElement(emptyData);
68
+ const emptyContent = <View onRender={onComponentRender} testID={testID+"_EmptyData"} style={styles.hasNotData}>
69
+ {emptyData}
70
+ </View>
136
71
  const {fFilters,headersContent,footersContent,totalWidths} = React.useMemo(()=>{
137
72
  const headersContent = [],footersContent = [],fFilters = [];
138
73
  let totalWidths = 0;
139
- visibleColumns.map((i,index)=>{
74
+ visibleColsNames.map((i,index)=>{
140
75
  headersContent.push(headers[i]);
141
76
  totalWidths+=cols[i].width;
142
77
  if(showFooters && stateHasFooters){
@@ -148,50 +83,9 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
148
83
  });
149
84
 
150
85
  return {headersContent,totalWidths,footersContent,fFilters};
151
- },[visibleColumns,showFilters,showFooters,layoutRef.current]);
152
- const prevData = React.usePrevious(data);
153
- const prevColumns = React.usePrevious(columns);
154
- const itemsRef = React.useRef(null);
155
- const hasChangedDataRef = React.useRef(false);
156
- hasChangedDataRef.current = false;
157
- const items = React.useMemo(()=>{
158
- if(data === prevData && prevColumns == columns && Array.isArray(itemsRef.current)){
159
- hasChangedDataRef.current = false;
160
- return itemsRef.current;
161
- }
162
- hasChangedDataRef.current = true;
163
- const items = [];
164
- const filter = typeof customFilter =='function'? customFilter : x=>true;
165
- data.map((item,index)=>{
166
- const rowIndex = index;
167
- if(!isObj(item) || filter({item,index,_index:rowIndex}) ===false) return null;
168
- const rowArgs = {data:item,isTable:true,isAccordion:false,item,row:item,rowData:item,rowIndex,index};
169
- const rProps = defaultObj(getRowProps ? getRowProps(rowArgs) : {});
170
- rowArgs.rowProps = rProps;
171
- rowArgs.rowStyle = rProps.style = StyleSheet.flatten([rowProps.style,getRowStyle(rowArgs),styles.rowNoPadding,rProps.style]);
172
- if(item.isSectionListHeader){
173
- rowArgs.isSectionListHeader = true;
174
- }
175
- const sItem = typeof renderItem == 'function'? renderItem(rowArgs) : undefined;
176
- const cells = React.isValidElement(sItem) ? sItem : columnsNames.map((columnField,columnIndex)=>{
177
- const columnDef = cols[columnField];
178
- return <Cell
179
- rowArgs = {rowArgs}
180
- style = {StyleSheet.flatten([styles.headerItemOrCell,{width:columnDef.width}])}
181
- //key = {"_Cell_"+columnField+"_"+index}
182
- cellArgs={{columnIndex,columnDef,columnField:columnField}}
183
- renderCell = {renderCell}
184
- rowIndex = {index}
185
- children = {item[columnField]}
186
- testID={testID+"_Cell_"+columnField+"_"+index}
187
- />
188
- });
189
- if(!Array.isArray(cells) && !React.isValidElement(cells)) return null;
190
- items.push(<Row cells={cells} columns={vColumnsMapping} testID={testID+"_Row_"+index} {...rowProps} {...rProps} style={[styles.row,rProps.style]}/>);
191
- });
192
- itemsRef.current = items;
193
- return items;
194
- },[data,columns]);
86
+ },[visibleColsNames,showFilters,showFooters,layoutRef.current]);
87
+
88
+
195
89
  const scrollContentContainerStyle = {flex:1,width:listWidth,minWidth:totalWidths,height:'100%'};
196
90
  const scrollEventThrottle = isMobileNative()?200:50;
197
91
  const scrollViewFlexGrow = {flexGrow:0};
@@ -255,7 +149,7 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
255
149
  onRender(a,b,c);
256
150
  }
257
151
  //au paravant il était possible de faire scroller le composant Table lorsque les données sont raffraichies, ce qui n'avait pas un bon impact sur le rendu de la table de données
258
- if(false && hasChangedDataRef.current){
152
+ if(false && itemsChanged){
259
153
  //permet de restaurer la position scrollé où scroll initial à chaque fois que le composant est re render
260
154
  //ce qui n'est pas très interessant
261
155
  if(headerScrollViewRef.current && headerScrollViewRef.current.scrollTo){
@@ -267,14 +161,25 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
267
161
  }
268
162
  }
269
163
  };
164
+ const headerFootersFilters = <>
165
+ <Header visible={!!(showTableHeaders && headersContent.length)} testID={testID+"_Header"} {...headerContainerProps} style={[styles.header,headerContainerProps.style,footersContent.length]}>
166
+ {headersContent}
167
+ </Header>
168
+ <Header visible = {!!fFilters.length} {...headerContainerProps} testID={testID+"_Filters"} style={[styles.header,styles.footers,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0,headerContainerProps.style]}>
169
+ {fFilters}
170
+ </Header>
171
+ <Header visible={!!(showTableHeaders && footersContent.length)} testID={testID+"_Footer"} {...footerContainerProps} style={[styles.header,styles.footers,headerContainerProps.style,footerContainerProps.style,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
172
+ {footersContent}
173
+ </Header>
174
+ </>
270
175
  return <View testID= {testID+"_Container"} {...containerProps} onLayout={(e)=>{
271
176
  layoutRef.current = e.nativeEvent.layout;
272
177
  if(containerProps.onLayout){
273
178
  containerProps.onLayout(e);
274
179
  }
275
180
  }} style={[styles.container,{alignItems:'stretch'},containerProps.style]}>
276
- <RNView style={[cStyle]} testID={testID+"_Headers_ScrollViewContainer"}>
277
- <ScrollView
181
+ {isNative && <RNView style={[cStyle]} testID={testID+"_Headers_ScrollViewContainer"}>
182
+ <ScrollView
278
183
  testID={testID+"_HeaderScrollView"}
279
184
  {...headerScrollViewProps}
280
185
  contentContainerStyle = {[allScrollViewProps.contentContainerStyle,headerScrollViewProps.contentContainerStyle,{flex:1,flexWrap: 'wrap'}]}
@@ -285,21 +190,11 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
285
190
  showsHorizontalScrollIndicator
286
191
  >
287
192
  <View testID={testID+"Header2FootersWrapper"} style={[theme.styles.w100]}>
288
- <FiltersOrFooters visible={!!(showTableHeaders && headersContent.length)} testID={testID+"_Header"} {...headerContainerProps} style={[styles.header,headerContainerProps.style,footersContent.length]}>
289
- {headersContent}
290
- </FiltersOrFooters>
291
- <FiltersOrFooters visible = {!!fFilters.length} testID={testID+"_Filters"} style={[styles.header,styles.footers,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
292
- {fFilters}
293
- </FiltersOrFooters>
294
- <FiltersOrFooters visible={!!(showTableHeaders && footersContent.length)} testID={testID+"_Footer"} {...footerContainerProps} style={[styles.header,styles.footers,footerContainerProps.style,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
295
- {footersContent}
296
- </FiltersOrFooters>
193
+ {headerFootersFilters}
297
194
  </View>
298
195
  </ScrollView>
299
- </RNView>
300
- {hasEmptyData ? <View onRender={onComponentRender} testID={testID+"_Empty"} style={styles.hasNotData}>
301
- {emptyData}
302
- </View> : <ScrollView {...scrollViewProps} scrollEventThrottle = {scrollEventThrottle} horizontal contentContainerStyle={[scrollContentContainerStyle,scrollViewProps.contentContainerStyle,{height:'100%'}]} showsVerticalScrollIndicator={false}
196
+ </RNView>}
197
+ {hasEmptyData && isNative ? emptyContent : <ScrollNative {...scrollViewProps} scrollEventThrottle = {scrollEventThrottle} horizontal contentContainerStyle={[scrollContentContainerStyle,scrollViewProps.contentContainerStyle,{height:'100%'}]} showsVerticalScrollIndicator={false}
303
198
  onScroll = {getOnScrollCb([headerScrollViewRef,footerScrollViewRef],null,(args)=>{
304
199
  const nativeEvent = args.nativeEvent;
305
200
  if(absoluteScrollViewRef.current && absoluteScrollViewRef.current.checkVisibility){
@@ -325,6 +220,8 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
325
220
  <List
326
221
  containerProps = {{style:[cStyle,listContainerStyle]}}
327
222
  estimatedItemSize = {200}
223
+ renderTable
224
+ columns = {columns}
328
225
  {...props}
329
226
  onContentSizeChange = {(width,height)=>{
330
227
  if(props.onContentSizeChange){
@@ -357,7 +254,7 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
357
254
  items = {items}
358
255
  contentContainerStyle = {[styles.contentContainer,{width:listWidth,minWidth:totalWidths}]}
359
256
  style = {[styles.datagrid,{width:listWidth,minWidth:totalWidths}]}
360
- keyExtractor = {typeof getRowKey =='function'? getRowKey : React.getKey}
257
+ keyExtractor = {keyExtractor}
361
258
  onScroll = {getOnScrollCb([absoluteScrollViewRef],(args)=>{
362
259
  if(!absoluteScrollViewRef.current) return;
363
260
  const offset = args?.nativeEvent?.contentOffset.y;
@@ -370,26 +267,37 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
370
267
  },500);
371
268
  }
372
269
  })}
373
- renderItem = {({index})=>items[index]}
270
+ renderItem = {({item,index})=>{
271
+ return <Row rowData={item} index={index} testID={testID+"_Row_"+index}/>
272
+ }}
273
+ fixedHeaderContent={(index, user) => {
274
+ return headerFootersFilters;
275
+ }}
276
+ components = {{
277
+ TableRow: (props) => {
278
+ const index = props['data-index'];
279
+ const item = getRowByIndex(index) || props?.item || null;
280
+ if(!item) return null;
281
+ const args = {rowData:item,rowIndex:index,bordered:true,isTable:true};
282
+ args.isSelected = withDatagridContext ? isRowSelected(args) : false;
283
+ return <TableRowComponent {...props} style={[getRowStyle(args),props.style]}/>
284
+ },
285
+ Table: VirtuosoTableComponent,
286
+ }}
374
287
  />
375
- <AbsoluteScrollView
288
+ {isNative ? <AbsoluteScrollView
376
289
  ref={absoluteScrollViewRef}
377
290
  listRef = {listRef}
378
291
  scrollEventThrottle = {scrollEventThrottle}
379
292
  onScroll = {(args)=>{
380
293
  if(!absoluteScrollViewRefCanScroll.current || absoluteScrollingRef.current) return;
381
- //clearTimeout(absoluteScrollTimeout.current);
382
- //absoluteScrollTimeout.current = setTimeout(()=>{
383
- //absoluteScrollingRef.current = true;
384
- const offset = args?.nativeEvent?.contentOffset.y;
385
- if(typeof offset =='number' && listRef.current && listRef.current.scrollToOffset){
386
- listRef.current.scrollToOffset({animated:true,offset});
387
- }
388
- //absoluteScrollingRef.current = false;
389
- //},100);
294
+ const offset = args?.nativeEvent?.contentOffset.y;
295
+ if(typeof offset =='number' && listRef.current && listRef.current.scrollToOffset){
296
+ listRef.current.scrollToOffset({animated:true,offset});
297
+ }
390
298
  }}
391
- />
392
- </ScrollView>}
299
+ />:null}
300
+ </ScrollNative>}
393
301
 
394
302
  </View>
395
303
  });
@@ -403,96 +311,11 @@ const RowType = PropTypes.shape({
403
311
 
404
312
  });
405
313
 
406
- export const styles = StyleSheet.create({
407
- datagrid : {
408
- flex:1,
409
- },
410
- contentContainer : {
411
- flex:1,
412
- },
413
- container : {
414
- width : '100%',
415
- minHeight : 300,
416
- paddingBottom : 10,
417
- paddingLeft : 10,
418
- paddingRight : 0,
419
- flex : 1,
420
- position : 'relative',
421
- },
422
- header2footerContainer:{
423
- flexDirection : 'column',
424
- width : '100%',
425
- height : '100%',
426
- minHeight : 50,
427
- },
428
- headerContainer : {
429
- width : '100%',
430
- flexDirection : 'row',
431
- },
432
- header: {
433
- flexDirection: 'row',
434
- paddingVertical : 7,
435
- alignItems : 'center',
436
- width : '100%',
437
- },
438
- footerContainer : {
439
- width : '100%',
440
- flexDirection : 'row',
441
- flexWrap : 'wrap',
442
- },
443
- footers : {
444
- minHeight : 40,
445
- },
446
- headerItemOrCell : {
447
- alignItems: 'flex-start',
448
- alignSelf : 'center',
449
- height : '100%',
450
- justifyContent: 'center',
451
- textAlign : 'left',
452
- flexWrap : 'wrap',
453
- paddingHorizontal:5,
454
- paddingVertical : 0,
455
- },
456
- filterCell : {
457
- alignSelf : "flex-start",
458
- textAlign : "left",
459
- paddingHorizontal : 2,
460
- paddingVertical : 0,
461
- marginVertical : 0,
462
- marginHorizontal : 0,
463
- justifyContent : 'flex-start',
464
- },
465
- headerItem: {
466
- minHeight: 30,
467
- },
468
- column : {
469
- flexDirection : 'row',
470
- justifyContent : 'center',
471
- alignItems : 'flex-start',
472
- },
473
- row : {
474
- flexDirection : "row",
475
- justifyContent : "flex-start",
476
- alignItems : 'flex-start',
477
- width : '100%',
478
- },
479
- rowNoPadding : {
480
- paddingHorizontal:0,
481
- marginHorizontal : 0,
482
- marginVertical : 0,
483
- },
484
- hasNotData : {
485
- flexDirection : 'column',
486
- width : '100%',
487
- justifyContent : 'center',
488
- alignItems : 'center'
489
- }
490
- })
314
+
491
315
  TableComponent.popTypes = {
492
316
  containerProps : PropTypes.object,
493
317
  renderHeaderCell : PropTypes.func,
494
318
  renderFilterCell : PropTypes.func,
495
- renderRow : PropTypes.func,
496
319
  renderCell : PropTypes.func,
497
320
  renderFooterCell : PropTypes.func,///la fonction appelée pour le rendu des entêtes du footer
498
321
  footerCellContainerProps : PropTypes.object,
@@ -510,7 +333,7 @@ TableComponent.popTypes = {
510
333
  PropTypes.objectOf(ColumnType),
511
334
  PropTypes.arrayOf(ColumnType)
512
335
  ]).isRequired,
513
- data : PropTypes.arrayOf(RowType),
336
+ data : PropTypes.array,
514
337
  columnsWidths : PropTypes.object,
515
338
  colsWidths : PropTypes.object,//alias à columnsWidths
516
339
  columnWidth: PropTypes.number,
@@ -537,4 +360,23 @@ TableComponent.popTypes = {
537
360
 
538
361
  TableComponent.displayName = "TableComponent";
539
362
 
540
- export default TableComponent;
363
+ const TableComponentProvider = React.forwardRef(({children,renderCell,testID,withDatagridContext,getRowKey,filter,data,...props},ref)=>{
364
+ testID = props.testID = defaultStr(testID,"RN_TableComponent");
365
+ const prepatedColumns = usePrepareColumns(props);
366
+ const keyExtractor = typeof getRowKey =='function'? getRowKey : React.getKey;
367
+ const items = React.useMemo(()=>{
368
+ filter = typeof filter =='function'? filter : x=>true;
369
+ return data.filter((i,...rest)=>isObj(i) && !!filter(i,...rest));
370
+ },[data]);
371
+ const getItem = (index)=>items[index]||null;
372
+ return <TableContext.Provider value={{...props,...prepatedColumns,getItem,getRowByIndex:getItem,testID,data,withDatagridContext,keyExtractor,
373
+ renderCell,
374
+ items
375
+ }}>
376
+ <TableComponent {...props} ref={ref}/>
377
+ </TableContext.Provider>
378
+ });
379
+ TableComponentProvider.displayName = "TableComponentProvider";
380
+ TableComponentProvider.propTypes = TableComponent.propTypes;
381
+
382
+ export default TableComponentProvider;
@@ -0,0 +1,104 @@
1
+ import { StyleSheet } from "react-native";
2
+ import {isMobileNative} from "$cplatform";
3
+
4
+ const styles = StyleSheet.create({
5
+ datagrid : {
6
+ flex:1,
7
+ },
8
+ contentContainer : {
9
+ flex:1,
10
+ },
11
+ container : {
12
+ width : '100%',
13
+ minHeight : 300,
14
+ paddingBottom : 10,
15
+ paddingLeft : 0,
16
+ paddingRight : 0,
17
+ flex : 1,
18
+ position : 'relative',
19
+ },
20
+ header2footerContainer:{
21
+ flexDirection : 'column',
22
+ width : '100%',
23
+ height : '100%',
24
+ minHeight : 50,
25
+ },
26
+ headerContainer : {
27
+ width : '100%',
28
+ flexDirection : 'row',
29
+ },
30
+ header: {
31
+ flexDirection: 'row',
32
+ paddingVertical : 7,
33
+ alignItems : 'center',
34
+ width : '100%',
35
+ },
36
+ footerContainer : {
37
+ width : '100%',
38
+ flexDirection : 'row',
39
+ flexWrap : 'wrap',
40
+ },
41
+ footers : {
42
+ minHeight : 40,
43
+ },
44
+ headerItemOrCell : {
45
+ alignItems: 'flex-start',
46
+ alignSelf : 'center',
47
+ height : '100%',
48
+ justifyContent: 'center',
49
+ textAlign : 'left',
50
+ flexWrap : 'wrap',
51
+ paddingHorizontal:5,
52
+ paddingVertical : 0,
53
+ },
54
+ filterCell : {
55
+ alignSelf : "flex-start",
56
+ textAlign : "left",
57
+ paddingHorizontal : 2,
58
+ paddingVertical : 0,
59
+ marginVertical : 0,
60
+ marginHorizontal : 0,
61
+ justifyContent : 'flex-start',
62
+ },
63
+ headerItem: {
64
+ minHeight: 30,
65
+ },
66
+ column : {
67
+ flexDirection : 'row',
68
+ justifyContent : 'center',
69
+ alignItems : 'flex-start',
70
+ },
71
+ row : {
72
+ flexDirection : "row",
73
+ justifyContent : "flex-start",
74
+ alignItems : 'flex-start',
75
+ width : '100%',
76
+ },
77
+ rowNoPadding : {
78
+ paddingHorizontal:0,
79
+ marginHorizontal : 0,
80
+ marginVertical : 0,
81
+ },
82
+ hasNotData : {
83
+ flexDirection : 'column',
84
+ width : '100%',
85
+ justifyContent : 'center',
86
+ alignItems : 'center'
87
+ },
88
+ cell : isMobileNative()? {
89
+ paddingLeft:10,
90
+ paddingRight : 5,
91
+ paddingBottom : 5,
92
+ paddingTop : 5,
93
+ } : {
94
+ paddingLeft: 10,
95
+ paddingTop:5,
96
+ paddingBottom:5,
97
+ paddingRight: 10
98
+ },
99
+ sectionListHeader : {
100
+ paddingVertical : 10,
101
+ paddingHorizontal : 10,
102
+ }
103
+ });
104
+ export default styles;
@@ -0,0 +1 @@
1
+ export const DEFAULT_COLUMN_WIDTH = 60;
@@ -3,7 +3,7 @@ import appConfig from "$capp/config";
3
3
  import {MD3LightTheme,MD3DarkTheme} from "react-native-paper";
4
4
  import { useMaterial3Theme } from '@pchmn/expo-material3-theme';
5
5
  import {colorsAlias,Colors} from "$theme";
6
- import {isObj,isNonNullString} from "$cutils";
6
+ import {isObj,isNonNullString,defaultStr} from "$cutils";
7
7
  import eMainScreens from "$escreens/mainScreens";
8
8
  import {ExpoUIContext} from "./hooks";
9
9
  import Login from "$eauth/Login";
@@ -78,8 +78,22 @@ const Provider = ({children,getTableData,navigation,components,convertFiltersToS
78
78
  }
79
79
  theme.fonts = newTheme.fonts;
80
80
  const r = typeof extendAppTheme == 'function'? extendAppTheme(theme) : theme;
81
+ const _theme = (isObj(r) ? r : theme);
82
+ const customCSS = _theme.customCSS;
81
83
  return {
82
- ...(isObj(r) ? r : theme),
84
+ ..._theme,
85
+ get customCSS(){
86
+ const prevCSS = defaultStr(typeof customCSS ==='function'? customCSS(theme) : customCSS);
87
+ return `
88
+ .virtuoso-table-component,
89
+ .virtuoso-table-component th,
90
+ .virtuoso-table-component tr,
91
+ .virtuoso-table-component td{
92
+ border-collapse : collapse!important;
93
+ }
94
+ ${prevCSS}
95
+ `;
96
+ },
83
97
  get textFieldMode (){
84
98
  /***** possibilité de charger le mode d'affichage par défaut des champs textuels dans le theme de l'application */
85
99
  if(typeof theme.textFieldMode =='string' && theme.textFieldMode && modes[theme.textFieldMode]){
@@ -23,17 +23,18 @@ const AppBarLayout = React.forwardRef(({backActionProps,withDrawer,backAction,ba
23
23
  goBack();
24
24
  return false;
25
25
  }
26
- if(drawerRef && drawerRef?.current){
27
- if(drawerRef?.current?.isMinimized() && drawerRef?.current?.isOpen()){
28
- drawerRef?.current?.restore();
29
- return false;
30
- }
31
- if(!drawerRef?.current?.isPermanent()){
32
- drawerRef?.current?.toggle();
33
- } else if(!drawerRef?.current?.isOpen()){
34
- drawerRef?.current?.open();
35
- }
26
+ if(!drawerRef || !drawerRef?.current) return false;
27
+ if(!drawerRef?.current?.isOpen()){
28
+ drawerRef.current.toggle();
29
+ return false;
30
+ }
31
+ if(drawerRef?.current?.isMinimized()){
32
+ drawerRef?.current?.restore();
33
+ return false;
36
34
  }
35
+ if(!drawerRef?.current?.isPermanent()){
36
+ drawerRef?.current?.toggle();
37
+ }
37
38
  return false;
38
39
  }}
39
40
  ref = {mergedRef}