@fto-consult/expo-ui 2.4.8 → 2.5.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.
- package/package.json +3 -3
- package/src/components/BottomSheet/Menu.js +4 -2
- package/src/components/Datagrid/Accordion/index.js +14 -10
- package/src/components/Datagrid/Common/Common.js +42 -22
- package/src/components/Datagrid/Footer/Footer.js +10 -12
- package/src/components/Datagrid/Table/index.js +29 -42
- package/src/components/Date/DatePickerInput/index.js +1 -1
- package/src/components/Date/DateTime.js +11 -6
- package/src/components/Date/Time.js +5 -1
- package/src/components/Dialog/confirm/showConfirmOrAlertOrPrompt.js +4 -0
- package/src/components/Dropdown/index.js +4 -5
- package/src/components/Fab/Group.js +2 -2
- package/src/components/Filter/index.js +17 -8
- package/src/components/Table/AbsoluteScrollView.js +91 -0
- package/src/components/Table/index.js +126 -34
- package/src/components/TextField/index.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@expo/html-elements": "^0.2.0",
|
|
63
63
|
"@expo/metro-config": "^0.4.0",
|
|
64
64
|
"@expo/webpack-config": "^0.17.2",
|
|
65
|
-
"@fto-consult/common": "^1.
|
|
65
|
+
"@fto-consult/common": "^1.12.2",
|
|
66
66
|
"@gorhom/portal": "^1.0.14",
|
|
67
67
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
68
68
|
"@react-native-community/datetimepicker": "6.5.2",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"babel-plugin-inline-dotenv": "^1.7.0",
|
|
74
74
|
"babel-plugin-module-resolver": "^4.1.0",
|
|
75
75
|
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
|
|
76
|
-
"expo": "^47.0.
|
|
76
|
+
"expo": "^47.0.8",
|
|
77
77
|
"expo-camera": "~13.0.0",
|
|
78
78
|
"expo-clipboard": "~4.0.1",
|
|
79
79
|
"expo-image-picker": "~14.0.1",
|
|
@@ -8,7 +8,7 @@ import PropTypes from "prop-types";
|
|
|
8
8
|
import {getContentHeight} from "./utils";
|
|
9
9
|
|
|
10
10
|
const BottomSheetMenuComponent = React.forwardRef((props,ref)=>{
|
|
11
|
-
let {anchor,screenIndent,height:customHeight,bindResizeEvent,onDismiss,testID,visible:customVisible,controlled,mobile,animateOnClose,renderMenuContent,sheet,children,...rest} = props;
|
|
11
|
+
let {anchor,anchorProps,screenIndent,height:customHeight,bindResizeEvent,onDismiss,testID,visible:customVisible,controlled,mobile,animateOnClose,renderMenuContent,sheet,children,...rest} = props;
|
|
12
12
|
rest = defaultObj(rest);
|
|
13
13
|
const isControlled = controlled ? true : false;
|
|
14
14
|
const visibleRef = React.useRef(null);
|
|
@@ -44,12 +44,13 @@ const BottomSheetMenuComponent = React.forwardRef((props,ref)=>{
|
|
|
44
44
|
setState({...state,visible:false})
|
|
45
45
|
}
|
|
46
46
|
const Component = isMob ? BottomSheet : Menu;
|
|
47
|
+
anchorProps = defaultObj(anchorProps);
|
|
47
48
|
if(isMob){
|
|
48
49
|
if(typeof anchor ==='function'){
|
|
49
50
|
anchor = anchor(!isControlled?{onPress:open}:{});
|
|
50
51
|
}
|
|
51
52
|
if(React.isValidElement(anchor)){
|
|
52
|
-
anchor = <View testID={testID+"_Anchor"} ref={anchorRef} collapsable={false}>{anchor}</View>
|
|
53
|
+
anchor = <View testID={testID+"_Anchor"} ref={anchorRef} {...anchorProps} collapsable={false}>{anchor}</View>
|
|
53
54
|
}
|
|
54
55
|
if(renderMenuContent !== false){
|
|
55
56
|
children = renderItems({testID:testID+".Items",...props,closeMenu:close,openMenu:open,isBottomSheetItem:true});
|
|
@@ -101,6 +102,7 @@ const BottomSheetMenuComponent = React.forwardRef((props,ref)=>{
|
|
|
101
102
|
height = {controlled?customHeight:height}
|
|
102
103
|
ref = {React.useMergeRefs(innerRef,ref)}
|
|
103
104
|
anchor = {anchor}
|
|
105
|
+
anchorProps = {anchorProps}
|
|
104
106
|
children = {visible && (React.isValidElement(children) || Array.isArray(children))?children:undefined}
|
|
105
107
|
/>
|
|
106
108
|
</>
|
|
@@ -245,9 +245,6 @@ const DatagridFactory = (Factory)=>{
|
|
|
245
245
|
getMaxSelectedRows(){
|
|
246
246
|
return isMobileMedia()? 30 : 50;
|
|
247
247
|
}
|
|
248
|
-
prepareFilter(props,headerFilters){
|
|
249
|
-
return headerFilters.push(props);
|
|
250
|
-
}
|
|
251
248
|
showFilters(){
|
|
252
249
|
if(!this._isMounted()) {
|
|
253
250
|
this.isUpdating = false;
|
|
@@ -299,6 +296,12 @@ const DatagridFactory = (Factory)=>{
|
|
|
299
296
|
</View>
|
|
300
297
|
})
|
|
301
298
|
}
|
|
299
|
+
renderEmpty(){
|
|
300
|
+
if(isObj(this.currentAccordionProps) && typeof this.currentAccordionProps.renderEmpty =='function'){
|
|
301
|
+
return this.currentAccordionProps.renderEmpty();
|
|
302
|
+
}
|
|
303
|
+
return super.renderEmpty();
|
|
304
|
+
}
|
|
302
305
|
render (){
|
|
303
306
|
let {
|
|
304
307
|
filters,
|
|
@@ -332,6 +335,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
332
335
|
if(isObj(accordion)){
|
|
333
336
|
accordionProps = {...accordion,...accordionProps};
|
|
334
337
|
}
|
|
338
|
+
this.currentAccordionProps = accordionProps;
|
|
335
339
|
backToTopRef = defaultVal(backToTopRef,accordionProps.backToTopRef,true);
|
|
336
340
|
|
|
337
341
|
let descOrContentProps = isObj(accordionProps.descriptionProps)? Object.assign({},accordionProps.descriptionProps) : isObj(accordionProps.contentProps)? Object.assign({},accordionProps.contentProps) : {};
|
|
@@ -381,7 +385,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
381
385
|
if(toggleFilters === false){
|
|
382
386
|
filters = false;
|
|
383
387
|
}
|
|
384
|
-
let {showFilters,
|
|
388
|
+
let {showFilters,showFooters} = this.state;
|
|
385
389
|
let max = this.getMaxSelectableRows();
|
|
386
390
|
let restItems = [];
|
|
387
391
|
|
|
@@ -495,9 +499,9 @@ const DatagridFactory = (Factory)=>{
|
|
|
495
499
|
closeOnPress : false,
|
|
496
500
|
} : null,
|
|
497
501
|
hasFooterFields ? {
|
|
498
|
-
onPress : ()=>{
|
|
499
|
-
,icon :
|
|
500
|
-
,text : (
|
|
502
|
+
onPress : ()=>{showFooters?this.hideFooter():this.showFooters()}
|
|
503
|
+
,icon : showFooters?'view-column':'view-module'
|
|
504
|
+
,text : (showFooters?'Masquer/Ligne des totaux':'Afficher/Ligne des totaux')
|
|
501
505
|
}:null,
|
|
502
506
|
...restItems,
|
|
503
507
|
this.canScrollTo() && {
|
|
@@ -539,7 +543,6 @@ const DatagridFactory = (Factory)=>{
|
|
|
539
543
|
</View>
|
|
540
544
|
</ScrollView>
|
|
541
545
|
</View>
|
|
542
|
-
renderEmpty = defaultFunc(accordionProps.renderEmpty,renderEmpty,x=>null)
|
|
543
546
|
return <View testID={testID+"_Container"} pointerEvents={pointerEvents} style={[styles.container]} collapsable={false}>
|
|
544
547
|
{ <View testID={testID+"_ContentContainer"} style={[this.bindResizeEvents()?{height:this.renderedListHeight}:undefined]}>
|
|
545
548
|
<View testID={testID+"_AccordionHeader"} style={[styles.accordionHeader]} ref={this.layoutRef} onLayout={this.updateLayout.bind(this)}>
|
|
@@ -554,7 +557,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
554
557
|
/>
|
|
555
558
|
{datagridHeader}
|
|
556
559
|
{_progressBar}
|
|
557
|
-
{
|
|
560
|
+
{showFooters ? (
|
|
558
561
|
<View testID={testID+"_FooterContainer"} pointerEvents={pointerEvents} style={[{justifyContent:'center'}]}>
|
|
559
562
|
<View testID={testID+"_FooterContentContainer"} style={[styles.footersContainer]}>
|
|
560
563
|
<ScrollView testID={testID+"_FooterScrollView"} horizontal contentContainerStyle={[styles.contentContainerStyle]}>
|
|
@@ -564,6 +567,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
564
567
|
key = {field}
|
|
565
568
|
testID={testID+"_FooterItem_"+field}
|
|
566
569
|
{...footer}
|
|
570
|
+
anchorProps = {{style:[theme.styles.ph1,theme.styles.mh05]}}
|
|
567
571
|
/>
|
|
568
572
|
})}
|
|
569
573
|
</View>
|
|
@@ -591,7 +595,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
591
595
|
}:false}
|
|
592
596
|
keyExtractor = {this.getRowKey.bind(this)}
|
|
593
597
|
/> : <View style={styles.hasNotData}>
|
|
594
|
-
{renderEmpty()}
|
|
598
|
+
{this.renderEmpty()}
|
|
595
599
|
</View>}
|
|
596
600
|
</View>}
|
|
597
601
|
{backToTopRef ? <BackToTop testID={testID+"_BackToTop"} {...backToTopProps} ref={this.backToTopRef} style={[styles.backToTop,backToTopProps.style]} onPress={this.scrollToTop.bind(this)}/>:null}
|
|
@@ -71,13 +71,13 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
71
71
|
});
|
|
72
72
|
selectedRows = sRows;
|
|
73
73
|
let sData = this.getSessionData()
|
|
74
|
-
sData.
|
|
74
|
+
sData.showFooters = defaultVal(sData.showFooters,true);
|
|
75
75
|
sData.fixedTable = defaultBool(sData.fixedTable,false);
|
|
76
76
|
extendObj(this.state, {
|
|
77
77
|
data,
|
|
78
78
|
sort :defaultObj(props.sort),
|
|
79
79
|
showFilters : defaultBool(props.showFilters,(sData.showFilter? true : this.isPivotDatagrid())),
|
|
80
|
-
|
|
80
|
+
showFooters : defaultBool(props.showFooters,(sData.showFooters? true : false)),
|
|
81
81
|
fixedTable : sData.fixedTable
|
|
82
82
|
});
|
|
83
83
|
Object.defineProperties(this,{
|
|
@@ -96,6 +96,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
96
96
|
[footerFieldName] : {
|
|
97
97
|
value : uniqid(footerFieldName),override:false, writable: false
|
|
98
98
|
},
|
|
99
|
+
currentFilteringColumns : {value:{}}
|
|
99
100
|
})
|
|
100
101
|
|
|
101
102
|
this.state.sort.dir = defaultStr(this.state.sort.dir,this.state.sort.column == "date"?"desc":'asc')
|
|
@@ -783,16 +784,16 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
783
784
|
}
|
|
784
785
|
|
|
785
786
|
|
|
786
|
-
|
|
787
|
+
showFooters(){
|
|
787
788
|
if(!this._isMounted()) {
|
|
788
789
|
this.isUpdating = false;
|
|
789
790
|
return;
|
|
790
791
|
}
|
|
791
792
|
if(this.isUpdating) return false;
|
|
792
793
|
this.isUpdating = true;
|
|
793
|
-
this.setState( {
|
|
794
|
+
this.setState( {showFooters:true},()=>{
|
|
794
795
|
this.isUpdating = false;
|
|
795
|
-
this.setSessionData({
|
|
796
|
+
this.setSessionData({showFooters:true})
|
|
796
797
|
})
|
|
797
798
|
}
|
|
798
799
|
hideFooter (){
|
|
@@ -801,9 +802,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
801
802
|
return;
|
|
802
803
|
}
|
|
803
804
|
if(this.isUpdating) return false;
|
|
804
|
-
this.setState({
|
|
805
|
+
this.setState({showFooters:false},()=>{
|
|
805
806
|
this.isUpdating = false;
|
|
806
|
-
this.setSessionData({
|
|
807
|
+
this.setSessionData({showFooters:false});
|
|
807
808
|
})
|
|
808
809
|
}
|
|
809
810
|
|
|
@@ -847,13 +848,20 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
847
848
|
});
|
|
848
849
|
}
|
|
849
850
|
prepareFilter(props,filteredColumns){
|
|
850
|
-
|
|
851
|
+
filteredColumns.push(props);
|
|
851
852
|
}
|
|
852
853
|
renderFilter(props){
|
|
853
854
|
return <Filter {...props}/>
|
|
854
855
|
}
|
|
855
856
|
prepareColumn(){}
|
|
856
857
|
beforePrepareColumns(){}
|
|
858
|
+
renderEmpty(){
|
|
859
|
+
if(typeof this.props.renderEmpty =='function'){
|
|
860
|
+
const r = this.props.renderEmpty();
|
|
861
|
+
return React.isValidElement(r)? r : null;
|
|
862
|
+
}
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
857
865
|
prepareColumns (args){
|
|
858
866
|
this.beforePrepareColumns();
|
|
859
867
|
args = defaultObj(args);
|
|
@@ -891,14 +899,18 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
891
899
|
let colFilter = defaultVal(restCol.filter,true);
|
|
892
900
|
field = header.field = defaultStr(header.field,field,headerIndex);
|
|
893
901
|
delete restCol.filter;
|
|
902
|
+
|
|
903
|
+
const type = defaultStr(header.type).toLowerCase();
|
|
904
|
+
sortType = defaultStr(sortType,type).toLowerCase();
|
|
894
905
|
width = defaultDecimal(width);
|
|
895
906
|
if(width <COLUMN_WIDTH/2){
|
|
896
907
|
width = COLUMN_WIDTH;
|
|
897
908
|
}
|
|
898
|
-
const type = defaultStr(header.type).toLowerCase();
|
|
899
|
-
sortType = defaultStr(sortType,type).toLowerCase();
|
|
900
909
|
if(type.contains("date")|| type.contains("time")){
|
|
901
|
-
|
|
910
|
+
const mWidth = type.toLowerCase().contains('datetime')? (DATE_COLUMN_WIDTH+30) : DATE_COLUMN_WIDTH;
|
|
911
|
+
width = Math.max(width,mWidth);
|
|
912
|
+
} else if((type.contains("number") || type.contains("decimal") && this.props.format)){
|
|
913
|
+
width = Math.max(width,DATE_COLUMN_WIDTH-30);
|
|
902
914
|
}
|
|
903
915
|
totalWidths +=width;
|
|
904
916
|
widths[header.field] = width;
|
|
@@ -945,6 +957,17 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
945
957
|
delete restCol.sortable;
|
|
946
958
|
filterProps = {
|
|
947
959
|
...restCol,
|
|
960
|
+
columnIndex,
|
|
961
|
+
visibleColumnIndex,
|
|
962
|
+
sortable:isColumnSortable,
|
|
963
|
+
sorted:isColumnSorted,
|
|
964
|
+
sortedColumn :sortedProps,///les props de la columns triée
|
|
965
|
+
sortedProps,
|
|
966
|
+
width,
|
|
967
|
+
columnField : field,
|
|
968
|
+
columnDef : header,
|
|
969
|
+
index : headerIndex,
|
|
970
|
+
visible,
|
|
948
971
|
key : header.field,
|
|
949
972
|
label : defaultStr(header.label,header.text),
|
|
950
973
|
orOperator : filterOrOperator,
|
|
@@ -958,6 +981,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
958
981
|
operator : fCol.operator,
|
|
959
982
|
action : defaultStr(fCol.originAction,fCol.action),
|
|
960
983
|
};
|
|
984
|
+
this.currentFilteringColumns[header.field] = filterProps;
|
|
961
985
|
this.prepareFilter(filterProps,headerFilters);
|
|
962
986
|
}
|
|
963
987
|
this.prepareColumn({
|
|
@@ -1169,19 +1193,15 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1169
1193
|
onFilterChange(arg){
|
|
1170
1194
|
this.filteredValues = defaultObj(this.filteredValues);
|
|
1171
1195
|
let {field,operator,originAction,action,value} = defaultObj(arg);
|
|
1172
|
-
const
|
|
1173
|
-
if(
|
|
1196
|
+
const filter = isNonNullString(field)? this.currentFilteringColumns[field] : null;
|
|
1197
|
+
if(!isObj(filter)) return;
|
|
1198
|
+
if(isNonNullString(operator) && isNonNullString(action)){
|
|
1174
1199
|
this.filteredValues[field] = {
|
|
1175
1200
|
operator,action,value,field
|
|
1176
1201
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
filter.operator = operator;
|
|
1181
|
-
filter.action = defaultStr(originAction,action);
|
|
1182
|
-
}
|
|
1183
|
-
});
|
|
1184
|
-
|
|
1202
|
+
filter.originValue = filter.defaultValue = arg.defaultValue;
|
|
1203
|
+
filter.operator = operator;
|
|
1204
|
+
filter.action = defaultStr(originAction,action);
|
|
1185
1205
|
}
|
|
1186
1206
|
return this.doFilter(arg);
|
|
1187
1207
|
}
|
|
@@ -1705,7 +1725,7 @@ CommonDatagridComponent.propTypes = {
|
|
|
1705
1725
|
/*** affiche ou masque les filtres */
|
|
1706
1726
|
showFilters : PropTypes.bool,
|
|
1707
1727
|
/*** si le pied de page sera affiché */
|
|
1708
|
-
|
|
1728
|
+
showFooters : PropTypes.bool,
|
|
1709
1729
|
/*** les donnnées peuvent être soient retournées par une fonction, soit par un tableau soit une promesse */
|
|
1710
1730
|
data : PropTypes.oneOfType([PropTypes.array, PropTypes.func,PropTypes.object]),//.isRequired,
|
|
1711
1731
|
columns:PropTypes.oneOfType([PropTypes.array,PropTypes.object]),//.isRequired,
|
|
@@ -3,7 +3,7 @@ import Menu from "$ecomponents/BottomSheet/Menu";
|
|
|
3
3
|
import View from "$ecomponents/View";
|
|
4
4
|
import {Pressable,StyleSheet} from "react-native";
|
|
5
5
|
import Label from "$ecomponents/Label";
|
|
6
|
-
import {defaultVal} from "$utils";
|
|
6
|
+
import {defaultVal,defaultObj} from "$utils";
|
|
7
7
|
import React from "$react";
|
|
8
8
|
import theme from "$theme"
|
|
9
9
|
|
|
@@ -18,7 +18,9 @@ const formatValue = ({value,format,method})=>{
|
|
|
18
18
|
return (format === 'money' && method != 'count')? value.formatMoney():value.formatNumber();
|
|
19
19
|
}
|
|
20
20
|
export default function DGGridFooterValue (props){
|
|
21
|
-
let {label,text,displayLabel,style,format} = props;
|
|
21
|
+
let {label,text,displayLabel,style,format,testID,anchorProps} = props;
|
|
22
|
+
anchorProps = defaultObj(anchorProps);
|
|
23
|
+
testID = defaultStr(testID,"RN_DatagridFooterComponent");
|
|
22
24
|
label = defaultVal(label,text);
|
|
23
25
|
const defLabel = label;
|
|
24
26
|
if(displayLabel !== false){
|
|
@@ -50,19 +52,19 @@ export default function DGGridFooterValue (props){
|
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
return <Menu
|
|
55
|
+
testID = {testID+"_Menu"}
|
|
53
56
|
items = {menuItems}
|
|
54
|
-
style = {{minWidth:220}}
|
|
55
57
|
title = {'Totaux de la colonne '+(defLabel?("[ "+defLabel+"]"):'')}
|
|
56
58
|
animateOnClose
|
|
57
59
|
anchor = {(p)=>{
|
|
58
|
-
return <Pressable {...p} style={[styles.anchor,style,label?styles.row:null]} title={title}>
|
|
60
|
+
return <Pressable {...anchorProps} {...p} testID={testID} style={[styles.anchor,anchorProps.style,label?styles.row:null]} title={title}>
|
|
59
61
|
{label ?
|
|
60
62
|
<>
|
|
61
|
-
<View><Label style={[styles.label]}>{label}</Label></View>
|
|
62
|
-
<View><Label style = {styles.label}> : </Label></View>
|
|
63
|
+
<View testID={testID+"_Label"}><Label style={[styles.label]}>{label}</Label></View>
|
|
64
|
+
<View testID={testID+"_LabelPoint"}><Label style = {styles.label}> : </Label></View>
|
|
63
65
|
</>
|
|
64
66
|
: null}
|
|
65
|
-
<Label primary style={[styles.value]}>
|
|
67
|
+
<Label testID={testID+"_LabelContent"} primary style={[styles.value]}>
|
|
66
68
|
{formatValue({value:defaultDecimal(props[active]),method:active,format})}
|
|
67
69
|
</Label>
|
|
68
70
|
</Pressable>
|
|
@@ -75,11 +77,7 @@ const styles = StyleSheet.create({
|
|
|
75
77
|
flexDirection : 'row',
|
|
76
78
|
alignItems : 'center',
|
|
77
79
|
},
|
|
78
|
-
anchor : {
|
|
79
|
-
paddingVertical : 10,
|
|
80
|
-
marginHorizontal : 10,
|
|
81
|
-
paddingHorizontal : 5,
|
|
82
|
-
},
|
|
80
|
+
anchor : {},
|
|
83
81
|
value : {
|
|
84
82
|
fontWeight : 'bold'
|
|
85
83
|
}
|
|
@@ -13,6 +13,7 @@ import React from "$react";
|
|
|
13
13
|
import {Menu as BottomSheetMenu} from "$ecomponents/BottomSheet"
|
|
14
14
|
import RenderType from "../RenderType";
|
|
15
15
|
import Footer from "../Footer/Footer";
|
|
16
|
+
import theme from "$theme";
|
|
16
17
|
import Table from "$ecomponents/Table";
|
|
17
18
|
|
|
18
19
|
|
|
@@ -62,41 +63,23 @@ const DatagridFactory = (Factory)=>{
|
|
|
62
63
|
}
|
|
63
64
|
return null;
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
if(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}}
|
|
81
|
-
/>
|
|
82
|
-
</View>
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return ret;
|
|
86
|
-
}
|
|
87
|
-
beforePrepareColumns(){
|
|
88
|
-
this.customFilteredColumns = {};
|
|
89
|
-
}
|
|
90
|
-
prepareColumn({filterProps,columnField,columnDef,key,field,visible,filter},filters){
|
|
91
|
-
this.customFilteredColumns = defaultObj(this.customFilteredColumns);
|
|
92
|
-
if(visible){
|
|
93
|
-
if(filter){
|
|
94
|
-
this.customFilteredColumns[columnField] = filterProps;
|
|
95
|
-
} else {
|
|
96
|
-
this.customFilteredColumns[columnField] = null;
|
|
97
|
-
}
|
|
66
|
+
renderFilterCell(props){
|
|
67
|
+
const {columnField,style} = props;
|
|
68
|
+
const filterC = this.currentFilteringColumns[columnField];
|
|
69
|
+
if(isObj(filterC)){
|
|
70
|
+
return <Filter
|
|
71
|
+
{...filterC}
|
|
72
|
+
withLabel = {false}
|
|
73
|
+
style = {[styles.filter,theme.styles.pv0,theme.styles.mv0]}
|
|
74
|
+
anchorProps ={{size:20}}
|
|
75
|
+
mode = "flat"
|
|
76
|
+
inputProps = {{
|
|
77
|
+
style : [styles.filter],
|
|
78
|
+
mode : "flat",
|
|
79
|
+
}}
|
|
80
|
+
/>
|
|
98
81
|
}
|
|
99
|
-
return
|
|
82
|
+
return null;
|
|
100
83
|
}
|
|
101
84
|
updateLayout(e){
|
|
102
85
|
if(this.state.fixedTable === false) return;
|
|
@@ -176,7 +159,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
176
159
|
})*/
|
|
177
160
|
const {visibleColumns} = this.preparedColumns;
|
|
178
161
|
const hasFooterFields = this.hasFooterFields();
|
|
179
|
-
const {columnsWidths:widths,showFilters,
|
|
162
|
+
const {columnsWidths:widths,showFilters,showFooters} = this.state;
|
|
180
163
|
let isAllRowsSelected = this.isAllRowsSelected();
|
|
181
164
|
const isLoading = this.isLoading();
|
|
182
165
|
let _progressBar = this.getProgressBar();
|
|
@@ -227,10 +210,10 @@ const DatagridFactory = (Factory)=>{
|
|
|
227
210
|
{hasFooterFields ? <Button
|
|
228
211
|
normal
|
|
229
212
|
style={styles.paginationItem}
|
|
230
|
-
onPress = {()=>{
|
|
231
|
-
icon = {
|
|
213
|
+
onPress = {()=>{showFooters?this.hideFooter():this.showFooters()} }
|
|
214
|
+
icon = {showFooters?'view-column':'view-module'}
|
|
232
215
|
>
|
|
233
|
-
{
|
|
216
|
+
{showFooters?'Masquer/Ligne des totaux':'Afficher/Ligne des totaux'}
|
|
234
217
|
</Button>:null}
|
|
235
218
|
{selectableMultiple && (<>
|
|
236
219
|
{restItems.map((item,index)=>{
|
|
@@ -287,9 +270,9 @@ const DatagridFactory = (Factory)=>{
|
|
|
287
270
|
,text : (showFilters?'Masquer/Filtres':'Afficher/Filtres')
|
|
288
271
|
} : null,
|
|
289
272
|
isMobile && hasFooterFields?{
|
|
290
|
-
onPress : ()=>{
|
|
291
|
-
,icon :
|
|
292
|
-
,text : (
|
|
273
|
+
onPress : ()=>{showFooters?this.hideFooter():this.showFooters()}
|
|
274
|
+
,icon : showFooters?'view-column':'view-module'
|
|
275
|
+
,text : (showFooters?'Masquer/Ligne des totaux':'Afficher/Ligne des totaux')
|
|
293
276
|
} : null,
|
|
294
277
|
...(selectableMultiple ? restItems : [])
|
|
295
278
|
] : visibleColumns}
|
|
@@ -340,7 +323,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
340
323
|
ref = {this.listRef}
|
|
341
324
|
hasFooters = {hasFooterFields}
|
|
342
325
|
showFilters = {showFilters}
|
|
343
|
-
showFooters = {
|
|
326
|
+
showFooters = {showFooters}
|
|
344
327
|
headerContainerProps = {{}}
|
|
345
328
|
headerCellContainerProps = {{
|
|
346
329
|
style : showFilters?{justifyContent:'flex-start'}:null
|
|
@@ -358,7 +341,9 @@ const DatagridFactory = (Factory)=>{
|
|
|
358
341
|
}}
|
|
359
342
|
data = {this.state.data}
|
|
360
343
|
renderHeaderCell={this.renderHeaderCell.bind(this)}
|
|
344
|
+
renderFilterCell={this.renderFilterCell.bind(this)}
|
|
361
345
|
renderFooterCell={this.renderFooterCell.bind(this)}
|
|
346
|
+
renderEmpty = {this.renderEmpty.bind(this)}
|
|
362
347
|
/>
|
|
363
348
|
</View>
|
|
364
349
|
}
|
|
@@ -440,8 +425,10 @@ const styles = StyleSheet.create({
|
|
|
440
425
|
maxHeight : 40,
|
|
441
426
|
height : 40,
|
|
442
427
|
width : "100%",
|
|
428
|
+
alignSelf : 'flex-start',
|
|
443
429
|
flexGrow : 1,
|
|
444
430
|
minHeight : 40,
|
|
431
|
+
backgroundColor : 'transparent'
|
|
445
432
|
},
|
|
446
433
|
layoutContent : {
|
|
447
434
|
maxWidth : '100%',
|
|
@@ -166,7 +166,7 @@ const DatePickerInput = React.forwardRef(({
|
|
|
166
166
|
onChange({dateObject:state.inputDate,date:state.inputDate,sqlDate:date,value:date})
|
|
167
167
|
}
|
|
168
168
|
},[state])
|
|
169
|
-
const labelText = render_filter ? label :
|
|
169
|
+
const labelText = withLabel === false ? null: (render_filter ? label : getLabel({ label, inputFormat:inputFormatLabel, withDateFormatInLabel }));
|
|
170
170
|
return (
|
|
171
171
|
<>
|
|
172
172
|
<TextField
|
|
@@ -13,7 +13,7 @@ import { toDateObj } from "./utils";
|
|
|
13
13
|
import TextField from "$components/TextField";
|
|
14
14
|
import PeriodActionComponent from "./PeriodAction";
|
|
15
15
|
|
|
16
|
-
export default function DateTimePickerComponent({left,isPeriodAction,withSeconds,right,format,dateFormat,timeFormat,defaultValue,onChange,testID,dateProps,disabled,readOnly,timeProps,...rest}){
|
|
16
|
+
export default function DateTimePickerComponent({left,isPeriodAction,contentProps,withSeconds,right,format,dateFormat,timeFormat,defaultValue,onChange,testID,dateProps,disabled,readOnly,timeProps,...rest}){
|
|
17
17
|
if(!isPeriodAction){
|
|
18
18
|
isPeriodAction = isNonNullString(defaultValue) && defaultValue.contains("=>");
|
|
19
19
|
}
|
|
@@ -28,6 +28,7 @@ export default function DateTimePickerComponent({left,isPeriodAction,withSeconds
|
|
|
28
28
|
}
|
|
29
29
|
dateProps = defaultObj(dateProps);
|
|
30
30
|
timeProps = defaultObj(timeProps);
|
|
31
|
+
contentProps = defaultObj(contentProps);
|
|
31
32
|
testID = defaultStr(testID,"RN_DateTimeComponent")
|
|
32
33
|
const anchorTimeProps = defaultObj(timeProps.anchorProps);
|
|
33
34
|
const timePropsContainerProps = defaultObj(timeProps.containerProps);
|
|
@@ -52,8 +53,8 @@ export default function DateTimePickerComponent({left,isPeriodAction,withSeconds
|
|
|
52
53
|
const timeDefaultValue = getTimeValue(dateObj);
|
|
53
54
|
const changedTimeArgsRef = {current:{...defaultObj(parseTime(timeDefaultValue,withSeconds))}};
|
|
54
55
|
withSeconds = defaultBool(timeProps.withSeconds,withSeconds,true);
|
|
55
|
-
|
|
56
|
-
const maxWidth =
|
|
56
|
+
const cStyle = [theme.styles.noPadding,theme.styles.noMargin];
|
|
57
|
+
const maxWidth = 110;
|
|
57
58
|
const callOnChange = ()=>{
|
|
58
59
|
if(onChange){
|
|
59
60
|
const dObj = changeDateArgsRef.current;
|
|
@@ -71,6 +72,8 @@ export default function DateTimePickerComponent({left,isPeriodAction,withSeconds
|
|
|
71
72
|
onChange(args);
|
|
72
73
|
}
|
|
73
74
|
}
|
|
75
|
+
const tInputProps = defaultObj(timeProps.inputProps);
|
|
76
|
+
const dStyle = flattenStyle([rest.style,dateProps.style]);
|
|
74
77
|
return <DateComponent
|
|
75
78
|
defaultValue = {dateObj}
|
|
76
79
|
disabled = {disabled}
|
|
@@ -79,7 +82,7 @@ export default function DateTimePickerComponent({left,isPeriodAction,withSeconds
|
|
|
79
82
|
{...rest}
|
|
80
83
|
format = {dateFormat}
|
|
81
84
|
{...dateProps}
|
|
82
|
-
style = {
|
|
85
|
+
style = {dStyle}
|
|
83
86
|
calendarIconBefore = {true}
|
|
84
87
|
onChange = {(args)=>{
|
|
85
88
|
changeDateArgsRef.current = args;
|
|
@@ -102,15 +105,17 @@ export default function DateTimePickerComponent({left,isPeriodAction,withSeconds
|
|
|
102
105
|
}}
|
|
103
106
|
withLabel = {false}
|
|
104
107
|
mode = {"flat"}
|
|
105
|
-
|
|
108
|
+
contentProps = {{style:cStyle}}
|
|
109
|
+
containerProps = {{...timePropsContainerProps,style:[{maxWidth},theme.styles.noPadding,theme.styles.noMargin,timePropsContainerProps.style]}}
|
|
106
110
|
divider = {false}
|
|
111
|
+
style = {[theme.styles.noPadding,{maxHeight:40},theme.styles.noMargin,timeProps.style,dStyle.backgroundColor && {backgroundColor:dStyle.backgroundColor}]}
|
|
107
112
|
anchorProps = {{
|
|
108
113
|
...anchorTimeProps,
|
|
109
114
|
testID:testID+"_TimeAnchor",
|
|
110
115
|
style : [theme.styles.noPadding,{borderRadius:0},theme.styles.noMargin,anchorTimeProps.style]
|
|
111
116
|
}}
|
|
112
117
|
inputProps = {{
|
|
113
|
-
...
|
|
118
|
+
...tInputProps,
|
|
114
119
|
mode : "flat",
|
|
115
120
|
}}
|
|
116
121
|
/>
|
|
@@ -44,8 +44,9 @@ export const timeToString = (value,withSeconds)=>{
|
|
|
44
44
|
return value.substring(0,5);
|
|
45
45
|
}
|
|
46
46
|
export default function TimePickerComponent (props){
|
|
47
|
-
let {right:customRight,upper,anchorProps,dialogProps,withLabel,containerProps,mode,onChange,withSeconds,cancelLabel,confirmLabel,label,text,upperCase,defaultValue,disabled,editable,withModal,readOnly,...rest} = props;
|
|
47
|
+
let {right:customRight,upper,anchorProps,dialogProps,withLabel,inputProps,containerProps,mode,onChange,withSeconds,cancelLabel,confirmLabel,label,text,upperCase,defaultValue,disabled,editable,withModal,readOnly,...rest} = props;
|
|
48
48
|
rest = defaultObj(rest);
|
|
49
|
+
inputProps = defaultObj(inputProps);
|
|
49
50
|
const isEditable = disabled !== true && readOnly !== true && editable !== false?true : false;
|
|
50
51
|
withModal = defaultBool(withModal,true);
|
|
51
52
|
if(!isEditable){
|
|
@@ -110,6 +111,7 @@ export default function TimePickerComponent (props){
|
|
|
110
111
|
if(!disabled){
|
|
111
112
|
containerProps.style = [containerProps.style,{opacity:1}]
|
|
112
113
|
}
|
|
114
|
+
const iContainerProps = defaultObj(inputProps.containerProps);
|
|
113
115
|
return <>
|
|
114
116
|
<TouchableRipple {...containerProps}
|
|
115
117
|
disabled = {!isEditable}
|
|
@@ -120,6 +122,8 @@ export default function TimePickerComponent (props){
|
|
|
120
122
|
<TextField
|
|
121
123
|
mode = {mode||theme.textFieldMode}
|
|
122
124
|
{...rest}
|
|
125
|
+
{...inputProps}
|
|
126
|
+
containerProps = {{...iContainerProps,style:[containerProps.style,iContainerProps.style]}}
|
|
123
127
|
label = {label}
|
|
124
128
|
right = {right}
|
|
125
129
|
disabled = {disabled}
|
|
@@ -30,6 +30,7 @@ export default function showConfirm (p,cb){
|
|
|
30
30
|
buttons,
|
|
31
31
|
messageProps,
|
|
32
32
|
inputProps,
|
|
33
|
+
format,
|
|
33
34
|
placeholder,
|
|
34
35
|
children,
|
|
35
36
|
withInputField,
|
|
@@ -116,8 +117,11 @@ export default function showConfirm (p,cb){
|
|
|
116
117
|
{messageContent}
|
|
117
118
|
{withInputField !== false ? <Component
|
|
118
119
|
type = {type}
|
|
120
|
+
enableCopy = {false}
|
|
119
121
|
defaultValue = {defaultValue}
|
|
120
122
|
placeholder = {placeholder}
|
|
123
|
+
affix = {false}
|
|
124
|
+
format = {format}
|
|
121
125
|
{...inputProps}
|
|
122
126
|
ref = {inputRef}
|
|
123
127
|
onChange = {(args)=>{
|
|
@@ -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,
|
|
@@ -7,7 +7,7 @@ import {MENU_ICON} from "$ecomponents/Icon";
|
|
|
7
7
|
import theme,{Colors} from "$theme";
|
|
8
8
|
import Group from "./GroupComponent";
|
|
9
9
|
import Portal from "$ecomponents/Portal";
|
|
10
|
-
import
|
|
10
|
+
import {isAllowedFromStr} from "$cauth/perms";
|
|
11
11
|
|
|
12
12
|
const FabGroupComponent = React.forwardRef((props,innerRef)=>{
|
|
13
13
|
let {openedIcon,screenName,display:customDisplay,primary,actionMutator,secondary,onOpen,prepareActions,fabStyle,open:customOpen,onClose,onStateChange:customOnStateChange,closedIcon,color,actions:customActions,children,...customRest} = props;
|
|
@@ -63,7 +63,7 @@ const FabGroupComponent = React.forwardRef((props,innerRef)=>{
|
|
|
63
63
|
if(!isObj(a) || !isNonNullString(a.label)) return null;
|
|
64
64
|
const {perm,isAllowed,primary,secondary,...restItem} = a;
|
|
65
65
|
if(typeof isAllowed =='function' && isAllowed() === false) return null;
|
|
66
|
-
if(isNonNullString(perm) && !
|
|
66
|
+
if(isNonNullString(perm) && !isAllowedFromStr(perm)) return false;
|
|
67
67
|
if(primary){
|
|
68
68
|
restItem.style = StyleSheet.flatten([restItem.style,{color:theme.colors.primaryText,backgroundColor:theme.colors.primary}])
|
|
69
69
|
} else if(secondary){
|
|
@@ -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
|
-
|
|
294
|
-
if(isFunction(success)){
|
|
302
|
+
if(isFunction(success)){
|
|
295
303
|
success(data.start+"=>"+data.end);
|
|
296
304
|
}
|
|
297
305
|
DialogProvider.close();
|
|
@@ -324,7 +332,7 @@ export default class Filter extends AppComponent {
|
|
|
324
332
|
diff = DateLib.currentMonthDaysLimits(currentDate);
|
|
325
333
|
break;
|
|
326
334
|
case "$week":
|
|
327
|
-
diff = DateLib.currentWeekDaysLimits(currentDate)
|
|
335
|
+
diff = DateLib.currentWeekDaysLimits(currentDate);
|
|
328
336
|
break;
|
|
329
337
|
case "$prevWeek":
|
|
330
338
|
diff = DateLib.previousWeekDaysLimits(currentDate)
|
|
@@ -382,8 +390,8 @@ export default class Filter extends AppComponent {
|
|
|
382
390
|
field,
|
|
383
391
|
style,
|
|
384
392
|
anchorProps,
|
|
385
|
-
mode,
|
|
386
|
-
inputProps,
|
|
393
|
+
//mode,
|
|
394
|
+
//inputProps,
|
|
387
395
|
moreOptions,
|
|
388
396
|
isLoading,
|
|
389
397
|
searchIconTooltip,
|
|
@@ -471,6 +479,7 @@ export default class Filter extends AppComponent {
|
|
|
471
479
|
}
|
|
472
480
|
anchorProps = defaultObj(anchorProps);
|
|
473
481
|
rest.anchorProps = anchorProps;
|
|
482
|
+
rest.withLabel = withLabel;
|
|
474
483
|
rest.pointerEvents = "auto";
|
|
475
484
|
rest.right = isLoading ? <ActivityIndicator color={theme.colors.secondaryOnSurface} animating/> :<>
|
|
476
485
|
<Menu
|
|
@@ -556,7 +565,7 @@ export default class Filter extends AppComponent {
|
|
|
556
565
|
if(ignoreDefaultValue) {
|
|
557
566
|
rest.isPeriodAction = true;
|
|
558
567
|
}
|
|
559
|
-
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])}>
|
|
560
569
|
<Component
|
|
561
570
|
{...rest}
|
|
562
571
|
readOnly = {ignoreDefaultValue}
|
|
@@ -0,0 +1,91 @@
|
|
|
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 { ScrollView,StyleSheet,View,useWindowDimensions} from "react-native";
|
|
6
|
+
import React from "$react";
|
|
7
|
+
import {defaultStr,defaultObj,isObj,isNumber} from "$utils";
|
|
8
|
+
import Portal from "$ecomponents/Portal";
|
|
9
|
+
import {isMobileNative,isTouchDevice} from "$platform";
|
|
10
|
+
|
|
11
|
+
const isNative = isMobileNative() || isTouchDevice();
|
|
12
|
+
const AbsoluteScrollView = React.forwardRef(({testID,contentProps,listRef,containerProps,...props},ref)=>{
|
|
13
|
+
if(isNative) return null;
|
|
14
|
+
containerProps = defaultObj(containerProps);
|
|
15
|
+
contentProps = defaultObj(contentProps);
|
|
16
|
+
const win = useWindowDimensions();
|
|
17
|
+
const scrollViewRef = React.useRef(null);
|
|
18
|
+
testID = defaultStr(testID,"RN_TableAbsoluteScrollViewComponent");
|
|
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
|
+
}
|
|
35
|
+
React.setRef(ref,{
|
|
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
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return toggleVisible();
|
|
47
|
+
},
|
|
48
|
+
scrollViewRef
|
|
49
|
+
});
|
|
50
|
+
React.useEffect(()=>{
|
|
51
|
+
return ()=>{
|
|
52
|
+
React.setRef(ref,null);
|
|
53
|
+
}
|
|
54
|
+
},[]);
|
|
55
|
+
React.useEffect(()=>{
|
|
56
|
+
toggleVisible();
|
|
57
|
+
},[styles])
|
|
58
|
+
return <Portal>
|
|
59
|
+
{<View testID={testID+"_Containter"} {...containerProps} style={[mainStyles.container,containerProps.style,styles.container,{left:win.width-10},!visible &&{display:'none',width:0,opacity:0}]}>
|
|
60
|
+
<ScrollView
|
|
61
|
+
{...props}
|
|
62
|
+
ref = {scrollViewRef}
|
|
63
|
+
testID={testID}
|
|
64
|
+
contentContainerStyle = {[props.contentContainerStyle,mainStyles.contentContainer,styles.containerContainer]}
|
|
65
|
+
vertical
|
|
66
|
+
>
|
|
67
|
+
<View
|
|
68
|
+
testID={testID+"Content"}
|
|
69
|
+
{...contentProps}
|
|
70
|
+
style={[mainStyles.content,contentProps.style,styles.content]}
|
|
71
|
+
/>
|
|
72
|
+
</ScrollView>
|
|
73
|
+
</View>}
|
|
74
|
+
</Portal>
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export default AbsoluteScrollView;
|
|
78
|
+
|
|
79
|
+
const mainStyles = StyleSheet.create({
|
|
80
|
+
container : {
|
|
81
|
+
...StyleSheet.absoluteFill,
|
|
82
|
+
width : 10,
|
|
83
|
+
},
|
|
84
|
+
content : {
|
|
85
|
+
width:10,
|
|
86
|
+
},
|
|
87
|
+
contentContainer : {
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
AbsoluteScrollView.displayName = "TableVerticalScrollView";
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {FlashList
|
|
1
|
+
import {FlashList} from "$ecomponents/List";
|
|
2
2
|
import View from "$ecomponents/View";
|
|
3
|
-
import {defaultObj,defaultStr,debounce,
|
|
3
|
+
import {defaultObj,defaultStr,debounce,defaultNumber,defaultVal} from "$utils";
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
5
|
export const DEFAULT_COLUMN_WIDTH = 60;
|
|
6
6
|
import React from "$react";
|
|
7
7
|
import Label from "$ecomponents/Label";
|
|
8
|
-
import { StyleSheet,ScrollView,Dimensions} from "react-native";
|
|
8
|
+
import { StyleSheet,View as RNView,ScrollView,Dimensions} from "react-native";
|
|
9
9
|
import { getRowStyle } from "$ecomponents/Datagrid/utils";
|
|
10
10
|
import {isMobileNative} from "$cplatform";
|
|
11
11
|
import theme from "$theme";
|
|
12
|
+
import AbsoluteScrollView from "./AbsoluteScrollView";
|
|
13
|
+
|
|
12
14
|
const isSCrollingRef = React.createRef();
|
|
13
15
|
const scrollLists = (opts,refs)=>{
|
|
14
16
|
refs.map((ref)=>{
|
|
@@ -18,19 +20,29 @@ const scrollLists = (opts,refs)=>{
|
|
|
18
20
|
});
|
|
19
21
|
isSCrollingRef.current = false;
|
|
20
22
|
}
|
|
21
|
-
const getOnScrollCb = (refs)=>{
|
|
23
|
+
const getOnScrollCb = (refs,pos,cb2)=>{
|
|
22
24
|
const cb = (args)=>{
|
|
23
25
|
if(isSCrollingRef.current) return;
|
|
24
26
|
if(!isObj(args) || !args.nativeEvent) {
|
|
25
27
|
isSCrollingRef.current = false;
|
|
26
28
|
}
|
|
27
29
|
isSCrollingRef.current = true;
|
|
28
|
-
|
|
30
|
+
if(typeof pos =='function'){
|
|
31
|
+
pos(args);
|
|
32
|
+
isSCrollingRef.current = false;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
pos = pos && (pos =='x' || pos=='y')? pos : "x";
|
|
36
|
+
const a = {[pos]:args.nativeEvent.contentOffset?.[pos]};
|
|
37
|
+
scrollLists(a,refs);
|
|
38
|
+
if(typeof cb2 == 'function'){
|
|
39
|
+
cb2(args);
|
|
40
|
+
}
|
|
29
41
|
};
|
|
30
42
|
return isMobileNative()? cb : debounce(cb,200);
|
|
31
43
|
}
|
|
32
44
|
|
|
33
|
-
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)=>{
|
|
45
|
+
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)=>{
|
|
34
46
|
containerProps = defaultObj(containerProps);
|
|
35
47
|
testID = defaultStr(testID,"RN_TableComponent");
|
|
36
48
|
cellContainerProps = defaultObj(cellContainerProps);
|
|
@@ -41,13 +53,14 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
41
53
|
const getRowProps = typeof rowProps ==='function'? rowProps : undefined;
|
|
42
54
|
let rowProps = isObj(customRowProps)? customRowProps:{};
|
|
43
55
|
const prepareState = React.useCallback(()=>{
|
|
44
|
-
const cols = {},headers = {},footers = {},visibleColumns = [];
|
|
56
|
+
const cols = {},headers = {},footers = {},filters = {},visibleColumns = [];
|
|
45
57
|
let hasFooters = false;
|
|
46
58
|
columnProps = defaultObj(columnProps);
|
|
47
59
|
let columnIndex = 0;
|
|
48
60
|
const widths = defaultObj(columnsWidths,colsWidths);
|
|
49
61
|
headerCellContainerProps = defaultObj(headerCellContainerProps);
|
|
50
62
|
footerCellContainerProps = defaultObj(footerCellContainerProps);
|
|
63
|
+
filterCellContainerProps = defaultObj(filterCellContainerProps);
|
|
51
64
|
Object.map(columns,(columnDef,field)=>{
|
|
52
65
|
if(!isObj(columnDef) /*|| columnDef.visible === false*/) return;
|
|
53
66
|
const columnField = defaultStr(columnDef.field,field);
|
|
@@ -73,6 +86,12 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
73
86
|
headers[columnField] = <View testID={testID+"_HeaderCell_"+columnField} {...headerCellContainerProps} {...hContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,headerCellContainerProps.style,hContainerProps.style,style]}>
|
|
74
87
|
<Label textBold primary>{content}</Label>
|
|
75
88
|
</View>;
|
|
89
|
+
if(typeof renderFilterCell =='function'){
|
|
90
|
+
const filterCell = renderFilterCell(colArgs);
|
|
91
|
+
filters[columnField] = <View testID={testID+"_Filter_Cell_"+columnField} {...filterCellContainerProps} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,styles.filterCell,filterCellContainerProps.style,style]}>
|
|
92
|
+
{React.isValidElement(filterCell)? filterCell : null}
|
|
93
|
+
</View>
|
|
94
|
+
}
|
|
76
95
|
if(typeof renderFooterCell ==='function') {
|
|
77
96
|
const footerProps = {...colArgs,containerProps:{}};
|
|
78
97
|
let cellFooter = renderFooterCell(footerProps);
|
|
@@ -87,7 +106,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
87
106
|
if(!hasFooters && cellFooter){
|
|
88
107
|
hasFooters = true;
|
|
89
108
|
}
|
|
90
|
-
footers[columnField] = <View testID={testID+"_Footer_Cell_"+columnField}
|
|
109
|
+
footers[columnField] = <View testID={testID+"_Footer_Cell_"+columnField} key={columnField} style={[styles.headerItem,styles.headerItemOrCell,footerCellContainerProps.style,style]}>
|
|
91
110
|
<Label primary children={cellFooter}/>
|
|
92
111
|
</View>
|
|
93
112
|
}
|
|
@@ -104,7 +123,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
104
123
|
}
|
|
105
124
|
columnIndex++;
|
|
106
125
|
});
|
|
107
|
-
return {columns:cols,visibleColumns,headers,hasFooters,footers};
|
|
126
|
+
return {columns:cols,visibleColumns,headers,hasFooters,footers,filters};
|
|
108
127
|
},[columns,data]);
|
|
109
128
|
const [state,setState] = React.useState({
|
|
110
129
|
headers : {},
|
|
@@ -117,11 +136,13 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
117
136
|
React.useEffect(()=>{
|
|
118
137
|
setState({...state,...prepareState()});
|
|
119
138
|
},[data,columns]);
|
|
120
|
-
const
|
|
139
|
+
const emptyData = typeof renderEmpty =='function' && !Object.size(data,true)? renderEmpty() : null;
|
|
140
|
+
const hasEmptyData = emptyData && React.isValidElement(emptyData);
|
|
141
|
+
const {visibleColumns,columns:cols,headers,footers,filters} = state;
|
|
121
142
|
headerContainerProps = defaultObj(headerContainerProps);
|
|
122
143
|
footerContainerProps = defaultObj(footerContainerProps);
|
|
123
144
|
let hProps = typeof headerProps =='function'? hProps({columns:col,visibleColumns}) : {};
|
|
124
|
-
const h = [],f = [];
|
|
145
|
+
const h = [],f = [],fFilters = [];
|
|
125
146
|
let totalWidths = 0;
|
|
126
147
|
visibleColumns.map((i)=>{
|
|
127
148
|
if(!isObj(cols[i])) return;
|
|
@@ -130,6 +151,9 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
130
151
|
if(showFooters && state.hasFooters){
|
|
131
152
|
f.push(footers[i]);
|
|
132
153
|
}
|
|
154
|
+
if(showFilters && filters[i]){
|
|
155
|
+
fFilters.push(filters[i]);
|
|
156
|
+
}
|
|
133
157
|
});
|
|
134
158
|
const scrollContentContainerStyle = {flex:1,width:listWidth,minWidth:totalWidths,height:'100%'};
|
|
135
159
|
const scrollEventThrottle = isMobileNative()?200:50;
|
|
@@ -138,7 +162,7 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
138
162
|
scrollEventThrottle,
|
|
139
163
|
horizontal : true,
|
|
140
164
|
...scrollViewProps,
|
|
141
|
-
style : [
|
|
165
|
+
style : [scrollViewProps.style],
|
|
142
166
|
contentContainerStyle : [styles.scrollView,scrollViewProps.contentContainerStyle,scrollViewFlexGrow,scrollContentContainerStyle]
|
|
143
167
|
}
|
|
144
168
|
const listWidth = '100%';
|
|
@@ -175,13 +199,19 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
175
199
|
const hContent = h.length ? <View testID={testID+"_Header"}{...hProps} {...headerContainerProps} style={[styles.header,headerContainerProps.style,hProps.style,f.length]}>
|
|
176
200
|
{h}
|
|
177
201
|
</View> : null,
|
|
178
|
-
|
|
202
|
+
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]}>
|
|
179
203
|
{f}
|
|
180
|
-
</View> : null
|
|
204
|
+
</View> : null,
|
|
205
|
+
filtersContent = fFilters.length ? <View testID={testID+"_Filters"} style={[styles.header,styles.footers,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
|
|
206
|
+
{fFilters}
|
|
207
|
+
</View> : null
|
|
208
|
+
|
|
209
|
+
const absoluteScrollViewRefCanScroll = React.useRef(true);
|
|
181
210
|
React.setRef(tableRef,context);
|
|
182
211
|
const cStyle = {width:listWidth}
|
|
183
|
-
|
|
184
|
-
|
|
212
|
+
const absoluteScrollViewRef = React.useRef(null);
|
|
213
|
+
return <View testID= {testID+"_Container"} {...containerProps} style={[styles.container,{alignItems:'stretch'},containerProps.style,theme.styles.pl0,theme.styles.pr0]}>
|
|
214
|
+
<RNView style={[cStyle]} testID={testID+"_Headers_ScrollViewContainer"}>
|
|
185
215
|
<ScrollView
|
|
186
216
|
testID={testID+"_HeaderScrollView"}
|
|
187
217
|
{...headerScrollViewProps}
|
|
@@ -191,15 +221,49 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
191
221
|
onScroll = {getOnScrollCb([scrollViewRef,footerScrollViewRef])}
|
|
192
222
|
showsHorizontalScrollIndicator
|
|
193
223
|
>
|
|
194
|
-
{
|
|
224
|
+
<View testID={testID+"Header2FootersWrapper"} style={[theme.styles.w100]}>
|
|
225
|
+
{hContent}
|
|
226
|
+
{filtersContent}
|
|
227
|
+
{fContent}
|
|
228
|
+
</View>
|
|
195
229
|
</ScrollView>
|
|
196
|
-
</
|
|
197
|
-
|
|
230
|
+
</RNView>
|
|
231
|
+
{hasEmptyData ? <View testID={testID+"_Empty"} style={styles.hasNotData}>
|
|
232
|
+
{emptyData}
|
|
233
|
+
</View> : <ScrollView {...scrollViewProps} scrollEventThrottle = {scrollEventThrottle} horizontal contentContainerStyle={[scrollContentContainerStyle,scrollViewProps.contentContainerStyle]} showsVerticalScrollIndicator={false}
|
|
234
|
+
onScroll = {getOnScrollCb([headerScrollViewRef,footerScrollViewRef],null,(args)=>{
|
|
235
|
+
const nativeEvent = args.nativeEvent;
|
|
236
|
+
if(absoluteScrollViewRef.current && absoluteScrollViewRef.current.checkVisibility){
|
|
237
|
+
absoluteScrollViewRef.current.checkVisibility(nativeEvent);
|
|
238
|
+
}
|
|
239
|
+
})} ref={scrollViewRef} testID={testID+"_ScrollView"}>
|
|
198
240
|
<FlashList
|
|
199
241
|
containerProps = {{style:[cStyle]}}
|
|
200
242
|
//prepareItems = {Array.isArray(items)? false : undefined}
|
|
201
243
|
estimatedItemSize = {200}
|
|
202
244
|
{...props}
|
|
245
|
+
onContentSizeChange = {(width,height)=>{
|
|
246
|
+
if(props.onContentSizeChange){
|
|
247
|
+
props.onContentSizeChange(width,height);
|
|
248
|
+
}
|
|
249
|
+
if(!absoluteScrollViewRef.current) return;
|
|
250
|
+
absoluteScrollViewRef.current.setStyles({
|
|
251
|
+
content : {height,width}
|
|
252
|
+
});
|
|
253
|
+
}}
|
|
254
|
+
onLayout = {(args)=>{
|
|
255
|
+
if(props.onLayout){
|
|
256
|
+
props.onLayout(args);
|
|
257
|
+
}
|
|
258
|
+
if(!absoluteScrollViewRef.current) return;
|
|
259
|
+
const {nativeEvent:{layout}}=args;
|
|
260
|
+
const top = defaultNumber(layout.top,layout.y);
|
|
261
|
+
const height = layout.height;
|
|
262
|
+
absoluteScrollViewRef.current.setStyles({
|
|
263
|
+
container : {top,height},
|
|
264
|
+
contentContainer : {height},
|
|
265
|
+
});
|
|
266
|
+
}}
|
|
203
267
|
ref = {listRef}
|
|
204
268
|
numberOfLines = {1}
|
|
205
269
|
responsive = {false}
|
|
@@ -209,6 +273,18 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
209
273
|
style = {[styles.datagrid,{width:listWidth,minWidth:totalWidths}]}
|
|
210
274
|
keyExtractor = {typeof getRowKey =='function'? getRowKey : React.getKey}
|
|
211
275
|
//stickyHeaderIndices={[0]}
|
|
276
|
+
onScroll = {getOnScrollCb([absoluteScrollViewRef],(args)=>{
|
|
277
|
+
if(!absoluteScrollViewRef.current) return;
|
|
278
|
+
const offset = args?.nativeEvent?.contentOffset.y;
|
|
279
|
+
const scrollViewRef = absoluteScrollViewRef.current?.scrollViewRef;
|
|
280
|
+
if(typeof offset =='number' && scrollViewRef.current && scrollViewRef.current.scrollTo){
|
|
281
|
+
absoluteScrollViewRefCanScroll.current = false;
|
|
282
|
+
scrollViewRef.current.scrollTo({animated:false,y:offset});
|
|
283
|
+
setTimeout(()=>{
|
|
284
|
+
absoluteScrollViewRefCanScroll.current = true;
|
|
285
|
+
},500);
|
|
286
|
+
}
|
|
287
|
+
})}
|
|
212
288
|
renderItem = {(arg)=>{
|
|
213
289
|
const item = arg.item, data = arg.item,allData=Array.isArray(item.items)? item.items : data;
|
|
214
290
|
const cells = visibleColumns.map((i,index)=>{
|
|
@@ -237,11 +313,23 @@ const TableComponent = React.forwardRef(({containerProps,isRowSelected,headerScr
|
|
|
237
313
|
</View>;
|
|
238
314
|
}}
|
|
239
315
|
/>
|
|
240
|
-
|
|
316
|
+
<AbsoluteScrollView
|
|
317
|
+
ref={absoluteScrollViewRef}
|
|
318
|
+
listRef = {listRef}
|
|
319
|
+
scrollEventThrottle = {scrollEventThrottle}
|
|
320
|
+
onScroll = {(args)=>{
|
|
321
|
+
if(!absoluteScrollViewRefCanScroll.current) return;
|
|
322
|
+
const offset = args?.nativeEvent?.contentOffset.y;
|
|
323
|
+
if(typeof offset =='number' && listRef.current && listRef.current.scrollToOffset){
|
|
324
|
+
listRef.current.scrollToOffset({animated:true,offset});
|
|
325
|
+
}
|
|
326
|
+
}}
|
|
327
|
+
/>
|
|
328
|
+
</ScrollView>}
|
|
329
|
+
|
|
241
330
|
</View>
|
|
242
331
|
});
|
|
243
332
|
|
|
244
|
-
|
|
245
333
|
const ColumnType = PropTypes.shape({
|
|
246
334
|
field : PropTypes.string,
|
|
247
335
|
label : PropTypes.text,
|
|
@@ -299,6 +387,15 @@ const styles = StyleSheet.create({
|
|
|
299
387
|
paddingHorizontal:5,
|
|
300
388
|
paddingVertical : 0,
|
|
301
389
|
},
|
|
390
|
+
filterCell : {
|
|
391
|
+
alignSelf : "flex-start",
|
|
392
|
+
textAlign : "left",
|
|
393
|
+
paddingHorizontal : 2,
|
|
394
|
+
paddingVertical : 0,
|
|
395
|
+
marginVertical : 0,
|
|
396
|
+
marginHorizontal : 0,
|
|
397
|
+
justifyContent : 'flex-start',
|
|
398
|
+
},
|
|
302
399
|
headerItem: {
|
|
303
400
|
minHeight: 30,
|
|
304
401
|
},
|
|
@@ -318,14 +415,22 @@ const styles = StyleSheet.create({
|
|
|
318
415
|
marginHorizontal : 0,
|
|
319
416
|
marginVertical : 0,
|
|
320
417
|
},
|
|
418
|
+
hasNotData : {
|
|
419
|
+
flexDirection : 'column',
|
|
420
|
+
width : '100%',
|
|
421
|
+
justifyContent : 'center',
|
|
422
|
+
alignItems : 'center'
|
|
423
|
+
}
|
|
321
424
|
})
|
|
322
425
|
TableComponent.popTypes = {
|
|
323
426
|
containerProps : PropTypes.object,
|
|
324
427
|
renderHeaderCell : PropTypes.func,
|
|
428
|
+
renderFilterCell : PropTypes.func,
|
|
325
429
|
renderRow : PropTypes.func,
|
|
326
430
|
renderCell : PropTypes.func,
|
|
327
431
|
renderFooterCell : PropTypes.func,///la fonction appelée pour le rendu des entêtes du footer
|
|
328
432
|
footerCellContainerProps : PropTypes.object,
|
|
433
|
+
filterCellContainerProps : PropTypes.object,
|
|
329
434
|
footerContainerProps : PropTypes.object,
|
|
330
435
|
showFilters : PropTypes.bool,
|
|
331
436
|
showFooters : PropTypes.bool,
|
|
@@ -364,19 +469,6 @@ TableComponent.popTypes = {
|
|
|
364
469
|
footerScrollViewProps : PropTypes.object,
|
|
365
470
|
}
|
|
366
471
|
|
|
367
|
-
const ScrollViewCustom = React.forwardRef((props,ref)=>{
|
|
368
|
-
const {testID,onScroll,style,handle} = props;
|
|
369
|
-
const context = {};
|
|
370
|
-
React.setRef(ref,context);
|
|
371
|
-
return <View
|
|
372
|
-
{...props}
|
|
373
|
-
ref = {ref}
|
|
374
|
-
style = {[styles.scrollViewCustom,style,{backgroundColor:theme.colors.primary}]}
|
|
375
|
-
onScroll={onScroll}
|
|
376
|
-
testID={(testID||'RN_TableComponentScrollViewCustom')}
|
|
377
|
-
/>
|
|
378
|
-
});
|
|
379
|
-
ScrollViewCustom.displayName = "TableComponentScrollViewCustom";
|
|
380
472
|
|
|
381
473
|
TableComponent.displayName = "TableComponent";
|
|
382
474
|
|
|
@@ -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);
|