@fto-consult/expo-ui 6.24.2 → 6.25.0

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 (66) 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 +6 -3
  10. package/src/App.js +3 -3
  11. package/src/components/Datagrid/Accordion/Row.js +74 -100
  12. package/src/components/Datagrid/Accordion/ToogleRow.js +9 -0
  13. package/src/components/Datagrid/Accordion/index.js +30 -35
  14. package/src/components/Datagrid/Actions/index.js +12 -44
  15. package/src/components/Datagrid/Checkbox.js +4 -7
  16. package/src/components/Datagrid/Common/Common.js +112 -148
  17. package/src/components/Datagrid/Dashboard/index.js +2 -2
  18. package/src/components/Datagrid/IndexComponent.js +8 -13
  19. package/src/components/Datagrid/Table/index.js +53 -51
  20. package/src/components/Datagrid/Test/index.js +10 -3
  21. package/src/components/Datagrid/events/evx.js +7 -0
  22. package/src/components/Datagrid/events/index.js +11 -0
  23. package/src/components/Datagrid/hooks/Provider.js +6 -0
  24. package/src/components/Datagrid/hooks/context.js +5 -0
  25. package/src/components/Datagrid/hooks/index.js +104 -0
  26. package/src/components/Datagrid/utils.js +6 -4
  27. package/src/components/Dialog/Dialog.js +13 -12
  28. package/src/components/Dialog/DialogContent.js +11 -0
  29. package/src/components/KeyboardAvoidingView/index.js +7 -3
  30. package/src/components/List/Common.js +5 -3
  31. package/src/components/List/FlashList.js +13 -13
  32. package/src/components/List/Virtuoso/index.js +29 -8
  33. package/src/components/List/Virtuoso/index.native.js +6 -1
  34. package/src/components/Table/FiltersOrFooters.js +11 -3
  35. package/src/components/Table/Header/Cell/index.js +10 -0
  36. package/src/components/Table/Header/Cell/index.native.js +7 -0
  37. package/src/components/Table/{Header.js → Header/Component.js} +0 -4
  38. package/src/components/Table/{Row.js → Header/Component.native.js} +3 -3
  39. package/src/components/Table/Header/index.js +12 -0
  40. package/src/components/Table/List/index.js +3 -1
  41. package/src/components/Table/List/index.native.js +2 -1
  42. package/src/components/Table/Row/Cell/Content.js +17 -0
  43. package/src/components/Table/Row/Cell/Content.native.js +15 -0
  44. package/src/components/Table/Row/Cell/index.js +29 -0
  45. package/src/components/Table/Row/RowWrapper.js +7 -0
  46. package/src/components/Table/Row/RowWrapper.native.js +10 -0
  47. package/src/components/Table/Row/index.js +38 -0
  48. package/src/components/Table/RowTemplate/index.js +10 -0
  49. package/src/components/Table/RowTemplate/index.web.js +9 -0
  50. package/src/components/Table/ScrollNative/index.js +7 -0
  51. package/src/components/Table/ScrollNative/index.native.js +8 -0
  52. package/src/components/Table/VirtuosoTable/index.js +5 -0
  53. package/src/components/Table/VirtuosoTable/index.native.js +3 -0
  54. package/src/components/Table/hooks.js +84 -0
  55. package/src/components/Table/index.js +88 -247
  56. package/src/components/Table/styles.js +88 -0
  57. package/src/components/Table/utils.js +1 -0
  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
@@ -14,6 +14,7 @@ import RenderType from "../RenderType";
14
14
  import Footer from "../Footer/Footer";
15
15
  import theme from "$theme";
16
16
  import Table from "$ecomponents/Table";
17
+ import DatagridProvider from "../hooks/Provider";
17
18
 
18
19
 
