@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "6.26.18",
3
+ "version": "6.27.1",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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 = {(e)=>{
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 {wrapperStyle,title,right,rightProps,description,avatarContent,rowProps} = props;
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 = {React.useMergeRefs(ref,innerRef)}
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
- if(isObj(this.renderingItemsProps) && isObj(this.renderingItemsProps[rowKey]) ){
205
- this.renderingItemsProps[rowKey].ref = el;
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 : 5,
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 : 10,
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: 'transparent',
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,
@@ -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";
@@ -2,4 +2,6 @@ export * from "./hooks";
2
2
 
3
3
  export {default} from "./hooks";
4
4
 
5
- export {default as Provider} from "./Provider";
5
+ export {default as Provider} from "./Provider";
6
+
7
+ export * from "./TableData";
@@ -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
- <Surface testID={testID+"_MainTab_Content"} elevation={5} {...contentProps} style={[styles.noMarging,contentProps.style,styles.h100,styles.noPadding]}>
388
+ <View testID={testID+"_MainTab_Content"} {...contentProps} style={[styles.noMarging,contentProps.style,styles.h100,styles.noPadding]}>
389
389
  {header}
390
390
  {content}
391
- </Surface>
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
- <Surface elevation={elevation} testID={testID+"_ContentHeader"} style={[styles.screenContent,theme.styles.p1,header?styles.screenContentWithHeader:null]}>
403
+ <View testID={testID+"_ContentHeader"} style={[styles.screenContent,theme.styles.p1,header?styles.screenContentWithHeader:null]}>
404
404
  {header}
405
405
  {content}
406
- </Surface>
407
- {ct ? <Surface {...contentProps} testID={testID+"_DesktopContentTabs"} elevation={elevation} style={[contentProps.style]}>
406
+ </View>
407
+ {ct ? <View {...contentProps} testID={testID+"_DesktopContentTabs"} style={[contentProps.style]}>
408
408
  {ct}
409
- </Surface> : null}
409
+ </View> : null}
410
410
  </ScrollView>
411
411
  </View>
412
412
  }
413
413
  } else {
414
- mainContent = <View {...contentProps} testID={testID+"_MainContentContainer"} elevation={elevation} style={[styles.container,{backgroundColor:theme.colors[theme.isDark()?"background":"surface"]},styles.noPadding,{paddingTop:0,marginTop:0},contentProps.style]}>
415
- <ScrollView withAutoSizer testID={testID+"_MainContentScrollViewWithoutTab"}>
416
- <View testID={testID+"_MainContent"} style={[styles.screenContent,!isMobOrTab && theme.styles.p1,header?styles.screenContentWithHeader:null]}>
417
- {header}
418
- {content}
419
- </View>
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){
@@ -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
  }
@@ -46,6 +46,7 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,filter,index})=
46
46
  groupName = GROUP_NAMES.PRIVATE;
47
47
  authRequired = true;
48
48
  }
49
+ authRequired = authRequired || groupName === GROUP_NAMES.PRIVATE;
49
50
  } else {
50
51
  authRequired = false;
51
52
  }