@fto-consult/expo-ui 2.7.13 → 2.9.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,115 +1,115 @@
1
- {
2
- "name": "@fto-consult/expo-ui",
3
- "version": "2.7.13",
4
- "description": "Bibliothèque de composants UI Expo,react-native",
5
- "main": "index.js",
6
- "resolutions": {
7
- "@expo/cli": "xxx"
8
- },
9
- "scripts": {
10
- "publish1": "npm publish --access=public",
11
- "unpublish": "npm -f unpublish @fto-consult/expo-ui",
12
- "build-web": "",
13
- "dev": "npx expo start -c --no-minify",
14
- "start": "npx expo start --dev --no-minify",
15
- "start-d": "npx expo start -c --no-dev --no-minify",
16
- "start-p": "npm run start-d",
17
- "expo-start-client": "npx expo start --dev --no-minify --dev-client",
18
- "start-m": "npx expo start - c--dev--no -minify",
19
- "android": "npx expo start --android -c",
20
- "ios": "npx expo start --ios",
21
- "web": "npx expo start --web",
22
- "web-c": "npx expo start --web -c",
23
- "eject": "expo eject",
24
- "emulator": "npm run android-emulator",
25
- "web-server": "npx serve web-build",
26
- "build-android": "eas build --clear-cache -p android --profile preview",
27
- "build-android-local": "eas build --platform android --local",
28
- "build-android-dist": "eas build --clear-cache -p android",
29
- "build-ios": "eas build --clear-cache -p ios --profile preview",
30
- "build-ios-dist": "eas build --clear-cache -p ios",
31
- "install-apk": "adb -s emulator-5554 install myapp.apk",
32
- "android-emulator": "emulator -avd EMULATOR",
33
- "flipper": "npx cross-env METRO_SERVER_PORT=19000 E:\\Studies\\react-native\\debugger\\Flipper-win\\Flipper.exe",
34
- "build-electron": "electron-webpack && electron-builder --dir -c.compression=store",
35
- "test:build": "electron-webpack && electron-builder --dir -c.compression=store -c.mac.identity=null",
36
- "compile-electron": "webpack --config ./electron/webpack.config.js",
37
- "compile-electron-p": "webpack --config ./electron/webpack.config.js --mode=production",
38
- "electron": "electron ./electron",
39
- "logcat": "adb -d logcat com.ftc.apps.salite1:E > errors.txt",
40
- "logcat-export": "adb -d logcat com.ftc.apps.salite1 *:S > logcat.txt",
41
- "electron-c": "npm run compile-electron && npm run electron",
42
- "electron-p": "npm run compile-electron-p && npm run electron",
43
- "update-app-version": "node ./update-app-version.js",
44
- "find-licenses": "node ./find-licenses.js",
45
- "fix-dependencies": "expo doctor --fix-dependencies",
46
- "delete-node-modules": "rimraf ./**/node_modules"
47
- },
48
- "repository": {
49
- "type": "git",
50
- "url": "git+https://github.com/borispipo/expo-ui.git"
51
- },
52
- "keywords": [
53
- "Expo",
54
- "React-Native"
55
- ],
56
- "author": "Boris Fouomene",
57
- "license": "ISC",
58
- "bugs": {
59
- "url": "https://github.com/borispipo/expo-ui/issues"
60
- },
61
- "homepage": "https://github.com/borispipo/expo-ui#readme",
62
- "dependencies": {
63
- "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
64
- "@babel/preset-react": "^7.18.6",
65
- "@emotion/native": "^11.10.0",
66
- "@expo/html-elements": "^0.2.0",
67
- "@expo/metro-config": "^0.4.0",
68
- "@expo/vector-icons": "^13.0.0",
69
- "@expo/webpack-config": "^0.17.2",
70
- "@fto-consult/common": "^1.13.1",
71
- "@gorhom/portal": "^1.0.14",
72
- "@react-native-async-storage/async-storage": "~1.17.3",
73
- "@react-native-community/datetimepicker": "6.5.2",
74
- "@react-native-community/netinfo": "9.3.5",
75
- "@react-navigation/native": "^6.0.13",
76
- "@react-navigation/native-stack": "^6.9.1",
77
- "@shopify/flash-list": "1.3.1",
78
- "babel-plugin-inline-dotenv": "^1.7.0",
79
- "babel-plugin-module-resolver": "^4.1.0",
80
- "babel-plugin-transform-inline-environment-variables": "^0.4.4",
81
- "expo": "^47.0.8",
82
- "expo-camera": "~13.1.0",
83
- "expo-clipboard": "~4.0.1",
84
- "expo-font": "~11.0.1",
85
- "expo-image-picker": "~14.0.2",
86
- "expo-linking": "~3.2.3",
87
- "expo-sqlite": "~11.0.0",
88
- "expo-status-bar": "~1.4.2",
89
- "expo-system-ui": "~2.0.1",
90
- "expo-web-browser": "~12.0.0",
91
- "google-libphonenumber": "^3.2.31",
92
- "htmlparser2-without-node-native": "^3.9.2",
93
- "mongo-parse": "^2.1.0",
94
- "parent-package-json": "^2.0.1",
95
- "prop-types": "^15.8.1",
96
- "react": "18.1.0",
97
- "react-apexcharts": "^1.4.0",
98
- "react-content-loader": "^6.2.0",
99
- "react-dom": "18.1.0",
100
- "react-native": "0.70.5",
101
- "react-native-big-list": "^1.5.5",
102
- "react-native-gesture-handler": "~2.8.0",
103
- "react-native-paper": "^4.12.5",
104
- "react-native-paper-dates": "^0.9.2",
105
- "react-native-reanimated": "~2.12.0",
106
- "react-native-safe-area-context": "4.4.1",
107
- "react-native-screens": "~3.18.0",
108
- "react-native-svg": "13.4.0",
109
- "react-native-web": "~0.18.7",
110
- "react-native-webview": "11.23.1",
111
- "sharp-cli": "^2.1.0",
112
- "tippy.js": "^6.3.7",
113
- "yargs": "^17.1.1-candidate.0"
114
- }
115
- }
1
+ {
2
+ "name": "@fto-consult/expo-ui",
3
+ "version": "2.9.0",
4
+ "description": "Bibliothèque de composants UI Expo,react-native",
5
+ "main": "index.js",
6
+ "resolutions": {
7
+ "@expo/cli": "xxx"
8
+ },
9
+ "scripts": {
10
+ "publish1": "npm publish --access=public",
11
+ "unpublish": "npm -f unpublish @fto-consult/expo-ui",
12
+ "build-web": "",
13
+ "dev": "npx expo start -c --no-minify",
14
+ "start": "npx expo start --dev --no-minify",
15
+ "start-d": "npx expo start -c --no-dev --no-minify",
16
+ "start-p": "npm run start-d",
17
+ "expo-start-client": "npx expo start --dev --no-minify --dev-client",
18
+ "start-m": "npx expo start - c--dev--no -minify",
19
+ "android": "npx expo start --android -c",
20
+ "ios": "npx expo start --ios",
21
+ "web": "npx expo start --web",
22
+ "web-c": "npx expo start --web -c",
23
+ "eject": "expo eject",
24
+ "emulator": "npm run android-emulator",
25
+ "web-server": "npx serve web-build",
26
+ "build-android": "eas build --clear-cache -p android --profile preview",
27
+ "build-android-local": "eas build --platform android --local",
28
+ "build-android-dist": "eas build --clear-cache -p android",
29
+ "build-ios": "eas build --clear-cache -p ios --profile preview",
30
+ "build-ios-dist": "eas build --clear-cache -p ios",
31
+ "install-apk": "adb -s emulator-5554 install myapp.apk",
32
+ "android-emulator": "emulator -avd EMULATOR",
33
+ "flipper": "npx cross-env METRO_SERVER_PORT=19000 E:\\Studies\\react-native\\debugger\\Flipper-win\\Flipper.exe",
34
+ "build-electron": "electron-webpack && electron-builder --dir -c.compression=store",
35
+ "test:build": "electron-webpack && electron-builder --dir -c.compression=store -c.mac.identity=null",
36
+ "compile-electron": "webpack --config ./electron/webpack.config.js",
37
+ "compile-electron-p": "webpack --config ./electron/webpack.config.js --mode=production",
38
+ "electron": "electron ./electron",
39
+ "logcat": "adb -d logcat com.ftc.apps.salite1:E > errors.txt",
40
+ "logcat-export": "adb -d logcat com.ftc.apps.salite1 *:S > logcat.txt",
41
+ "electron-c": "npm run compile-electron && npm run electron",
42
+ "electron-p": "npm run compile-electron-p && npm run electron",
43
+ "update-app-version": "node ./update-app-version.js",
44
+ "find-licenses": "node ./find-licenses.js",
45
+ "fix-dependencies": "expo doctor --fix-dependencies",
46
+ "delete-node-modules": "rimraf ./**/node_modules"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/borispipo/expo-ui.git"
51
+ },
52
+ "keywords": [
53
+ "Expo",
54
+ "React-Native"
55
+ ],
56
+ "author": "Boris Fouomene",
57
+ "license": "ISC",
58
+ "bugs": {
59
+ "url": "https://github.com/borispipo/expo-ui/issues"
60
+ },
61
+ "homepage": "https://github.com/borispipo/expo-ui#readme",
62
+ "dependencies": {
63
+ "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
64
+ "@babel/preset-react": "^7.18.6",
65
+ "@emotion/native": "^11.10.0",
66
+ "@expo/html-elements": "^0.2.0",
67
+ "@expo/metro-config": "^0.4.0",
68
+ "@expo/vector-icons": "^13.0.0",
69
+ "@expo/webpack-config": "^0.17.2",
70
+ "@fto-consult/common": "^1.14.16",
71
+ "@gorhom/portal": "^1.0.14",
72
+ "@react-native-async-storage/async-storage": "~1.17.3",
73
+ "@react-native-community/datetimepicker": "6.5.2",
74
+ "@react-native-community/netinfo": "9.3.5",
75
+ "@react-navigation/native": "^6.0.13",
76
+ "@react-navigation/native-stack": "^6.9.1",
77
+ "@shopify/flash-list": "1.3.1",
78
+ "babel-plugin-inline-dotenv": "^1.7.0",
79
+ "babel-plugin-module-resolver": "^4.1.0",
80
+ "babel-plugin-transform-inline-environment-variables": "^0.4.4",
81
+ "expo": "^47.0.8",
82
+ "expo-camera": "~13.1.0",
83
+ "expo-clipboard": "~4.0.1",
84
+ "expo-font": "~11.0.1",
85
+ "expo-image-picker": "~14.0.2",
86
+ "expo-linking": "~3.2.3",
87
+ "expo-sqlite": "~11.0.0",
88
+ "expo-status-bar": "~1.4.2",
89
+ "expo-system-ui": "~2.0.1",
90
+ "expo-web-browser": "~12.0.0",
91
+ "google-libphonenumber": "^3.2.31",
92
+ "htmlparser2-without-node-native": "^3.9.2",
93
+ "mongo-parse": "^2.1.0",
94
+ "parent-package-json": "^2.0.1",
95
+ "prop-types": "^15.8.1",
96
+ "react": "18.1.0",
97
+ "react-apexcharts": "^1.4.0",
98
+ "react-content-loader": "^6.2.0",
99
+ "react-dom": "18.1.0",
100
+ "react-native": "0.70.5",
101
+ "react-native-big-list": "^1.5.5",
102
+ "react-native-gesture-handler": "~2.8.0",
103
+ "react-native-paper": "^4.12.5",
104
+ "react-native-paper-dates": "^0.9.2",
105
+ "react-native-reanimated": "~2.12.0",
106
+ "react-native-safe-area-context": "4.4.1",
107
+ "react-native-screens": "~3.18.0",
108
+ "react-native-svg": "13.4.0",
109
+ "react-native-web": "~0.18.7",
110
+ "react-native-webview": "11.23.1",
111
+ "sharp-cli": "^2.1.0",
112
+ "tippy.js": "^6.3.7",
113
+ "yargs": "^17.1.1-candidate.0"
114
+ }
115
+ }
package/src/auth/Login.js CHANGED
@@ -86,7 +86,7 @@ export default function LoginComponent(props){
86
86
  },1000)
