@fto-consult/expo-ui 5.7.11 → 5.8.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "5.7.11",
3
+ "version": "5.8.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
@@ -5,23 +5,13 @@ import {defaultObj} from "$cutils";
5
5
  import {updateTheme,defaultTheme} from "$theme";
6
6
  import {Provider as PaperProvider } from 'react-native-paper';
7
7
  import Index from './index';
8
- import {Portal } from 'react-native-paper';
9
- import {PreloaderProvider} from "$epreloader";
10
- import DropdownAlert from '$ecomponents/Dialog/DropdownAlert';
11
- import notify, {notificationRef} from "$notify";
12
- import BottomSheetProvider from "$ecomponents/BottomSheet/Provider";
13
- import DialogProvider from "$ecomponents/Dialog/Provider";
14
- import { DialogProvider as FormDataDialogProvider } from '$eform/FormData';
8
+ import notify from "$notify";
15
9
  import { SafeAreaProvider } from 'react-native-safe-area-context';
16
10
  import { PreferencesContext } from './Preferences';
17
11
  import {AuthProvider} from '$cauth';
18
- import {PortalProvider } from '$ecomponents/Portal';
19
12
  import ErrorBoundary from "$ecomponents/ErrorBoundary";
20
- import ErrorBoundaryProvider from "$ecomponents/ErrorBoundary/Provider";
21
13
  import {GestureHandlerRootView} from "react-native-gesture-handler";
22
14
  import StatusBar from "$ecomponents/StatusBar";
23
- import SimpleSelect from '$ecomponents/SimpleSelect';
24
- import {Provider as AlertProvider} from '$ecomponents/Dialog/confirm/Alert';
25
15
  import APP from "$app";
26
16
  import FontIcon from "$ecomponents/Icon/Font"
27
17
  import {isMobileNative} from "$cplatform";
@@ -40,7 +30,9 @@ Object.map(Utils,(v,i)=>{
40
30
  window[i] = v;
41
31
  }
42
32
  });
