@fto-consult/expo-ui 6.2.0 → 6.3.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.
@@ -20,36 +20,26 @@ module.exports = (opts)=>{
20
20
  r["$econfirm"] = path.resolve(r["$expo-components"],"Dialog","confirm");
21
21
  r["$confirm"] = r["$confirm"] || r["$econfirm"];
22
22
  r["$eauth"] = path.resolve(expo,"auth");
23
- r["$etableLink"] = r["$eTableLink"] = path.resolve(r["$ecomponents"],"TableLink");
24
- r.$tableLink = r.$TableLink = r.$tableLink || r.$TableLink || path.resolve(r.$etableLink,"default");
25
23
  r["$components"] = r["$components"] || r["$ecomponents"];
26
24
  r["$elayouts"] = path.resolve(expo,"layouts");
27
25
  r["$emedia"] = path.resolve(expo,"media");
28
26
  r["$enavigation"] = path.resolve(expo,"navigation");
29
27
  r["$escreens"] = path.resolve(expo,"screens");
30
- r["$emainScreens"] = path.resolve(expo,"screens","mainScreens");
31
28
  ///les screens principaux de l'application
32
- r["$mainScreens"] = r["$mainScreens"] || r["$emainScreens"];
33
29
  r["$escreen"] = r["$eScreen"] = path.resolve(expo,"layouts/Screen");
34
- r["$eTableDataScreen"] = path.resolve(expo,"layouts","Screen","TableData");
35
- r["$TableDataScreen"] = r["$tableDataScreen"] = r["$TableDataScreen"] || r["$tableDataScreen"] || r["$eTableDataScreen"]
36
30
  r["$eassets"] = path.resolve(dir,"assets");
37
31
  r["$ethemeSelectorComponent"] = path.resolve(expo,"auth","ThemeSelector");
38
32
  /*** le composant permettant de sélectionner un theme utilisateur */
39
33
  r["$themeSelectorComponent"] = r["$themeSelectorComponent"] || r["$ethemeSelectorComponent"];
40
-
34
+ r.$tableLink = r.$TableLink = r["$etableLink"] = r["$eTableLink"] = path.resolve(r["$ecomponents"],"TableLink");
35
+
41
36
  r["$Screen"] = r["$Screen"] || r["$eScreen"];
42
- ///pour personnaliser les écrans de l'application, il suffit de redefinir l'alis $screens, pointant vers le repertoire racine des écrans personnalisés
43
- ///cependant, ce repertoire doit contenir un fichier mainScreens.js qui contient la liste de tous les écrans de lapplicaiton
44
37
  r["$screens"] = r["$screens"] || r["$escreens"];
45
38
 
46
39
  r["$expo"] = r["$expo-ui"] = expo;
47
40
  r["$epreloader"] = path.resolve(expo,"components/Preloader");
48
41
  r["$eform"] = path.resolve(expo,"components","Form");
49
42
 
50
- //l'alias $extendFormFields, pour étendre les formFields qu'on veut définir
51
- r["$extendFormFields"] = r["$extendFormFields"] || path.resolve(r["$eform"],"Fields","$extendFormFields")
52
-
53
43
  r["$form"] = r["$form"] || r["$eform"];
54
44
  r["$eform-data"] = r["$eformData"]= path.resolve(expo,"components","Form","FormData");
55
45
  r["$formData"] = r["$formData"] || r["$eformData"];
@@ -72,26 +62,10 @@ module.exports = (opts)=>{
72
62
  if(!r["$file-system"]){
73
63
  r["$file-system"] = r["$efile-system"];
74
64
  }
75
- /*** cet alias est utilisé pour modifier les différents items par défaut, rendu par le composant Drawer
76
- * l'alias @drawerItems doit retourner en default, soit un tableau où un objet d'objet où une fonction
77
- * si c'est une fonction, alors la function est exécutée pour obtenir la liste des items à utiliser par le drawer principal
78
- */
79
- if(!r["$drawerItems"]){
80
- r["$drawerItems"] = path.resolve(expo,"navigation","Drawer","items","default")
81
- }
82
65
  ///si l'alias $navigation n'a pas été définie par défaut, alors celui cet allias prendra la même valeur que celle de $envigation
83
66
  if(r["$navigation"] == r["$cnavigation"]){
84
67
  r["$navigation"] = r["$enavigation"];
85
68
  }
86
- if(r["$loginComponent"] == r["$cloginComponent"]){
87
- r["$loginComponent"] = path.resolve(expo,"auth","Login");
88
- }
89
-
90
- /*** alias pour le composant logo par défaut : */
91
- r["$elogoComponent"] = path.resolve(expo,"components","Logo","defaultComponent");
92
- if(!r["$logoComponent"]){
93
- r["$logoComponent"] = r["$elogoComponent"];
94
- }
95
69
  if(typeof opts.mutator =='function'){
96
70
  opts.mutator(r);
97
71
  }
@@ -133,9 +107,9 @@ module.exports = (opts)=>{
133
107
  //le chemin ver le repertoire electron
134
108
  r.$eelectron = r["$e-electron"] = $electron;
135
109
  r.$electron = r.$electron || r.$eelectron;
136
- r.$econtext = path.resolve(expo,"context");
110
+ r.$econtext/hooks = path.resolve(expo,"context");
137
111
  if(!r.$context){
138
- r.$context = r.$econtext;
112
+ r.$context = r.$econtext/hooks;
139
113
  }
140
114
  const electronAssetsPath = path.resolve(dir,"electron","assets");
141
115
  if($assets){
package/index.js CHANGED
@@ -18,9 +18,9 @@ import {isObj} from "$cutils";
18
18
  * }
19
19
  */
20
20
  export default function registerApp (options){
21
- const {onMount,onUnmount,onRender,swrConfig,...rest} = isObj(options)? options : {};
21
+ const {onMount,onUnmount,onRender,render,swrConfig,...rest} = isObj(options)? options : {};
22
22
  registerRootComponent(function(props){
23
- return <Provider {...props} {...rest} swrConfig={isObj(swrConfig) && swrConfig || {}} children={<App onMount={onMount} onUnmount={onUnmount} onRender={onRender}/>}/>
23
+ return <Provider {...props} {...rest} swrConfig={isObj(swrConfig) && swrConfig || {}} children={<App render={render} onMount={onMount} onUnmount={onUnmount} onRender={onRender}/>}/>
24
24
  });
25
25
  }
26
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "6.2.0",
3
+ "version": "6.3.0",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/App.js CHANGED
@@ -17,7 +17,8 @@ import { timeout as SWR_REFRESH_TIMEOUT} from '$ecomponents/Datagrid/SWRDatagrid
17
17
  import { Dimensions,Keyboard } from 'react-native';
18
18
  import {isTouchDevice} from "$platform";
19
19
  import * as Utils from "$cutils";
20
- import useContext from "$econtext";
20
+ import {useContext} from "$econtext/hooks";
21
+ import appConfig from "$capp/config";
21
22
 
22
23
  Object.map(Utils,(v,i)=>{
23
24
  if(typeof v =='function' && typeof window !='undefined' && window && !window[i]){
@@ -25,8 +26,8 @@ Object.map(Utils,(v,i)=>{
25
26
  }
26
27
  });
27
28
 
28
- export default function getIndex({onMount,onUnmount,onRender}){
29
- const {swrConfig,appConfig} = useContext();
29
+ export default function getIndex({onMount,onUnmount,render,onRender}){
30
+ const {swrConfig} = useContext();
30
31
  const isScreenFocusedRef = React.useRef(true);
31
32
  ///garde pour chaque écran sa date de dernière activité
32
33
  const screensRef = React.useRef({});//la liste des écrans actifs
@@ -140,7 +141,7 @@ export default function getIndex({onMount,onUnmount,onRender}){
140
141
  >
141
142
  <GestureHandlerRootView style={{ flex: 1 }}>
142
143
  <SafeAreaProvider>
143
- <Index {...rest} onMount={onMount}/>
144
+ <Index onMount={onMount} render={render} onUnmount={onUnmount} onRender={onRender}/>
144
145
  </SafeAreaProvider>
145
146
  </GestureHandlerRootView>
146
147
  </SWRConfig>
@@ -55,7 +55,7 @@ const AppbarContent = ({
55
55
  ]}
56
56
  numberOfLines={1}
57
57
  accessible
58
- accessibilityRole={
58
+ role={
59
59
  onPress
60
60
  ? 'none'
61
61
  : Platform.OS === 'web'
@@ -86,7 +86,7 @@ const AppbarContent = ({
86
86
  <TouchableWithoutFeedback
87
87
  testID={testID+"_Container"}
88
88
  {...containerProps}
89
- accessibilityRole={touchableRole}
89
+ role={touchableRole}
90
90
  accessibilityTraits={touchableRole}
91
91
  accessibilityComponentType="button"
92
92
  onPress={onPress}
@@ -247,7 +247,7 @@ const styles = StyleSheet.create({
247
247
  text: {
248
248
  minHeight: 24,
249
249
  lineHeight: 24,
250
- textAlignVertical: 'center',
250
+ verticalAlign: 'center',
251
251
  marginVertical: 4,
252
252
  },
253
253
  avatar: {
@@ -7,7 +7,7 @@ import DateLib from "$date";
7
7
  import Image from "$ecomponents/Image";
8
8
  import React from "$react";
9
9
  import Label from "$ecomponents/Label";
10
- import TableLink from "$TableLink";
10
+ import TableLink from "$components/TableLink";
11
11
  import {Flag} from "$ecomponents/Countries";
12
12
  import { StyleSheet } from "react-native";
13
13
  import {isDesktopMedia} from "$dimensions";
@@ -25,7 +25,7 @@ import {getRowsPerPagesLimits} from "./Common/utils";
25
25
  import PropTypes from "prop-types";
26
26
  import {Menu} from "$ecomponents/BottomSheet";
27
27
  import session from "$session";
28
- import useContext from "$econtext";
28
+ import useContext from "$econtext/hooks";
29
29
 
30
30
  export const getSessionKey = ()=>{
31
31
  return Auth.getSessionKey("swrDatagrid");
@@ -252,7 +252,8 @@ const DrawerComponent = React.forwardRef((props,ref)=>{
252
252
  return isItemActive(opts);
253
253
  }
254
254
  return false;
255
- },getState:getDrawerState,getDrawerRef}}>
255
+ },getState:getDrawerState,getDrawerRef
256
+ }}>
256
257
  <View style={styles.container} testID={`${testID}_Container`}>
257
258
  <DrawerLayout
258
259
  testID = {`${testID}_DrawerLayout`}
@@ -882,12 +882,12 @@ class DropdownComponent extends AppComponent {
882
882
  onPress={this.open.bind(this)}
883
883
  disabled = {disabled}
884
884
  onLayout={bindResizeEvents === false ? undefined : this.onLayout.bind(this)}
885
- pointerEvents = {pointerEvents}
885
+ style = {{pointerEvents}}
886
886
  accessibilityLabel={defaultStr(accessibilityLabel,label,text)}
887
887
  testID = {testID}
888
888
  >
889
889
  {<React.Fragment>{
890
- <View {...dropdownProps} {...contentContainerProps} style={[contentContainerProps.style,flattenStyle]}
890
+ <View {...dropdownProps} {...contentContainerProps} style={[contentContainerProps.style,{pointerEvents},flattenStyle]}
891
891
  ref = {this.anchorRef}
892
892
  collapsable = {false}
893
893
  >
@@ -900,15 +900,14 @@ class DropdownComponent extends AppComponent {
900
900
  mode = {mode}
901
901
  enableCopy = {enableCopy}
902
902
  label = {labelTextField}
903
- pointerEvents = "none"
903
+ style = {[inputProps.style,textInputProps.style,{pointerEvents:"none"}]}
904
904
  disabled = {disabled}
905
905
  readOnly = {readOnly}
906
906
  //divider = {canHandle}
907
907
  alwaysUseLabel = {renderTag?true : false}
908
908
  contentContainerProps = {{
909
909
  ...contentContainerProps,
910
- pointerEvents:iconDisabled && (!enableCopy && disabled)?'none':'auto',
911
- style : [renderTag? styles.inputContainerTag:null,contentContainerProps.style],
910
+ style : [renderTag? styles.inputContainerTag:null,{pointerEvents:iconDisabled && (!enableCopy && disabled)?'none':'auto'},contentContainerProps.style],
912
911
  }}
913
912
  containerProps = {{...containerProps,style:[containerProps.style,styles.mbO]}}
914
913
  error = {!!error}
@@ -932,7 +931,7 @@ class DropdownComponent extends AppComponent {
932
931
  onPress = {this.open.bind(this)}
933
932
  placeholder={placeholder}
934
933
  render = {!renderTag?inputProps.render : (tagProps)=>{
935
- return <View pointerEvents={pointerEvents} style={[styles.tagsContentContainer,isFlatMode?styles.tagsContentContainerFlatMode:null]}>
934
+ return <View style={[styles.tagsContentContainer,{pointerEvents},isFlatMode?styles.tagsContentContainerFlatMode:null]}>
936
935
  {tagsContent}
937
936
  </View>
938
937
  }}
@@ -1001,8 +1000,8 @@ class DropdownComponent extends AppComponent {
1001
1000
  height : !isMob?contentContainerHeight:'90%',
1002
1001
  },
1003
1002
  isMob && {flex:1},
1003
+ {pointerEvents}
1004
1004
  ]}
1005
- pointerEvents = {pointerEvents}
1006
1005
  testID = {testID+"_Container"}
1007
1006
  >
1008
1007
  {showSearch !== false && <>
@@ -11,7 +11,7 @@ import {getFetchOptions,prepareFilters} from "$cutils/filters";
11
11
  import fetch from "$capi"
12
12
  import {willConvertFiltersToSQL} from "$ecomponents/Datagrid/utils";
13
13
  import React from "$react";
14
- import appConfig from "$appConfig";
14
+ import useApp from "$econtext/hooks";
15
15
 
16
16
  /*** la tabledataSelectField permet de faire des requêtes distantes pour rechercher les données
17
17
  * Elle doit prendre en paramètre et de manière requis : les props suivante :
@@ -19,8 +19,9 @@ import appConfig from "$appConfig";
19
19
  * foreignKeyTable : la tableData dans laquelle effectuer les donées de la requêtes
20
20
  * foreignKeyLabel : Le libélé dans la table étrangère
21
21
  */
22
- const TableDataSelectField = React.forwardRef(({foreignKeyColumn,prepareFilters:cPrepareFilters,bindUpsert2RemoveEvents,onAdd,showAdd:customShowAdd,canShowAdd,foreignKeyTable,fetchItemsPath,foreignKeyLabel,foreignKeyLabelIndex,dropdownActions,fields,fetchItems:customFetchItem,convertFiltersToSQL,mutateFetchedItems,getForeignKeyTable,onFetchItems,isFilter,isUpdate,isDocEditing,items,onAddProps,fetchOptions,...props},ref)=>{
22
+ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,prepareFilters:cPrepareFilters,bindUpsert2RemoveEvents,onAdd,showAdd:customShowAdd,canShowAdd,foreignKeyTable,fetchItemsPath,foreignKeyLabel,foreignKeyLabelIndex,dropdownActions,fields,fetchItems:customFetchItem,convertFiltersToSQL,mutateFetchedItems,onFetchItems,isFilter,isUpdate,isDocEditing,items,onAddProps,fetchOptions,...props},ref)=>{
23
23
  props.data = defaultObj(props.data);
24
+ const {getTableData:getForeignKeyTable} = useApp();
24
25
  if(!foreignKeyColumn && isNonNullString(props.field)){
25
26
  foreignKeyColumn = props.field;
26
27
  }
@@ -32,11 +33,13 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,prepareFilters:
32
33
  foreignKeyLabel = foreignKeyLabel.ltrim("[").rtrim("]").split(",");
33
34
  }
34
35
  convertFiltersToSQL = defaultVal(convertFiltersToSQL,willConvertFiltersToSQL());
35
- getForeignKeyTable = getForeignKeyTable || appConfig.getTableData;
36
- const foreignKeyTableStr = defaultStr(foreignKeyTable,props.table,props.tableName);
37
- let fKeyTable = typeof getForeignKeyTable =='function' ? getForeignKeyTable(foreignKeyTableStr,props) : undefined;
36
+ const foreignKeyTableStr = defaultStr(foreignKeyTable,props.tableName,props.table);
37
+ if(typeof getForeignKeyTable !=='function'){
38
+ console.error("la fonction getTableData non définie des les paramètres d'initialisation de l'application!!! Rassurez vous d'avoir définier cette fonction!!, options : foreignKeyTable:",foreignKeyTable,"foreignKeyColumn:",foreignKeyColumn,props)
39
+ return null;
40
+ }
41
+ let fKeyTable = getForeignKeyTable(foreignKeyTableStr,props);
38
42
  fetchItemsPath = defaultStr(fetchItemsPath).trim();
39
-
40
43
  if(!fetchItemsPath && (!isObj(fKeyTable) || !(defaultStr(fKeyTable.tableName,fKeyTable.table)))){
41
44
  console.error("type de données invalide pour la foreignKeyTable ",foreignKeyTable," label : ",foreignKeyLabel,fKeyTable," composant SelectTableData",foreignKeyColumn,foreignKeyTable,props);
42
45
  return null;
@@ -306,7 +309,6 @@ TableDataSelectField.propTypes = {
306
309
  canShowAdd : PropTypes.func, //({foreignKeyTable,foreignKeyColumn})=><boolean> la fonction permettant de spécifier si l'on peut afficher le bouton showAdd
307
310
  mutateFetchedItems : PropTypes.func, //la fonction permettant d'effectuer une mutation sur l'ensemble des donnéees récupérées à distance
308
311
  fetchItems : PropTypes.func,//la fonction de rappel à utiliser pour faire une requête fetch permettant de selectionner les données à distance
309
- getForeignKeyTable : PropTypes.func, //la fonction permettant de récupérer la fKeyTable data dont fait référence le champ
310
312
  foreignKeyTable : PropTypes.string, //le nom de la fKeyTable data à laquelle se reporte le champ
311
313
  fetchItemsPath : PropTypes.string, //le chemin d'api pour récupérer les items des données étrangères en utilisant la fonction fetch
312
314
  beforeFetchItems : PropTypes.func, //appelée immédiatement avant l'exécution de la requête fetch
@@ -16,12 +16,10 @@ import Image from "./Image";
16
16
  import Tel from "./Tel";
17
17
  import SelectCountry from "./SelectCountry";
18
18
  import Html from "./Html";
19
- import * as eFormFields from "$extendFormFields";
20
19
  import "$cutils";
21
20
  import React from "$react";
22
21
  import SelectDateFormat from "./SelectDateFormat";
23
22
  import CurrencyFormat from "./CurrencyFormat";
24
- export * from "$extendFormFields";
25
23
 
26
24
  const defFormFields = {
27
25
  Field,
@@ -46,13 +44,6 @@ const defFormFields = {
46
44
  ,Html
47
45
  }
48
46
 
49
- //pour étendre les FormFields par défaut
50
- Object.map(eFormFields,(F,i)=>{
51
- if(React.isComponent(F)){
52
- defFormFields[i] = F;
53
- }
54
- })
55
-
56
47
  export default defFormFields;
57
48
 
58
49
  export {
@@ -4,11 +4,11 @@ import React from "$react";
4
4
  import theme,{remToPixel,Colors,flattenStyle} from '$theme';
5
5
  import {StyleSheet} from "react-native";
6
6
  import {defaultStr,defaultObj,defaultNumber} from "$cutils";
7
- import LogoComponent from "$logoComponent";
8
-
7
+ import useContext from "$econtext/hooks";
9
8
  export const height = 150;
10
9
  export const width = undefined;//300;
11
10
  export default function Logo (props) {
11
+ const {components:{logo:LogoComponent}} = useContext();
12
12
  let {icon,color,style,testID,containerProps,smallStyle,largeStyle,mediumStyle,height:customHeight,withImage,withText} = props;
13
13
  testID = defaultStr(testID,"RN_LogoComponent");
14
14
  containerProps = defaultObj(containerProps);
@@ -14,9 +14,10 @@ import Tooltip from "$ecomponents/Tooltip";
14
14
  import {navigateToTableData} from "$enavigation/utils";
15
15
  import Auth from "$cauth";
16
16
  import fetch from "$capi/fetch";
17
-
17
+ import useContext from "$econtext/hooks";
18
18
  const TableLinKComponent = React.forwardRef((props,ref)=>{
19
- let {disabled,readOnly,labelProps,server,containerProps,perm,id,fetchForeignData,foreignKeyTable,foreignKeyColumn,data,testID,Component,routeName,routeParams,component,primary,triggerProps,onPress,children, ...rest} = props;
19
+ const {components:{tableLinkPropsMutator}} = useContext();
20
+ let {disabled,readOnly,labelProps,server,containerProps,perm,id,fetchForeignData,foreignKeyTable,foreignKeyColumn,data,testID,Component,routeName,routeParams,component,primary,triggerProps,onPress,children, ...rest} = tableLinkPropsMutator(props);
20
21
  testID = defaultStr(testID,"RN_TableDataLinkContainer")
21
22
  foreignKeyTable = defaultStr(foreignKeyTable).trim();
22
23
  foreignKeyColumn = defaultStr(foreignKeyColumn).trim();
@@ -24,11 +25,11 @@ const TableLinKComponent = React.forwardRef((props,ref)=>{
24
25
  containerProps = defaultObj(containerProps)
25
26
  labelProps = defaultObj(labelProps);
26
27
  data = defaultObj(data);
27
- id = defaultStr(id);
28
+ id = typeof id =='number'? String(id) : defaultStr(id);
28
29
  if(!id || !foreignKeyTable){
29
30
  readOnly = true;
30
31
  }
31
- const pointerEvents = disabled || readOnly || !id? 'none' : 'auto';
32
+ const pointerEvents = disabled || readOnly ? 'none' : 'auto';
32
33
  const onPressLink = (event)=>{
33
34
  React.stopEventPropagation(event);
34
35
  if((isNonNullString(perm) && !Auth.isAllowedFromString(perm)) || !Auth.isTableDataAllowed({table:foreignKeyTable,action:'read'})){
@@ -55,9 +56,9 @@ const TableLinKComponent = React.forwardRef((props,ref)=>{
55
56
  cb().finally(closePreloader);
56
57
  }
57
58
  }
58
- rest.style = [rest.style,_styles.cursorPointer];
59
+ rest.style = [rest.style,{pointerEvents},_styles.cursorPointer];
59
60
  const CP = disabled || readOnly ? View : Pressable;
60
- return <CP testID={testID} onLongPres={(e)=>React.stopEventPropagation(e)} {...containerProps} onPress={disabled? undefined : onPressLink} style={[styles.container,containerProps.style]}>
61
+ return <CP testID={testID} onLongPres={(e)=>React.stopEventPropagation(e)} {...containerProps} onPress={disabled || readOnly? undefined : onPressLink} style={[styles.container,containerProps.style]}>
61
62
  <Tooltip testID={testID+"_Tooltip"} {...rest} Component={Component} onPress={disabled || readOnly?undefined:onPressLink} ref={ref} pointerEvents={pointerEvents} readOnly={readOnly} disabled = {disabled}>
62
63
  <Label testID={testID+"_Label"} underlined primary {...labelProps} style={[_styles.lh15,labelProps.style]} disabled={disabled} readOnly={readOnly}>{children}</Label>
63
64
  </Tooltip>
@@ -76,7 +77,7 @@ TableLinKComponent.propTypes = {
76
77
  ///les props à utiliser pour afficher la table de données en cas de click sur le lien
77
78
  triggerProps : PropTypes.object,
78
79
  /*** l'id de la données à récupérer en cas de clic sur le lien */
79
- id : PropTypes.string,
80
+ id : PropTypes.oneOfType([PropTypes.number,PropTypes.string]),
80
81
  routeName : PropTypes.string,///la route via laquelle on devra naviguer
81
82
  routeParam : PropTypes.object,///les props à passer à la route en question
82
83
  children : PropTypes.node
@@ -347,7 +347,7 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
347
347
  backgroundColor : 'transparent',
348
348
  color : !error && !isFocused && Colors.isValid(flattenStyle.color)?flattenStyle.color : inputColor,
349
349
  fontSize,
350
- textAlignVertical: 'center',//multiline ? 'top' : 'center',
350
+ verticalAlign: 'center',//multiline ? 'top' : 'center',
351
351
  overflow : 'hidden',
352
352
  },
353
353
  isWeb && { outline: 'none'},
@@ -0,0 +1,95 @@
1
+ import React from "$react";
2
+ import appConfig from "$capp/config";
3
+ import {MD3LightTheme,MD3DarkTheme} from "react-native-paper";
4
+ import { useMaterial3Theme } from '@pchmn/expo-material3-theme';
5
+ import {colorsAlias,Colors} from "$theme";
6
+ import {isObj} from "$cutils";
7
+ import eMainScreens from "$escreens/mainScreens";
8
+ import {ExpoUIContext} from "./hooks";
9
+
10
+ /*****
11
+ les utilitaires disponibles à passer au provider :
12
+ FontsIconsFilter : (font{object},fontName{string},fontNameLower{string})=><boolean> //porte le nom de la props de appConfig dans lequel définir les filtres à utiliser pour charger l'iconSet désirée pour l'appication
13
+ ///fonction de rappel appelée avant d'exit l'application, doit retourner une promesse que lorsque résolue, exit l'application
14
+ beforeExit : ()=><Promise>
15
+ getTableData : ()=>{object|array}
16
+ getStructData : ()=>{object|array}
17
+ tablesData : {object}, la liste des tables de données
18
+ strucsData : {object}, la liste des données de structures
19
+ components : {
20
+ logo : {
21
+ object |
22
+ ReactNode,
23
+ ReactComponent
24
+ },
25
+ //la fonction permettant de muter les props du composant TableLink
26
+ tableLinkPropsMutator : ({object})=><{object}>, la fonction permettant de muter les props du composant TableLink
27
+ },
28
+ navigation : {
29
+ screens : {Array}, les écrans de navigation,
30
+ drawerItems : {object|array|function}, la fonction permettant d'obtenir les items du drawer principal de l'application
31
+ }
32
+ */
33
+ const Provider = ({children,getTableData,navigation,components,getStructData,tablesData,structsData,...props})=>{
34
+ const {extendAppTheme} = appConfig;
35
+ const { theme : pTheme } = useMaterial3Theme();
36
+ navigation = defaultObj(navigation);
37
+ components = defaultObj(components);
38
+ const {screens} = navigation;
39
+ navigation.screens = [...(Array.isArray(screens)? screens : []),...eMainScreens];
40
+ structsData = isObj(structsData)? structsData : null;
41
+ appConfig.tablesData = tablesData;
42
+ appConfig.structsData = appConfig.structsData = isObj(structsData)? structsData : null;
43
+ appConfig.getTableData = getTableData;
44
+ appConfig.getStructData = getStructData;
45
+ //const colorScheme = useColorScheme();
46
+ appConfig.extendAppTheme = (theme)=>{
47
+ if(!isObj(theme)) return;
48
+ const newTheme = theme.dark || theme.isDark ? { ...MD3DarkTheme, colors: pTheme.dark } : { ...MD3LightTheme, colors: pTheme.light };
49
+ for(let i in newTheme){
50
+ if(i !== 'colors' && !(i in theme)){
51
+ theme[i] = newTheme[i];
52
+ }
53
+ }
54
+ if(isObj(theme.colors)){
55
+ colorsAlias.map((color)=>{
56
+ color = color.trim();
57
+ const cUpper = color.ucFirst();
58
+ //math theme colors to material desgin V3
59
+ const textA = `${color}Text`,onColor=`on${cUpper}`//,containerA = `${color}Container`,onColorContainer=`on${cUpper}Container`;
60
+ const c = Colors.isValid(theme.colors[onColor])? theme.colors[onColor] : (theme.colors[textA]) || undefined;
61
+ if(c){
62
+ theme.colors[onColor] = c;
63
+ }
64
+ });
65
+ for(let i in newTheme.colors){
66
+ if(!(i in theme.colors)){
67
+ theme.colors[i] = newTheme.colors[i];
68
+ }
69
+ }
70
+ }
71
+ theme.fonts = newTheme.fonts;
72
+ return typeof extendAppTheme == 'function'? extendAppTheme(theme) : theme;
73
+ }
74
+ return <ExpoUIContext.Provider
75
+ value={{
76
+ ...props,
77
+ navigation,
78
+ components : {
79
+ ...components,
80
+ tableLinkPropsMutator : (props)=>{
81
+ const prs = defaultObj(props);
82
+ const o = typeof components.tableLinkPropsMutator ==='function'? components.tableLinkPropsMutator(props) : null;
83
+ if(isObj(o)){
84
+ return {...prs,...o};
85
+ }
86
+ return prs
87
+ }
88
+ },
89
+ getTableData,getStructData,tablesData,structsData,appConfig
90
+ }}
91
+ children={children}
92
+ />;
93
+ }
94
+
95
+ export default Provider;
@@ -0,0 +1,11 @@
1
+ import { createContext,useContext as useReactContext } from "react";
2
+
3
+ export const ExpoUIContext = createContext(null);
4
+
5
+ export const useExpoUI = ()=> useReactContext(ExpoUIContext);
6
+
7
+ export default useExpoUI;
8
+
9
+ export const useContext = useExpoUI;
10
+
11
+ export const useApp = useContext;
@@ -1,57 +1,5 @@
1
- import React from "$react";
2
- import appConfig from "$capp/config";
3
- import {MD3LightTheme,MD3DarkTheme} from "react-native-paper";
4
- import { useMaterial3Theme } from '@pchmn/expo-material3-theme';
5
- import {colorsAlias,Colors} from "$theme";
1
+ export * from "./hooks";
6
2
 
7
- const ExpoUIContext = React.createContext(null);
3
+ export {default} from "./hooks";
8
4
 
9
-
10
- export const useExpoUI = ()=> React.useContext(ExpoUIContext);
11
-
12
-
13
- /*****
14
- les utilitaires disponibles à passer au provider :
15
- FontsIconsFilter : (font{object},fontName{string},fontNameLower{string})=><boolean> //porte le nom de la props de appConfig dans lequel définir les filtres à utiliser pour charger l'iconSet désirée pour l'appication
16
- ///fonction de rappel appelée avant d'exit l'application, doit retourner une promesse que lorsque résolue, exit l'application
17
- beforeExit : ()=><Promise>
18
-
19
- */
20
- export const Provider = ({children,...props})=>{
21
- const {extendAppTheme} = appConfig;
22
- const { theme : pTheme } = useMaterial3Theme();
23
- //const colorScheme = useColorScheme();
24
- appConfig.extendAppTheme = (theme)=>{
25
- if(!isObj(theme)) return;
26
- const newTheme = theme.dark || theme.isDark ? { ...MD3DarkTheme, colors: pTheme.dark } : { ...MD3LightTheme, colors: pTheme.light };
27
- for(let i in newTheme){
28
- if(i !== 'colors' && !(i in theme)){
29
- theme[i] = newTheme[i];
30
- }
31
- }
32
- if(isObj(theme.colors)){
33
- colorsAlias.map((color)=>{
34
- color = color.trim();
35
- const cUpper = color.ucFirst();
36
- //math theme colors to material desgin V3
37
- const textA = `${color}Text`,onColor=`on${cUpper}`//,containerA = `${color}Container`,onColorContainer=`on${cUpper}Container`;
38
- const c = Colors.isValid(theme.colors[onColor])? theme.colors[onColor] : (theme.colors[textA]) || undefined;
39
- if(c){
40
- theme.colors[onColor] = c;
41
- }
42
- });
43
- for(let i in newTheme.colors){
44
- if(!(i in theme.colors)){
45
- theme.colors[i] = newTheme.colors[i];
46
- }
47
- }
48
- }
49
- theme.fonts = newTheme.fonts;
50
- return typeof extendAppTheme == 'function'? extendAppTheme(theme) : theme;
51
- }
52
- return <ExpoUIContext.Provider value={{...props,appConfig}} children={children}/>;
53
- }
54
-
55
- export default useExpoUI;
56
-
57
- export const useContext = useExpoUI;
5
+ export {default as Provider} from "./Provider";
package/src/index.js CHANGED
@@ -39,7 +39,7 @@ import {updateTheme,defaultTheme} from "$theme";
39
39
  import StatusBar from "$ecomponents/StatusBar";
40
40
  import {Provider as PaperProvider } from 'react-native-paper';
41
41
  import FontIcon from "$ecomponents/Icon/Font";
42
- import useContext from "$econtext";
42
+ import useContext from "$econtext/hooks";
43
43
 
44
44
  let MAX_BACK_COUNT = 1;
45
45
  let countBack = 0;
@@ -57,9 +57,9 @@ const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
57
57
  * initialRouteName : la route initiale par défaut
58
58
  * getStartedRouteName : la route par défaut de getStarted lorsque l'application est en mode getStarted, c'est à dire lorsque la fonction init renvoie une erreur (reject)
59
59
  */
60
- function App({init:initApp,initialRouteName:appInitialRouteName,render,onMount,preferences:appPreferences,getStartedRouteName}) {
60
+ function App({init:initApp,initialRouteName:appInitialRouteName,render,onMount}) {
61
61
  AppStateService.init();
62
- const {FontsIconsFilter,beforeExit} = useContext();
62
+ const {FontsIconsFilter,beforeExit,preferences:appPreferences,getStartedRouteName} = useContext();
63
63
  const [initialState, setInitialState] = React.useState(undefined);
64
64
  const appReadyRef = React.useRef(true);
65
65
  const [state,setState] = React.useState({
@@ -100,7 +100,6 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
100
100
  }
101
101
  Auth.upsertUser({...u,avatar:u.avatar},false);
102
102
  }
103
-
104
103
  return <View ref ={ref}>
105
104
  <Menu
106
105
  anchor = { (aProps)=>{
@@ -131,34 +130,30 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
131
130
  />
132
131
  </View>
133
132
  }
134
- return <Button
133
+ return <Pressable
135
134
  normal
136
135
  upperCase = {false}
137
136
  disableRipple
138
137
  title = {tooltip}
139
138
  {...aProps}
140
139
  style = {[styles.container]}
141
- surfaceProps = {{style:[theme.styles.noMargin,theme.styles.noPadding]}}
140
+ //surfaceProps = {{style:[theme.styles.noMargin,theme.styles.noPadding]}}
142
141
  onLongPress = {onLongPress}
143
- left={props1 => <Image
142
+ >
143
+ <Image
144
144
  {...props}
145
- {...props1}
146
145
  size={size}
147
146
  style = {styles.itemLeft}
148
147
  testID = {"RN_ProfilAvatar_AvatarImage"}
149
148
  readOnly = {false}
150
149
  defaultSource ={avatarProps.defaultSrc}
151
150
  onChange = {onChangeAvatar}
152
- />}
153
- right = {(p)=>{
154
- return <Icon
155
- {...p}
156
- {...chevronIconProps}
157
- />
158
- }}
159
- >
160
- {children}
161
- </Button>
151
+ />
152
+ {children}
153
+ <Icon
154
+ {...chevronIconProps}
155
+ />
156
+ </Pressable>
162
157
  } }
163
158
  items={menItems}
164
159
  />
@@ -173,6 +168,10 @@ const styles = StyleSheet.create({
173
168
  container : {
174
169
  marginLeft : 0,
175
170
  marginVertical : 10,
171
+ flex : 1,
172
+ flexDirection : "row",
173
+ justifyContent : "start",
174
+ alignItems : "center",
176
175
  },
177
176
  labelContainer : {
178
177
  flexDirection : 'column',
@@ -2,9 +2,8 @@
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
4
 
5
- /*** afin d'éviter les redondances cycliques avec le module $loginComponent, ce composant doit être utiliser pour
6
- * le rendu de tous les composants implémentés définis dans le fichier $loginComponent car ne necessite pas de test sur
7
- le fait que l'utilisateur soit connecté où pas
5
+ /***
6
+ *le fait que l'utilisateur soit connecté pas
8
7
  */
9
8
 
10
9
  import ScreenWithOrWithoutAuthContainer from "./ScreenWithOrWithoutAuthContainer";
@@ -1,7 +1,7 @@
1
1
  import Drawer,{DrawerItems} from "$ecomponents/Drawer";
2
2
  import ProfilAvatar from "$elayouts/ProfilAvatar";
3
3
  import React from "$react";
4
- import items,{isItemActive,refresh as refreshItems} from "./items";
4
+ import useGetItems,{isItemActive} from "./items";
5
5
  import APP from "$capp/instance";
6
6
  import Auth from "$cauth";
7
7
  import Login from "$eauth/Login";
@@ -12,6 +12,20 @@ import Logo from "$ecomponents/Logo";
12
12
  const DrawerNavigator = React.forwardRef(({content,children,state,...props},ref)=>{
13
13
  const drawerRef = React.useRef(null);
14
14
  const mergedRefs = React.useMergeRefs(drawerRef,ref);
15
+ const items = useGetItems({refresh:()=>{
16
+ if(drawerRef.current && drawerRef.current && drawerRef.current.forceRenderNavigationView){
17
+ return drawerRef.current.forceRenderNavigationView();
18
+ }
19
+ }});
20
+ React.useEffect(()=>{
21
+ const onLogoutUser = ()=>{
22
+ setIsLoggedIn(false);
23
+ }
24
+ APP.on(APP.EVENTS.AUTH_LOGOUT_USER,onLogoutUser);
25
+ return ()=>{
26
+ APP.off(APP.EVENTS.AUTH_LOGOUT_USER,onLogoutUser);
27
+ }
28
+ },[])
15
29
  const headerCB = ({isMinimized})=>{
16
30
  if(isMinimized) return null;
17
31
  if(!theme.showProfilAvatarOnDrawer){
@@ -26,28 +40,6 @@ const DrawerNavigator = React.forwardRef(({content,children,state,...props},ref)
26
40
  state = defaultObj(state);
27
41
  const itemRefs = React.useRef(null);
28
42
  const uProfileRef = React.useRef(null);
29
- React.useEffect(()=>{
30
- const onRefreshItems = (a)=>{
31
- refreshItems();
32
- if(drawerRef.current && drawerRef.current && drawerRef.current.forceRenderNavigationView){
33
- return drawerRef.current.forceRenderNavigationView();
34
- }
35
- }
36
- const onLoginUser = ()=>{
37
- onRefreshItems();
38
- }
39
- const onLogoutUser = ()=>{
40
- setIsLoggedIn(false);
41
- }
42
- APP.on(APP.EVENTS.REFRESH_MAIN_DRAWER,onRefreshItems);
43
- APP.on(APP.EVENTS.AUTH_LOGIN_USER,onLoginUser);
44
- APP.on(APP.EVENTS.AUTH_LOGOUT_USER,onLogoutUser);
45
- return ()=>{
46
- APP.off(APP.EVENTS.REFRESH_MAIN_DRAWER,onRefreshItems);
47
- APP.off(APP.EVENTS.AUTH_LOGIN_USER,onLoginUser);
48
- APP.off(APP.EVENTS.AUTH_LOGOUT_USER,onLogoutUser);
49
- }
50
- },[]);
51
43
  React.useEffect(()=>{
52
44
  if(prevIsLoggedIn === isLoggedIn) return;
53
45
  navigate("Home");
@@ -3,66 +3,77 @@
3
3
  // license that can be found in the LICENSE file.
4
4
 
5
5
  import { isRouteActive} from "$cnavigation";
6
- import "$cutils";
6
+ import {defaultObj} from "$cutils";
7
7
  import appConfig from "$capp/config";
8
- import APP from "$capp";
8
+ import useContext from "$econtext/hooks";
9
+ import {useMemo,useEffect,useRef} from "react";
9
10
  ///les items du drawer
10
- import items from "$drawerItems";
11
11
  import { screenName as aboutScreenName} from "$escreens/Help/About";
12
12
  import theme from "$theme";
13
+ import APP from "$capp/instance";
13
14
 
14
- export const getItems = (force)=>{
15
- const name = !theme.showProfilAvatarOnDrawer ? 'Dashboard' : APP.getName();
16
- const itx = typeof items === "function" ? items() : items;
15
+ const useGetItems = (options)=>{
16
+ const {navigation:{drawerItems}} = useContext();
17
+ options = defaultObj(options);
18
+ const {refresh,force} = options;
19
+ const showProfilOnDrawer = theme.showProfilAvatarOnDrawer;
17
20
  const handleHelp = appConfig.get("handleHelpScreen") !== false ? true : false;
18
- const r = [
19
- {
20
- label : name,
21
- icon : 'view-dashboard',
22
- title : 'Dashboard',
23
- routeName : "Home",
24
- divider : true,
25
- },
26
- ];
27
- Object.map(itx,(item,i)=>{
28
- if(isObj(item)){
29
- r.push(item);
21
+ const refreshItemsRef = useRef(false);
22
+ useEffect(()=>{
23
+ const refreshItems = (...a)=>{
24
+ refreshItemsRef.current = !refreshItemsRef.current;
25
+ if(typeof refresh =='function'){
26
+ refresh(...a);
27
+ }
30
28
  }
31
- })
32
- if(handleHelp){
33
- r.push({divider:true});
34
- const dataHelp = {
35
- key : 'dataHelp',
36
- label : 'Aide',
37
- section : true,
38
- divider : false,
39
- items : [
40
- {
41
- icon : 'help',
42
- label : 'A propos de '+APP.getName(),
43
- routeName : aboutScreenName,
44
- }
45
- ]
46
- };
47
- r.push(dataHelp);
48
- }
49
- return r;
50
- }
51
-
52
-
53
- let CACHED_ITEMS = []
54
-
55
- export const refresh = ()=>{
56
- CACHED_ITEMS = getItems();
57
- return CACHED_ITEMS;
29
+ APP.on(APP.EVENTS.REFRESH_MAIN_DRAWER,refreshItems);
30
+ APP.on(APP.EVENTS.AUTH_LOGIN_USER,refreshItems);
31
+ APP.on(APP.EVENTS.AUTH_LOGOUT_USER,refreshItems);
32
+ return ()=>{
33
+ APP.off(APP.EVENTS.REFRESH_MAIN_DRAWER,refreshItems);
34
+ APP.off(APP.EVENTS.AUTH_LOGIN_USER,refreshItems);
35
+ APP.off(APP.EVENTS.AUTH_LOGOUT_USER,refreshItems);
36
+ }
37
+ },[])
38
+ return useMemo(()=>{
39
+ const name = !showProfilOnDrawer ? 'Dashboard' : appConfig.name;
40
+ const itx = typeof drawerItems === "function" ? drawerItems() : drawerItems;
41
+ const r = [
42
+ {
43
+ label : name,
44
+ icon : 'view-dashboard',
45
+ title : 'Dashboard',
46
+ routeName : "Home",
47
+ divider : true,
48
+ },
49
+ ];
50
+ Object.map(itx,(item,i)=>{
51
+ if(isObj(item)){
52
+ r.push(item);
53
+ }
54
+ })
55
+ if(handleHelp){
56
+ r.push({divider:true});
57
+ const dataHelp = {
58
+ key : 'dataHelp',
59
+ label : 'Aide',
60
+ section : true,
61
+ divider : false,
62
+ items : [
63
+ {
64
+ icon : 'help',
65
+ label : 'A propos de '+APP.getName(),
66
+ routeName : aboutScreenName,
67
+ }
68
+ ]
69
+ };
70
+ r.push(dataHelp);
71
+ }
72
+ return r;
73
+ },[showProfilOnDrawer,handleHelp,refreshItemsRef.current,force])
58
74
  }
59
75
 
60
- export default function mainDrawerItems(options){
61
- if(!CACHED_ITEMS.length){
62
- refresh();
63
- }
64
- return CACHED_ITEMS;
65
- };
76
+ export default useGetItems;
66
77
 
67
78
  export const isItemActive = (opts)=>{
68
79
  if(isRouteActive(opts)){
@@ -3,6 +3,7 @@ import {handleContent,sanitizeName} from '$escreens';
3
3
  import {Stack,setInitialRouteName } from "$cnavigation";
4
4
  import React from "$react";
5
5
  import DrawerNavigator from "./Drawer";
6
+ import useContext from "$econtext/hooks";
6
7
 
7
8
  export * from "./utils";
8
9
 
@@ -11,7 +12,8 @@ export * from "./utils";
11
12
  */
12
13
  export default function NavigationComponent (props){
13
14
  let {state,hasGetStarted,onGetStart,initialRouteName,extra} = props;
14
- const allScreens = initScreens({Factory:Stack,ModalFactory:Stack,filter:({name,Screen})=>{
15
+ const {navigation:{screens}} = useContext();
16
+ const allScreens = initScreens({Factory:Stack,screens,ModalFactory:Stack,filter:({name})=>{
15
17
  if(name === initialRouteName){
16
18
  extra = defaultObj(extra);
17
19
  extra.onGetStart = onGetStart;
@@ -2,7 +2,7 @@ import FormDataScreen from "$elayouts/Screen/FormData";
2
2
  import {defaultStr,defaultObj,isObjOrArray,isObj} from "$cutils";
3
3
  import Auth from "$cauth";
4
4
  import {navigate} from "$cnavigation";
5
- import SelectTheme from "$themeSelectorComponent";
5
+ import SelectTheme from "$ethemeSelectorComponent";
6
6
  import Preloader from "$epreloader";
7
7
  import {SignIn2SignOut} from "$cauth";
8
8
  import React from "$react";
@@ -1,10 +1,10 @@
1
1
  import {defaultBool,defaultArray,defaultVal,isObj,isNonNullString,defaultObj,isArray,defaultStr} from "$cutils";
2
2
  import {sanitizeName,GROUP_NAMES} from "./utils";
3
- import mainScreens from "$mainScreens"
4
3
  import React from "$react";
5
4
  import ScreenWrapper from "./ScreenWrapper";
6
5
  import { SCREEN_OPTIONS } from "./utils";
7
6
 
7
+
8
8
  export * from "./utils";
9
9
 
10
10
  export const handleScreen = ({Screen,Factory,ModalFactory,result,filter,index})=>{
@@ -96,7 +96,7 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,filter,index})=
96
96
  */
97
97
  export default function initScreens ({Factory,ModalFactory,screens,result,filter}){
98
98
  if(!isArray(screens) || !screens.length){
99
- screens = mainScreens;
99
+ screens = [];
100
100
  }
101
101
  result = defaultObj(result);
102
102
  result.screens = defaultObj(result.screens);
@@ -1,5 +0,0 @@
1
- // Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
2
- // Use of this source code is governed by a BSD-style
3
- // license that can be found in the LICENSE file.
4
-
5
- export default ()=> null;
File without changes