87
87
  }
88
88
  },[withPortal])
89
- const {header,withScrollView:customWithScrollView,children,initialize,contentTop,data:loginData,canGoToNext,keyboardEvents,onSuccess:onLoginSuccess,mutateData,canSubmit:canSubmitForm,onStepChange,...loginProps} = defaultObj(getProps({
89
+ const {header,withScrollView:customWithScrollView,children,initialize,contentTop,data:loginData,canGoToNext,keyboardEvents,onSuccess:onLoginSuccess,mutateData,beforeSubmit:beforeSubmitForm,canSubmit:canSubmitForm,onStepChange,...loginProps} = defaultObj(getProps({
90
90
  ...state,
91
91
  setState,
92
92
  state,
@@ -119,6 +119,7 @@ export default function LoginComponent(props){
119
119
  * par défaut, on envoie les données lorssqu'on est à l'étappe 2
120
120
  * **/
121
121
  const canSubmit = typeof canSubmitForm =='function'? canSubmitForm : ({step})=>step >= 2;
122
+ const beforeSubmit = typeof beforeSubmitForm =='function'? beforeSubmitForm : x=> true;
122
123
  const goToNext = ()=>{
123
124
  let step = state.step;
124
125
  const data = getData();
@@ -149,7 +150,7 @@ export default function LoginComponent(props){
149
150
  nextButtonRef.current?.enable();
150
151
  }
151
152
  if(step > 1){
152
- if(canSubmit(args)){
153
+ if(canSubmit(args) && beforeSubmit(args) !== false){
153
154
  ///pour modifier automatiquement la données à mettre à jour
154
155
  if(typeof mutateData =='function'){
155
156
  mutateData(data);
@@ -178,7 +179,7 @@ export default function LoginComponent(props){
178
179
  else {
179
180
  loginFields[i] = Object.clone(field);
180
181
  hasLoginFields = true;
181
- if("autoFocusOnStep" in loginFields[i]){
182
+ if("autoFocusOnStep" in loginFields[i] && typeof loginFields[i].autoFocus !=='boolean'){
182
183
  loginFields[i].autoFocus = !!loginFields[i].autoFocusOnStep;
183
184
  }
184
185
  }
@@ -11,7 +11,7 @@ const AppexChartComponent = React.forwardRef(({chartContext,options,...props},re
11
11
  if (chartContext.current && typeof chartContext.current.destroy === 'function') {
12
12
  setTimeout(()=>{
13
13
  try {chartContext.current.destroy();} catch{}
14
- },500);
14
+ },1000);
15
15
  }
16
16
  }
17
17
  },[]);
@@ -1,6 +1,6 @@
1
1
  import React from '$react'
2
2
  import PropTypes from 'prop-types'
3
- import {defaultStr} from "$utils";
3
+ import {defaultStr,defaultObj,uniqid} from "$utils";
4
4
  import {extend} from "./utils"
5
5
  import stableHash from 'stable-hash';
6
6
  import Chart from "./appexChart";
@@ -14,30 +14,34 @@ import Chart from "./appexChart";
14
14
  * options {number} - les options supplémentaires au chart
15
15
  *
16
16
  */
17
- const ChartComponent = React.forwardRef(({type, height, width, series, options,testID,webViewProps, ...props },ref)=>{
17
+ const ChartComponent = React.forwardRef(({type, height,chartId, width, series, options,testID,webViewProps, ...props },ref)=>{
18
18
  const chartContext = React.useRef(null);
19
+ options = defaultObj(options);
20
+ const chartIdRef = React.useRef(defaultStr(chartId,options.chart?.id,uniqid("chart-id")));
19
21
  const config = extend(options,{
20
22
  chart: {
21
23
  type,
22
24
  height,
23
- width
25
+ width,
26
+ id : chartIdRef.current
24
27
  },
25
28
  series,
26
29
  });
30
+ config.chart.id = chartIdRef.current;
27
31
  testID = defaultStr(testID,"RN_ChartComponent");
28
32
  const prevWidth = React.usePrevious(width), prevHeight = React.usePrevious(height);
29
- const prevOptions = React.usePrevious(options,stableHash);
33
+ const prevOptions = React.usePrevious(options,JSON.stringify);
30
34
  const prevSeries = React.usePrevious(series,JSON.stringify);
31
35
  React.useEffect(()=>{
32
36
  if(chartContext.current && chartContext.current.updateOptions){
33
- if((JSON.stringify(prevSeries) == JSON.stringify(series)) || width != prevWidth || height != prevHeight){
37
+ if((prevSeries == series) || width != prevWidth || height != prevHeight){
34
38
  chartContext.current.updateOptions(config);
35
- } else if(JSON.stringify(prevOptions) != JSON.stringify(options)){
39
+ } else if(prevOptions != options){
36
40
  chartContext.current.updateSeries(series);
37
41
  }
38
42
  }
39
43
  },[stableHash({type,options,series,width,height})])
40
- return <Chart {...props} options={config} chartContext={chartContext} testID={testID} ref={ref}/>
44
+ return <Chart {...props} options={config} chartId={chartIdRef.current} chartContext={chartContext} testID={testID} ref={ref}/>
41
45
  });
42
46
 
43
47
 
@@ -11,7 +11,7 @@ import {notify,showConfirm} from "$ecomponents/Dialog";
11
11
  import Label from "$ecomponents/Label";
12
12
  import Image from "$ecomponents/Image";
13
13
  import Icon,{COPY_ICON} from "$ecomponents/Icon";
14
- import filterUtils from "$ecomponents/Filter/utils";
14
+ import filterUtils from "$cfilters";
15
15
  import Hashtag from "$ecomponents/Hashtag";
16
16
  import {sortBy,isDecimal,extendObj,isObjOrArray,defaultNumber,defaultStr,isFunction,defaultBool,defaultArray,defaultObj,isNonNullString,defaultDecimal} from "$utils";
17
17
  import {Datagrid as DatagridContentLoader} from "$ecomponents/ContentLoader";
@@ -900,7 +900,7 @@ export default class CommonDatagridComponent extends AppComponent {
900
900
  field = header.field = defaultStr(header.field,field,headerIndex);
901
901
  delete restCol.filter;
902
902
 
903
- const type = defaultStr(header.type).toLowerCase();
903
+ const type = defaultStr(header.jsType,header.type,"text").toLowerCase();
904
904
  sortType = defaultStr(sortType,type).toLowerCase();
905
905
  width = defaultDecimal(width);
906
906
  if(width <COLUMN_WIDTH/2){
@@ -929,6 +929,7 @@ export default class CommonDatagridComponent extends AppComponent {
929
929
  });
930
930
  restCol.field = header.field;
931
931
  restCol.label = defaultStr(header.text,header.label) ;
932
+ restCol.type = type;
932
933
  if(!restCol.label){
933
934
  console.error(header," has not label or text in datagrid",columns,this.props)
934
935
  }
@@ -957,6 +958,7 @@ export default class CommonDatagridComponent extends AppComponent {
957
958
  delete restCol.sortable;
958
959
  filterProps = {
959
960
  ...restCol,
961
+ type,
960
962
  columnIndex,
961
963
  visibleColumnIndex,
962
964
  sortable:isColumnSortable,
@@ -986,6 +988,7 @@ export default class CommonDatagridComponent extends AppComponent {
986
988
  }
987
989
  this.prepareColumn({
988
990
  visible,
991
+ type,
989
992
  columnIndex,
990
993
  visibleColumnIndex,
991
994
  sortable:isColumnSortable,
@@ -1493,6 +1496,7 @@ export default class CommonDatagridComponent extends AppComponent {
1493
1496
  if(!isObj(rowData)) return {render:null,extra:{}};
1494
1497
  let _render = null;
1495
1498
  columnDef = defaultObj(columnDef);
1499
+ let _type = defaultStr(columnDef.jsType,columnDef.type).trim().toLowerCase();
1496
1500
  if(this.isSelectableColumn(columnDef,columnField)){
1497
1501
  rowKey = rowKey ? rowKey : this.getRowKey(rowData,rowIndex);
1498
1502
  return {render :handleSelectableColumn === false ? null : this.renderSelectableCheckboxCell({
@@ -1528,7 +1532,6 @@ export default class CommonDatagridComponent extends AppComponent {
1528
1532
  _render = defaultDecimal(columnDef.multiplicater({...renderArgs,value:rowData[columnField]}),rowData[columnField]);
1529
1533
  } else {
1530
1534
  _render = defaultValue;
1531
- let _type = defaultStr(columnDef.type).trim().toLowerCase();
1532
1535
  if(defaultStr(columnDef.format).toLowerCase() === 'hashtag'){
1533
1536
  _render = <Hashtag>{_render}</Hashtag>
1534
1537
  } else if(typeof columnDef.render === "function"){
@@ -3,6 +3,7 @@ import {isObj,defaultStr} from "$utils";
3
3
  import View from "$ecomponents/View";
4
4
  import Portal from "$ecomponents/Portal";
5
5
  import theme,{Colors} from "$theme";
6
+ import Dimensions,{isMobileMedia,isTabletMedia,isDesktopMedia} from "$dimensions";
6
7
  import {
7
8
  StyleSheet,
8
9
  TouchableOpacity,
@@ -598,7 +599,7 @@ export default class DropdownAlert extends Component {
598
599
  wrapperStyle,
599
600
  tapToCloseEnabled,
600
601
  accessibilityLabel,
601
- testID,
602
+ testID:customTestId,
602
603
  accessible,
603
604
  contentContainerStyle,
604
605
  defaultTextContainer,
@@ -608,6 +609,7 @@ export default class DropdownAlert extends Component {
608
609
  showCancel,
609
610
  imageStyle,
610
611
  } = this.props;
612
+ const testID = defaultStr(customTestId,"RN_DropdownAlert");
611
613
  const {animationValue, bottomValue, height} = this.state;
612
614
  const {type, payload} = this.alertData;
613
615
  let style = this.getStyleForType(type);
@@ -641,14 +643,6 @@ export default class DropdownAlert extends Component {
641
643
  right: 0,
642
644
  elevation: elevation,
643
645
  };
644
- /*wrapperAnimStyle.zIndex = 1000100;
645
- if (zIndex != null) {
646
- wrapperAnimStyle.zIndex = zIndex;
647
- }*/
648
- let ContentView = View//SafeAreaView;
649
- if (IS_IOS_BELOW_11 || IS_ANDROID) {
650
- ContentView = View;
651
- }
652
646
  const activeOpacity = !tapToCloseEnabled || showCancel ? 1 : 0.95;
653
647
  const onPress = !tapToCloseEnabled
654
648
  ? null
@@ -658,28 +652,45 @@ export default class DropdownAlert extends Component {
658
652
  <Animated.View
659
653
  ref={(ref) => (this.mainView = ref)}
660
654
  {...this.panResponder.panHandlers}
655
+ testID={testID+"_AnimatedView"}
661
656
  style={[wrapperAnimStyle, wrapperStyle]}>
662
657
  <TouchableOpacity
663
- activeOpacity={activeOpacity}
664
- onPress={onPress}
665
- disabled={!tapToCloseEnabled}
666
- onLayout={(event) => this._onLayoutEvent(event)}
667
- testID={testID}
668
- accessibilityLabel={accessibilityLabel}
669
- accessible={accessible}>
670
- <View style={style}>
671
- <ContentView style={StyleSheet.flatten(contentContainerStyle)}>
672
- {this._renderImage(imageSrc, imageStyle)}
673
- <View style={StyleSheet.flatten(defaultTextContainer)}>
674
- {this._renderTitle()}
675
- {this._renderMessage()}
658
+ activeOpacity={activeOpacity}
659
+ onPress={onPress}
660
+ disabled={!tapToCloseEnabled}
661
+ onLayout={(event) => this._onLayoutEvent(event)}
662
+ testID={testID}
663
+ accessibilityLabel={accessibilityLabel}
664
+ accessible={accessible}>
665
+ <View style={style} testID={testID+"_ContentContainer"}>
666
+ <View testID={testID+"_ContentWrapper"} style={[contentContainerStyle,getContainerStyle().style]}
667
+ mediaQueryUpdateNativeProps={(args)=>{
668
+ return getContainerStyle(args);
669
+ }}
670
+ >
671
+ {this._renderImage(imageSrc, imageStyle)}
672
+ <View testID={testID+"_Content"} style={defaultTextContainer}>
673
+ {this._renderTitle()}
674
+ {this._renderMessage()}
675
+ </View>
676
+ {this._renderCancel(showCancel)}
676
677
  </View>
677
- {this._renderCancel(showCancel)}
678
- </ContentView>
679
678
  </View>
680
679
  </TouchableOpacity>
681
680
  </Animated.View>
682
681
  </Portal>
683
682
  );
684
683
  }
684
+ }
685
+
686
+ const getContainerStyle = (args)=>{
687
+ if(!isObj(args)){
688
+ args = {isMobile : isMobileMedia(),isTablet : isTabletMedia()};
689
+ }
690
+ const {width} = Dimensions.get("window");
691
+ return {
692
+ style : {
693
+ maxWidth : args.isMobile ? (90*width)/100 : args.isTablet? Math.max((70*width/100),350) : 500
694
+ }
695
+ }
685
696
  }
@@ -9,8 +9,122 @@ import Group from "./GroupComponent";
9
9
  import Portal from "$ecomponents/Portal";
10
10
  import {isAllowedFromStr} from "$cauth/perms";
11
11
 
12
+ const activeRef = {current:null};
13
+
14
+ export const isValid = (context)=>{
15
+ if(!isObj(context) || !isNonNullString(context.fabId) || typeof context.show !=="function" || context.hide !="function") return false;
16
+ return true;
17
+ }
18
+ /*** retourne le fab d'ont l'id est passé en paramètre */
19
+ export const getFab = (fabId)=>{
20
+ if(!isNonNullString(fabId)) return null;
21
+ return isValid(allFabs[fabId])? allFabs[fabId] : null;
22
+ }
23
+ const allFabs = {};
24
+ ///les ids des fabs
25
+ const fabIdRefs = {current:[]};
26
+
27
+ //ajoute l'id du fab dans la lite des fabActif
28
+ export const activateFabId = (fabId)=>{
29
+ if(!isNonNullString(fabId)) return fabIdRefs.current;
30
+ const nIds = desactivateFabId(fabId);
31
+ ///le fab active devient en top des id
32
+ nIds.push(fabId);
33
+ fabIdRefs.current = nIds;
34
+ }
35
+
36
+ export const desactivateFabId = (fabId)=>{
37
+ if(!isNonNullString(fabId)) return fabIdRefs.current;
38
+ const nIds = [];
39
+ for(let i in fabIdRefs.current){
40
+ if(fabIdRefs.current[i] != fabId){
41
+ nIds.push(fabIdRefs.current[i]);
42
+ }
43
+ }
44
+ fabIdRefs.current = nIds;
45
+ return nIds;
46
+ }
47
+
48
+ export const isActive = (fabId)=>{
49
+ return isNonNullString(fabId) && fabIdRefs.current[fabIdRefs.current.length-1] == fabId && isValid(getFab(fabId));
50
+ }
51
+
52
+ export const MANAGER = {
53
+ get active (){
54
+ return activeRef.current;
55
+ },
56
+ ///la liste des fabs
57
+ get all (){
58
+ return allFabs;
59
+ },
60
+ ///la liste des fabs Id
61
+ get fabIds (){
62
+ return fabIdRefs.current;
63
+ },
64
+ set active(active){
65
+ active = isValid(active)? active : null;
66
+ if(active){
67
+ ///on désactive l'ancien fab qui était actif
68
+ if(isValid(activeRef.current)){
69
+ activeRef.current.hide();
70
+ }
71
+ activateFabId(active.fabId);
72
+ activeRef.current = active;
73
+ } else {
74
+ //l'ancien fab devient active
75
+ let length = fabIdRefs.current.length-1;
76
+ let prevActive = null,prevFabId = null;
77
+ ///ça veut dire que l'ancien fab active a été démonté
78
+ if(isValid(activeRef.current)){
79
+ prevFabId = activeRef.current.fabId
80
+ }
81
+ while(length >=0 && !isValid(prevActive)){
82
+ const fId = fabIdRefs.current[length];
83
+ if(isNonNullString(fId) && fId !== prevFabId){
84
+ prevActive = allFabs[fId];
85
+ if(isValid(prevActive)){
86
+ break;
87
+ }
88
+ }
89
+ length --;
90
+ }
91
+ if(!prevActive){
92
+ fabIdRefs.current = [];
93
+ Object.map(allFabs,(f,i)=>{
94
+ delete allFabs[i];
95
+ })
96
+ }
97
+ if(isValid(prevActive)){
98
+ prevActive.show();
99
+ activateFabId(prevActive.fabId);
100
+ }
101
+ activeRef.current = prevActive;
102
+ }
103
+ },
104
+ get hasActive(){
105
+ return isValid(activeRef.current);
106
+ },
107
+ get get (){
108
+ return getFab;
109
+ }
110
+ };
111
+
112
+ export const activate = (args)=>{
113
+ const {context,fabId} = args;
114
+ if(!isNonNullString(fabId)|| !isObj(context)) return false;
115
+ let hasFound = false;
116
+ for(let i in allFabs){
117
+ if(allFabs[i]?.fabId == fabId){
118
+ hasFound = true;
119
+ break;
120
+ }
121
+ }
122
+ }
12
123
  const FabGroupComponent = React.forwardRef((props,innerRef)=>{
13
- let {openedIcon,screenName,display:customDisplay,primary,actionMutator,secondary,onOpen,prepareActions,fabStyle,open:customOpen,onClose,onStateChange:customOnStateChange,closedIcon,color,actions:customActions,children,...customRest} = props;
124
+ let {openedIcon,screenName,fabId,display:customDisplay,onMount,onUnmount,primary,actionMutator,secondary,onOpen,prepareActions,fabStyle,open:customOpen,onClose,onStateChange:customOnStateChange,closedIcon,color,actions:customActions,children,...customRest} = props;
125
+ const fabIdRef = React.useRef(defaultStr(fabId,uniqid("fab-id-ref")));
126
+ fabId = fabIdRef.current;
127
+ const isMountedRef = React.useRef(false);
14
128
  const [state, setState] = React.useStateIfMounted({
15
129
  open: typeof customOpen =='boolean'? customOpen : false,
16
130
  display : typeof customDisplay ==='boolean'? customDisplay : true,
@@ -27,6 +141,8 @@ const FabGroupComponent = React.forwardRef((props,innerRef)=>{
27
141
  const context = {
28
142
  open:x=>setState({...state,open:true}),
29
143
  close : x=> {setState({...state,open:false})},
144
+ fabId,
145
+ id : fabId,
30
146
  hide : x=> {
31
147
  setState({...state,display:false})
32
148
  },
@@ -35,9 +151,11 @@ const FabGroupComponent = React.forwardRef((props,innerRef)=>{
35
151
  },
36
152
  isHidden : x => !state.display,
37
153
  isShown : x => state.display,
154
+ isVisible : x=> state.display,
38
155
  isClosed : x => !state.open,
39
156
  isOpened : x => state.open,
40
157
  }
158
+ allFabs[fabId] = context;
41
159
  const {open,display} = state;
42
160
  openedIcon = defaultStr(openedIcon,"close");
43
161
  closedIcon = defaultStr(closedIcon,MENU_ICON);
@@ -77,11 +195,24 @@ const FabGroupComponent = React.forwardRef((props,innerRef)=>{
77
195
  },[customActions,prepareActions,open])();
78
196
 
79
197
  React.useEffect(()=>{
198
+ onMount && onMount(context);
80
199
  React.setRef(innerRef,context);
200
+ isMountedRef.current = true;
81
201
  return ()=>{
202
+ onUnmount && onUnmount({fabId});
203
+ delete allFabs[fabId];
204
+ desactivateFabId(fabId);
205
+ isMountedRef.current = false;
82
206
  React.setRef(innerRef,null);
83
207
  }
84
208
  },[])
209
+ React.useEffect(()=>{
210
+ if(display){
211
+ MANAGER.active = context;
212
+ } else {
213
+ MANAGER.active = null;
214
+ }
215
+ },[display]);
85
216
  return <Portal>
86
217
  <Group
87
218
  {...rest}
@@ -112,6 +243,9 @@ const actionType = PropTypes.shape({
112
243
  });
113
244
  FabGroupComponent.propTypes = {
114
245
  ...defaultObj(FAB.Group.propTypes),
246
+ fabId : PropTypes.string,//l'id du fab
247
+ onMount : PropTypes.func, ///lorsque le composant est monté
248
+ onUnmount : PropTypes.func, //lorsque le composant est démonté
115
249
  actionMutator : PropTypes.func,
116
250
  prepareActions : PropTypes.bool, //si un retraitement sera effectué sur les actions du FAB
117
251
  onOpen : PropTypes.func,