43
- export default function getIndex({onMount,onUnmount,swrConfig,onRender,preferences:appPreferences,...rest}){
33
+ export default function getIndex({onMount,onUnmount,swrConfig,render,onRender,preferences:appPreferences,...rest}){
34
+ const child = <Index {...rest} theme={theme}/>;
35
+ const content = typeof render == 'function'? render({children:child}) : child;
44
36
  const isScreenFocusedRef = React.useRef(true);
45
37
  ///garde pour chaque écran sa date de dernière activité
46
38
  const screensRef = React.useRef({});//la liste des écrans actifs
@@ -178,23 +170,12 @@ export default function getIndex({onMount,onUnmount,swrConfig,onRender,preferenc
178
170
  >
179
171
  <SafeAreaProvider>
180
172
  <AuthProvider>
181
- <PortalProvider>
182
- <Portal.Host>
183
- <ErrorBoundary>
184
- <StatusBar/>
185
- <PreferencesContext.Provider value={preferences}>
186
- <DropdownAlert ref={notificationRef}/>
187
- <PreloaderProvider/>
188
- <DialogProvider responsive/>
189
- <AlertProvider SimpleSelect={SimpleSelect}/>
190
- <FormDataDialogProvider/>
191
- {<Index {...rest} theme={theme}/>}
192
- <ErrorBoundaryProvider/>
193
- <BottomSheetProvider/>
194
- </PreferencesContext.Provider>
195
- </ErrorBoundary>
196
- </Portal.Host>
197
- </PortalProvider>
173
+ <ErrorBoundary>
174
+ <StatusBar/>
175
+ <PreferencesContext.Provider value={preferences}>
176
+ {React.isValidElement(content) && content || child}
177
+ </PreferencesContext.Provider>
178
+ </ErrorBoundary>
198
179
  </AuthProvider>
199
180
  </SafeAreaProvider>
200
181
  </PaperProvider>
@@ -2459,6 +2459,7 @@ export default class CommonDatagridComponent extends AppComponent {
2459
2459
  render,
2460
2460
  readOnly,
2461
2461
  disabled,
2462
+ editable,
2462
2463
  visible,
2463
2464
  defaultValue,
2464
2465
  id,
@@ -2469,7 +2470,7 @@ export default class CommonDatagridComponent extends AppComponent {
2469
2470
  } = header;
2470
2471
  restCol = Object.clone(defaultObj(restCol));
2471
2472
  let colFilter = defaultVal(restCol.filter,true);
2472
- field = header.field = defaultStr(header.field,field,headerIndex);
2473
+ field = header.field = restCol.field = defaultStr(header.field,field,headerIndex);
2473
2474
  delete restCol.filter;
2474
2475
 
2475
2476
  const type = defaultStr(header.jsType,header.type,"text").toLowerCase();
@@ -2617,14 +2618,14 @@ export default class CommonDatagridComponent extends AppComponent {
2617
2618
  this.sectionListColumnsSize.current++;
2618
2619
  }
2619
2620
  const mItem = {
2620
- ...header,
2621
+ ...restCol,
2621
2622
  field,
2622
2623
  type,
2623
2624
  onPress : ()=>{
2624
2625
  this.toggleColumnInSectionList(field);
2625
2626
  return false;
2626
2627
  },
2627
- title : title,
2628
+ title,
2628
2629
  icon : isInSectionListHeader?CHECKED_ICON_NAME : null,
2629
2630
  };
2630
2631
  if(this.isSectionListColumnConfigurable(mItem)){
@@ -35,8 +35,10 @@ const DrawerComponent = React.forwardRef((props,ref)=>{
35
35
  permanentToggleIcon,minimizedToggleIcon,temporaryToggleIcon,withMinimizedIcon,
36
36
  isItemActive,onPageResize,navigationViewRef,
37
37
  children,
38
+ testID,
38
39
  drawerType} = props;
39
40
  sessionName = defaultStr(sessionName);
41
+ testID = defaultStr(testID,"RN_DrawerComponent")
40
42
  const sessionRef = React.useRef({});
41
43
  const session = React.useMemo(()=>{
42
44
  if(sessionName){
@@ -251,8 +253,9 @@ const DrawerComponent = React.forwardRef((props,ref)=>{
251
253
  }
252
254
  return false;
253
255
  },getState:getDrawerState,getDrawerRef}}>
254
- <View style={styles.container}>
256
+ <View style={styles.container} testID={`${testID}_Container`}>
255
257
  <DrawerLayout
258
+ testID = {`${testID}_DrawerLayout`}
256
259
  {...restP}
257
260
  permanent = {isPermanent}
258
261
  onDrawerSlide={onDrawerSlide}
@@ -339,7 +342,7 @@ const DrawerComponent = React.forwardRef((props,ref)=>{
339
342
  {paddingBottom:30},
340
343
  contentContainerStyle
341
344
  ]
342
- }>
345
+ }>
343
346
  {children}
344
347
  </DrawerLayout>
345
348
  </View>
@@ -991,7 +991,7 @@ class DropdownComponent extends AppComponent {
991
991
  {...restProps}
992
992
  testID = {testID+"_ModalComponent"}
993
993
  withScrollView = {false}
994
- visible={visible && canHandle ? true : false}
994
+ visible={visible}
995
995
  onDismiss={this.hide.bind(this)}
996
996
  contentStyle = {[{paddingVertical:0},restProps.contentStyle]}
997
997
  anchor={anchor}
@@ -21,6 +21,9 @@ import appConfig from "$appConfig";
21
21
  */
22
22
  const TableDataSelectField = React.forwardRef(({foreignKeyColumn,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)=>{
23
23
  props.data = defaultObj(props.data);
24
+ if(!foreignKeyColumn && isNonNullString(props.field)){
25
+ foreignKeyColumn = props.field;
26
+ }
24
27
  if(isNonNullString(foreignKeyColumn)){
25
28
  foreignKeyColumn = foreignKeyColumn.trim();
26
29
  }
@@ -34,7 +37,7 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,bindUpsert2Remo
34
37
  fetchItemsPath = defaultStr(fetchItemsPath).trim();
35
38
 
36
39
  if(!fetchItemsPath && (!isObj(fKeyTable) || !(defaultStr(fKeyTable.tableName,fKeyTable.table)))){
37
- console.error("type de données invalide pour la foreignKeyTable ",fKeyTable," composant SelectTableData",foreignKeyColumn,foreignKeyTable,props);
40
+ console.error("type de données invalide pour la foreignKeyTable ",foreignKeyTable," label : ",foreignKeyLabel,fKeyTable," composant SelectTableData",foreignKeyColumn,foreignKeyTable,props);
38
41
  return null;
39
42
  }
40
43
  fKeyTable = defaultObj(fKeyTable);
@@ -280,13 +283,12 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,bindUpsert2Remo
280
283
  }
281
284
  return rItem(p);
282
285
  }}
283
- hideOnAdd
284
286
  onAdd = {(args)=>{
285
287
  onAddProps = defaultObj(isFunction(onAddProps)? onAddProps.call(context,{context,foreignKeyTable,dbName,props}) : onAddProps);
286
288
  if(typeof onAdd =='function'){
287
289
  return onAdd({...args,...onAddProps});
288
290
  }
289
- return navigateToTableData({...onAddProps,foreignKeyTable,table:foreignKeyTable,foreignKeyColumn,tableName : foreignKeyTable,...args})
291
+ return navigateToTableData(foreignKeyTable,{routeParams:{...onAddProps,foreignKeyTable,table:foreignKeyTable,foreignKeyColumn,tableName : foreignKeyTable}});
290
292
  }}
291
293
  />
292
294
  });
@@ -7,6 +7,7 @@ import View from "$ecomponents/View";
7
7
  import {isNativeMobile} from "$cplatform";
8
8
  import {defaultDecimal} from "$cutils";
9
9
  import {LogoProgress} from "$ecomponents/Logo";
10
+ import {defaultStr} from "$cutils";
10
11
  import styles, {
11
12
  _solidBackground,
12
13
  _staticBackground,
@@ -72,9 +73,11 @@ class AnimatedSplash extends React.Component {
72
73
  backgroundColor,
73
74
  imageBackgroundSource,
74
75
  imageBackgroundResizeMode,
76
+ testID,
75
77
  disableAppScale,
76
78
  disableImageBackgroundAnimation,
77
79
  } = this.props
80
+ testID = defaultStr(testID,"RN_SplashscreenComponent")
78
81
  logoWidth = defaultDecimal(logoWidth,150);
79
82
  logoHeight = defaultDecimal(logoHeight,250);
80
83
  const opacityClearToVisible = {
@@ -127,12 +130,13 @@ class AnimatedSplash extends React.Component {
127
130
  }
128
131
 
129
132
  return (
130
- <View style={[styles.container]}>
131
- {!animationDone && <View style={StyleSheet.absoluteFill} />}
133
+ <View style={[styles.container]} testID={testID} nativeID={testID}>
134
+ {!animationDone && <View style={StyleSheet.absoluteFill} testID={testID+"_Animation"}/>}
132
135
  <View style={styles.containerGlue}>
133
136
  {!animationDone && (
134
137
  <Animated.View
135
138
  style={_staticBackground(logoOpacity, backgroundColor)}
139
+ testID={testID+"_AnimationDone"}
136
140
  />
137
141
  )}
138
142
  {(animationDone || isNative) && <Component style={[!disableAppScale && appScale, opacityClearToVisible, styles.flex]}>
@@ -140,6 +144,7 @@ class AnimatedSplash extends React.Component {
140
144
  </Component>}
141
145
  {!animationDone && (
142
146
  <Animated.Image
147
+ testID={testID+"AnimateImage"}
143
148
  resizeMode={imageBackgroundResizeMode || "cover"}
144
149
  source={imageBackgroundSource}
145
150
  style={[disableImageBackgroundAnimation && _staticBackground(
@@ -153,9 +158,10 @@ class AnimatedSplash extends React.Component {
153
158
  />
154
159
  )}
155
160
  {!animationDone && (
156
- <View style={[StyleSheet.absoluteFill, styles.logoStyle]}>
161
+ <View testID={testID+"_LogoContainer"} style={[StyleSheet.absoluteFill, styles.logoStyle]}>
157
162
  {(
158
163
  <Animated.View
164
+ testID={testID+"_Logo"}
159
165
  style={_dynamicCustomComponentStyle(
160
166
  logoScale,
161
167
  logoOpacity,
package/src/index.js CHANGED
@@ -13,7 +13,6 @@ import {set as setSession,get as getSession} from "$session";
13
13
  import { showConfirm } from "$ecomponents/Dialog";
14
14
  import {close as closePreloader, isVisible as isPreloaderVisible} from "$epreloader";
15
15
  import SplashScreen from "$ecomponents/SplashScreen";
16
- import {notify} from "$ecomponents/Dialog";
17
16
  import {decycle} from "$cutils/json";
18
17
  import init from "$capp/init";
19
18
  import { setIsInitialized} from "$capp/utils";
@@ -21,6 +20,17 @@ import {isObj,isNonNullString,isPromise,defaultObj,defaultStr} from "$cutils";
21
20
  import {loadFonts} from "$ecomponents/Icon/Font";
22
21
  import appConfig from "$capp/config";
23
22
  import Preloader from "$preloader";
23
+ import {PreloaderProvider} from "$epreloader";
24
+ import BottomSheetProvider from "$ecomponents/BottomSheet/Provider";
25
+ import DialogProvider from "$ecomponents/Dialog/Provider";
26
+ import SimpleSelect from '$ecomponents/SimpleSelect';
27
+ import {Provider as AlertProvider} from '$ecomponents/Dialog/confirm/Alert';
28
+ import { DialogProvider as FormDataDialogProvider } from '$eform/FormData';
29
+ import {Portal } from 'react-native-paper';
30
+ import {PortalProvider,PortalHost } from '$ecomponents/Portal';
31
+ import ErrorBoundaryProvider from "$ecomponents/ErrorBoundary/Provider";
32
+ import notify, {notificationRef} from "$notify";
33
+ import DropdownAlert from '$ecomponents/Dialog/DropdownAlert';
24
34
 
25
35
  let MAX_BACK_COUNT = 1;
26
36
  let countBack = 0;
@@ -219,14 +229,25 @@ function App({init:initApp,initialRouteName:appInitialRouteName,getStartedRouteN
219
229
  }
220
230
  }
221
231
  >
222
- <Navigation
223
- initialRouteName = {defaultStr(hasGetStarted ? appInitialRouteName : getStartedRouteName,"Home")}
224
- state = {state}
225
- hasGetStarted = {hasGetStarted}
226
- onGetStart = {(e)=>{
227
- setState({...state,hasGetStarted:true})
228
- }}
229
- />
232
+ <PortalProvider>
233
+ <Portal.Host>
234
+ <PreloaderProvider/>
235
+ <DialogProvider responsive/>
236
+ <AlertProvider SimpleSelect={SimpleSelect}/>
237
+ <FormDataDialogProvider/>
238
+ <BottomSheetProvider/>
239
+ <DropdownAlert ref={notificationRef}/>
240
+ <ErrorBoundaryProvider/>
241
+ <Navigation
242
+ initialRouteName = {defaultStr(hasGetStarted ? appInitialRouteName : getStartedRouteName,"Home")}
243
+ state = {state}
244
+ hasGetStarted = {hasGetStarted}
245
+ onGetStart = {(e)=>{
246
+ setState({...state,hasGetStarted:true})
247
+ }}
248
+ />
249
+ </Portal.Host>
250
+ </PortalProvider>
230
251
  </NavigationContainer>
231
252
  </SplashScreen>);
232
253
  }
@@ -2,14 +2,14 @@ import React from '$react';
2
2
  import {StyleSheet} from 'react-native';
3
3
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
4
  import PropTypes from "prop-types";
5
- import {defaultObj,defaultStr,defaultNumber,defaultBool} from "$cutils";
5
+ import {defaultObj,defaultStr,defaultNumber,defaultBool,uniqid} from "$cutils";
6
6
  import View from "$ecomponents/View";
7
7
  import { useNavigation} from '$cnavigation';
8
8
  import Fab from "$layouts/Fab";
9
9
  import APP from "$capp";
10
10
  import AppBar,{createAppBarRef} from "$elayouts/AppBar";
11
- import ErrorBoundary from "$ecomponents/ErrorBoundary";
12
11
  import Portal from "$ecomponents/Portal";
12
+ import { FullWindowOverlay } from 'react-native-screens';
13
13
  import theme,{StyleProp} from "$theme";
14
14
  import StatusBar from "$ecomponents/StatusBar";
15
15
  import ScrollView from "$ecomponents/ScrollView";
@@ -108,57 +108,60 @@ export default function MainScreenScreenWithOrWithoutAuthContainer(props) {
108
108
  });
109
109
  }
110
110
  }, [title,subtitle]);
111
- const Wrapper = modal ? Portal : React.Fragment;
111
+ const Wrapper = modal ? PortalCP : React.Fragment;
112
+ const WrapperProps = modal? {screenName} : {};
112
113
  const fab = withFab ? <Fab
113
114
  {...fabProps}
114
115
  screenName={screenName}
115
116
  /> : null;
116
117
  const profilAvatar = typeof renderProfilAvatar =='function'? renderProfilAvatar(profilAvatarProps) : null;
117
- const child = <>
118
- {withStatusBar !== false ? <StatusBar/> : null}
119
- <ErrorBoundary testID={testID+"_ScreenLayoutErrorBoundary"}>
120
- <View testID={testID} {...containerProps} style={[styles.container,{backgroundColor},modal && styles.modal,containerProps.style]}>
121
- {appBar === false ? null : React.isValidElement(appBar)? state.AppBar : <AppBar
122
- testID={testID+'_AppBar'} {...appBarProps}
123
- backAction = {defaultVal(appBarProps.backAction,backAction)}
124
- elevation={defaultNumber(appBarProps.elevation,elevation)}
125
- withDrawer={withDrawer} options={options}
126
- ref={appBarRef} title={title}
127
- subtitle={subtitle}
128
- right = {withProfilAvatarOnAppBar && <View testID={testID+"_ProfilAvatar_Container"} {...profilAvatarContainerProps} style={[profilAvatarContainerProps.style,styles.profilAvatarContainer]} >
129
- {React.isValidElement(profilAvatar) && profilAvatar || null}
130
- </View> || null}
131
- />}
132
- {withScrollView !== false ? (
133
- <ScrollView
134
- testID = {testID+'_ScreenContentScrollView'}
135
- {...rest}
136
- contentContainerStyle={[contentContainerStyle]}
137
- style={[containerStyle,styles.container, style]}
138
- >
139
- {children}
140
- {fab}
141
- </ScrollView>
142
- ) : (
143
- <View testID={testID+'_ScreenContent'} {...rest} style={[containerStyle,styles.wrapper,styles.container, style]}>
144
- {children}
145
- {fab}
146
- </View>
147
- )}
148
- </View>
149
- </ErrorBoundary>
150
- </>
151
- return <Wrapper>
118
+ const portalId = uniqid("screeen-container-"+screenName);
119
+ return <Wrapper {...WrapperProps}>
152
120
  {renderChildren({
153
121
  containerProps : {
154
122
  ...authProps,
155
123
  required : authRequired,
156
124
  },
157
- children : child,
125
+ children : <View testID={testID} nativeID={portalId} {...containerProps} style={[styles.container,{backgroundColor},modal && styles.modal,containerProps.style]}>
126
+ {withStatusBar !== false ? <StatusBar/> : null}
127
+ {appBar === false ? null : React.isValidElement(appBar)? state.AppBar : <AppBar
128
+ testID={testID+'_AppBar'} {...appBarProps}
129
+ backAction = {defaultVal(appBarProps.backAction,backAction)}
130
+ elevation={defaultNumber(appBarProps.elevation,elevation)}
131
+ withDrawer={withDrawer} options={options}
132
+ ref={appBarRef} title={title}
133
+ subtitle={subtitle}
134
+ right = {withProfilAvatarOnAppBar && <View testID={testID+"_ProfilAvatar_Container"} {...profilAvatarContainerProps} style={[profilAvatarContainerProps.style,styles.profilAvatarContainer]} >
135
+ {React.isValidElement(profilAvatar) && profilAvatar || null}
136
+ </View> || null}
137
+ />}
138
+ {withScrollView !== false ? (
139
+ <ScrollView
140
+ testID = {testID+'_ScreenContentScrollView'}
141
+ {...rest}
142
+ contentContainerStyle={[contentContainerStyle]}
143
+ style={[containerStyle,styles.container, style]}
144
+ >
145
+ {children}
146
+ {fab}
147
+ </ScrollView>
148
+ ) : (
149
+ <View testID={testID+'_ScreenContent'} {...rest} style={[containerStyle,styles.wrapper,styles.container, style]}>
150
+ {children}
151
+ {fab}
152
+ </View>
153
+ )}
154
+ </View>,
158
155
  })}
159
156
  </Wrapper>
160
157
  }
161
158
 
159
+ const PortalCP = ({children,screenName})=>{
160
+ return <Portal>
161
+ {children}
162
+ </Portal>
163
+ }
164
+
162
165
  const styles = StyleSheet.create({
163
166
  container: {
164
167
  flex: 1,