19
20
  const DatagridFactory = (Factory)=>{
@@ -276,57 +277,58 @@ const DatagridFactory = (Factory)=>{
276
277
  </View>
277
278
  </ScrollView>
278
279
  </View> : null;
279
- return <View style={[styles.container,{flex:1}]} testID={testID+"_TableContainer"} pointerEvents={pointerEvents}>
280
- <View ref={this.layoutRef} testID={testID+"_LayoutContainer"}>
281
- {this.props.showActions !== false ? <DatagridActions
282
- pointerEvents = {pointerEvents}
283
- title = {this.renderDataSourceSelector()}
284
- context = {this}
285
- selectedRows = {Object.assign({},this.selectedRows)}
286
- selectedRowsActions = {this.renderSelectedRowsActions.bind(this)}
287
- actions = {actions}
288
- /> : null}
289
- {rPagination}
290
- {progressBar}
291
- </View>
292
- {canRenderChart ?
293
- <View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
294
- {this.renderChart()}
295
- </View> :
296
- <Table
297
- ref = {this.listRef}
298
- {...rest}
299
- sortedColumn = {sortedColumn}
300
- onRender = {this.onRender.bind(this)}
301
- getItemType = {this.getFlashListItemType.bind(this)}
302
- renderItem = {this.renderFlashListItem.bind(this)}
303
- hasFooters = {hasFootersFields && !canRenderChart ? true : false}
304
- showFilters = {showFilters}
305
- showFooters = {showFooters && !canRenderChart ? true : false}
306
- showHeaders = { canRenderChart ? !!showFilters : true}
307
- headerContainerProps = {{}}
308
- headerCellContainerProps = {{
309
- style : showFilters?{justifyContent:'flex-start'}:null
310
- }}
311
- isRowSelected = {this.isRowSelected.bind(this)}
312
- columns = {this.state.columns}
313
- //renderRow={this.renderRow.bind(this)}
314
- getRowKey = {this.getRowKey.bind(this)}
315
- columnsWidths = {widths}
316
- renderCell={this.renderRowCell.bind(this)}
317
- rowContainerProps = {(props)=>{
318
- return {
319
- style : getRowStyle(props,{selected:this.isRowSelected.bind(this)}),
320
- }
321
- }}
322
- data = {this.state.data}
323
- footers = {this.getFooterValues()}
324
- renderHeaderCell={this.renderHeaderCell.bind(this)}
325
- renderFilterCell={this.renderFilterCell.bind(this)}
326
- renderFooterCell={this.renderFooterCell.bind(this)}
327
- renderEmpty = {this.renderEmpty.bind(this)}
328
- />}
329
- </View>
280
+ return <DatagridProvider context={this}>
281
+ <View style={[styles.container,{flex:1}]} testID={testID+"_TableContainer"} pointerEvents={pointerEvents}>
282
+ <View ref={this.layoutRef} testID={testID+"_LayoutContainer"}>
283
+ {this.props.showActions !== false ? <DatagridActions
284
+ pointerEvents = {pointerEvents}
285
+ title = {this.renderDataSourceSelector()}
286
+ actions = {actions}
287
+ /> : null}
288
+ {rPagination}
289
+ {progressBar}
290
+ </View>
291
+ {canRenderChart ?
292
+ <View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
293
+ {this.renderChart()}
294
+ </View> :
295
+ <Table
296
+ ref = {this.listRef}
297
+ {...rest}
298
+ withDatagridContext
299
+ sortedColumn = {sortedColumn}
300
+ onRender = {this.onRender.bind(this)}
301
+ getItemType = {this.getFlashListItemType.bind(this)}
302
+ renderItem = {this.renderFlashListItem.bind(this)}
303
+ renderSectionHeader = {this.renderFlashListItem.bind(this)}
304
+ hasFooters = {hasFootersFields && !canRenderChart ? true : false}
305
+ showFilters = {showFilters}
306
+ showFooters = {showFooters && !canRenderChart ? true : false}
307
+ showHeaders = { canRenderChart ? !!showFilters : true}
308
+ headerCellContainerProps = {{
309
+ style : showFilters?{justifyContent:'flex-start'}:null
310
+ }}
311
+ isRowSelected = {this.isRowSelected.bind(this)}
312
+ columns = {this.state.columns}
313
+ //renderRow={this.renderRow.bind(this)}
314
+ getRowKey = {this.getRowKey.bind(this)}
315
+ columnsWidths = {widths}
316
+ renderCell={this.renderRowCell.bind(this)}
317
+ rowContainerProps = {(props)=>{
318
+ return {
319
+ style : getRowStyle(props,{selected:this.isRowSelected.bind(this)}),
320
+ }
321
+ }}
322
+ data = {this.state.data}
323
+ footers = {this.getFooterValues()}
324
+ renderHeaderCell={this.renderHeaderCell.bind(this)}
325
+ renderFilterCell={this.renderFilterCell.bind(this)}
326
+ renderFooterCell={this.renderFooterCell.bind(this)}
327
+ renderEmpty = {this.renderEmpty.bind(this)}
328
+ />}
329
+ </View>
330
+
331
+ </DatagridProvider>
330
332
  }
331
333
  }
