@fto-consult/expo-ui 2.5.0 → 2.5.2

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.
@@ -0,0 +1,52 @@
1
+ // Copyright 2022 @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
+ /***Fork of https://github.com/CaptainOmega/react-native-drag-resize components */
5
+ import React, {PureComponent} from 'react';
6
+ import {
7
+ View,
8
+ } from 'react-native';
9
+ import PropTypes from 'prop-types';
10
+
11
+ /**
12
+ * Drag resize container.
13
+ * Allow calculate limitation by container size.
14
+ */
15
+ export class DragResizeContainer extends PureComponent {
16
+
17
+ render() {
18
+ const {
19
+ style,
20
+ onInit,
21
+ children,
22
+ } = this.props;
23
+
24
+ return (
25
+ <View
26
+ ref={view => {
27
+ this.canvas = view;
28
+ }}
29
+ style={style}
30
+ onLayout={() => {
31
+ this.canvas.measure(
32
+ (fx, fy, w, h, x, y) => {
33
+ onInit({
34
+ x: 0,
35
+ y: 0,
36
+ w,
37
+ h,
38
+ });
39
+ }
40
+ );
41
+ }}
42
+ >
43
+ {children}
44
+ </View>
45
+ );
46
+ }
47
+ };
48
+
49
+ DragResizeContainer.propTypes = {
50
+ onInit: PropTypes.func.isRequired,
51
+ style: PropTypes.object,
52
+ };
@@ -0,0 +1,42 @@
1
+ // Copyright 2022 @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
+ /***Fork of https://github.com/CaptainOmega/react-native-drag-resize components */
5
+ import {defaultNumber} from "$utils";
6
+ import React from "$react";
7
+ export default function DragResizeComponent ({x,y,width,height,onResize,...props}){
8
+ x = defaultNumber(x); y = defaultNumber(y);
9
+ const [resize, setResize] = React.useState([x, y]);
10
+ return <DragResizeBlock
11
+ w = {width}
12
+ h = {height}
13
+ {...props}
14
+ x={resize[0]}
15
+ y={resize[1]}
16
+ onResize={(value) => setResize(value)}
17
+ />
18
+ }
19
+
20
+
21
+ export {
22
+ DragResizeBlock,
23
+ AXIS_X,
24
+ AXIS_Y,
25
+ AXIS_ALL,
26
+ } from './DragResizeBlock';
27
+ import {DragResizeBlock} from "./DragResizeBlock"
28
+ export {
29
+ DragResizeContainer,
30
+ } from './DragResizeContainer';
31
+
32
+ export {
33
+ CONNECTOR_TOP_LEFT,
34
+ CONNECTOR_TOP_MIDDLE,
35
+ CONNECTOR_TOP_RIGHT,
36
+ CONNECTOR_MIDDLE_RIGHT,
37
+ CONNECTOR_BOTTOM_RIGHT,
38
+ CONNECTOR_BOTTOM_MIDDLE,
39
+ CONNECTOR_BOTTOM_LEFT,
40
+ CONNECTOR_MIDDLE_LEFT,
41
+ CONNECTOR_CENTER,
42
+ } from './Connector';
@@ -745,9 +745,10 @@ class DropdownComponent extends AppComponent {
745
745
  const inputRest = {disabled,editable,label,error}
746
746
  clearTimeout(this.doSearchFilter);
747
747
  this.doSearchFilter = null;
748
-
748
+ mode = defaultStr(mode,inputProps.mode);
749
749
  const textInputProps = {
750
750
  ...inputRest,
751
+ mode,
751
752
  editable,disabled,
752
753
  style : StyleSheet.flatten([styles.input,inputProps.style])
753
754
  }
@@ -840,8 +841,7 @@ class DropdownComponent extends AppComponent {
840
841
  }
841
842
  helperText = <HelperText disabled = {disabled} error={error}>{helperText}</HelperText>
842
843
  let labelTextField = defaultVal(label,text);
843
-
844
- const isFlatMode = textInputProps.mode === flatMode;
844
+ const isFlatMode = textInputProps.mode === flatMode;
845
845
  let backgroundColor = Colors.isValid(textInputProps.style.backgroundColor)?textInputProps.style.backgroundColor : Colors.isValid(flattenStyle.backgroundColor)? flattenStyle.backgroundColor : theme.colors.surface;
846
846
  const tagLabelStyle = {backgroundColor,color:Colors.setAlpha(theme.colors.text,theme.ALPHA)}
847
847
  if(!isFlatMode && backgroundColor ==='transparent'){
@@ -904,9 +904,9 @@ class DropdownComponent extends AppComponent {
904
904
  defaultValue={selectedText}
905
905
  autoHeight = {renderTag}
906
906
  useReadOnlyOpacity = {false}
907
- mode = {mode}
908
907
  {...inputProps}
909
908
  {...textInputProps}
909
+ mode = {mode}
910
910
  enableCopy = {enableCopy}
911
911
  label = {labelTextField}
912
912
  pointerEvents = "none"
@@ -1270,7 +1270,6 @@ DropdownComponent.propTypes = {
1270
1270
  onUnmount : PropTypes.func,
1271
1271
  label : PropTypes.string,
1272
1272
  placeholder : PropTypes.string,
1273
- mode : PropTypes.oneOf(["outlined", "flat"]),
1274
1273
  inputProps : PropTypes.object,
1275
1274
  selectedColor:PropTypes.string,
1276
1275
  accessibilityLabel : PropTypes.string,
@@ -24,6 +24,7 @@ export * from "./utils";
24
24
 
25
25
  const _actions = {
26
26
  '$eq' : 'Egal à',
27
+ "$ne" : 'Défférent de',
27
28
  '$gt' : 'Supérieur à',
28
29
  '$gte' : 'Supérieur ou égal',
29
30
  '$lt' : 'Inférieur à',
@@ -135,6 +136,10 @@ export default class Filter extends AppComponent {
135
136
  this.props.onValidate({...this.getStateValues(),field:this.props.name,...arg})
136
137
  }
137
138
  }
139
+ isDecimal(){
140
+ const t = defaultStr(this.type,this.props.type).toLowerCase();
141
+ return t =="number" || t =='decimal' ? true : false;
142
+ }
138
143
  onFilterValidate(arg){
139
144
  arg = defaultObj(arg);
140
145
  if(JSON.stringify(this.state.defaultValue) === JSON.stringify(arg.value)){
@@ -190,11 +195,15 @@ export default class Filter extends AppComponent {
190
195
  value = undefined;
191
196
  }
192
197
  let originValue = value;
193
- const type = defaultStr(this.props.type).toLowerCase().trim();
194
- value = parseDecimal(value,type);
195
198
  if(action =="$today" || action =='$yesterday'){
196
199
  force = true;
197
200
  }
201
+ if(this.isDecimal()){
202
+ value = parseDecimal(value)
203
+ if(value == 0){
204
+ value = undefined;
205
+ }
206
+ }
198
207
  const prev = JSON.stringify(defaultObj(this.previousRef.current)), current = {value,operator,action,ignoreCase};
199
208
  let tV = isArray(value) && value.length <= 0 ? undefined : value;
200
209
  this.isInitializedRef.current = this.props.dynamicRendered || this.isInitializedRef.current;
@@ -290,8 +299,7 @@ export default class Filter extends AppComponent {
290
299
  if(data.start && data.end && data.start> data.end){
291
300
  return notify.error("La date de fin doit être supérieure à la date de début");
292
301
  }
293
- console.log(data," is dataa")
294
- if(isFunction(success)){
302
+ if(isFunction(success)){
295
303
  success(data.start+"=>"+data.end);
296
304
  }
297
305
  DialogProvider.close();
@@ -325,7 +333,6 @@ export default class Filter extends AppComponent {
325
333
  break;
326
334
  case "$week":
327
335
  diff = DateLib.currentWeekDaysLimits(currentDate);
328
- console.log(diff," is diffffff");
329
336
  break;
330
337
  case "$prevWeek":
331
338
  diff = DateLib.previousWeekDaysLimits(currentDate)
@@ -383,8 +390,8 @@ export default class Filter extends AppComponent {
383
390
  field,
384
391
  style,
385
392
  anchorProps,
386
- mode,
387
- inputProps,
393
+ //mode,
394
+ //inputProps,
388
395
  moreOptions,
389
396
  isLoading,
390
397
  searchIconTooltip,
@@ -472,6 +479,7 @@ export default class Filter extends AppComponent {
472
479
  }
473
480
  anchorProps = defaultObj(anchorProps);
474
481
  rest.anchorProps = anchorProps;
482
+ rest.withLabel = withLabel;
475
483
  rest.pointerEvents = "auto";
476
484
  rest.right = isLoading ? <ActivityIndicator color={theme.colors.secondaryOnSurface} animating/> :<>
477
485
  <Menu
@@ -557,7 +565,7 @@ export default class Filter extends AppComponent {
557
565
  if(ignoreDefaultValue) {
558
566
  rest.isPeriodAction = true;
559
567
  }
560
- return <View testID={testID+"_FilterContainer"} {...containerProps} style={[theme.styles.w100,containerProps.style]}>
568
+ return <View testID={testID+"_FilterContainer"} {...containerProps} style={StyleSheet.flatten([theme.styles.w100,containerProps.style])}>
561
569
  <Component
562
570
  {...rest}
563
571
  readOnly = {ignoreDefaultValue}
@@ -0,0 +1,7 @@
1
+ // Copyright 2022 @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
+ export default function ResizableComponent({children}){
6
+ return children;
7
+ }
@@ -0,0 +1,33 @@
1
+ // Copyright 2022 @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
+ import { Resizable } from 'react-resizable';
6
+ import React from "$react";
7
+ import {defaultObj} from "$utils";
8
+ import PropTypes from "prop-types";
9
+
10
+ const ResizableComponent = React.forwardRef(({width,onResize,height,...props},ref)=>{
11
+ const [state,setState] = React.useState({
12
+ width,
13
+ height,
14
+ });
15
+ return <Resizable {...props} height={state.height} width={state.width} onResize={(event, {element, size, handle}) => {
16
+ setState({width: size.width, height: size.height});
17
+ if(onResize){
18
+ onResize({...size,element,handle,event});
19
+ }
20
+ }}>
21
+
22
+ </Resizable>
23
+ });
24
+
25
+ ResizableComponent.displayName ="ResizableComponent";
26
+
27
+ export default ResizableComponent;
28
+
29
+ ResizableComponent.propTypes = {
30
+ ...defaultObj(Resizable.propTypes),
31
+ width : PropTypes.oneOfType([PropTypes.number,PropTypes.string]),
32
+ height : PropTypes.oneOfType([PropTypes.number,PropTypes.string])
33
+ }
@@ -4,31 +4,59 @@
4
4
 
5
5
  import { ScrollView,StyleSheet,View,useWindowDimensions} from "react-native";
6
6
  import React from "$react";
7
- import {defaultStr,defaultObj,isObj} from "$utils";
7
+ import {defaultStr,defaultObj,isObj,isNumber} from "$utils";
8
8
  import Portal from "$ecomponents/Portal";
9
+ import {isMobileNative,isTouchDevice} from "$platform";
9
10
 
10
- const AbsoluteScrollView = React.forwardRef(({testID,contentProps,containerProps,...props},ref)=>{
11
+ const isNative = isMobileNative() || isTouchDevice();
12
+ const AbsoluteScrollView = React.forwardRef(({testID,contentProps,listRef,containerProps,...props},ref)=>{
13
+ if(isNative) return null;
11
14
  containerProps = defaultObj(containerProps);
12
15
  contentProps = defaultObj(contentProps);
13
16
  const win = useWindowDimensions();
14
17
  const scrollViewRef = React.useRef(null);
15
18
  testID = defaultStr(testID,"RN_TableAbsoluteScrollViewComponent");
16
- const [styles,setStyles] = React.useState({});
19
+ const [state,setState] = React.useState({
20
+ styles : {},
21
+ visible : true,
22
+ })
23
+ const {styles,visible} = state,setStyles = (s)=>{
24
+ if(isObj(s)){
25
+ setState({...state,styles:{...styles,...s}});
26
+ }
27
+ },toggleVisible = ()=>{
28
+ if(isObj(styles.content) && isObj(styles.container)){
29
+ const visible = isNumber(styles.content.height) && isNumber(styles.container.height) && (styles.content.height-20)> styles.container.height? true : false;
30
+ if(visible != state.visible){
31
+ setState({...state,visible});
32
+ }
33
+ }
34
+ }
17
35
  React.setRef(ref,{
18
- setStyles : (s)=>{
19
- if(isObj(s)){
20
- setStyles({...styles,...s});
36
+ setStyles,
37
+ checkVisibility : (args)=>{
38
+ args = defaultObj(args);
39
+ if(isObj(args.contentOffset) && isObj(args.contentSize)){
40
+ const {x} = args.contentOffset;
41
+ const visible = x >=win.width ? false : true;
42
+ if(state.visible != visible){
43
+ return setState({...state,visible});
44
+ }
21
45
  }
46
+ return toggleVisible();
22
47
  },
23
48
  scrollViewRef
24
- })
49
+ });
25
50
  React.useEffect(()=>{
26
51
  return ()=>{
27
52
  React.setRef(ref,null);
28
53
  }
29
- },[])
54
+ },[]);
55
+ React.useEffect(()=>{
56
+ toggleVisible();
57
+ },[styles])
30
58
  return <Portal>
31
- <View testID={testID+"_Containter"} {...containerProps} style={[mainStyles.container,containerProps.style,styles.container,{left:win.width-10}]}>
59
+ {<View testID={testID+"_Containter"} {...containerProps} style={[mainStyles.container,containerProps.style,styles.container,{left:win.width-10},!visible &&{display:'none',width:0,opacity:0}]}>
32
60
  <ScrollView
33
61
  {...props}
34
62
  ref = {scrollViewRef}
@@ -42,7 +70,7 @@ const AbsoluteScrollView = React.forwardRef(({testID,contentProps,containerProps
42
70
  style={[mainStyles.content,contentProps.style,styles.content]}
43
71
  />
44
72
  </ScrollView>
45
- </View>
73
+ </View>}
46
74
  </Portal>
47
75
  });
48
76
 
@@ -10,6 +10,7 @@ import { getRowStyle } from "$ecomponents/Datagrid/utils";
10
10
  import {isMobileNative} from "$cplatform";
11
11
  import theme from "$theme";
12
12
  import AbsoluteScrollView from "./AbsoluteScrollView";
13
+ import DragResize,{CONNECTOR_MIDDLE_RIGHT} from "$ecomponents/DragResize";
13
14
 
14
15
  const isSCrollingRef = React.createRef();
15
16
  const scrollLists = (opts,refs)=>{
@@ -42,7 +43,7 @@ const getOnScrollCb = (refs,pos,cb2)=>{
42
43
  return isMobileNative()? cb : debounce(cb,200);
43
44
  }
44
45
 
45
- const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScrollViewProps,footerScrollViewProps,scrollViewProps,showFooters,renderFooterCell,footerCellContainerProps,headerContainerProps,headerCellContainerProps,headerProps,rowProps:customRowProps,renderCell,cellContainerProps,hasFooters,renderHeaderCell,columnProps,getRowKey,columnsWidths,colsWidths,footerContainerProps,showFilters,columns,data,testID,...props},tableRef)=>{
46
+ const TableComponent = React.forwardRef(({containerProps,renderEmpty,isRowSelected,headerScrollViewProps,footerScrollViewProps,scrollViewProps,showFooters,renderFooterCell,footerCellContainerProps,filterCellContainerProps,headerContainerProps,headerCellContainerProps,headerProps,rowProps:customRowProps,renderCell,cellContainerProps,hasFooters,renderHeaderCell,renderFilterCell,columnProps,getRowKey,columnsWidths,colsWidths,footerContainerProps,showFilters,columns,data,testID,...props},tableRef)=>{
46
47
  containerProps = defaultObj(containerProps);
47
48
  testID = defaultStr(testID,"RN_TableComponent");
48
49
  cellContainerProps = defaultObj(cellContainerProps);
@@ -53,13 +54,14 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
53
54
  const getRowProps = typeof rowProps ==='function'? rowProps : undefined;
54
55
  let rowProps = isObj(customRowProps)? customRowProps:{};
55
56
  const prepareState = React.useCallback(()=>{
56
- const cols = {},headers = {},footers = {},visibleColumns = [];
57
+ const cols = {},headers = {},footers = {},filters = {},visibleColumns = [];
57
58
  let hasFooters = false;
58
59
  columnProps = defaultObj(columnProps);
59
60
  let columnIndex = 0;
60
61
  const widths = defaultObj(columnsWidths,colsWidths);
61
62
  headerCellContainerProps = defaultObj(headerCellContainerProps);
62
63
  footerCellContainerProps = defaultObj(footerCellContainerProps);
64
+ filterCellContainerProps = defaultObj(filterCellContainerProps);
63
65
  Object.map(columns,(columnDef,field)=>{
64
66
  if(!isObj(columnDef) /*|| columnDef.visible === false*/) return;
65
67
  const columnField = defaultStr(columnDef.field,field);
@@ -68,7 +70,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
68
70
  type = defaultStr(type,"text").toLowerCase().trim();
69
71
  colProps = defaultObj(colProps);
70
72
  width = defaultDecimal(widths[columnField],width,DEFAULT_COLUMN_WIDTH);
71
- const style = [colProps.style,{width}];
73
+ const style = StyleSheet.flatten([colProps.style,{width}]);
72
74
  const colArgs = {width,type,style,columnDef,containerProps:{},columnField,index:columnIndex,columnIndex};
73
75
  let content = typeof renderHeaderCell =='function'? renderHeaderCell(colArgs) : defaultVal(columnDef.text,columnDef.label,columnField);
74
76
  let hContainerProps = {};
@@ -82,9 +84,16 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
82
84
  console.error(content," is not valid element of header ",columnDef," it could not be render on table");
83
85
  return null;
84
86
  }
87
+
85
88
  headers[columnField] = <View testID={testID+"_HeaderCell_"+columnField} {...headerCellContainerProps} {...hContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,headerCellContainerProps.style,hContainerProps.style,style]}>
86
- <Label textBold primary>{content}</Label>
89
+ <Label style={[theme.styles.w100,theme.styles.h100]} textBold primary>{content}</Label>
87
90
  </View>;
91
+ if(typeof renderFilterCell =='function'){
92
+ const filterCell = renderFilterCell(colArgs);
93
+ filters[columnField] = <View testID={testID+"_Filter_Cell_"+columnField} {...filterCellContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,styles.filterCell,filterCellContainerProps.style,style]}>
94
+ {React.isValidElement(filterCell)? filterCell : null}
95
+ </View>
96
+ }
88
97
  if(typeof renderFooterCell ==='function') {
89
98
  const footerProps = {...colArgs,containerProps:{}};
90
99
  let cellFooter = renderFooterCell(footerProps);
@@ -99,7 +108,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
99
108
  if(!hasFooters && cellFooter){
100
109
  hasFooters = true;
101
110
  }
102
- footers[columnField] = <View testID={testID+"_Footer_Cell_"+columnField} {...fContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,footerCellContainerProps.style,fContainerProps.style,style]}>
111
+ footers[columnField] = <View testID={testID+"_Footer_Cell_"+columnField} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,footerCellContainerProps.style,style]}>
103
112
  <Label primary children={cellFooter}/>
104
113
  </View>
105
114
  }
@@ -116,7 +125,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
116
125
  }
117
126
  columnIndex++;
118
127
  });
119
- return {columns:cols,visibleColumns,headers,hasFooters,footers};
128
+ return {columns:cols,visibleColumns,headers,hasFooters,footers,filters};
120
129
  },[columns,data]);
121
130
  const [state,setState] = React.useState({
122
131
  headers : {},
@@ -129,11 +138,13 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
129
138
  React.useEffect(()=>{
130
139
  setState({...state,...prepareState()});
131
140
  },[data,columns]);
132
- const {visibleColumns,columns:cols,headers,footers} = state;
141
+ const emptyData = typeof renderEmpty =='function' && !Object.size(data,true)? renderEmpty() : null;
142
+ const hasEmptyData = emptyData && React.isValidElement(emptyData);
143
+ const {visibleColumns,columns:cols,headers,footers,filters} = state;
133
144
  headerContainerProps = defaultObj(headerContainerProps);
134
145
  footerContainerProps = defaultObj(footerContainerProps);
135
146
  let hProps = typeof headerProps =='function'? hProps({columns:col,visibleColumns}) : {};
136
- const h = [],f = [];
147
+ const h = [],f = [],fFilters = [];
137
148
  let totalWidths = 0;
138
149
  visibleColumns.map((i)=>{
139
150
  if(!isObj(cols[i])) return;
@@ -142,6 +153,9 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
142
153
  if(showFooters && state.hasFooters){
143
154
  f.push(footers[i]);
144
155
  }
156
+ if(showFilters && filters[i]){
157
+ fFilters.push(filters[i]);
158
+ }
145
159
  });
146
160
  const scrollContentContainerStyle = {flex:1,width:listWidth,minWidth:totalWidths,height:'100%'};
147
161
  const scrollEventThrottle = isMobileNative()?200:50;
@@ -150,7 +164,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
150
164
  scrollEventThrottle,
151
165
  horizontal : true,
152
166
  ...scrollViewProps,
153
- style : [{maxHeight:120},scrollViewProps.style],
167
+ style : [scrollViewProps.style],
154
168
  contentContainerStyle : [styles.scrollView,scrollViewProps.contentContainerStyle,scrollViewFlexGrow,scrollContentContainerStyle]
155
169
  }
156
170
  const listWidth = '100%';
@@ -187,15 +201,19 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
187
201
  const hContent = h.length ? <View testID={testID+"_Header"}{...hProps} {...headerContainerProps} style={[styles.header,headerContainerProps.style,hProps.style,f.length]}>
188
202
  {h}
189
203
  </View> : null,
190
- fContent = f.length ? <View testID={testID+"_Footer"} {...footerContainerProps} style={[styles.header,styles.footers,footerContainerProps.style]}>
204
+ fContent = f.length ? <View testID={testID+"_Footer"} {...footerContainerProps} style={[styles.header,styles.footers,footerContainerProps.style,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
191
205
  {f}
192
- </View> : null;
206
+ </View> : null,
207
+ filtersContent = fFilters.length ? <View testID={testID+"_Filters"} style={[styles.header,styles.footers,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
208
+ {fFilters}
209
+ </View> : null
210
+
193
211
  const absoluteScrollViewRefCanScroll = React.useRef(true);
194
212
  React.setRef(tableRef,context);
195
213
  const cStyle = {width:listWidth}
196
214
  const absoluteScrollViewRef = React.useRef(null);
197
- return <View testID= {testID+"_Container"} {...containerProps} style={[styles.container,{alignItems:'stretch'},containerProps.style]}>
198
- <View autoHeight style={[cStyle]} testID={testID+"_Headers_ScrollViewContainer"}>
215
+ return <View testID= {testID+"_Container"} {...containerProps} style={[styles.container,{alignItems:'stretch'},containerProps.style,theme.styles.pl0,theme.styles.pr0]}>
216
+ <RNView style={[cStyle]} testID={testID+"_Headers_ScrollViewContainer"}>
199
217
  <ScrollView
200
218
  testID={testID+"_HeaderScrollView"}
201
219
  {...headerScrollViewProps}
@@ -205,12 +223,22 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
205
223
  onScroll = {getOnScrollCb([scrollViewRef,footerScrollViewRef])}
206
224
  showsHorizontalScrollIndicator
207
225
  >
208
- {hContent}
226
+ <View testID={testID+"Header2FootersWrapper"} style={[theme.styles.w100]}>
227
+ {hContent}
228
+ {filtersContent}
229
+ {fContent}
230
+ </View>
209
231
  </ScrollView>
210
- </View>
211
- <ScrollView {...scrollViewProps} scrollEventThrottle = {scrollEventThrottle} horizontal contentContainerStyle={[scrollContentContainerStyle,scrollViewProps.contentContainerStyle]} showsVerticalScrollIndicator={false}
232
+ </RNView>
233
+ {hasEmptyData ? <View testID={testID+"_Empty"} style={styles.hasNotData}>
234
+ {emptyData}
235
+ </View> : <ScrollView {...scrollViewProps} scrollEventThrottle = {scrollEventThrottle} horizontal contentContainerStyle={[scrollContentContainerStyle,scrollViewProps.contentContainerStyle]} showsVerticalScrollIndicator={false}
212
236
  onScroll = {getOnScrollCb([headerScrollViewRef,footerScrollViewRef],null,(args)=>{
213
- })} ref={scrollViewRef} testID={testID+"_ScrollView"}>
237
+ const nativeEvent = args.nativeEvent;
238
+ if(absoluteScrollViewRef.current && absoluteScrollViewRef.current.checkVisibility){
239
+ absoluteScrollViewRef.current.checkVisibility(nativeEvent);
240
+ }
241
+ })} ref={scrollViewRef} testID={testID+"_ScrollView"}>
214
242
  <FlashList
215
243
  containerProps = {{style:[cStyle]}}
216
244
  //prepareItems = {Array.isArray(items)? false : undefined}
@@ -222,7 +250,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
222
250
  }
223
251
  if(!absoluteScrollViewRef.current) return;
224
252
  absoluteScrollViewRef.current.setStyles({
225
- content : {height}
253
+ content : {height,width}
226
254
  });
227
255
  }}
228
256
  onLayout = {(args)=>{
@@ -248,6 +276,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
248
276
  keyExtractor = {typeof getRowKey =='function'? getRowKey : React.getKey}
249
277
  //stickyHeaderIndices={[0]}
250
278
  onScroll = {getOnScrollCb([absoluteScrollViewRef],(args)=>{
279
+ if(!absoluteScrollViewRef.current) return;
251
280
  const offset = args?.nativeEvent?.contentOffset.y;
252
281
  const scrollViewRef = absoluteScrollViewRef.current?.scrollViewRef;
253
282
  if(typeof offset =='number' && scrollViewRef.current && scrollViewRef.current.scrollTo){
@@ -286,18 +315,20 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
286
315
  </View>;
287
316
  }}
288
317
  />
289
- <AbsoluteScrollView
290
- ref={absoluteScrollViewRef}
291
- scrollEventThrottle = {scrollEventThrottle}
292
- onScroll = {(args)=>{
293
- if(!absoluteScrollViewRefCanScroll.current) return;
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
- }
298
- }}
299
- />
300
- </ScrollView>
318
+ <AbsoluteScrollView
319
+ ref={absoluteScrollViewRef}
320
+ listRef = {listRef}
321
+ scrollEventThrottle = {scrollEventThrottle}
322
+ onScroll = {(args)=>{
323
+ if(!absoluteScrollViewRefCanScroll.current) return;
324
+ const offset = args?.nativeEvent?.contentOffset.y;
325
+ if(typeof offset =='number' && listRef.current && listRef.current.scrollToOffset){
326
+ listRef.current.scrollToOffset({animated:true,offset});
327
+ }
328
+ }}
329
+ />
330
+ </ScrollView>}
331
+
301
332
  </View>
302
333
  });
303
334
 
@@ -358,6 +389,15 @@ const styles = StyleSheet.create({
358
389
  paddingHorizontal:5,
359
390
  paddingVertical : 0,
360
391
  },
392
+ filterCell : {
393
+ alignSelf : "flex-start",
394
+ textAlign : "left",
395
+ paddingHorizontal : 2,
396
+ paddingVertical : 0,
397
+ marginVertical : 0,
398
+ marginHorizontal : 0,
399
+ justifyContent : 'flex-start',
400
+ },
361
401
  headerItem: {
362
402
  minHeight: 30,
363
403
  },
@@ -377,14 +417,22 @@ const styles = StyleSheet.create({
377
417
  marginHorizontal : 0,
378
418
  marginVertical : 0,
379
419
  },
420
+ hasNotData : {
421
+ flexDirection : 'column',
422
+ width : '100%',
423
+ justifyContent : 'center',
424
+ alignItems : 'center'
425
+ }
380
426
  })
381
427
  TableComponent.popTypes = {
382
428
  containerProps : PropTypes.object,
383
429
  renderHeaderCell : PropTypes.func,
430
+ renderFilterCell : PropTypes.func,
384
431
  renderRow : PropTypes.func,
385
432
  renderCell : PropTypes.func,
386
433
  renderFooterCell : PropTypes.func,///la fonction appelée pour le rendu des entêtes du footer
387
434
  footerCellContainerProps : PropTypes.object,
435
+ filterCellContainerProps : PropTypes.object,
388
436
  footerContainerProps : PropTypes.object,
389
437
  showFilters : PropTypes.bool,
390
438
  showFooters : PropTypes.bool,
@@ -244,12 +244,12 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
244
244
  if(isFocused || error){
245
245
  placeholderColor = labelColor;
246
246
  }
247
+ let labelText = React.isValidElement(label,true)?React.getTextContent(label):"";
247
248
  const defaultBackgroundColor = theme.surfaceBackgroundColor;
248
249
  let backgroundColor = Colors.isValid(flattenStyle.backgroundColor)? flattenStyle.backgroundColor : defaultBackgroundColor;
249
- if(backgroundColor ==='transparent' && dynamicBackgroundColor !== false){
250
+ if(labelText && (backgroundColor ==='transparent' && dynamicBackgroundColor !== false)){
250
251
  backgroundColor = defaultBackgroundColor;
251
252
  }
252
- let labelText = React.isValidElement(label,true)?React.getTextContent(label):"";
253
253
  placeholder = defaultStr(placeholder,labelText);
254
254
  const parsedValue = canValueBeDecimal ? parseValueToDecimal(text):text;
255
255
  const formattedValue = formatValue(text);