@fto-consult/expo-ui 6.26.18 → 6.27.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 +1 -1
- package/src/components/BottomSheet/Provider.js +6 -1
- package/src/components/Datagrid/Accordion/Row.js +18 -4
- package/src/components/Datagrid/Accordion/index.js +11 -6
- package/src/components/Swiper/index.js +2 -1
- package/src/context/Provider.js +15 -3
- package/src/context/TableData.js +104 -0
- package/src/context/index.js +3 -1
- package/src/layouts/Screen/TableData.js +12 -14
- package/src/navigation/utils.js +1 -0
- package/src/screens/index.js +1 -0
package/package.json
CHANGED
|
@@ -43,10 +43,15 @@ const Provider = React.forwardRef((props,innerRef)=>{
|
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
React.setRef(ref,context);
|
|
46
|
-
return <Menu {...props} {...state} visible={visible} sheet controlled onDismiss = {(
|
|
46
|
+
return <Menu {...props} {...state} visible={visible} sheet controlled onDismiss = {(...args)=>{
|
|
47
47
|
if(visible){
|
|
48
48
|
setVisible(false);
|
|
49
49
|
}
|
|
50
|
+
if(typeof state.onDismiss =='function'){
|
|
51
|
+
state.onDismiss(...args)
|
|
52
|
+
} else if(typeof props.onDismiss =='function'){
|
|
53
|
+
props.onDismiss(...args);
|
|
54
|
+
}
|
|
50
55
|
}}/>
|
|
51
56
|
});
|
|
52
57
|
|
|
@@ -6,7 +6,6 @@ import Label from "$ecomponents/Label";
|
|
|
6
6
|
import PropTypes from "prop-types";
|
|
7
7
|
import React from "$react";
|
|
8
8
|
import theme from "$theme"
|
|
9
|
-
import {isMobileNative} from "$cplatform";
|
|
10
9
|
import {styles as rStyles,getRowStyle} from "../utils";
|
|
11
10
|
import Swipeable from 'react-native-gesture-handler/Swipeable';
|
|
12
11
|
import { useIsRowSelected,useDatagrid} from "../hooks";
|
|
@@ -30,7 +29,7 @@ const DatagridAccordionRow = React.forwardRef((props,ref)=>{
|
|
|
30
29
|
callArgs,
|
|
31
30
|
} = props;
|
|
32
31
|
const {context} = useDatagrid();
|
|
33
|
-
let {
|
|
32
|
+
let {title,right,rightProps,description,avatarContent,rowProps} = props;
|
|
34
33
|
rightProps = defaultObj(rightProps);
|
|
35
34
|
if(!isObj(item)) {
|
|
36
35
|
return null;
|
|
@@ -108,6 +107,11 @@ const DatagridAccordionRow = React.forwardRef((props,ref)=>{
|
|
|
108
107
|
}
|
|
109
108
|
right = typeof right === 'function'? right ({color:theme.colors.primaryOnSurface,selectable:true,style:[rStyles.lineHeight,styles.right]}) : right;
|
|
110
109
|
const swipeableRef = React.useRef(null);
|
|
110
|
+
React.useEffect(()=>{
|
|
111
|
+
return ()=>{
|
|
112
|
+
React.setRef(swipeableRef,null);
|
|
113
|
+
}
|
|
114
|
+
},[])
|
|
111
115
|
return <Pressable
|
|
112
116
|
disabled = {selectable===false?true : false}
|
|
113
117
|
{...rowProps}
|
|
@@ -125,7 +129,15 @@ const DatagridAccordionRow = React.forwardRef((props,ref)=>{
|
|
|
125
129
|
selectable !== false && theme.styles.cursorPointer,
|
|
126
130
|
//style,
|
|
127
131
|
]}
|
|
128
|
-
ref = {
|
|
132
|
+
ref = {(el)=>{
|
|
133
|
+
if(el){
|
|
134
|
+
el.toggleExpand = (expand)=>{
|
|
135
|
+
setExpanded(typeof expand =='boolean'? expand : !expanded);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
React.setRef(ref,el);
|
|
139
|
+
React.setRef(innerRef,el);
|
|
140
|
+
}}
|
|
129
141
|
>
|
|
130
142
|
<Swipeable
|
|
131
143
|
ref = {swipeableRef}
|
|
@@ -168,7 +180,9 @@ const DatagridAccordionRow = React.forwardRef((props,ref)=>{
|
|
|
168
180
|
style={[styles.renderedContent,viewWrapperStyle]}
|
|
169
181
|
testID={testID+'_ContentContainer'}
|
|
170
182
|
>
|
|
171
|
-
{avatarContent}
|
|
183
|
+
{hasAvatar?<View testID={testID+"_AvatarContentContainer"} style={[styles.avatarContent]}>
|
|
184
|
+
{avatarContent}
|
|
185
|
+
</View> : avatarContent}
|
|
172
186
|
<View testID={testID+"_Content"} style={[styles.content,styles.wrap]}>
|
|
173
187
|
{title}
|
|
174
188
|
{description}
|
|
@@ -201,9 +201,9 @@ const DatagridFactory = (Factory)=>{
|
|
|
201
201
|
numColumns = {numColumns}
|
|
202
202
|
key = {index}
|
|
203
203
|
ref = {(el)=>{
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
this.renderingItemsProps = defaultObj(this.renderingItemsProps);
|
|
205
|
+
this.renderingItemsProps[rowKey] = defaultObj(this.renderingItemsProps[rowKey]);
|
|
206
|
+
this.renderingItemsProps[rowKey].ref = el;
|
|
207
207
|
}}
|
|
208
208
|
style = {style}
|
|
209
209
|
callArgs = {this.getItemCallArgs({item,index})}
|
|
@@ -263,9 +263,14 @@ const DatagridFactory = (Factory)=>{
|
|
|
263
263
|
/*** affiche les infos de l'item */
|
|
264
264
|
onToggleExpandItem({item,index,rowIndex,rowKey,...rest}){
|
|
265
265
|
if(!isObj(this.bottomSheetContext) || typeof this.bottomSheetContext.open !=='function') return;
|
|
266
|
+
if(!isObj(this.renderingItemsProps) || !isObj(this.renderingItemsProps[rowKey])) return;
|
|
266
267
|
const callArgs = this.getItemCallArgs({item,index})
|
|
267
268
|
return this.bottomSheetContext.open({
|
|
268
269
|
...rest,
|
|
270
|
+
onDismiss : ()=>{
|
|
271
|
+
const ref = this.renderingItemsProps[rowKey].ref;
|
|
272
|
+
ref?.toggleExpand && ref?.toggleExpand(false);
|
|
273
|
+
},
|
|
269
274
|
children : <View style={[styles.expandedItemContent]} testID={'RN_DatagridAccordionExpanded'}>
|
|
270
275
|
{Object.mapToArray(this.state.columns,(columnDef,columnField,index)=>{
|
|
271
276
|
callArgs.columnDef = columnDef;
|
|
@@ -552,7 +557,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
552
557
|
items = {this.state.data}
|
|
553
558
|
isLoading = {isLoading}
|
|
554
559
|
ref = {this.listRef}
|
|
555
|
-
style = {styles.list}
|
|
560
|
+
style = {[styles.list,rest.style]}
|
|
556
561
|
backToTopRef = {backToTopRef?(e)=>{
|
|
557
562
|
return this.backToTopRef.current;
|
|
558
563
|
}:false}
|
|
@@ -607,7 +612,7 @@ const styles = StyleSheet.create({
|
|
|
607
612
|
maxHeight : 60
|
|
608
613
|
},
|
|
609
614
|
list : {
|
|
610
|
-
paddingHorizontal :
|
|
615
|
+
paddingHorizontal : isNativeMobile()?10:0,
|
|
611
616
|
},
|
|
612
617
|
container : {
|
|
613
618
|
position : 'relative',
|
|
@@ -628,7 +633,7 @@ const styles = StyleSheet.create({
|
|
|
628
633
|
flexDirection:'row',
|
|
629
634
|
alignItems : 'center',
|
|
630
635
|
flex:1,
|
|
631
|
-
paddingHorizontal :
|
|
636
|
+
paddingHorizontal : 0,
|
|
632
637
|
},
|
|
633
638
|
pullRight : {
|
|
634
639
|
flexDirection : 'row',
|
|
@@ -440,11 +440,12 @@ const styles = {
|
|
|
440
440
|
},
|
|
441
441
|
// Fix web vertical scaling (like expo v33-34)
|
|
442
442
|
container: (positionFixed, x, y, width, height,autoHeight) => addAutoHeight(({
|
|
443
|
-
backgroundColor:
|
|
443
|
+
backgroundColor: "transparent",
|
|
444
444
|
// Fix safari vertical bounces
|
|
445
445
|
position: positionFixed ? 'fixed' : 'relative',
|
|
446
446
|
overflow: 'hidden',
|
|
447
447
|
flexGrow: 1,
|
|
448
|
+
//flex : 1,
|
|
448
449
|
top: positionFixed ? y : 0,
|
|
449
450
|
left: positionFixed ? x : 0,
|
|
450
451
|
width,
|
package/src/context/Provider.js
CHANGED
|
@@ -9,6 +9,8 @@ import {ExpoUIContext} from "./hooks";
|
|
|
9
9
|
import Login from "$eauth/Login";
|
|
10
10
|
import {modes} from "$ecomponents/TextField";
|
|
11
11
|
import {isMobileMedia} from "$cdimensions";
|
|
12
|
+
import { prepareScreens } from "./TableData";
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
/*****
|
|
14
16
|
les utilitaires disponibles à passer au provider :
|
|
@@ -27,7 +29,9 @@ import {isMobileMedia} from "$cdimensions";
|
|
|
27
29
|
ReactComponent
|
|
28
30
|
},
|
|
29
31
|
loginPropsMutator : ({object})=><{object}>, la fonction permettant de muter les props du composant Login,
|
|
30
|
-
tableLinkPropsMutator : ({object})=><{object}>, la fonction permettant de muter les props du composant TableLink
|
|
32
|
+
tableLinkPropsMutator : ({object})=><{object}>, la fonction permettant de muter les props du composant TableLink,
|
|
33
|
+
TableDataScreen | TableDataScreenItem : {ReactComponent}, le composant TableDataScreenItem, à utiliser pour le rendu des écrans
|
|
34
|
+
TableDataScreenList | TableDataListScreen {ReactComponent}, le composant TableDataList à utiliser pour le rendu des écrans listants les éléments du table data
|
|
31
35
|
},
|
|
32
36
|
navigation : {
|
|
33
37
|
screens : {Array}, les écrans de navigation,
|
|
@@ -39,8 +43,6 @@ const Provider = ({children,getTableData,navigation,components,convertFiltersToS
|
|
|
39
43
|
const { theme : pTheme } = useMaterial3Theme();
|
|
40
44
|
navigation = defaultObj(navigation);
|
|
41
45
|
components = defaultObj(components);
|
|
42
|
-
const {screens} = navigation;
|
|
43
|
-
navigation.screens = [...(Array.isArray(screens)? screens : []),...eMainScreens];
|
|
44
46
|
structsData = isObj(structsData)? structsData : null;
|
|
45
47
|
appConfig.tablesData = tablesData;
|
|
46
48
|
appConfig.structsData = appConfig.structsData = isObj(structsData)? structsData : null;
|
|
@@ -110,6 +112,16 @@ const Provider = ({children,getTableData,navigation,components,convertFiltersToS
|
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
}
|
|
115
|
+
const {screens} = navigation;
|
|
116
|
+
navigation.screens = React.useMemo(()=>{
|
|
117
|
+
const r = prepareScreens({
|
|
118
|
+
tables:tablesData,
|
|
119
|
+
screens,
|
|
120
|
+
TableDataScreen:components.TableDataScreen || components.TableDataScreenItem,
|
|
121
|
+
TableDataScreenList:components.TableDataScreenList||components.TableDataListScreen
|
|
122
|
+
});
|
|
123
|
+
return [...r,...eMainScreens];
|
|
124
|
+
},[]);
|
|
113
125
|
return <ExpoUIContext.Provider
|
|
114
126
|
value={{
|
|
115
127
|
...props,
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
import {getRouteOptions} from "$cnavigation";
|
|
5
|
+
import React from "$react";
|
|
6
|
+
import useExpo from "./hooks";
|
|
7
|
+
import {defaultStr,defaultBool,isObj,isNonNullString} from "$cutils";
|
|
8
|
+
import {getTableDataListRouteName,getTableDataRouteName,tableDataRouteName} from "$enavigation/utils";
|
|
9
|
+
|
|
10
|
+
export function TableDataListScreen({tableName,table,screenName,...props}){
|
|
11
|
+
const {getTable} = useExpo();
|
|
12
|
+
const List = React.useMemo(()=>{
|
|
13
|
+
return TableDataScreenComponentRef.List;
|
|
14
|
+
},[]);
|
|
15
|
+
if(!React.isComponent(List)){
|
|
16
|
+
throw "Impossible d'effectuer le rendu de la liste des éléments liés à la table "+tableName+", Le composant List est invalide, rassurez vous de faire passer dans la fonction registerApp, un composant TableDataScreenList à utiliser pour le dit rendu";
|
|
17
|
+
}
|
|
18
|
+
tableName = defaultStr(tableName,table).toUpperCase();
|
|
19
|
+
let tableObj = getTable(tableName);
|
|
20
|
+
if(!tableObj){
|
|
21
|
+
throw `object table invalide, pour le rendu de la liste des éléments liés à la table ${tableName}.`;
|
|
22
|
+
}
|
|
23
|
+
const title = defaultStr(tableObj?.text,tableObj?.label);
|
|
24
|
+
return <List testID={"RN_TableDataScreenList_"+tableName.toUpperCase()} table={table} screenName={screenName} tableObj={tableObj} {...props} key={tableName} tableName={tableName} title={title}/>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
TableDataListScreen.Stack = false;
|
|
28
|
+
|
|
29
|
+
const loopForScreen = (lScreens,screens,foundTables)=>{
|
|
30
|
+
screens = Array.isArray(screens)? screens : [];
|
|
31
|
+
foundTables = isObj(foundTables) ? foundTables : {};
|
|
32
|
+
Object.map(lScreens,(Titem)=>{
|
|
33
|
+
if(!Titem) return;
|
|
34
|
+
if(Array.isArray(Titem)){
|
|
35
|
+
loopForScreen(Titem,screens,foundTables)
|
|
36
|
+
} else if(isNonNullString(Titem.screenName)) {
|
|
37
|
+
foundTables[Titem.screenName] = Titem;
|
|
38
|
+
screens.push(Titem);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return {screens,foundTables};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/****
|
|
45
|
+
prepare les différents écrans de l'application
|
|
46
|
+
@param {object} tables, les différentes tables de l'application
|
|
47
|
+
@param {Array} screens, les écrancs initiaux de l'application
|
|
48
|
+
@param {component} TableDataScreen, le composant react à utiliser pour le rendu TableDataScreen, d'un item du tableData
|
|
49
|
+
@return {Array}, la liste des écrans apprêtés
|
|
50
|
+
*/
|
|
51
|
+
export function prepareScreens ({tables,screens:screensProps,TableDataScreen,TableDataScreenList}){
|
|
52
|
+
const foundTables = {};
|
|
53
|
+
const screens = [];
|
|
54
|
+
TableDataScreenComponentRef.current = React.isComponent(TableDataScreen)? TableDataScreen : TableDataScreenComponentRef.current;
|
|
55
|
+
TableDataScreenComponentRef.List = React.isComponent(TableDataScreenList)? TableDataScreenList : TableDataScreenComponentRef.List;
|
|
56
|
+
const Modal = defaultBool(TableDataScreenComponentRef.current?.Modal,TableDataScreenComponentRef.current?.modal,true)
|
|
57
|
+
loopForScreen(screensProps,screens,foundTables);
|
|
58
|
+
Object.map(tables,(table,i)=>{
|
|
59
|
+
if(!isObj(table) || !isNonNullString(i)) return;
|
|
60
|
+
const screenName = getTableDataRouteName(i);
|
|
61
|
+
const listScreenName = getTableDataListRouteName(i);
|
|
62
|
+
if(!foundTables[screenName]){
|
|
63
|
+
screens.push({
|
|
64
|
+
Component : TableDataScreenItem,
|
|
65
|
+
screenName,
|
|
66
|
+
Modal
|
|
67
|
+
})
|
|
68
|
+
foundTables[screenName] = TableDataScreenItem;
|
|
69
|
+
} else if(React.isComponent(foundTables[screenName])){
|
|
70
|
+
foundTables[screenName].Modal = defaultBool(foundTables[screenName]?.Modal,foundTables[screenName].modal,Modal)
|
|
71
|
+
}
|
|
72
|
+
if(!foundTables[listScreenName] && table.datagrid !== false){
|
|
73
|
+
screens.push({
|
|
74
|
+
Component : TableDataListScreen,
|
|
75
|
+
screenName : listScreenName,
|
|
76
|
+
});
|
|
77
|
+
foundTables[listScreenName] = TableDataListScreen;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return screens;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export {tableDataRouteName};
|
|
84
|
+
|
|
85
|
+
const TableDataScreenComponentRef = {current:null};
|
|
86
|
+
export const TableDataScreenItem = (props)=>{
|
|
87
|
+
const Item = React.useMemo(()=>{
|
|
88
|
+
return TableDataScreenComponentRef.current;
|
|
89
|
+
},[])
|
|
90
|
+
if(!React.isComponent(Item)) {
|
|
91
|
+
throw "Impossible de rendre le composant TableDataScreen, car la fonction registerApp n'a pas été initialisé avec un composant devant servir pour le rendu des TableData screens item";
|
|
92
|
+
}
|
|
93
|
+
const {params,data,tableName:tbName} = getRouteOptions(props);
|
|
94
|
+
const {getTable} = useExpo();
|
|
95
|
+
const tableName = defaultStr(params?.tableName,params?.table,tbName);
|
|
96
|
+
const tableObj = getTable(tableName);
|
|
97
|
+
if(!isObj(tableObj)){
|
|
98
|
+
throw "Objet table invalide, impossible de rendre le contenu de la tableDataScreen liée à la table "+tableName;
|
|
99
|
+
}
|
|
100
|
+
return <Item testID={"RN_TableDataScreenItem_"+(defaultStr(tableName)).toUpperCase()}{...props} tableObj={tableObj} data={data} tableName={tableName} {...params}/>
|
|
101
|
+
}
|
|
102
|
+
TableDataScreenItem.Modal = true;
|
|
103
|
+
|
|
104
|
+
TableDataScreenItem.displayName = "TableDataScreenItem";
|
package/src/context/index.js
CHANGED
|
@@ -385,10 +385,10 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
385
385
|
if(hasTabs){
|
|
386
386
|
if(isMobOrTab){
|
|
387
387
|
renderingTabsProps.firstTab = <Tab.Item testID={testID+"_MainTab"} label={"Principal"} {...firstTabProps} key={tabKey}>
|
|
388
|
-
<
|
|
388
|
+
<View testID={testID+"_MainTab_Content"} {...contentProps} style={[styles.noMarging,contentProps.style,styles.h100,styles.noPadding]}>
|
|
389
389
|
{header}
|
|
390
390
|
{content}
|
|
391
|
-
</
|
|
391
|
+
</View>
|
|
392
392
|
</Tab.Item>
|
|
393
393
|
} else {
|
|
394
394
|
//tabsProps.tabItemsProps.elevation = 0;
|
|
@@ -400,25 +400,23 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
400
400
|
} else {
|
|
401
401
|
mainContent = <View {...contentProps} testID={testID+"_ContentContainer"} style={[styles.container,styles.noPadding,contentProps.style]}>
|
|
402
402
|
<ScrollView withAutoSizer testID={testID+"_MainContentScrollView"} contentProps={{style:theme.styles.p1}}>
|
|
403
|
-
<
|
|
403
|
+
<View testID={testID+"_ContentHeader"} style={[styles.screenContent,theme.styles.p1,header?styles.screenContentWithHeader:null]}>
|
|
404
404
|
{header}
|
|
405
405
|
{content}
|
|
406
|
-
</
|
|
407
|
-
{ct ? <
|
|
406
|
+
</View>
|
|
407
|
+
{ct ? <View {...contentProps} testID={testID+"_DesktopContentTabs"} style={[contentProps.style]}>
|
|
408
408
|
{ct}
|
|
409
|
-
</
|
|
409
|
+
</View> : null}
|
|
410
410
|
</ScrollView>
|
|
411
411
|
</View>
|
|
412
412
|
}
|
|
413
413
|
} else {
|
|
414
|
-
mainContent = <
|
|
415
|
-
<
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
</ScrollView>
|
|
421
|
-
</View>
|
|
414
|
+
mainContent = <ScrollView testID={testID+"_MainContentScrollViewWithoutTab"}>
|
|
415
|
+
<View testID={testID+"_MainContent"} style={[styles.screenContent,!isMobOrTab && theme.styles.p1,header?styles.screenContentWithHeader:null]}>
|
|
416
|
+
{header}
|
|
417
|
+
{content}
|
|
418
|
+
</View>
|
|
419
|
+
</ScrollView>
|
|
422
420
|
}
|
|
423
421
|
const appBarProps = this.getAppBarActionsProps(restProps);
|
|
424
422
|
if(hasTabs && isMobOrTab){
|
package/src/navigation/utils.js
CHANGED
|
@@ -37,6 +37,7 @@ const navigateToTableOrStructData = function(tableName,params,actionType){
|
|
|
37
37
|
if(!isAllowed){
|
|
38
38
|
return Auth.showError();
|
|
39
39
|
}
|
|
40
|
+
params.tableName = tableName;
|
|
40
41
|
params.routeName = buildScreenRoute(tableName,actionType =='structdata'? structDataRouteName : tableDataRouteName);
|
|
41
42
|
return navigate(params)
|
|
42
43
|
}
|
package/src/screens/index.js
CHANGED