332
334
  clx.propTypes = {
@@ -2,19 +2,26 @@
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
4
 
5
- import fields from "./fields";
6
- import Table from "../Table";
5
+ import Table from "../IndexComponent";
7
6
  import React from "$react";
8
7
  import { faker } from '@faker-js/faker';
9
8
  export default function TestDatagridComponent({count,...props}){
10
9
  const data = React.useMemo(()=>{
11
- count = typeof count =='number' && count > 10 ? count : 5000;
10
+ count = typeof count =='number' && count > 10 ? count : 100;
12
11
  return faker.helpers.multiple(createRandomUser, {
13
12
  count,
14
13
  });
15
14
  },[count])
16
15
  return <Table
17
16
  title = "Utilisateurs"
17
+ accordion = {({rowData})=>{
18
+ return {
19
+ content : `${rowData.email}`,
20
+ title : rowData?.username,
21
+ //avatar : rowData.avatar,
22
+ right : rowData.birthdate,
23
+ }
24
+ }}
18
25
  columns={{
19
26
  userId : {
20
27
  primaryKey : true,
@@ -0,0 +1,7 @@
1
+ export const ON_ROW_TOGGLE = "ON_ROW_TOGGLE";//l'orsqu'on toggle on ligne
2
+
3
+ export const ON_ALL_ROWS_TOGGLE = "ON_ALL_ROWS_TOGGLE";
4
+
5
+ export const ON_FETCH_DATA = "ON_FETCH_DATA";
6
+
7
+ export const ON_UPDATE = "ON_UPDATE";
@@ -0,0 +1,11 @@
1
+ import {isNonNullString} from "$cutils";
2
+ import * as events from "./evx";
3
+
4
+ export const sanitize = (event)=>{
5
+ if(!isNonNullString(event)) return "";
6
+ return event.trim().toSnackCase();
7
+ }
8
+ export * from "./evx";
9
+
10
+ export default events;
11
+
@@ -0,0 +1,6 @@
1
+
2
+ import { DatagridContext } from "./context";
3
+ import React from "$react";
4
+ export default function DatagridComponentProvider({children,context,...props}){
5
+ return <DatagridContext.Provider value={{...props,context}} children={children}/>
6
+ }
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+
3
+ const DatagridContext = createContext(null);
4
+
5
+ export {DatagridContext};
@@ -0,0 +1,104 @@
1
+ import { useContext,useEffect,useMemo,useReducer } from "react";
2
+ import { DatagridContext } from "./context";
3
+ import {isObj,isNonNullString} from "$cutils";
4
+ import events from "../events";
5
+ export const useDatagrid = x=> {
6
+ const t = useContext(DatagridContext)
7
+ if(!t || !t?.context || !t?.context?.state || !t?.context?.state?.data){
8
+ throw "Le composant Datagrid actions doit être enfant d'un contexe de datagrid valide";
9
+ }
10
+ return t;
11
+ };
12
+ export const useDatagridContext = ()=>{
13
+ return useDatagrid()?.context;
14
+ }
15
+ export const useData = ()=>{
16
+ const {context} = useDatagrid();
17
+ return Array.isArray(context.state.data) && context.state.data || [];
18
+ }
19
+ export const useSelectedRows = ()=>{
20
+ const {context} = useDatagrid();
21
+ }
22
+ export const useGetRowKey = ({rowData,rowIndex})=>{
23
+ const {context} = useDatagrid();
24
+ return context.getRowKey(rowData,rowIndex);
25
+ };
26
+ /****
27
+ @param {string|Array} event, l'évènement ou les évènements en question, qui est trigger par le contexte de datagrid
28
+ @param {function|string} getter, la fonction getter, est la fonction qui prenant en paramètre le contexte, retourne la valeur liée à l'évènement event
29
+ @param {function} onEvent, la fonction appelée lorsque l'évènement est exécutée
30
+ */
31
+ export const useOnEvent = (event,getter,onEvent)=>{
32
+ const {context} = useDatagrid();
33
+ if((!isNonNullString(event) && !Array.isArray(event)) || !event.length){
34
+ throw `méthode invalide ${method} supportée par le contexte`;
35
+ }
36
+ if(typeof getter !=='function') {
37
+ throw "méthode getter invalide pour la récupéreration de l'état lié au contexte du datagrid";
38
+ }
39
+ const evBack = event;
40
+ event = Array.isArray(event) ? event : isNonNullString(event)? event.trim().split(",") : [];
41
+ const [state, dispatch] = useReducer(function(state2,action){
42
+ if(event.filter(ev=>action.type.toLowerCase() === ev?.toLowerCase().trim()).length){
43
+ return getter(context,action.type);
44
+ }
45
+ return null;
46
+ }, getter(context,evBack));
47
+ const callbacks = useMemo((...args)=>{
48
+ const callbacks = {};
49
+ event.map((ev)=>{
50
+ callbacks[ev] = (...args)=>{
51
+ if(typeof onEvent ==='function' && onEvent(ev,...args) === false) return false;
52
+ return dispatch({type:ev});
53
+ }
54
+ });
55
+ return callbacks;
56
+ },[event.join(",")]);
57
+ useEffect(()=>{
58
+ Object.map(callbacks,(cb,event)=>{
59
+ context.on(event,cb);
60
+ });
61
+ return ()=>{
62
+ Object.map(callbacks,(cb,ev)=>{
63
+ context.off(ev,cb);
64
+ });
65
+ }
66
+ },[]);
67
+ return state;
68
+ }
69
+
70
+
71
+ /****
72
+ ecoute l'évènement event sur le contexte de datagrid
73
+ @param {string} event, l'évènement à écouter
74
+ @param {function} onEvent, la fonction appelée lorsque l'évènement est écoutée
75
+ */
76
+ export const useBindEvent = (event,onEvent)=>{
77
+ const {context} = useDatagrid();
78
+ if(!isNonNullString(event)){
79
+ throw `impossible d'écouter un évènemet invalide pour le contexte de datagrid`;
80
+ }
81
+ useEffect(()=>{
82
+ context.on(event,onEvent);
83
+ return ()=>{
84
+ context.off(event,onEvent);
85
+ }
86
+ },[]);
87
+ return onEvent;
88
+ }
89
+ export const useIsRowSelected = (...args)=>{
90
+ return useOnEvent([events.ON_ROW_TOGGLE,events.ON_ALL_ROWS_TOGGLE],(context)=>{
91
+ return context.isRowSelected(...args);
92
+ });
93
+ };
94
+
95
+ export const useGetSelectedRowsCount = ()=>{
96
+ return useOnEvent([events.ON_ROW_TOGGLE,events.ON_ALL_ROWS_TOGGLE],(context)=>{
97
+ return context.getSelectedRowsCount();
98
+ });
99
+ }
100
+ export const useIsAllRowsSelected = ()=>{
101
+ return useOnEvent([events.ON_ROW_TOGGLE,events.ON_ALL_ROWS_TOGGLE],(context)=>{
102
+ return context.isAllRowsSelected();
103
+ });
104
+ };
@@ -1,4 +1,4 @@
1
- import theme,{LINE_HEIGHT} from "$theme";
1
+ import theme,{Colors,LINE_HEIGHT} from "$theme";
2
2
  import { StyleSheet } from "react-native";
3
3
  import {get as getSession} from "./Common/session";
4
4
  import appConfig from "$capp/config";
@@ -98,7 +98,9 @@ export const ROW_EVEN_STYLE = {
98
98
  }
99
99
 
100
100
  export const ROW_SELECTED_STYLE = {
101
- backgroundColor : ROW_SELECTED_BACKGROUND_COLOR
101
+ get backgroundColor(){
102
+ return theme.isDark()? Colors.lighten(theme.colors.surface) : Colors.darken(theme.colors.surface);
103
+ }
102
104
  }
103
105
 
104
106
  export const ROW_BORDER_STYLE = {
@@ -119,7 +121,7 @@ export const DATE_COLUMN_WIDTH = 200;
119
121
 
120
122
  export {LINE_HEIGHT}
121
123
 
122
- export const styles = StyleSheet.create({
124
+ export const styles = ({
123
125
  approved : ROW_APPROVED_STYLE,
124
126
  archived : ROW_ARCHIVED_STYLE,
125
127
  selected : ROW_SELECTED_STYLE,
@@ -167,7 +169,7 @@ export const getRowStyle = ({row,bordered,numColumns,rowData,isAccordion,isTable
167
169
  if(rowIndex !== undefined){
168
170
  style.push(rowIndex%2===0?styles.even : theme.isDark()?styles.oddDark : styles.odd)
169
171
  }
170
- if(false && selected){
172
+ if(selected){
171
173
  style.push(styles.selected,{borderBottomWidth:1,borderBottomColor:theme.colors.primary})
172
174
  }
173
175
  if(paid || row.paid){
@@ -20,7 +20,7 @@ import {ACTION_ICON_SIZE} from "$ecomponents/AppBar";
20
20
  import DialogFooter from "./DialogFooter";
21
21
  import { Dimensions } from "react-native";
22
22
  import Surface from "$ecomponents/Surface";
23
- import KeyboardAvoidingView from "$ecomponents/KeyboardAvoidingView";
23
+ import DialogContent from "./DialogContent";
24
24
 
25
25
  export const FOOTER_HEIGHT = 50;
26
26
  export const HEADER_HEIGHT = 50;
@@ -198,14 +198,14 @@ const DialogComponent = React.forwardRef((props,ref)=>{
198
198
  testID = {testID}
199
199
  contentContainerProps = {contentContainerProps}
200
200
  >
201
- <Surface
202
- testID = {testID+"_Overlay"}
203
- ref={overlayRef}
204
- {...overlayProps}
205
- style={[styles.overlay,isAlert && styles.overlayAlert,{backgroundColor},overlayProps.style,fullScreenStyle]}
206
- >
207
- <KeyboardAvoidingView>
208
- {(!isAlert && (actions || title || subtitle)) ? <AppBarDialog
201
+ <DialogContent isFullScreen={isFullScreenDialog} isPreloader={isPreloader}>
202
+ <Surface
203
+ testID = {testID+"_Overlay"}
204
+ ref={overlayRef}
205
+ {...overlayProps}
206
+ style={[styles.overlay,isAlert && styles.overlayAlert,{backgroundColor},overlayProps.style,fullScreenStyle]}
207
+ >
208
+ {(!isAlert && (actions || title || subtitle)) ? <AppBarDialog
209
209
  actionsProps = {actionsProps}
210
210
  testID = {testID+"_AppBar"}
211
211
  {...appBarProps}
@@ -269,14 +269,15 @@ const DialogComponent = React.forwardRef((props,ref)=>{
269
269
  isFullScreen = {isFullScreenDialog}
270
270
  fullScreen = {customFullScreen}
271
271
  children = {footer}
272
- /> : null}
273
- </KeyboardAvoidingView>
274
- </Surface>
272
+ /> : null}
273
+ </Surface>
274
+ </DialogContent>
275
275
  </ModalComponent>
276
276
  </Portal>
277
277
  });
278
278
  export default DialogComponent;
279
279
 
280
+
280
281
  DialogComponent.propTypes= {
281
282
  ...Modal.propTypes,
282
283
  isAlert : PropTypes.bool,//si c'est le rendu alert, pour le rendu de l'alerte
@@ -0,0 +1,11 @@
1
+ import KeyboardAvoidingView from "../KeyboardAvoidingView";
2
+ import React from "$react";
3
+ import { useWindowDimensions } from "react-native";
4
+
5
+ const DialogContentComponent = ({isPreloader,isFullScreen,...props})=>{
6
+ const isFull = isFullScreen();
7
+ //useWindowDimensions();
8
+ const content = React.useMemo(()=>props.children,[isPreloader]);
9
+ return isPreloader || !isFull ? content : <KeyboardAvoidingView>{content}</KeyboardAvoidingView>
10
+ }
11
+ export default DialogContentComponent;
@@ -1,8 +1,12 @@
1
1
  import View from "$ecomponents/View";
2
2
  import React from "$react";
3
- const KeyboardAvoidingViewComponent = React.forwardRef(({children,...props},ref)=>{
4
- return <View {...props}>{children}</View>
3
+ import {isNonNullString} from "$cutils";
4
+ import theme from "$theme";
5
+ const KeyboardAvoidingViewComponent = React.forwardRef(({children,style,testID,...props},ref)=>{
6
+ return <View {...props} style={[theme.styles.flex1,style]} children={children} testID={isNonNullString(testID) ? `${testID.trim()}_KeyboardAvoidingView` : "RN_KeyboardAvoidingView"}/>
5
7
  });
6
8
 
7
9
  KeyboardAvoidingViewComponent.displayName = "KeyboardAvoidingViewComponent";
8
- KeyboardAvoidingViewComponent.propTypes = Object.assign({},View.propTypes);
10
+ KeyboardAvoidingViewComponent.propTypes = Object.assign({},View.propTypes);
11
+
12
+ export default KeyboardAvoidingViewComponent;
@@ -3,7 +3,7 @@ import React from "$react";
3
3
  import { prepareItems as customPrepareItems,getBToTopRef } from "./utils";
4
4
  import {grid,StylePropTypes} from "$theme";
5
5
  import PropTypes from "prop-types";
6
- import {defaultObj,extendObj,isObj,defaultDecimal,defaultArray,defaultFunc} from "$cutils";
6
+ import {defaultObj,defaultStr,extendObj,isObj,defaultDecimal,defaultArray,defaultFunc} from "$cutils";
7
7
  import {isMobileMedia} from "$cplatform/dimensions";
8
8
  import BackToTop from "$ecomponents/BackToTop";
9
9
  import {FlatList,StyleSheet,View} from "react-native";
@@ -13,7 +13,7 @@ import { useList } from "./hooks";
13
13
 
14
14
  const CommonListComponent = React.forwardRef((props,ref)=>{
15
15
  const context = useList(props);
16
- let {responsive,defaultItemHeight,itemHeight,windowWidth,onRender,componentProps,columnWrapperStyle,onViewableItemsChanged,withFlatListItem,Component,withBackToTop,backToTopRef:customBackToTopRef,withBackToTopButton,onScroll,onScrollEnd,onMount,onUnmount,renderScrollViewWrapper,prepareItems,getItemKey,getKey,keyExtractor,items,filter,renderItem,numColumns,containerProps,bindResizeEvents,...rest} = props;
16
+ let {responsive,testID,defaultItemHeight,itemHeight,windowWidth,onRender,componentProps,columnWrapperStyle,onViewableItemsChanged,withFlatListItem,Component,withBackToTop,backToTopRef:customBackToTopRef,withBackToTopButton,onScroll,onScrollEnd,onMount,onUnmount,renderScrollViewWrapper,prepareItems,getItemKey,getKey,keyExtractor,items,filter,renderItem,numColumns,containerProps,bindResizeEvents,...rest} = props;
17
17
  withBackToTopButton = withBackToTop === true || withBackToTopButton == true || isMobileMedia()? true : false;
18
18
  rest = defaultObj(rest);
19
19
  containerProps = defaultObj(containerProps);
@@ -30,6 +30,7 @@ const CommonListComponent = React.forwardRef((props,ref)=>{
30
30
  const hasCustomBackToTop = typeof customBackToTopRef == 'function'? true : false;
31
31
  const backToTopRef = React.useRef(null);
32
32
  const isFlatList = Component === FlatList;
33
+ defaultStr(props.testID,"RN_CommonListComponent");
33
34
  extendObj(context,{
34
35
  getKey : typeof keyExtractor =='function'? keyExtractor : typeof getItemKey =='function'? getItemKey : typeof getKey =='function'? getKey : undefined,
35
36
  addItemsRefs : function(ref, itemRef){
@@ -150,12 +151,13 @@ const CommonListComponent = React.forwardRef((props,ref)=>{
150
151
  const restP = numColumns > 1 && isFlatList ? {
151
152
  columnWrapperStyle : [styles.columnWrapperStyle,props.columnWrapperStyle]
152
153
  } : {};
153
- return <View {...containerProps} style={[styles.container,containerProps.style]}>
154
+ return <View testID={testID+"_CommonListContainer"} {...containerProps} style={[styles.container,containerProps.style]}>
154
155
  <Component
155
156
  onEndReachedThreshold={0}
156
157
  scrollEventThrottle={16}
157
158
  {...rest}
158
159
  {...restP}
160
+ testID = {testID}
159
161
  ref = {listRef}
160
162
  onScroll={context.onScroll}
161
163
  data = {context.items}
@@ -7,19 +7,19 @@ import View from "$ecomponents/View";
7
7
  const FlashListComponent = React.forwardRef((props,ref)=>{
8
8
  const {testID} = props
9
9
  return (<CommonListComponent
10
- testID = {'RN_FlashListComponent'}
11
- estimatedItemSize = {50}
12
- ListHeaderComponent={() => (
13
- <View testID={(testID||'RN_FlashListComponent')+"_Header"}>{props.children}</View>
14
- )}
15
- //disableAutoLayout
16
- //disableHorizontalListHeightMeasurement = {props.horizontal?undefined : true}
17
- {...props}
18
- contentContainerStyle = {undefined}
19
- style = {undefined}
20
- Component = {FlashList}
21
- ref={ref}
22
- />)
10
+ testID = {'RN_FlashListComponent'}
11
+ estimatedItemSize = {50}
12
+ ListHeaderComponent={() => (
13
+ <View testID={(testID||'RN_FlashListComponent')+"_Header"}>{props.children}</View>
14
+ )}
15
+ //disableAutoLayout
16
+ //disableHorizontalListHeightMeasurement = {props.horizontal?undefined : true}
17
+ {...props}
18
+ contentContainerStyle = {undefined}
19
+ style = {undefined}
20
+ Component = {FlashList}
21
+ ref={ref}
22
+ />)
23
23
  })
24
24
 
25
25
  FlashListComponent.propTypes = {
@@ -2,7 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
4
 
5
- import {Virtuoso,VirtuosoGrid} from "react-virtuoso/dist/index.mjs";
5
+ import {Virtuoso,VirtuosoGrid,TableVirtuoso} from "react-virtuoso/dist/index.mjs";
6
6
  import React from "$react";
7
7
  import PropTypes from "prop-types";
8
8
  import {defaultObj,classNames,defaultNumber,isObj,isDOMElement,isNumber,uniqid,isNonNullString,defaultStr} from "$cutils";
@@ -10,6 +10,8 @@ import { View } from "react-native";
10
10
  import {useList} from "../hooks";
11
11
  import theme,{grid} from "$theme";
12
12
  import Dimensions from "$cdimensions";
13
+ import { StyleSheet } from "react-native";
14
+ import {isMobileNative} from "$cplatform";
13
15
 
14
16
  const propTypes = {
15
17
  ...defaultObj(Virtuoso.propTypes),
@@ -29,12 +31,19 @@ const propTypes = {
29
31
  isScrolling : PropTypes.func,
30
32
  };
31
33
  /***@see : https://virtuoso.dev/virtuoso-api-reference/ */
32
- const VirtuosoListComponent = React.forwardRef(({onRender,listClassName,components,itemProps,windowWidth,numColumns,responsive,testID,renderItem,onEndReached,onLayout,onContentSizeChange,onScroll,isScrolling,estimatedItemSize,onEndReachedThreshold,containerProps,style,autoSizedStyle,...props},ref)=>{
33
- const Component = React.useMemo(()=>responsive?VirtuosoGrid:Virtuoso,[responsive])
34
+ const VirtuosoListComponent = React.forwardRef(({onRender,fixedHeaderContent,rowProps,renderTable,listClassName,components,itemProps,windowWidth,numColumns,responsive,testID,renderItem,onEndReached,onLayout,onContentSizeChange,onScroll,isScrolling,estimatedItemSize,onEndReachedThreshold,containerProps,style,autoSizedStyle,...props},ref)=>{
35
+ if(renderTable){
36
+ responsive = false;
37
+ }
38
+ const Component = React.useMemo(()=>renderTable ? TableVirtuoso : responsive?VirtuosoGrid:Virtuoso,[responsive,renderTable]);
34
39
  const context = useList(props);
35
40
  itemProps = defaultObj(itemProps);
36
41
  const items = context.items;
42
+ renderTable ? rowProps = defaultObj(rowProps) : null;
37
43
  const r2 = {};
44
+ if(renderTable){
45
+ r2.fixedHeaderContent = fixedHeaderContent;
46
+ }
38
47
  Object.map(Component.propTypes,(_,i)=>{
39
48
  if(i in props){
40
49
  r2[i] = props[i];
@@ -48,7 +57,7 @@ const VirtuosoListComponent = React.forwardRef(({onRender,listClassName,componen
48
57
  const sizeRef = React.useRef({width:0,height:0});
49
58
  const listSize = sizeRef.current;
50
59
  const isValid = ()=> listRef.current;
51
- const listStyle = {height:'100%',width:"100%",overflowX:'hidden'};
60
+ const listStyle = {height:'100%',width:"100%",overflowX:renderTable?"auto":"hidden",maxWidth:"100%"};
52
61
  r2["data-test-id"] = testID+"_ListContent";
53
62
  if(isObj(estimatedItemSize)){
54
63
  if(isNumber(estimatedItemSize.width)){
@@ -137,8 +146,10 @@ const VirtuosoListComponent = React.forwardRef(({onRender,listClassName,componen
137
146
  }
138
147
  }}
139
148
  components = {{
140
- Item : responsive ? function(props){return <ItemContainer {...props} style={[itemProps.style,props.style]} numColumns={numColumns}/>} : undefined,
141
- //List : responsive ? ResponsiveVirtuosoListItemContainer: undefined,
149
+ Item : renderTable ? undefined : responsive ? function(props){return <ItemContainer {...props} style={[itemProps.style,props.style]} numColumns={numColumns}/>} : undefined,
150
+ ...(renderTable ? {
151
+ TableRow: TableRowComponent,
152
+ }:{}),
142
153
  ...defaultObj(components),
143
154
  }}
144
155
  />
@@ -147,7 +158,10 @@ const VirtuosoListComponent = React.forwardRef(({onRender,listClassName,componen
147
158
 
148
159
  VirtuosoListComponent.propTypes = {
149
160
  ...propTypes,
161
+ fixedHeaderContent : PropTypes.func,//la fonction rendant le contenu fixe du tableau
162
+ renderTable : PropTypes.bool,//si le composant Table sera rendu
150
163
  numColumns : PropTypes.number,
164
+ rowProps : PropTypes.object,//les props du TableRow, lorsque le rendu est de type table
151
165
  items : PropTypes.oneOfType([
152
166
  PropTypes.object,
153
167
  PropTypes.array,
@@ -202,7 +216,7 @@ const normalizeEvent = (e)=>{
202
216
  },[windowWidth,numColumns]);
203
217
  const style = width && {width} || grid.col(windowWidth);
204
218
  const dataIntex = "index" in props ? props.index : "data-index" in props ? props["data-index"] : ""
205
- const dataItemIndex = props["data-item-index"];
219
+ const dataItemIndex = "data-item-index" in props ? props["data-item-index"] : "";
206
220
  if(isObj(style)){
207
221
  style.paddingRight = style.paddingLeft = style.paddingHorizontal = undefined;
208
222
  }
@@ -232,4 +246,11 @@ const normalizeEvent = (e)=>{
232
246
  .${gridClassName}{display:flex;flex-direction:row;align-items:flex-start;flex-wrap:wrap;justify-content:flex-start;};
233
247
  `;
234
248
  document.body.appendChild(style);
235
- }
249
+ }
250
+
251
+ export const TableRowComponent = ({testID,style,...props}) => {
252
+ const index = props['data-index'];
253
+ const isOdd = typeof index =='number' ? index%2 > 0 : false;
254
+ testID = defaultStr(testID,"_VirtuosoTableRow_"+index);
255
+ return <tr data-test-id={testID} {...props} style={StyleSheet.flatten(style)} className={classNames(props.className,"virtuoso-table-row",`table-row-${isOdd?"odd":"even"}`)}/>
256
+ };
@@ -2,4 +2,9 @@
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
4
 
5
- export {default} from "$ecomponents/List/FlashList";
5
+ export {default} from "$ecomponents/List/FlashList";
6
+
7
+
8
+ export const TableRowComponent = ({children}) => {
9
+ return children;
10
+ };
@@ -4,13 +4,21 @@
4
4
  import React from "$react";
5
5
  import { View } from "react-native";
6
6
  import PropTypes from "prop-types";
7
- export default function TableFiltersComponent({visible,children:cChildren,...rest}){
7
+ import { StyleSheet } from "react-native";
8
+ import {isMobileNative} from "$cplatform";
9
+ import {classNames} from "$cutils";
10
+ const isNative = isMobileNative();
11
+ const Component = isNative ? View : "tr";
12
+
13
+ export default function TableFiltersComponent({visible,className,children:cChildren,...rest}){
8
14
  const children = React.useMemo(()=>{
9
15
  return cChildren;
10
16
  },[cChildren]);
11
- return <View {...rest} style={[rest.style,!visible && {height:0,opacity:0,display:'none'}]}>
17
+ const rP = isNative ? rest : {className:classNames(className,"table-footer-or-header-row")}
18
+ if(!isNative && !visible) return null;
19
+ return <Component {...rP} style={StyleSheet.flatten([rest.style,!visible && {height:0,opacity:0,display:'none'}])}>
12
20
  {children}
13
- </View>
21
+ </Component>
14
22
  }
15
23
 
16
24
  TableFiltersComponent.propTypes = {
@@ -0,0 +1,10 @@
1
+ import React from "$react";
2
+ import {classNames} from "$cutils";
3
+ import theme from "$theme";
4
+
5
+ import { StyleSheet } from "react-native";
6
+ const TableHeaderCellComponent = React.forwardRef(({columnDef,className,width,style,children,...props},ref)=>{
7
+ return <th ref={ref} className={classNames(className,"table-header-cell")} children={children} style={StyleSheet.flatten([style])}/>
8
+ });
9
+ TableHeaderCellComponent.displayName = "TableTableHeaderCellComponent";
10
+ export default TableHeaderCellComponent;
@@ -0,0 +1,7 @@
1
+ import View from "$ecomponents/View";
2
+ import React from "$react";
3
+ const TableHeaderCellComponent = React.forwardRef(({width,style,...props},ref)=>{
4
+ return <View ref={ref} {...props} style={[style,width && {width}]}/>
5
+ });
6
+ TableHeaderCellComponent.displayName = "TableTableHeaderCellComponent";
7
+ export default TableHeaderCellComponent;
@@ -1,7 +1,3 @@
1
- // Copyright 2023 @fto-consult/Boris Fouomene. All rights reserved.
2
- // Use of this source code is governed by a BSD-style
3
- // license that can be found in the LICENSE file.
4
-
5
1
  // Copyright 2023 @fto-consult/Boris Fouomene. All rights reserved.
6
2
  // Use of this source code is governed by a BSD-style
7
3
  // license that can be found in the LICENSE file.