@fto-consult/expo-ui 3.4.0 → 3.6.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.
- package/package.json +3 -3
- package/src/components/{AutoResizer/index.js → AutoSizer/AutoResizer.js} +0 -0
- package/src/components/AutoSizer/Vertical.js +88 -0
- package/src/components/AutoSizer/index.js +3 -0
- package/src/components/Datagrid/Accordion/index.js +1 -3
- package/src/components/Datagrid/Common/Common.js +6 -0
- package/src/components/Datagrid/SWRDatagrid.js +2 -0
- package/src/components/Datagrid/Table/index.js +5 -10
- package/src/components/ScrollView/index copy.js +38 -0
- package/src/components/ScrollView/index.back.js +84 -0
- package/src/components/ScrollView/index.js +24 -66
- package/src/components/ScrollView/index.withWeb.js +83 -0
- package/src/components/Table/AbsoluteScrollView.js +13 -3
- package/src/components/Table/{List.js → List/List.js} +1 -1
- package/src/components/Table/{List.native.js → List/List.native.js} +0 -0
- package/src/components/Table/List/index.js +15 -0
- package/src/components/Table/index.js +1 -2
- package/src/layouts/Screen/TableData.js +7 -3
- package/src/layouts/Screen/utils.js +5 -2
- package/src/screens/Help/About.js +38 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@emotion/native": "^11.10.0",
|
|
62
62
|
"@expo/html-elements": "^0.2.0",
|
|
63
63
|
"@expo/vector-icons": "^13.0.0",
|
|
64
|
-
"@fto-consult/common": "^2.15.
|
|
64
|
+
"@fto-consult/common": "^2.15.4",
|
|
65
65
|
"@gorhom/portal": "^1.0.14",
|
|
66
66
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
67
67
|
"@react-native-community/datetimepicker": "6.5.2",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"react-native-svg": "13.4.0",
|
|
106
106
|
"react-native-web": "~0.18.7",
|
|
107
107
|
"react-native-webview": "11.23.1",
|
|
108
|
-
"react-virtuoso": "^4.0.
|
|
108
|
+
"react-virtuoso": "^4.0.6",
|
|
109
109
|
"sharp-cli": "^2.1.0",
|
|
110
110
|
"tippy.js": "^6.3.7",
|
|
111
111
|
"use-event-callback": "^0.1.0",
|
|
File without changes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from '$react';
|
|
2
|
+
import { Dimensions} from 'react-native';
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import View from "$ecomponents/View";
|
|
5
|
+
import theme from "$theme";
|
|
6
|
+
import {defaultStr,defaultObj,defaultNumber} from "$utils";
|
|
7
|
+
import APP from "$capp/instance";
|
|
8
|
+
import ActivityIndicator from "$ecomponents/ActivityIndicator";
|
|
9
|
+
import {isWeb} from "$cplatform";
|
|
10
|
+
|
|
11
|
+
/***
|
|
12
|
+
* ce composant a pour but de définir la taille d'un contenu en se basant sur sa positin top, de manière à ce que, le contentu du composant fit
|
|
13
|
+
* le reste de la taille de la page, avec comme valeur de la props minHeight
|
|
14
|
+
*/
|
|
15
|
+
const AutoSizerVerticalComponent = React.forwardRef(({onLayout,isScrollView,withActivityIndicator,testID,withPadding,maxHeight,minHeight,style,children:cChildren,...rest},ref) => {
|
|
16
|
+
testID = defaultStr(testID,'RN_AutoSizerVerticalComponent');
|
|
17
|
+
const hasUpdateLayoutRef = React.useRef(false);
|
|
18
|
+
const layoutRef = React.useRef(null);
|
|
19
|
+
const [layout,setLayout] = React.useState(Dimensions.get("window"));
|
|
20
|
+
const {height,width} = layout;
|
|
21
|
+
const hasInitializedRef = React.useRef(false);
|
|
22
|
+
const children = React.useStableMemo(()=>cChildren,[cChildren]);
|
|
23
|
+
const updateLayout = ()=>{
|
|
24
|
+
return new Promise((resolve)=>{
|
|
25
|
+
hasUpdateLayoutRef.current = true;
|
|
26
|
+
if(layoutRef.current && layoutRef.current.measureInWindow){
|
|
27
|
+
layoutRef.current.measureInWindow((x, y, width, height) => {
|
|
28
|
+
const r = {...Dimensions.get("window"),layout:{ x, y, width, height }};
|
|
29
|
+
setLayout(r);
|
|
30
|
+
hasInitializedRef.current = true;
|
|
31
|
+
resolve(r);
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
setLayout(Dimensions.get("window"))
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
React.setRef(ref,{
|
|
39
|
+
updateLayout,
|
|
40
|
+
layoutRef,
|
|
41
|
+
ref : layoutRef
|
|
42
|
+
});
|
|
43
|
+
React.useEffect(()=>{
|
|
44
|
+
const onResizePage = ()=>{
|
|
45
|
+
setTimeout(()=>{
|
|
46
|
+
updateLayout();
|
|
47
|
+
},300);
|
|
48
|
+
}
|
|
49
|
+
APP.on(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
50
|
+
return ()=>{
|
|
51
|
+
APP.off(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
52
|
+
React.setRef(ref,null);
|
|
53
|
+
}
|
|
54
|
+
},[]);
|
|
55
|
+
const hasUpdateLayout = hasUpdateLayoutRef.current;
|
|
56
|
+
const cStyle ={width:'100%',maxHeight:Math.max(height-100,250)};
|
|
57
|
+
const contentLayout = defaultObj(layout.layout);
|
|
58
|
+
cStyle.minHeight = Math.min(Math.max(layout.height-defaultNumber(contentLayout.y),minHeight && minHeight ||250));
|
|
59
|
+
const cMaxHeight = layout.height-defaultNumber(contentLayout.y);
|
|
60
|
+
if(cMaxHeight>=250){
|
|
61
|
+
cStyle.maxHeight = cMaxHeight;
|
|
62
|
+
}
|
|
63
|
+
if(withPadding !== false){
|
|
64
|
+
cStyle.paddingBottom = 50;
|
|
65
|
+
}
|
|
66
|
+
const fStyle = !hasUpdateLayout && withActivityIndicator !== false && {flex:1,flexDirection:'column',maxHeight:cStyle.maxHeight,maxWidth : Math.max(layout.width-defaultNumber(contentLayout.x)),justifyContent:'center',alignItems:'center'} || {};
|
|
67
|
+
return <View ref={layoutRef}
|
|
68
|
+
onLayout={(a,b,c)=>{
|
|
69
|
+
if(onLayout && onLayout(a,b,c) === false) return;
|
|
70
|
+
if(!hasInitializedRef.current){
|
|
71
|
+
updateLayout();
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
{...rest}
|
|
75
|
+
style={[theme.styles.w100,cStyle,style,fStyle,maxHeight && {maxHeight}, minHeight && {minHeight}]} testID={testID+"_ScrollViewContainer"}>
|
|
76
|
+
{hasUpdateLayout || withActivityIndicator === false ?children : <ActivityIndicator size={'large'}/>}
|
|
77
|
+
</View>
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
AutoSizerVerticalComponent.displayName = "AutoSizerVerticalComponent";
|
|
81
|
+
export default AutoSizerVerticalComponent;
|
|
82
|
+
|
|
83
|
+
AutoSizerVerticalComponent.propTypes = {
|
|
84
|
+
...defaultObj(View.propTypes),
|
|
85
|
+
withActivityIndicator : PropTypes.bool,//si l'on utilisera l'activity indicator pour le chargement du contentu
|
|
86
|
+
maxHeight : PropTypes.number,
|
|
87
|
+
minHeight : PropTypes.number,
|
|
88
|
+
}
|
|
@@ -406,7 +406,6 @@ const DatagridFactory = (Factory)=>{
|
|
|
406
406
|
}
|
|
407
407
|
]
|
|
408
408
|
}
|
|
409
|
-
const maxHeight = this.getMaxListHeight();
|
|
410
409
|
const isLoading = this.isLoading();
|
|
411
410
|
const _progressBar = this.getProgressBar();
|
|
412
411
|
const pointerEvents = this.getPointerEvents();
|
|
@@ -524,7 +523,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
524
523
|
</ScrollView>
|
|
525
524
|
</View>
|
|
526
525
|
return <View testID={testID+"_Container"} pointerEvents={pointerEvents} style={[styles.container]} collapsable={false}>
|
|
527
|
-
{ <View testID={testID+"_ContentContainer"}
|
|
526
|
+
{ <View testID={testID+"_ContentContainer"}>
|
|
528
527
|
<View testID={testID+"_AccordionHeader"} style={[styles.accordionHeader]} ref={this.layoutRef} onLayout={this.updateLayout.bind(this)}>
|
|
529
528
|
{this.props.showActions !== false ? <DatagridActions
|
|
530
529
|
testID={testID+"_Actions"}
|
|
@@ -564,7 +563,6 @@ const DatagridFactory = (Factory)=>{
|
|
|
564
563
|
prepareItems = {false}
|
|
565
564
|
{...rest}
|
|
566
565
|
{...accordionProps}
|
|
567
|
-
containerProps = {{style:[{maxHeight}]}}
|
|
568
566
|
onRender = {this.onRender.bind(this)}
|
|
569
567
|
testID = {testID}
|
|
570
568
|
extraData = {this.state.refresh}
|
|
@@ -558,6 +558,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
558
558
|
isDatagrid(){
|
|
559
559
|
return false;
|
|
560
560
|
}
|
|
561
|
+
isSWRDatagrid(){
|
|
562
|
+
return !!this.props.isSWRDatagrid;
|
|
563
|
+
}
|
|
561
564
|
callSRowCallback({selected,row,rowIndex,key,cb}){
|
|
562
565
|
let count = Object.size(this.selectedRows);
|
|
563
566
|
let sArg = this.getActionsArgs(selected);
|
|
@@ -3338,6 +3341,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3338
3341
|
delete fetchOptions.limit
|
|
3339
3342
|
}
|
|
3340
3343
|
}
|
|
3344
|
+
if(this.isSWRDatagrid()){
|
|
3345
|
+
fetchOptions.withTotal = true;
|
|
3346
|
+
}
|
|
3341
3347
|
return fetchOptions;
|
|
3342
3348
|
}
|
|
3343
3349
|
getFetchDataOpts(){
|
|
@@ -416,6 +416,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
416
416
|
opts = getFetchOptions({showError:showProgressRef.current,...opts});
|
|
417
417
|
isInitializedRef.current = true;
|
|
418
418
|
fetchOptionsRef.current = opts;
|
|
419
|
+
opts.withTotal = true;
|
|
419
420
|
sortRef.current = opts.fetchOptions.sort;
|
|
420
421
|
if(force){
|
|
421
422
|
pageRef.current = firstPage;
|
|
@@ -423,6 +424,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
423
424
|
doRefresh(force);
|
|
424
425
|
return false;
|
|
425
426
|
}}
|
|
427
|
+
isSWRDatagrid
|
|
426
428
|
isTableData
|
|
427
429
|
fetchData = {undefined}
|
|
428
430
|
data = {dataRef.current}
|
|
@@ -190,8 +190,8 @@ const DatagridFactory = (Factory)=>{
|
|
|
190
190
|
}
|
|
191
191
|
const maxHeight = this.getMaxListHeight();
|
|
192
192
|
const rPagination = showPagination ? <View style={[styles.paginationContainer]}>
|
|
193
|
-
<ScrollView horizontal style={styles.paginationContainerStyle} contentContainerStyle={styles.minW100}>
|
|
194
|
-
<View style={[styles.paginationContent]}>
|
|
193
|
+
<ScrollView testID={testID+"_Datagrid_Headers"} horizontal style={styles.paginationContainerStyle} contentContainerStyle={styles.minW100}>
|
|
194
|
+
<View testID={testID+"_HeaderPaginationContent"} style={[styles.paginationContent]}>
|
|
195
195
|
<View testID={testID+"_HeaderQueryLimit"}>
|
|
196
196
|
{this.renderQueryLimit(this.getStateDataSize().formatNumber())}
|
|
197
197
|
</View>
|
|
@@ -229,6 +229,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
229
229
|
})}
|
|
230
230
|
</>}
|
|
231
231
|
<BottomSheetMenu
|
|
232
|
+
testID = {testID+"_BottomSheetMenu"}
|
|
232
233
|
anchor = {(props)=>{
|
|
233
234
|
return <Icon {...props} title={isMobile?"Actions":"Colonnes"} name={isMobile?MENU_ICON:'view-column'}></Icon>
|
|
234
235
|
}}
|
|
@@ -292,8 +293,8 @@ const DatagridFactory = (Factory)=>{
|
|
|
292
293
|
</View>
|
|
293
294
|
</ScrollView>
|
|
294
295
|
</View> : null;
|
|
295
|
-
return <View style={[styles.container,{flex:1,maxHeight}]} pointerEvents={pointerEvents}>
|
|
296
|
-
<View ref={this.layoutRef}>
|
|
296
|
+
return <View style={[styles.container,{flex:1,maxHeight}]} testID={testID+"_TableContainer"} pointerEvents={pointerEvents}>
|
|
297
|
+
<View ref={this.layoutRef} testID={testID+"_LayoutContainer"}>
|
|
297
298
|
{this.props.showActions !== false ? <DatagridActions
|
|
298
299
|
pointerEvents = {pointerEvents}
|
|
299
300
|
title = {title}
|
|
@@ -312,12 +313,6 @@ const DatagridFactory = (Factory)=>{
|
|
|
312
313
|
<Table
|
|
313
314
|
ref = {this.listRef}
|
|
314
315
|
{...rest}
|
|
315
|
-
onLayout = {(args)=>{
|
|
316
|
-
if(rest.onLayout){
|
|
317
|
-
rest.onLayout(args);
|
|
318
|
-
}
|
|
319
|
-
this.updateLayout(args);
|
|
320
|
-
}}
|
|
321
316
|
sortedColumn = {sortedColumn}
|
|
322
317
|
onRender = {this.onRender.bind(this)}
|
|
323
318
|
getItemType = {this.getFlashListItemType.bind(this)}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from '$react';
|
|
2
|
+
import { ScrollView} from 'react-native';
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import {defaultStr,defaultObj} from "$utils";
|
|
5
|
+
import {Vertical as AutoSizeVertical} from "$ecomponents/AutoSizer";
|
|
6
|
+
|
|
7
|
+
const ScrollViewComponent = React.forwardRef(({withAutoSizer,autoSizerProps,testID,...rest},ref) => {
|
|
8
|
+
testID = defaultStr(testID,'RN_ScrollViewComponent');
|
|
9
|
+
const autoSize = React.useRef(withAutoSizer).current;
|
|
10
|
+
if(!autoSize || rest.horizontal === true || rest.vertical === false){
|
|
11
|
+
return <ScrollView testID={testID} ref={ref} {...rest}/>
|
|
12
|
+
}
|
|
13
|
+
autoSizerProps = defaultObj(autoSizerProps);
|
|
14
|
+
const autoSizeRef = React.useRef(null);
|
|
15
|
+
return <AutoSizeVertical {...autoSizerProps} ref = {autoSizeRef} testID={testID+"_ScrollViewContainer"}>
|
|
16
|
+
<ScrollView
|
|
17
|
+
ref={ref}
|
|
18
|
+
{...rest}
|
|
19
|
+
testID={testID}
|
|
20
|
+
onContentSizeChange = {(a,b,c,d)=>{
|
|
21
|
+
if(rest.onContentSizeChange && rest.onContentSizeChange(a,b,c,d)===false) return;
|
|
22
|
+
if(autoSizeRef.current && autoSizeRef.current.updateLayout){
|
|
23
|
+
return autoSizeRef.current.updateLayout();
|
|
24
|
+
}
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
</AutoSizeVertical>
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
ScrollViewComponent.displayName = "ScrollViewComponent";
|
|
31
|
+
export default ScrollViewComponent;
|
|
32
|
+
|
|
33
|
+
ScrollViewComponent.propTypes = {
|
|
34
|
+
...defaultObj(ScrollView.propTypes),
|
|
35
|
+
withAutoSizer : PropTypes.bool,//si le contenu du scrollView sera wrap par le composant AutoSizer
|
|
36
|
+
maxHeight : PropTypes.number,
|
|
37
|
+
minHeight : PropTypes.number,
|
|
38
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from '$react';
|
|
2
|
+
import { ScrollView,Dimensions} from 'react-native';
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import View from "$ecomponents/View";
|
|
5
|
+
import theme from "$theme";
|
|
6
|
+
import {defaultStr,defaultObj,defaultNumber} from "$utils";
|
|
7
|
+
import APP from "$capp/instance";
|
|
8
|
+
import ActivityIndicator from "$ecomponents/ActivityIndicator";
|
|
9
|
+
const ScrollViewComponent = React.forwardRef(({withAutoSizer,containerProps,maxHeight,minHeight,testID:customTestID,children:cChildren,...rest},ref) => {
|
|
10
|
+
const testID = defaultStr(customTestID,'RN_ScrollViewComponent');
|
|
11
|
+
const autoSizeRef = React.useRef(withAutoSizer);
|
|
12
|
+
if(!autoSizeRef.current || rest.horizontal === true || rest.vertical === false){
|
|
13
|
+
return <ScrollView testID={testID} ref={ref} {...rest} children={cChildren}/>
|
|
14
|
+
}
|
|
15
|
+
containerProps = defaultObj(containerProps)
|
|
16
|
+
const hasUpdateLayoutRef = React.useRef(false);
|
|
17
|
+
const isKeyboardOpenRef = React.useRef(false);
|
|
18
|
+
const layoutRef = React.useRef(null);
|
|
19
|
+
const [layout,setLayout] = React.useState(Dimensions.get("window"));
|
|
20
|
+
const {height} = layout;
|
|
21
|
+
const hasInitializedRef = React.useRef(false);
|
|
22
|
+
const children = React.useStableMemo(()=>cChildren,[cChildren]);
|
|
23
|
+
const updateLayout = ()=>{
|
|
24
|
+
return new Promise((resolve)=>{
|
|
25
|
+
hasUpdateLayoutRef.current = true;
|
|
26
|
+
if(layoutRef.current && layoutRef.current.measureInWindow){
|
|
27
|
+
layoutRef.current.measureInWindow((x, y, width, height) => {
|
|
28
|
+
const r = {...Dimensions.get("window"),layout:{ x, y, width, height }};
|
|
29
|
+
setLayout(r);
|
|
30
|
+
hasInitializedRef.current = true;
|
|
31
|
+
resolve(r);
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
setLayout(Dimensions.get("window"))
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
React.useEffect(()=>{
|
|
39
|
+
const onKeyboardToggle = ({visible})=>{
|
|
40
|
+
isKeyboardOpenRef.current = visible;
|
|
41
|
+
};
|
|
42
|
+
const onResizePage = ()=>{
|
|
43
|
+
setTimeout(()=>{
|
|
44
|
+
if(isKeyboardOpenRef.current) return;
|
|
45
|
+
updateLayout();
|
|
46
|
+
},300);
|
|
47
|
+
}
|
|
48
|
+
APP.on(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
49
|
+
APP.on(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle)
|
|
50
|
+
return ()=>{
|
|
51
|
+
APP.off(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
52
|
+
APP.off(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle);
|
|
53
|
+
}
|
|
54
|
+
},[]);
|
|
55
|
+
const hasUpdateLayout = hasUpdateLayoutRef.current;
|
|
56
|
+
const cStyle ={width:'100%',maxHeight:Math.max(height-100,250)};
|
|
57
|
+
const contentLayout = defaultObj(layout.layout);
|
|
58
|
+
cStyle.minHeight = Math.min(Math.max(layout.height-defaultNumber(contentLayout.y),250));
|
|
59
|
+
const contentContainerStyle = ([cStyle,rest.contentContainerStyle]);
|
|
60
|
+
const fStyle = !hasUpdateLayout && {flex:1,maxWidth:layout.width - defaultNumber(contentLayout.x)};
|
|
61
|
+
return <View ref={layoutRef} onLayout={()=>{
|
|
62
|
+
if(!hasInitializedRef.current){
|
|
63
|
+
updateLayout();
|
|
64
|
+
}
|
|
65
|
+
}} {...containerProps} style={[theme.styles.w100,containerProps.style,fStyle]} testID={testID+"_ScrollViewContainer"}>
|
|
66
|
+
<ScrollView
|
|
67
|
+
ref={ref} {...rest}
|
|
68
|
+
testID={testID}
|
|
69
|
+
children={hasUpdateLayout?children : <ActivityIndicator size={'large'}
|
|
70
|
+
style={[{flex:1}]}/>}
|
|
71
|
+
contentContainerStyle = {[contentContainerStyle,fStyle]}
|
|
72
|
+
/>
|
|
73
|
+
</View>
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
ScrollViewComponent.displayName = "ScrollViewComponent";
|
|
77
|
+
export default ScrollViewComponent;
|
|
78
|
+
|
|
79
|
+
ScrollViewComponent.propTypes = {
|
|
80
|
+
...defaultObj(ScrollView.propTypes),
|
|
81
|
+
withAutoSizer : PropTypes.bool,//si la taille du scrollView sera withAutoSizer
|
|
82
|
+
maxHeight : PropTypes.number,
|
|
83
|
+
minHeight : PropTypes.number,
|
|
84
|
+
}
|
|
@@ -1,74 +1,33 @@
|
|
|
1
1
|
import React from '$react';
|
|
2
|
-
import { ScrollView
|
|
2
|
+
import { ScrollView} from 'react-native';
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import View from "$ecomponents/View";
|
|
5
|
-
import theme from "$theme";
|
|
6
4
|
import {defaultStr,defaultObj} from "$utils";
|
|
7
|
-
import
|
|
8
|
-
const ScrollViewComponent = React.forwardRef(({virtualized,vertical,horizontal,contentProps,containerProps,mediaQueryUpdateNativeProps,testID:customTestID,children:cChildren,screenIndent:sIndent,...rest},ref) => {
|
|
9
|
-
const testID = defaultStr(customTestID,'RN_ScrollViewComponent');
|
|
10
|
-
containerProps = defaultObj(containerProps)
|
|
11
|
-
if(horizontal === true || vertical === false){
|
|
12
|
-
return <ScrollView horizontal testID={testID} ref={ref} {...rest} children={cChildren}/>
|
|
13
|
-
}
|
|
14
|
-
const isKeyboardOpenRef = React.useRef(false);
|
|
15
|
-
const layoutRef = React.useRef(null);
|
|
16
|
-
const [layout,setLayout] = React.useState(Dimensions.get("window"));
|
|
17
|
-
const {height} = layout;
|
|
18
|
-
const hasInitializedRef = React.useRef(false);
|
|
19
|
-
const children = React.useStableMemo(()=>cChildren,[cChildren]);
|
|
20
|
-
const updateLayout = ()=>{
|
|
21
|
-
return new Promise((resolve)=>{
|
|
22
|
-
if(layoutRef.current && layoutRef.current.measureInWindow){
|
|
23
|
-
layoutRef.current.measureInWindow((x, y, width, height) => {
|
|
24
|
-
const r = {...Dimensions.get("window"),layout:{ x, y, width, height }};
|
|
25
|
-
setLayout(r);
|
|
26
|
-
hasInitializedRef.current = true;
|
|
27
|
-
resolve(r);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
React.useEffect(()=>{
|
|
33
|
-
const onKeyboardToggle = ({visible})=>{
|
|
34
|
-
isKeyboardOpenRef.current = visible;
|
|
35
|
-
};
|
|
36
|
-
const onResizePage = ()=>{
|
|
37
|
-
setTimeout(()=>{
|
|
38
|
-
if(isKeyboardOpenRef.current) return;
|
|
39
|
-
updateLayout();
|
|
40
|
-
},300);
|
|
41
|
-
}
|
|
42
|
-
APP.on(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
43
|
-
APP.on(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle)
|
|
44
|
-
return ()=>{
|
|
45
|
-
APP.off(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
46
|
-
APP.off(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle);
|
|
47
|
-
}
|
|
48
|
-
},[]);
|
|
5
|
+
import {Vertical as AutoSizeVertical} from "$ecomponents/AutoSizer";
|
|
49
6
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
cStyle.minHeight = minHeight;
|
|
56
|
-
}
|
|
7
|
+
const ScrollViewComponent = React.forwardRef(({withAutoSizer,autoSizerProps,testID,...rest},ref) => {
|
|
8
|
+
testID = defaultStr(testID,'RN_ScrollViewComponent');
|
|
9
|
+
const autoSize = React.useRef(withAutoSizer).current;
|
|
10
|
+
if(!autoSize || rest.horizontal === true || rest.vertical === false){
|
|
11
|
+
return <ScrollView testID={testID} ref={ref} {...rest}/>
|
|
57
12
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
updateLayout();
|
|
62
|
-
}
|
|
63
|
-
}} {...containerProps} style={[theme.styles.w100,containerProps.style]} testID={testID+"_ScrollViewContainer"}>
|
|
13
|
+
autoSizerProps = defaultObj(autoSizerProps);
|
|
14
|
+
const autoSizerRef = React.useRef(null);
|
|
15
|
+
return <AutoSizeVertical ref={autoSizerRef} isScrollView {...autoSizerProps} testID={testID+"_ScrollViewContainer"}>
|
|
64
16
|
<ScrollView
|
|
65
17
|
ref={ref} {...rest}
|
|
66
|
-
vertical = {vertical}
|
|
67
18
|
testID={testID}
|
|
68
|
-
|
|
69
|
-
|
|
19
|
+
onContentSizeChange = {(a,b,c,d)=>{
|
|
20
|
+
if(rest.onContentSizeChange && rest.onContentSizeChange(a,b,c,d)===false) return;
|
|
21
|
+
return;
|
|
22
|
+
if(autoSizerRef.current && autoSizerRef.current.updateLayout){
|
|
23
|
+
console.log("updating layout ",autoSizerRef.current);
|
|
24
|
+
autoSizerRef.current.updateLayout();
|
|
25
|
+
}
|
|
26
|
+
}}
|
|
27
|
+
style = {[{flex:1}]}
|
|
28
|
+
contentContainerStyle = {[{flex:1,height:'100%'},rest.contentContainerStyle]}
|
|
70
29
|
/>
|
|
71
|
-
</
|
|
30
|
+
</AutoSizeVertical>
|
|
72
31
|
});
|
|
73
32
|
|
|
74
33
|
ScrollViewComponent.displayName = "ScrollViewComponent";
|
|
@@ -76,8 +35,7 @@ export default ScrollViewComponent;
|
|
|
76
35
|
|
|
77
36
|
ScrollViewComponent.propTypes = {
|
|
78
37
|
...defaultObj(ScrollView.propTypes),
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
contentProps : PropTypes.object,
|
|
38
|
+
withAutoSizer : PropTypes.bool,//si le contenu du scrollView sera wrap par le composant AutoSizer
|
|
39
|
+
maxHeight : PropTypes.number,
|
|
40
|
+
minHeight : PropTypes.number,
|
|
83
41
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from '$react';
|
|
2
|
+
import { ScrollView,Dimensions } from 'react-native';
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import View from "$ecomponents/View";
|
|
5
|
+
import theme from "$theme";
|
|
6
|
+
import {defaultStr,defaultObj} from "$utils";
|
|
7
|
+
import APP from "$capp/instance";
|
|
8
|
+
import {isWeb as isw} from "$cplatform";
|
|
9
|
+
const ScrollViewComponent = React.forwardRef(({containerProps,withAutoSizer,testID,...rest},ref) => {
|
|
10
|
+
testID = defaultStr(testID,'RN_ScrollViewComponent');
|
|
11
|
+
const autoSize = React.useRef(withAutoSizer).current;
|
|
12
|
+
if(!autoSize || rest.horizontal === true || rest.vertical === false){
|
|
13
|
+
return <ScrollView testID={testID} ref={ref} {...rest}/>
|
|
14
|
+
}
|
|
15
|
+
containerProps = defaultObj(containerProps)
|
|
16
|
+
const isWeb = isw();
|
|
17
|
+
const isKeyboardOpenRef = React.useRef(false);
|
|
18
|
+
const layoutRef = React.useRef(null);
|
|
19
|
+
const [layout,setLayout] = React.useState(Dimensions.get("window"));
|
|
20
|
+
const {height} = layout;
|
|
21
|
+
const hasInitializedRef = React.useRef(false);
|
|
22
|
+
const children = React.useStableMemo(()=>rest.children,[rest.children]);
|
|
23
|
+
const updateLayout = ()=>{
|
|
24
|
+
return new Promise((resolve)=>{
|
|
25
|
+
if(layoutRef.current && layoutRef.current.measureInWindow){
|
|
26
|
+
layoutRef.current.measureInWindow((x, y, width, height) => {
|
|
27
|
+
const r = {...Dimensions.get("window"),layout:{ x, y, width, height }};
|
|
28
|
+
setLayout(r);
|
|
29
|
+
hasInitializedRef.current = true;
|
|
30
|
+
resolve(r);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
React.useEffect(()=>{
|
|
36
|
+
const onKeyboardToggle = ({visible})=>{
|
|
37
|
+
isKeyboardOpenRef.current = visible;
|
|
38
|
+
};
|
|
39
|
+
const onResizePage = ()=>{
|
|
40
|
+
setTimeout(()=>{
|
|
41
|
+
if(isKeyboardOpenRef.current) return;
|
|
42
|
+
updateLayout();
|
|
43
|
+
},300);
|
|
44
|
+
}
|
|
45
|
+
APP.on(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
46
|
+
APP.on(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle)
|
|
47
|
+
return ()=>{
|
|
48
|
+
APP.off(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
49
|
+
APP.off(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle);
|
|
50
|
+
}
|
|
51
|
+
},[]);
|
|
52
|
+
|
|
53
|
+
const cStyle = {maxHeight:Math.max(height-100,250),width:'100%'};
|
|
54
|
+
if(isObj(layout.layout) && typeof layout.layout.y =='number' && layout.layout.y>=10){
|
|
55
|
+
const {layout : {x,y}} = layout;
|
|
56
|
+
const minHeight = height - y;
|
|
57
|
+
if(minHeight> 0){
|
|
58
|
+
cStyle.minHeight = minHeight;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const contentContainerStyle = [cStyle,rest.contentContainerStyle];
|
|
62
|
+
return <View ref={layoutRef} onLayout={()=>{
|
|
63
|
+
if(!hasInitializedRef.current){
|
|
64
|
+
updateLayout();
|
|
65
|
+
}
|
|
66
|
+
}} {...containerProps} style={[theme.styles.w100,containerProps.style]} testID={testID+"_ScrollViewContainer"}>
|
|
67
|
+
<ScrollView
|
|
68
|
+
ref={ref}
|
|
69
|
+
{...rest}
|
|
70
|
+
testID={testID}
|
|
71
|
+
children={children}
|
|
72
|
+
contentContainerStyle = {contentContainerStyle}
|
|
73
|
+
/>
|
|
74
|
+
</View>
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
ScrollViewComponent.displayName = "ScrollViewComponent";
|
|
78
|
+
export default ScrollViewComponent;
|
|
79
|
+
|
|
80
|
+
ScrollViewComponent.propTypes = {
|
|
81
|
+
...defaultObj(ScrollView.propTypes),
|
|
82
|
+
withAutoSizer : PropTypes.bool,
|
|
83
|
+
}
|
|
@@ -49,8 +49,9 @@ const AbsoluteScrollView = React.forwardRef(({testID,contentProps,listRef,contai
|
|
|
49
49
|
args = defaultObj(args);
|
|
50
50
|
if(isObj(args.contentOffset) && isObj(args.contentSize)){
|
|
51
51
|
const {x} = args.contentOffset;
|
|
52
|
+
const {width:contentWidth} = args.contentSize;
|
|
52
53
|
const {width} = Dimensions.get("window");
|
|
53
|
-
const visible = x >= width-10 ? false : true;
|
|
54
|
+
const visible = x >= width-10 && (contentWidth-x)<10 ? false : true;
|
|
54
55
|
if(state.visible != visible){
|
|
55
56
|
return setState({...state,visible});
|
|
56
57
|
}
|
|
@@ -67,13 +68,22 @@ const AbsoluteScrollView = React.forwardRef(({testID,contentProps,listRef,contai
|
|
|
67
68
|
React.useEffect(()=>{
|
|
68
69
|
toggleVisible();
|
|
69
70
|
},[styles])
|
|
71
|
+
let canBeVisible = true;
|
|
72
|
+
if(isObj(styles.content) && isObj(styles.contentContainer)){
|
|
73
|
+
if(typeof styles.content.height =='number' && typeof styles.contentContainer.height =='number'){
|
|
74
|
+
if(styles.content.height -10 <= styles.contentContainer.height){
|
|
75
|
+
canBeVisible = false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const hidden = (!canBeVisible || !visible || !layoutVisible) ;
|
|
70
80
|
return <Portal>
|
|
71
|
-
{<View testID={testID+"_Containter"} {...containerProps} style={[mainStyles.container,containerProps.style,styles.container,{left:win.width-10},
|
|
81
|
+
{<View testID={testID+"_Containter"} {...containerProps} style={[mainStyles.container,containerProps.style,styles.container,{left:win.width-10},hidden &&{display:'none',width:0,opacity:0}]}>
|
|
72
82
|
<ScrollView
|
|
73
83
|
{...props}
|
|
74
84
|
ref = {scrollViewRef}
|
|
75
85
|
testID={testID}
|
|
76
|
-
contentContainerStyle = {[props.contentContainerStyle,mainStyles.contentContainer,styles.
|
|
86
|
+
contentContainerStyle = {[props.contentContainerStyle,mainStyles.contentContainer,styles.contentContainer]}
|
|
77
87
|
vertical
|
|
78
88
|
>
|
|
79
89
|
<View
|
|
@@ -96,7 +96,7 @@ const VirtuosoListComponent = React.forwardRef(({items,onRender,testID,renderIte
|
|
|
96
96
|
}
|
|
97
97
|
},[]);
|
|
98
98
|
React.useOnRender(onRender,Math.max(Array.isArray(items) && items.length/10 || 0,500))
|
|
99
|
-
return <View {...containerProps} {...props} style={[{flex:1},containerProps.style,style,{minWidth:'100%',maxWidth:'100%'}]} onLayout={onLayout} testID={testID}>
|
|
99
|
+
return <View {...containerProps} {...props} style={[{flex:1},containerProps.style,style,{minWidth:'100%',height:'100%',maxWidth:'100%'}]} onLayout={onLayout} testID={testID}>
|
|
100
100
|
<Virtuoso
|
|
101
101
|
{...r2}
|
|
102
102
|
style = {listStyle}
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "$react";
|
|
2
|
+
import {Vertical as AutoSizeVertical} from "$ecomponents/AutoSizer";
|
|
3
|
+
import List from "./List";
|
|
4
|
+
import {defaultStr,defaultObj} from "$utils";
|
|
5
|
+
const AutoSizeVerticalList = React.forwardRef(({testID,autoSizerProps,...props},ref)=>{
|
|
6
|
+
testID = defaultStr(testID,"RN_AutoSizeVerticalListComponent")
|
|
7
|
+
autoSizerProps = defaultObj(autoSizerProps);
|
|
8
|
+
return <AutoSizeVertical testID={testID+"_AutoSizerVertical"} {...autoSizerProps} >
|
|
9
|
+
<List {...props} ref={ref}/>
|
|
10
|
+
</AutoSizeVertical>
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
AutoSizeVerticalList.displayName = "AutoSizeVerticalListComponent";
|
|
14
|
+
|
|
15
|
+
export default AutoSizeVerticalList;
|
|
@@ -7,7 +7,6 @@ import Label from "$ecomponents/Label";
|
|
|
7
7
|
import { StyleSheet,View as RNView,ScrollView,Dimensions} from "react-native";
|
|
8
8
|
import { getRowStyle } from "$ecomponents/Datagrid/utils";
|
|
9
9
|
import {isMobileNative} from "$cplatform";
|
|
10
|
-
import {isMobileMedia} from "$dimensions";
|
|
11
10
|
import theme from "$theme";
|
|
12
11
|
import AbsoluteScrollView from "./AbsoluteScrollView";
|
|
13
12
|
import Cell from "./Cell";
|
|
@@ -357,7 +356,7 @@ const TableComponent = React.forwardRef(({containerProps,sortedColumn,listContai
|
|
|
357
356
|
testID = {testID}
|
|
358
357
|
prepareItems = {false}
|
|
359
358
|
items = {items}
|
|
360
|
-
contentContainerStyle = {[styles.contentContainer,{width:listWidth,minWidth:totalWidths
|
|
359
|
+
contentContainerStyle = {[styles.contentContainer,{width:listWidth,minWidth:totalWidths}]}
|
|
361
360
|
style = {[styles.datagrid,{width:listWidth,minWidth:totalWidths}]}
|
|
362
361
|
keyExtractor = {typeof getRowKey =='function'? getRowKey : React.getKey}
|
|
363
362
|
onScroll = {getOnScrollCb([absoluteScrollViewRef],(args)=>{
|
|
@@ -394,7 +394,11 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
394
394
|
const isMobile = isMobileOrTabletMedia();
|
|
395
395
|
const contentProps = restProps.contentProps;
|
|
396
396
|
const elevation = restProps.elevation;
|
|
397
|
-
const renderingTabsProps = {tabs,data:this.getCurrentData(),
|
|
397
|
+
const renderingTabsProps = {tabs,data:this.getCurrentData(),tabsPropsMutator:({tabs,tabsProps})=>{
|
|
398
|
+
if(!isMobileOrTabletMedia()){
|
|
399
|
+
tabsProps.withScrollView = false;
|
|
400
|
+
}
|
|
401
|
+
},isMobile,sessionName:this.INITIAL_STATE.sessionName,props:restProps,tabProps,tabsProps,context,tabKey};
|
|
398
402
|
const hasTabs = Object.size(tabs,true);
|
|
399
403
|
let mainContent = undefined;
|
|
400
404
|
testID = defaultStr(testID,"RN_TableDataScreenItem_"+restProps.tableName);
|
|
@@ -417,7 +421,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
417
421
|
mainContent = ct;
|
|
418
422
|
} else {
|
|
419
423
|
mainContent = <View {...contentProps} testID={testID+"_ContentContainer"} style={[styles.container,styles.noPadding]}>
|
|
420
|
-
<ScrollView testID={testID+"_MainContentScrollView"} contentProps={{style:theme.styles.p1}}>
|
|
424
|
+
<ScrollView withAutoSizer testID={testID+"_MainContentScrollView"} contentProps={{style:theme.styles.p1}}>
|
|
421
425
|
<Surface elevation={elevation} testID={testID+"_ContentHeader"} style={[styles.screenContent,theme.styles.p1,header?styles.screenContentWithHeader:null]}>
|
|
422
426
|
{header}
|
|
423
427
|
{content}
|
|
@@ -443,7 +447,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
443
447
|
appBarProps.elevation = 0;
|
|
444
448
|
restProps.elevation = 0;
|
|
445
449
|
}
|
|
446
|
-
return <ScreenContainer
|
|
450
|
+
return <ScreenContainer {...restProps} withScrollView={false} appBarProps = {appBarProps} testID={testID}>
|
|
447
451
|
{this.wrapRenderingContent(mainContent,{testID})}
|
|
448
452
|
</ScreenContainer>
|
|
449
453
|
}
|
|
@@ -8,13 +8,13 @@ import {getTableDataRouteName} from "$enavigation/utils";
|
|
|
8
8
|
//@seee : https://github.com/typeorm/typeorm/blob/master/src/entity-schema/EntitySchemaColumnOptions.ts
|
|
9
9
|
export const generatedColumnsProperties = ["createDate","updateDate","deleteDate","createBy","updateBy","deleteBy"]
|
|
10
10
|
|
|
11
|
-
export const renderTabsContent = ({tabs,context,data,sessionName,isMobile,props,firstTab,tabKey,tabProps,tabsProps})=>{
|
|
11
|
+
export const renderTabsContent = ({tabs,context,data,sessionName,tabsPropsMutator,isMobile,props,firstTab,tabKey,tabProps,tabsProps})=>{
|
|
12
12
|
let tabsArr = [],hasFirstTab = false;
|
|
13
13
|
if(React.isValidElement(firstTab)){
|
|
14
14
|
tabsArr.push(firstTab);
|
|
15
15
|
hasFirstTab = true;
|
|
16
16
|
}
|
|
17
|
-
tabsProps = Object.
|
|
17
|
+
tabsProps = Object.clone(tabsProps);
|
|
18
18
|
tabsProps.centered = false;
|
|
19
19
|
tabKey = typeof tabKey =='string' || typeof tabKey =='number'? tabKey : 'first-tab-key';
|
|
20
20
|
let idx = tabsArr.length-1;
|
|
@@ -52,6 +52,9 @@ export const renderTabsContent = ({tabs,context,data,sessionName,isMobile,props,
|
|
|
52
52
|
})
|
|
53
53
|
}
|
|
54
54
|
if(tabsArr.length> (hasFirstTab ? 1 : 0)){
|
|
55
|
+
if(typeof tabsPropsMutator =='function' && tabsPropsMutator({tabsProps,tabs:tabsArr,hasFirstTab}) === false){
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
55
58
|
return <Tab testID={testID}
|
|
56
59
|
{...tabsProps}
|
|
57
60
|
onChange={(args)=>{
|
|
@@ -87,43 +87,45 @@ export default function HelpScreen(props){
|
|
|
87
87
|
<Label primary textBold style={theme.styles.mv05} >{appConfig.name+", Notes de mise à jour."}</Label>
|
|
88
88
|
</Link>
|
|
89
89
|
</View>
|
|
90
|
-
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
{Object.mapToArray(openLibraries,(lib,i,_i)=>{
|
|
109
|
-
return <Grid.Row key={i} style={borderStyle}>
|
|
110
|
-
<Label style={gridStyles[0]}>
|
|
111
|
-
{_i.formatNumber()}
|
|
112
|
-
</Label>
|
|
113
|
-
<AutoLink style={gridStyles[1]} url={lib.url}>
|
|
114
|
-
<Label splitText>{i}</Label>
|
|
115
|
-
</AutoLink>
|
|
116
|
-
<AutoLink style={gridStyles[2]}>
|
|
117
|
-
<Label splitText numberOfLines={2}>{defaultStr(lib.version)}</Label>
|
|
118
|
-
</AutoLink>
|
|
119
|
-
<AutoLink url={lib.licenseUrl} style={gridStyles[3]}>
|
|
120
|
-
<Label splitText>{lib.license}</Label>
|
|
121
|
-
</AutoLink>
|
|
90
|
+
<View style={theme.styles.w100}>
|
|
91
|
+
{Object.size(openLibraries,true) ? <View style={[theme.styles.w100]}>
|
|
92
|
+
<Expandable
|
|
93
|
+
testID={testID+"_OpenLibraries"}
|
|
94
|
+
title = {"A propos des librairies tiers"}
|
|
95
|
+
titleProps = {{style:theme.styles.ph1}}
|
|
96
|
+
style = {{backgroundColor:'transparent'}}
|
|
97
|
+
>
|
|
98
|
+
<View testID={testID+"_OpenLibraries_Header"} style={[theme.styles.row,theme.styles.flexWrap]}>
|
|
99
|
+
<Label testID={testID+"_OpenLibraries_HeaderLabel"} primary textBold>{appConfig.name+" "}</Label>
|
|
100
|
+
<Label>est bâti sur un ensemble d'outils et librairies open Source</Label>
|
|
101
|
+
</View>
|
|
102
|
+
<View testID={testID+"_OpenLibrariesContent"} style={[theme.styles.w100,theme.styles.pv1]}>
|
|
103
|
+
<Grid.Row style={borderStyle}>
|
|
104
|
+
<Label style={gridStyles[0]} textBold>#</Label>
|
|
105
|
+
<Label style={gridStyles[1]} textBold>Librairie/Outil</Label>
|
|
106
|
+
<Label style={gridStyles[2]} textBold>Version</Label>
|
|
107
|
+
<Label style={gridStyles[3]} textBold>Licence</Label>
|
|
122
108
|
</Grid.Row>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
109
|
+
{Object.mapToArray(openLibraries,(lib,i,_i)=>{
|
|
110
|
+
return <Grid.Row key={i} style={borderStyle}>
|
|
111
|
+
<Label style={gridStyles[0]}>
|
|
112
|
+
{_i.formatNumber()}
|
|
113
|
+
</Label>
|
|
114
|
+
<AutoLink style={gridStyles[1]} url={lib.url}>
|
|
115
|
+
<Label splitText>{i}</Label>
|
|
116
|
+
</AutoLink>
|
|
117
|
+
<AutoLink style={gridStyles[2]}>
|
|
118
|
+
<Label splitText numberOfLines={2}>{defaultStr(lib.version)}</Label>
|
|
119
|
+
</AutoLink>
|
|
120
|
+
<AutoLink url={lib.licenseUrl} style={gridStyles[3]}>
|
|
121
|
+
<Label splitText>{lib.license}</Label>
|
|
122
|
+
</AutoLink>
|
|
123
|
+
</Grid.Row>
|
|
124
|
+
})}
|
|
125
|
+
</View>
|
|
126
|
+
</Expandable>
|
|
127
|
+
</View>: null}
|
|
128
|
+
</View>
|
|
127
129
|
</View>
|
|
128
130
|
</Screen>
|
|
129
131
|
}
|