@fto-consult/expo-ui 6.1.5 → 6.2.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/appConfig.txt +1 -4
- package/babel.config.alias.js +4 -0
- package/index.js +4 -2
- package/package.json +3 -3
- package/src/App.js +7 -43
- package/src/components/AppBar/index.js +8 -11
- package/src/components/Datagrid/Common/Common.js +1 -1
- package/src/components/Datagrid/SWRDatagrid.js +5 -6
- package/src/components/ErrorBoundary/Provider.js +1 -2
- package/src/components/TextField/index.js +12 -13
- package/src/context/index.js +57 -0
- package/src/index.js +7 -6
- package/src/components/AppBar/Content2.js +0 -132
- package/src/components/ContentLoader/index copy.js +0 -148
package/appConfig.txt
CHANGED
|
@@ -8,9 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
/*** le nombre maximal de courbes qu'on peut afficher sur le même graphe***/
|
|
10
10
|
maxSupportedChartSeries {number}
|
|
11
|
-
|
|
12
|
-
///fonction de rappel appelée avant d'exit l'application, doit retourner une promesse que lorsque résolue, exit l'application
|
|
13
|
-
beforeExit : ()=><Promise>
|
|
11
|
+
|
|
14
12
|
|
|
15
13
|
/***les fonctions d'aggregations du datagrid**/
|
|
16
14
|
datagridAggregatorFunctions : {objectOf({code:{string},label:{string},eval:{function}})|| arrayOf({code:{string},label:{string},eval:{function}})}
|
|
@@ -19,7 +17,6 @@
|
|
|
19
17
|
"&libele&" : selectLabel,
|
|
20
18
|
}
|
|
21
19
|
getTableData : {function(tableName)=>table} retourne l'ojet table data,
|
|
22
|
-
swrRefreshTimeout : {number} le délai d'inactivité auquel, une fois l'application active, les données de type listData sont rafraichies
|
|
23
20
|
handleHelpScreen : {boolean}, //if Help screen will be added on navigation's main drawer
|
|
24
21
|
|
|
25
22
|
checkNavigationPermsOnTableOrStructData : {boolean}, si le test de la permission sur la table data où sur la struct data sera effectuée lorsqu'on appelera la fonction navigateToTableData ou navigateToStructData
|
package/babel.config.alias.js
CHANGED
|
@@ -133,6 +133,10 @@ module.exports = (opts)=>{
|
|
|
133
133
|
//le chemin ver le repertoire electron
|
|
134
134
|
r.$eelectron = r["$e-electron"] = $electron;
|
|
135
135
|
r.$electron = r.$electron || r.$eelectron;
|
|
136
|
+
r.$econtext = path.resolve(expo,"context");
|
|
137
|
+
if(!r.$context){
|
|
138
|
+
r.$context = r.$econtext;
|
|
139
|
+
}
|
|
136
140
|
const electronAssetsPath = path.resolve(dir,"electron","assets");
|
|
137
141
|
if($assets){
|
|
138
142
|
const l1 = path.resolve($assets,"logo.png"), l2 = path.resolve($assets,"logo.png");
|
package/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { registerRootComponent } from "expo";
|
|
2
2
|
import {Platform } from 'react-native';
|
|
3
3
|
import App from "./src/App";
|
|
4
|
+
import { Provider } from "$econtext";
|
|
4
5
|
const isWeb = Platform.OS === "web";
|
|
6
|
+
import {isObj} from "$cutils";
|
|
5
7
|
|
|
6
8
|
/****
|
|
7
9
|
* les options sont de la forme :
|
|
@@ -16,9 +18,9 @@ const isWeb = Platform.OS === "web";
|
|
|
16
18
|
* }
|
|
17
19
|
*/
|
|
18
20
|
export default function registerApp (options){
|
|
19
|
-
|
|
21
|
+
const {onMount,onUnmount,onRender,swrConfig,...rest} = isObj(options)? options : {};
|
|
20
22
|
registerRootComponent(function(props){
|
|
21
|
-
return <
|
|
23
|
+
return <Provider {...props} {...rest} swrConfig={isObj(swrConfig) && swrConfig || {}} children={<App onMount={onMount} onUnmount={onUnmount} onRender={onRender}/>}/>
|
|
22
24
|
});
|
|
23
25
|
}
|
|
24
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@emotion/native": "^11.11.0",
|
|
62
62
|
"@expo/html-elements": "^0.5.1",
|
|
63
63
|
"@expo/vector-icons": "^13.0.0",
|
|
64
|
-
"@fto-consult/common": "^3.
|
|
64
|
+
"@fto-consult/common": "^3.19.0",
|
|
65
65
|
"@gorhom/portal": "^1.0.14",
|
|
66
66
|
"@pchmn/expo-material3-theme": "^1.0.1",
|
|
67
67
|
"@react-native-async-storage/async-storage": "1.18.2",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@react-navigation/native-stack": "^6.9.12",
|
|
73
73
|
"@shopify/flash-list": "1.4.3",
|
|
74
74
|
"apexcharts": "^3.41.0",
|
|
75
|
-
"expo": "^49.0.
|
|
75
|
+
"expo": "^49.0.3",
|
|
76
76
|
"expo-camera": "~13.4.2",
|
|
77
77
|
"expo-clipboard": "~4.3.0",
|
|
78
78
|
"expo-font": "~11.4.0",
|
package/src/App.js
CHANGED
|
@@ -9,7 +9,6 @@ import {GestureHandlerRootView} from "react-native-gesture-handler";
|
|
|
9
9
|
import APP from "$app";
|
|
10
10
|
import {isMobileNative} from "$cplatform";
|
|
11
11
|
import {setDeviceIdRef} from "$capp";
|
|
12
|
-
import appConfig from "$capp/config";
|
|
13
12
|
import {showPrompt} from "$ecomponents/Dialog/confirm";
|
|
14
13
|
import { AppState } from 'react-native'
|
|
15
14
|
import {canFetchOffline} from "$capi/utils";
|
|
@@ -18,51 +17,17 @@ import { timeout as SWR_REFRESH_TIMEOUT} from '$ecomponents/Datagrid/SWRDatagrid
|
|
|
18
17
|
import { Dimensions,Keyboard } from 'react-native';
|
|
19
18
|
import {isTouchDevice} from "$platform";
|
|
20
19
|
import * as Utils from "$cutils";
|
|
21
|
-
import
|
|
22
|
-
import { useMaterial3Theme } from '@pchmn/expo-material3-theme';
|
|
23
|
-
import { useColorScheme } from 'react-native';
|
|
24
|
-
import {colorsAlias,Colors} from "$theme";
|
|
20
|
+
import useContext from "$econtext";
|
|
25
21
|
|
|
26
|
-
import { configureFonts} from 'react-native-paper';
|
|
27
22
|
Object.map(Utils,(v,i)=>{
|
|
28
23
|
if(typeof v =='function' && typeof window !='undefined' && window && !window[i]){
|
|
29
24
|
window[i] = v;
|
|
30
25
|
}
|
|
31
26
|
});
|
|
32
|
-
|
|
33
|
-
export default function getIndex({onMount,onUnmount,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//const colorScheme = useColorScheme();
|
|
37
|
-
appConfig.extendAppTheme = (theme)=>{
|
|
38
|
-
if(!isObj(theme)) return;
|
|
39
|
-
const newTheme = theme.dark || theme.isDark ? { ...MD3DarkTheme, colors: pTheme.dark } : { ...MD3LightTheme, colors: pTheme.light };
|
|
40
|
-
for(let i in newTheme){
|
|
41
|
-
if(i !== 'colors' && !(i in theme)){
|
|
42
|
-
theme[i] = newTheme[i];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if(isObj(theme.colors)){
|
|
46
|
-
colorsAlias.map((color)=>{
|
|
47
|
-
color = color.trim();
|
|
48
|
-
const cUpper = color.ucFirst();
|
|
49
|
-
//math theme colors to material desgin V3
|
|
50
|
-
const textA = `${color}Text`,onColor=`on${cUpper}`//,containerA = `${color}Container`,onColorContainer=`on${cUpper}Container`;
|
|
51
|
-
const c = Colors.isValid(theme.colors[onColor])? theme.colors[onColor] : (theme.colors[textA]) || undefined;
|
|
52
|
-
if(c){
|
|
53
|
-
theme.colors[onColor] = c;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
for(let i in newTheme.colors){
|
|
57
|
-
if(!(i in theme.colors)){
|
|
58
|
-
theme.colors[i] = newTheme.colors[i];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
theme.fonts = newTheme.fonts;
|
|
63
|
-
return typeof extendAppTheme == 'function'? extendAppTheme(theme) : theme;
|
|
64
|
-
}
|
|
65
|
-
const isScreenFocusedRef = React.useRef(true);
|
|
27
|
+
|
|
28
|
+
export default function getIndex({onMount,onUnmount,onRender}){
|
|
29
|
+
const {swrConfig,appConfig} = useContext();
|
|
30
|
+
const isScreenFocusedRef = React.useRef(true);
|
|
66
31
|
///garde pour chaque écran sa date de dernière activité
|
|
67
32
|
const screensRef = React.useRef({});//la liste des écrans actifs
|
|
68
33
|
const activeScreenRef = React.useRef('');
|
|
@@ -70,7 +35,6 @@ export default function getIndex({onMount,onUnmount,swrConfig,onRender,...rest})
|
|
|
70
35
|
const appStateRef = React.useRef({});
|
|
71
36
|
const isKeyboardOpenRef = React.useRef(false);
|
|
72
37
|
React.useOnRender(onRender);
|
|
73
|
-
swrConfig = defaultObj(swrConfig);
|
|
74
38
|
React.useEffect(()=>{
|
|
75
39
|
///la fonction de rappel lorsque le composant est monté
|
|
76
40
|
const onScreenFocus = ({sanitizedName})=>{
|
|
@@ -144,7 +108,7 @@ export default function getIndex({onMount,onUnmount,swrConfig,onRender,...rest})
|
|
|
144
108
|
}
|
|
145
109
|
const date = screensRef.current[screen];
|
|
146
110
|
const diff = new Date().getTime() - date.getTime();
|
|
147
|
-
const timeout = defaultNumber(
|
|
111
|
+
const timeout = defaultNumber(swrConfig.refreshTimeout,SWR_REFRESH_TIMEOUT)
|
|
148
112
|
screensRef.current[screen] = new Date();
|
|
149
113
|
return diff >= timeout ? true : false;
|
|
150
114
|
},
|
|
@@ -174,7 +138,7 @@ export default function getIndex({onMount,onUnmount,swrConfig,onRender,...rest})
|
|
|
174
138
|
}
|
|
175
139
|
}}
|
|
176
140
|
>
|
|
177
|
-
|
|
141
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
178
142
|
<SafeAreaProvider>
|
|
179
143
|
<Index {...rest} onMount={onMount}/>
|
|
180
144
|
</SafeAreaProvider>
|
|
@@ -114,15 +114,6 @@ const AppBarComponent = React.forwardRef((props,ref)=> {
|
|
|
114
114
|
titleProps = defaultObj(titleProps);
|
|
115
115
|
React.setRef(ref,context);
|
|
116
116
|
testID = defaultStr(testID,"RN_AppBarComponent")
|
|
117
|
-
const renderedActions = renderSplitedActions(splitedActions,{
|
|
118
|
-
...defaultObj(menuProps,appBarProps.menuProps),
|
|
119
|
-
anchorProps : {
|
|
120
|
-
style : anchorStyle,
|
|
121
|
-
color : anchorStyle.color,
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
const renderedRight = React.isValidElement(rightContent) && rightContent || right;
|
|
125
|
-
const hasRight = React.isValidElement(renderedActions) || React.isValidElement(renderedRight);
|
|
126
117
|
return (
|
|
127
118
|
<Appbar.Header elevation={elevation} {...appBarProps} testID={testID} style={[styles.header,{backgroundColor},elevStyle,appBarProps.style]} onLayout={onPageResize}>
|
|
128
119
|
{backAction}
|
|
@@ -132,8 +123,14 @@ const AppBarComponent = React.forwardRef((props,ref)=> {
|
|
|
132
123
|
subtitle = {defaultVal(subtitle,params.subtitle,options.subtitle)}
|
|
133
124
|
subtitleProps = {subtitleProps}
|
|
134
125
|
/>
|
|
135
|
-
{
|
|
136
|
-
|
|
126
|
+
{renderSplitedActions(splitedActions,{
|
|
127
|
+
...defaultObj(menuProps,appBarProps.menuProps),
|
|
128
|
+
anchorProps : {
|
|
129
|
+
style : anchorStyle,
|
|
130
|
+
color : anchorStyle.color,
|
|
131
|
+
}
|
|
132
|
+
})}
|
|
133
|
+
{React.isValidElement(rightContent) && rightContent || React.isValidElement(right) && right || null}
|
|
137
134
|
</Appbar.Header>
|
|
138
135
|
);
|
|
139
136
|
});
|
|
@@ -3371,7 +3371,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3371
3371
|
fetchOptions.dataSources = this.currentDataSources;
|
|
3372
3372
|
fetchOptions.selector = fetchFilters;
|
|
3373
3373
|
fetchOptions.sort = this.getSort();
|
|
3374
|
-
const canIncludeField = typeof this.props.includeFieldsInFetchOptions =='boolean'? this.props.includeFieldsInFetchOptions : defaultBool(appConfig.get("includeFieldsInDatagridFetchOptions")
|
|
3374
|
+
const canIncludeField = typeof this.props.includeFieldsInFetchOptions =='boolean'? this.props.includeFieldsInFetchOptions : defaultBool(appConfig.get("includeFieldsInDatagridFetchOptions")) !== false;
|
|
3375
3375
|
if(canIncludeField){
|
|
3376
3376
|
const ff = this.getFilterableColumnsNames();
|
|
3377
3377
|
let fields = ff;
|
|
@@ -25,6 +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
29
|
|
|
29
30
|
export const getSessionKey = ()=>{
|
|
30
31
|
return Auth.getSessionKey("swrDatagrid");
|
|
@@ -48,8 +49,8 @@ export const setSessionData = (key,value)=>{
|
|
|
48
49
|
export const timeout = 5000*60;//5 minutes
|
|
49
50
|
/***@see : https://swr.vercel.app/docs/api */
|
|
50
51
|
|
|
51
|
-
export const getSWROptions = ()=>{
|
|
52
|
-
const delay = defaultNumber(
|
|
52
|
+
export const getSWROptions = (defTimeout)=>{
|
|
53
|
+
const delay = defaultNumber(defTimeout,timeout);
|
|
53
54
|
return {
|
|
54
55
|
dedupingInterval : delay,
|
|
55
56
|
errorRetryInterval : Math.max(delay*2,timeout),
|
|
@@ -101,6 +102,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
101
102
|
defaultSortOrder,
|
|
102
103
|
...rest
|
|
103
104
|
} = props;
|
|
105
|
+
const {swrConfig} = useContext();
|
|
104
106
|
rest = defaultObj(rest);
|
|
105
107
|
rest.exportTableProps = defaultObj(rest.exportTableProps)
|
|
106
108
|
const firstPage = 1;
|
|
@@ -227,10 +229,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
227
229
|
});
|
|
228
230
|
},
|
|
229
231
|
showError : false,
|
|
230
|
-
swrOptions :
|
|
231
|
-
...getSWROptions(),
|
|
232
|
-
...defaultObj(appConfig.swr),
|
|
233
|
-
},
|
|
232
|
+
swrOptions : getSWROptions(swrConfig.refreshTimeout)
|
|
234
233
|
});
|
|
235
234
|
const isLoading = isLoadingRef.current && customIsLoading || false;
|
|
236
235
|
/*React.useEffect(()=>{
|
|
@@ -34,8 +34,7 @@ const Provider = React.forwardRef((_props,innerRef)=>{
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
isOpen : x=> {
|
|
37
|
-
|
|
38
|
-
return messageRef.current && messageRef.current.setNativeProps ? true : false
|
|
37
|
+
return messageRef.current && messageRef.current? true : false
|
|
39
38
|
},
|
|
40
39
|
});
|
|
41
40
|
setRef(ref,context);
|
|
@@ -124,6 +124,7 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
|
|
|
124
124
|
}
|
|
125
125
|
const isSecureText = type =="password"?true : false;
|
|
126
126
|
const [secureTextEntry,setSecureTextEntry] = React.useState(isSecureText);
|
|
127
|
+
const [toggle,setToggle] = React.useState(false);
|
|
127
128
|
const prevSecureTextEntry = React.usePrevious(secureTextEntry);
|
|
128
129
|
containerProps = defaultObj(containerProps);
|
|
129
130
|
mode = defaultStr(mode,theme.textFieldMode);
|
|
@@ -271,10 +272,8 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
|
|
|
271
272
|
}
|
|
272
273
|
}
|
|
273
274
|
let hasLabel = label && (isShadowMode || isNormalMode || alwaysUseLabel || text || (isFocused || (!usePlaceholderWhenEmpty && canValueBeFormattable)))? true : labelText !== placeholder;
|
|
274
|
-
const innerRef = (
|
|
275
|
-
|
|
276
|
-
React.setRef(inputRef,el,setRef);
|
|
277
|
-
};
|
|
275
|
+
const innerRef = React.useRef(null);
|
|
276
|
+
const componentRef = React.useMergeRefs(innerRef,ref,setRef);
|
|
278
277
|
validType = defaultStr(validType,validRule).toLowerCase();
|
|
279
278
|
multiline = isFilter ? false : defaultBool(multiline,multiple,!!numberOfLines);
|
|
280
279
|
let inputColor = (isFocused || error) ? labelColor : Colors.isValid(color)?color : theme.colors.text;
|
|
@@ -304,7 +303,7 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
|
|
|
304
303
|
keyboardAppearance : theme.isDark()? 'dark': 'default',
|
|
305
304
|
caretHidden : false,
|
|
306
305
|
...props,
|
|
307
|
-
innerRef,
|
|
306
|
+
innerRef:componentRef,
|
|
308
307
|
placeholder : (isFocused || isShadowMode || isNormalMode) && labelText ? "":placeholder,
|
|
309
308
|
placeholderTextColor : error ? theme.colors.error : placeholderColor,
|
|
310
309
|
selectionColor,
|
|
@@ -377,12 +376,12 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
|
|
|
377
376
|
text2 = "0"+text2;
|
|
378
377
|
}
|
|
379
378
|
if(multiline){
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
379
|
+
if(!text2 || text2.length < 30){
|
|
380
|
+
heightRef.current = HEIGHT;
|
|
381
|
+
setToggle(!toggle);
|
|
382
|
+
} else if(target.scrollHeight > heightRef.current){
|
|
383
|
+
heightRef.current = target.scrollHeight;
|
|
384
|
+
setToggle(!toggle);
|
|
386
385
|
}
|
|
387
386
|
}
|
|
388
387
|
const tVal = toCase(text2);
|
|
@@ -475,7 +474,7 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
|
|
|
475
474
|
} else affix = undefined;
|
|
476
475
|
}
|
|
477
476
|
elevation = defaultNumber(contentContainerProps.elevation,elevation,isShadowMode?4:0);
|
|
478
|
-
const paddingVertical = (hasRight || hasLeft)? isMob?5 : 0 : 10;
|
|
477
|
+
const paddingVertical = multiline ? 0 : (hasRight || hasLeft)? isMob?5 : 0 : 10;
|
|
479
478
|
const contentContainerStyle = isOutlinedMode ? {
|
|
480
479
|
borderColor,
|
|
481
480
|
borderWidth,
|
|
@@ -540,7 +539,7 @@ const TextFieldComponent = React.forwardRef((componentProps,inputRef)=>{
|
|
|
540
539
|
typeof render ==="function"? render(inputProps):
|
|
541
540
|
<RNTextInput
|
|
542
541
|
{...inputProps}
|
|
543
|
-
ref = {
|
|
542
|
+
ref = {componentRef}
|
|
544
543
|
/>
|
|
545
544
|
}
|
|
546
545
|
</KeyboardAvoidingView>
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
|
|
7
|
+
const ExpoUIContext = React.createContext(null);
|
|
8
|
+
|
|
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;
|
package/src/index.js
CHANGED
|
@@ -39,6 +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
43
|
|
|
43
44
|
let MAX_BACK_COUNT = 1;
|
|
44
45
|
let countBack = 0;
|
|
@@ -58,17 +59,17 @@ const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
|
|
|
58
59
|
*/
|
|
59
60
|
function App({init:initApp,initialRouteName:appInitialRouteName,render,onMount,preferences:appPreferences,getStartedRouteName}) {
|
|
60
61
|
AppStateService.init();
|
|
62
|
+
const {FontsIconsFilter,beforeExit} = useContext();
|
|
61
63
|
const [initialState, setInitialState] = React.useState(undefined);
|
|
62
64
|
const appReadyRef = React.useRef(true);
|
|
63
65
|
const [state,setState] = React.useState({
|
|
64
66
|
isLoading : true,
|
|
65
67
|
isInitialized:false,
|
|
66
68
|
});
|
|
67
|
-
|
|
69
|
+
React.useEffect(() => {
|
|
68
70
|
const loadResources = ()=>{
|
|
69
71
|
return new Promise((resolve)=>{
|
|
70
|
-
|
|
71
|
-
loadFonts(appConfig.get("FontsIconsFilter")).catch((e)=>{
|
|
72
|
+
loadFonts(FontsIconsFilter).catch((e)=>{
|
|
72
73
|
console.warn(e," ierror loading app resources fonts");
|
|
73
74
|
}).finally(()=>{
|
|
74
75
|
resolve(true);
|
|
@@ -111,10 +112,10 @@ function App({init:initApp,initialRouteName:appInitialRouteName,render,onMount,p
|
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
const exit = ()=>{
|
|
114
|
-
if(typeof
|
|
115
|
-
const r2 =
|
|
115
|
+
if(typeof beforeExit =='function'){
|
|
116
|
+
const r2 = beforeExit()
|
|
116
117
|
if(!isPromise(r2)){
|
|
117
|
-
throw {message:'La fonction before exit
|
|
118
|
+
throw {message:'La fonction before exit du contexte doit retourner une promesse',returnedResult:r2}
|
|
118
119
|
}
|
|
119
120
|
return r2.then(foreceExit).catch(reject);
|
|
120
121
|
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import React from '$react';
|
|
2
|
-
import {Platform,StyleSheet,Pressable,View} from 'react-native';
|
|
3
|
-
import Label from "$ecomponents/Label";
|
|
4
|
-
import theme,{Colors,StyleProp} from "$theme";
|
|
5
|
-
import PropTypes from "prop-types";
|
|
6
|
-
import {defaultObj,defaultStr} from "$cutils";
|
|
7
|
-
import {isIos,isAndroid,isWeb} from "$cplatform";
|
|
8
|
-
|
|
9
|
-
const AppbarContent = React.forwardRef(({
|
|
10
|
-
color: titleColor,
|
|
11
|
-
subtitle,
|
|
12
|
-
subtitleProps,
|
|
13
|
-
subtitleStyle,
|
|
14
|
-
onPress,
|
|
15
|
-
style,
|
|
16
|
-
titleProps,
|
|
17
|
-
titleRef,
|
|
18
|
-
titleStyle,
|
|
19
|
-
title,
|
|
20
|
-
testID,
|
|
21
|
-
containerProps,
|
|
22
|
-
...rest
|
|
23
|
-
},ref) => {
|
|
24
|
-
|
|
25
|
-
const titleTextColor = titleColor ? titleColor : theme.colors.primaryText;
|
|
26
|
-
titleProps = defaultObj(titleProps);
|
|
27
|
-
subtitleProps = defaultObj(subtitleProps);
|
|
28
|
-
testID = defaultStr(testID,"RN_AppBarContentComponent")
|
|
29
|
-
subtitle = subtitle === false ? null : subtitle;
|
|
30
|
-
const subtitleColor = Colors.setAlpha(titleTextColor,0.7);
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<Pressable testID={testID+"_Container"} {...defaultObj(containerProps)} onPress={onPress} disabled={!onPress}>
|
|
34
|
-
<View
|
|
35
|
-
pointerEvents="box-none"
|
|
36
|
-
style={[styles.container, style]}
|
|
37
|
-
{...rest}
|
|
38
|
-
testID = {testID}
|
|
39
|
-
ref = {ref}
|
|
40
|
-
>
|
|
41
|
-
<Label
|
|
42
|
-
ref={titleRef}
|
|
43
|
-
testID = {testID+"_Title"}
|
|
44
|
-
{...titleProps}
|
|
45
|
-
style={[
|
|
46
|
-
{
|
|
47
|
-
color: titleTextColor,
|
|
48
|
-
...(isIos()? theme.fonts.regular: theme.fonts.medium),
|
|
49
|
-
},
|
|
50
|
-
isWeb() && theme.styles.webFontFamilly,
|
|
51
|
-
titleProps.style,
|
|
52
|
-
titleStyle,
|
|
53
|
-
]}
|
|
54
|
-
numberOfLines={1}
|
|
55
|
-
accessible
|
|
56
|
-
// @ts-ignore Type '"heading"' is not assignable to type ...
|
|
57
|
-
role={Platform.OS === 'web' ? 'heading' : 'header'}
|
|
58
|
-
>
|
|
59
|
-
{title}
|
|
60
|
-
</Label>
|
|
61
|
-
{subtitle ? (
|
|
62
|
-
<Label
|
|
63
|
-
testID = {testID+"_Subtitle"}
|
|
64
|
-
{...subtitleProps}
|
|
65
|
-
style={[styles.subtitle, { color: subtitleColor }, subtitleProps.style, subtitleStyle]}
|
|
66
|
-
numberOfLines={1}
|
|
67
|
-
>
|
|
68
|
-
{subtitle}
|
|
69
|
-
</Label>
|
|
70
|
-
) : null}
|
|
71
|
-
</View>
|
|
72
|
-
</Pressable>
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
AppbarContent.displayName = 'Appbar.Content';
|
|
77
|
-
|
|
78
|
-
const styles = StyleSheet.create({
|
|
79
|
-
container: {
|
|
80
|
-
flex: 1,
|
|
81
|
-
paddingHorizontal: 5,
|
|
82
|
-
justifyContent : 'center',
|
|
83
|
-
alignItems : 'flex-start',
|
|
84
|
-
},
|
|
85
|
-
title: {
|
|
86
|
-
fontSize: Platform.OS === 'ios' ? 17 : 20,
|
|
87
|
-
},
|
|
88
|
-
subtitle: {
|
|
89
|
-
fontSize: Platform.OS === 'ios' ? 11 : 14,
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
export default AppbarContent;
|
|
94
|
-
const titleType = PropTypes.oneOfType([
|
|
95
|
-
PropTypes.string,
|
|
96
|
-
PropTypes.node,
|
|
97
|
-
PropTypes.bool,
|
|
98
|
-
])
|
|
99
|
-
|
|
100
|
-
AppbarContent.propTypes = {
|
|
101
|
-
/**
|
|
102
|
-
* Custom StyleProp for the text.
|
|
103
|
-
*/
|
|
104
|
-
StyleProp: PropTypes.string,
|
|
105
|
-
/**
|
|
106
|
-
* Text for the title.
|
|
107
|
-
*/
|
|
108
|
-
title: titleType,
|
|
109
|
-
/**
|
|
110
|
-
* Style for the title.
|
|
111
|
-
*/
|
|
112
|
-
titleStyle: StyleProp,
|
|
113
|
-
/**
|
|
114
|
-
* Reference for the title.
|
|
115
|
-
*/
|
|
116
|
-
titleRef : PropTypes.any,
|
|
117
|
-
/**
|
|
118
|
-
* @deprecated Deprecated in v5.x
|
|
119
|
-
* Text for the subtitle.
|
|
120
|
-
*/
|
|
121
|
-
subtitle : titleType,
|
|
122
|
-
/**
|
|
123
|
-
* @deprecated Deprecated in v5.x
|
|
124
|
-
* Style for the subtitle.
|
|
125
|
-
*/
|
|
126
|
-
subtitleStyle: StyleProp,
|
|
127
|
-
/**
|
|
128
|
-
* Function to execute on press.
|
|
129
|
-
*/
|
|
130
|
-
onPress : PropTypes.func,
|
|
131
|
-
style : StyleProp
|
|
132
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**** see : https://github.com/danilowoz/react-content-loader */
|
|
2
|
-
import {defaultObj} from "$cutils";
|
|
3
|
-
import View from "$ecomponents/View";
|
|
4
|
-
import {StyleSheet,Dimensions,useWindowDimensions} from "react-native";
|
|
5
|
-
import React from "react";
|
|
6
|
-
import ContentLoaderF, {Facebook as CLFacebook,Instagram as CLInstagram} from './Loader';
|
|
7
|
-
import PropTypes from "prop-types";
|
|
8
|
-
import BarcharComponent from "./BarChar";
|
|
9
|
-
import PieChartComponent from "./PieChart";
|
|
10
|
-
import FormComponent,{HEIGHT as formHeight} from "./Form";
|
|
11
|
-
import DatagridContentLoader,{HEIGHT as datagridHeight} from "./Datagrid";
|
|
12
|
-
import ProfileComponent from "./Profile";
|
|
13
|
-
import { getBackgroundColor } from "./utils";
|
|
14
|
-
import TaskListComponent from "./TaskList";
|
|
15
|
-
import theme,{Colors} from "$theme"
|
|
16
|
-
import Rect from "./Rect";
|
|
17
|
-
import Circle from "./Circle";
|
|
18
|
-
|
|
19
|
-
export * from "./utils";
|
|
20
|
-
|
|
21
|
-
export {Rect};
|
|
22
|
-
|
|
23
|
-
export {Circle};
|
|
24
|
-
|
|
25
|
-
export {default as Table} from "./Table";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export default function ContentLoaderWrapper (props){
|
|
29
|
-
let {instance,containerProps,mediaQueryUpdateNativeProps,instances,Component,count,...rest} = props;
|
|
30
|
-
const innerRef = React.useRef(null);
|
|
31
|
-
Component = defaultVal(Component,ContentLoaderF);
|
|
32
|
-
containerProps = defaultObj(containerProps);
|
|
33
|
-
const getChildren = ({width,height,count})=>{
|
|
34
|
-
const dimensions = Dimensions.get("window");
|
|
35
|
-
width = width || dimensions.width;
|
|
36
|
-
height = height || dimensions.height;
|
|
37
|
-
rest = {...defaultObj(rest),width,height}
|
|
38
|
-
const r = [];
|
|
39
|
-
rest = defaultObj(rest);
|
|
40
|
-
count = Math.ceil(defaultNumber(instances,instance,count,3))
|
|
41
|
-
rest.backgroundColor = Colors.isValid(rest.backgroundColor)? rest.backgroundColor : Colors.darken(theme.colors.background);
|
|
42
|
-
rest.backgroundColor= getBackgroundColor(rest.backgroundColor)// '#cecece';
|
|
43
|
-
if(count <= 1) count = 1;
|
|
44
|
-
for(let i = 1; i<= count; i++){
|
|
45
|
-
r.push(<Component {...rest} key={i+""} />)
|
|
46
|
-
}
|
|
47
|
-
return r;
|
|
48
|
-
}
|
|
49
|
-
const children = getChildren({count});
|
|
50
|
-
return <View ref={innerRef} onLayout = {React.mediaQueryUpdateNativePropsCallback(({target,...args})=>{
|
|
51
|
-
args.layout = args.nativeEvent.layout;
|
|
52
|
-
if(typeof mediaQueryUpdateNativeProps ==='function'){
|
|
53
|
-
const children = getChildren(defaultObj(mediaQueryUpdateNativeProps(args)));
|
|
54
|
-
console.log("will update target ",target,children);
|
|
55
|
-
target.setNativeProps({children});
|
|
56
|
-
}
|
|
57
|
-
},innerRef)} {...containerProps}
|
|
58
|
-
style={[styles.container,styles.fullWidth,containerProps.style]}
|
|
59
|
-
>
|
|
60
|
-
{children}
|
|
61
|
-
</View>
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
ContentLoaderWrapper.propTypes = {
|
|
65
|
-
//le nombre d'instance du content loader
|
|
66
|
-
instances : PropTypes.number,
|
|
67
|
-
instance : PropTypes.number,
|
|
68
|
-
count : PropTypes.number,
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function Facebook (props){
|
|
72
|
-
return <ContentLoaderWrapper {...props} Component={CLFacebook}/>
|
|
73
|
-
}
|
|
74
|
-
export function Instagram (props){
|
|
75
|
-
return <ContentLoaderWrapper {...props} Component={CLInstagram}/>
|
|
76
|
-
}
|
|
77
|
-
export function ContentLoader (props){
|
|
78
|
-
return <ContentLoaderWrapper {...props} Component={ContentLoaderF}/>
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function BarChart (props){
|
|
82
|
-
return <ContentLoaderWrapper {...props} Component={BarcharComponent}/>
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function PieChart (props){
|
|
86
|
-
return <ContentLoaderWrapper {...props} Component={PieChartComponent}/>
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function Form (props){
|
|
90
|
-
const {height} = Dimensions.get("window");
|
|
91
|
-
return <ContentLoaderWrapper
|
|
92
|
-
mediaQueryUpdateNativeProps = {({layout:{width,height}})=>{
|
|
93
|
-
width = Math.max(width-50,200);
|
|
94
|
-
return {width,count:Math.max(Math.trunc(height/formHeight),2)}
|
|
95
|
-
}}
|
|
96
|
-
{...props}
|
|
97
|
-
count = {Math.max(Math.trunc(height/formHeight),2)}
|
|
98
|
-
Component={FormComponent}
|
|
99
|
-
/>
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function Profile (props){
|
|
103
|
-
let {containerProps,...rest} = props;
|
|
104
|
-
containerProps = Object.assign({},containerProps);
|
|
105
|
-
containerProps.style = [styles.taskListContainer,containerProps.style];
|
|
106
|
-
return <ContentLoaderWrapper count={3} {...props} Component={ProfileComponent}/>
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function TaskList (props){
|
|
110
|
-
return <ContentLoaderWrapper count={3} {...props} Component={TaskListComponent}/>
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function Datagrid (props){
|
|
114
|
-
const {height} = Dimensions.get("window");
|
|
115
|
-
return <ContentLoaderWrapper
|
|
116
|
-
name = "ddddd"
|
|
117
|
-
mediaQueryUpdateNativeProps ={({layout:{width,height}})=>{
|
|
118
|
-
width = Math.max(props.width-50,200);
|
|
119
|
-
return {width,count:Math.max(Math.trunc((height-100)/datagridHeight),2)}
|
|
120
|
-
}}
|
|
121
|
-
{...props}
|
|
122
|
-
Component={DatagridContentLoader}
|
|
123
|
-
count = {Math.max(Math.trunc((height-100)/datagridHeight),2)}
|
|
124
|
-
/>
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const styles = StyleSheet.create({
|
|
129
|
-
fullWidth : {
|
|
130
|
-
width : '100%'
|
|
131
|
-
},
|
|
132
|
-
center : {
|
|
133
|
-
flex : 1,
|
|
134
|
-
justifyContent: 'center',
|
|
135
|
-
alignItems :'center',
|
|
136
|
-
},
|
|
137
|
-
container : {
|
|
138
|
-
marginHorizontal : 0,
|
|
139
|
-
paddingHorizontal : 0,
|
|
140
|
-
marginTop : 10,
|
|
141
|
-
alignItems : 'center',
|
|
142
|
-
justifyContent : 'flex-start'
|
|
143
|
-
},
|
|
144
|
-
taskListContainer : {
|
|
145
|
-
alignItems : 'flex-end',
|
|
146
|
-
alignSelf : 'flex-start',
|
|
147
|
-
},
|
|
148
|
-
})
|