@fto-consult/expo-ui 8.14.4 → 8.15.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.
@@ -2,7 +2,6 @@ const path = require("path");
2
2
  const fs = require("fs");
3
3
 
4
4
  module.exports = (opts)=>{
5
- const isLocalDev = require("./is-local-dev")();
6
5
  const dir = path.resolve(__dirname);
7
6
  const projectRoot = typeof opts.projectRoot =='string' && fs.existsSync(opts.projectRoot.trim()) && opts.projectRoot.trim() || process.cwd();
8
7
  const assets = path.resolve(dir,"assets");
@@ -19,9 +18,7 @@ module.exports = (opts)=>{
19
18
  const expo = path.resolve(expoUI,"src");
20
19
  r["$ecomponents"] = r["$expo-components"] = path.resolve(expo,"components");
21
20
  r["$econfirm"] = path.resolve(r["$expo-components"],"Dialog","confirm");
22
- r["$confirm"] = r["$confirm"] || r["$econfirm"];
23
21
  r["$eauth"] = path.resolve(expo,"auth");
24
- r["$components"] = r["$components"] || r["$ecomponents"];
25
22
  r["$elayouts"] = path.resolve(expo,"layouts");
26
23
  r["$emedia"] = path.resolve(expo,"media");
27
24
  r["$enavigation"] = path.resolve(expo,"navigation");
@@ -36,8 +33,6 @@ module.exports = (opts)=>{
36
33
  r.$tableLink = r.$TableLink = r["$etableLink"] = r["$eTableLink"] = path.resolve(r["$ecomponents"],"TableLink");
37
34
 
38
35
  r["$Screen"] = r["$Screen"] || r["$eScreen"];
39
- r["$screens"] = r["$screens"] || r["$escreens"];
40
-
41
36
  r["$expo"] = r["$expo-ui"] = expo;
42
37
  r["$epreloader"] = path.resolve(expo,"components/Preloader");
43
38
  r["$eform"] = path.resolve(expo,"components","Form");
@@ -55,12 +50,7 @@ module.exports = (opts)=>{
55
50
  if(!r["$preloader"] || r["$preloader"] === r["$cpreloader"]){
56
51
  r["$preloader"] = r["$epreloader"];
57
52
  }
58
- if(!r["$enotify"]){
59
- r["$enotify"] = r["$cnotify"];
60
- }
61
- if(!r["$chart"]){
62
- r["$chart"] = r["$echart"];
63
- }
53
+ r["$enotify"] = r["$cnotify"];
64
54
  if(!r["$file-system"]){
65
55
  r["$file-system"] = r["$efile-system"];
66
56
  }
@@ -84,15 +74,5 @@ module.exports = (opts)=>{
84
74
  r.$electronProjectRoot = path.resolve(r.$projectRoot,"electron");
85
75
  r.$econtext = path.resolve(expo,"context");
86
76
  r.$epdf = path.resolve(expo,"pdf");
87
- if(!r.$context){
88
- r.$context = r.$econtext;
89
- }
90
- r["$erealm"] = path.resolve(expo,'realm');
91
- if(!r.$realm){
92
- r.$realm = r.$erealm;
93
- }
94
- const {withRealm} = opts; //si la prise en compte de la base de données realm est nécessaire
95
- const $realmProvider = path.resolve(r.$realm,"Provider");
96
- r.$erealmProvider = r.$realmProvider = false && !withRealm ? path.resolve($realmProvider,"realm.not-enabled.js") : $realmProvider;
97
77
  return r;
98
78
  }
@@ -1 +1,38 @@
1
- module.exports = require("@fto-consult/expo-ui/metro.config.js");
1
+ const path = require("path");
2
+ const { getDefaultConfig } = require('@expo/metro-config');
3
+ module.exports = function(opts){
4
+ opts = opts && typeof opts =='object'? opts : {};
5
+ let {assetExts,sourceExts} = opts;
6
+ assetExts = Array.isArray(assetExts)? assetExts: [];
7
+ sourceExts= Array.isArray(sourceExts)?sourceExts : [];
8
+ const projectRoot = path.resolve(process.cwd());
9
+ //@see : https://docs.expo.dev/versions/latest/config/metro/
10
+ const config = getDefaultConfig(projectRoot,{});
11
+ // 2. Let Metro know where to resolve packages and in what order
12
+ const nodeModulesPaths = (Array.isArray(config.resolver.nodeModulesPaths)?config.resolver.nodeModulesPaths : []);
13
+ const nodeModulePath = path.resolve(projectRoot, 'node_modules');
14
+ if(!nodeModulesPaths.includes(nodeModulePath)){
15
+ nodeModulesPaths.unshift(nodeModulePath);
16
+ }
17
+ config.resolver.nodeModulesPaths = nodeModulesPaths;
18
+ config.projectRoot = projectRoot;
19
+ config.resolver.assetExts = [
20
+ ...config.resolver.assetExts,
21
+ ...assetExts,
22
+ "db",
23
+ "txt"
24
+ ];
25
+ config.resolver.sourceExts = [
26
+ ...config.resolver.sourceExts,
27
+ ...sourceExts,"txt",
28
+ 'jsx', 'js','tsx',
29
+ ]
30
+
31
+ // 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
32
+ config.resolver.disableHierarchicalLookup = true;
33
+
34
+ // Remove all console logs in production...
35
+ config.transformer.minifierConfig.compress.drop_console = false;
36
+
37
+ return config;
38
+ }
package/metro.config.js CHANGED
@@ -2,7 +2,6 @@ const path = require("path");
2
2
  const fs = require("fs");
3
3
  const { getDefaultConfig } = require('@expo/metro-config');
4
4
  module.exports = function(opts){
5
- const isDev = 'development' === process.env.NODE_ENV;
6
5
  opts = opts && typeof opts =='object'? opts : {};
7
6
  let {assetExts,sourceExts} = opts;
8
7
  assetExts = Array.isArray(assetExts)? assetExts: [];
@@ -20,17 +19,6 @@ module.exports = function(opts){
20
19
  if(hasTranspilePath){
21
20
  config.transformer.babelTransformerPath = transpilePath;
22
21
  }
23
- config.watchFolders = Array.isArray(config.watchFolders) && config.watchFolders || [];
24
- const isLocalTest = require("./is-local-dev")();
25
- if(!isLocalTest && isDev){
26
- config.watchFolders.push(localDir);
27
- }
28
- if(isDev){
29
- const commonP = path.resolve(projectRoot,"node_modules","@fto-consult","common");
30
- if(fs.existsSync(commonP)){
31
- config.watchFolders.push(commonP);
32
- }
33
- }
34
22
  // 2. Let Metro know where to resolve packages and in what order
35
23
  const nodeModulesPaths = (Array.isArray(config.resolver.nodeModulesPaths)?config.resolver.nodeModulesPaths : []);
36
24
  const nodeModulePath = path.resolve(projectRoot, 'node_modules');
@@ -60,13 +48,5 @@ module.exports = function(opts){
60
48
  // 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`, @see : https://docs.expo.dev/guides/monorepos/
61
49
  config.resolver.disableHierarchicalLookup = true;
62
50
 
63
- /*config.platforms = Array.isArray(config.platforms) && config.platforms || [];
64
- ['ios', 'android', 'windows', 'web',"electron"].map(p=>{
65
- if(!config.platforms.includes(p)){
66
- config.platforms.push(p);
67
- }
68
- });*/
69
- ///on génère les librairies open sources utilisées par l'application
70
- //require("./find-licenses");
71
51
  return config;
72
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "8.14.4",
3
+ "version": "8.15.0",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "scripts": {
6
6
  "clear-npx-cache": "npx clear-npx-cache",
@@ -48,7 +48,7 @@
48
48
  "dev": "npx expo start --no-dev --minify -c",
49
49
  "modifier-url-remote-git": "git remote set-url origin 'https://borispipo@github.com/borispipo/smart-eneo.git'",
50
50
  "update-app": "expo @emotion/native@latest react-native-big-list@latest @pchmn/expo-material3-theme@latest @emotion/native@latest @react-navigation/stack react-native-blob-util @react-navigation/native@latest @react-navigation/native-stack@latest && npx expo install --fix",
51
- "update": "npm i @fto-consult/node-utils@latest apexcharts@latest file-saver@latest google-libphonenumber@latest @fto-consult/common@latest react-native-iphone-x-helper@latest react-native-mime-types@latest react-native-paper@5 react-native-paper-dates@latest react-virtuoso@latest tippy.js@latest websql@latest xlsx@latest react-native-web@latest react-dom@latest react-native-get-random-values@latest && npm run update-apexchart && npm run find-licenses"
51
+ "update": "npm i @fto-consult/node-utils@latest apexcharts@latest file-saver@latest google-libphonenumber@latest @fto-consult/common@latest react-native-iphone-x-helper@latest react-native-mime-types@latest react-native-paper@5 react-native-paper-dates@latest react-virtuoso@latest tippy.js@latest websql@latest xlsx@latest react-native-get-random-values@latest && npm run update-apexchart && npm run find-licenses"
52
52
  },
53
53
  "bin": {
54
54
  "expo-ui": "./bin/index.js"
@@ -70,7 +70,7 @@
70
70
  "dependencies": {
71
71
  "@emotion/react": "^11.11.1",
72
72
  "@faker-js/faker": "^8.0.2",
73
- "@fto-consult/common": "^4.13.9",
73
+ "@fto-consult/common": "^4.15.56",
74
74
  "@fto-consult/node-utils": "^1.4.7",
75
75
  "apexcharts": "^3.45.2",
76
76
  "commander": "^11.1.0",
@@ -89,7 +89,7 @@
89
89
  "react-native-get-random-values": "^1.10.0",
90
90
  "react-native-iphone-x-helper": "^1.3.1",
91
91
  "react-native-mime-types": "^2.4.0",
92
- "react-native-paper": "^5.12.1",
92
+ "react-native-paper": "^5.12.3",
93
93
  "react-native-paper-dates": "^0.21.7",
94
94
  "react-native-web": "^0.19.10",
95
95
  "react-virtuoso": "^4.6.2",
@@ -33,13 +33,15 @@ import notify, {notificationRef} from "$notify";
33
33
  import DropdownAlert from '$ecomponents/Dialog/DropdownAlert';
34
34
  import { PreferencesContext } from '../Preferences';
35
35
  import ErrorBoundary from "$ecomponents/ErrorBoundary";
36
- import {updateTheme,defaultTheme} from "$theme";
36
+ import mainTheme, {updateTheme,defaultTheme} from "$theme";
37
37
  import StatusBar from "$ecomponents/StatusBar";
38
38
  import {Provider as PaperProvider,Portal } from 'react-native-paper';
39
39
  import FontIcon from "$ecomponents/Icon/Font";
40
40
  import useContext from "$econtext/hooks";
41
41
  import { StyleSheet } from "react-native";
42
+ import Logo from "$ecomponents/Logo";
42
43
  import AppEntryRootView from "./RootView";
44
+ import View from "$ecomponents/View";
43
45
  import { SafeAreaProvider } from 'react-native-safe-area-context';
44
46
 
45
47
  let MAX_BACK_COUNT = 1;
@@ -252,7 +254,9 @@ function App({init:initApp,initialRouteName:appInitialRouteName,children}) {
252
254
  containerProps.onStateChange(state,...rest);
253
255
  }
254
256
  }}
255
- fallback = {React.isValidElement(containerProps.fallback) ? containerProps.fallback : null}
257
+ fallback = {React.isValidElement(containerProps.fallback) ? containerProps.fallback : <View style={[mainTheme.styles.flex1,mainTheme.styles.justifyContentCenter,mainTheme.styles.alignItemsCenter]}>
258
+ <Logo.Progress/>
259
+ </View>}
256
260
  >
257
261
  <Navigation
258
262
  initialRouteName = {defaultStr(hasGetStarted ? appInitialRouteName : getStartedRouteName,"Home")}
@@ -0,0 +1,183 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Animated,
4
+ StyleSheet,
5
+ View,
6
+ } from 'react-native';
7
+
8
+ import { TouchableRipple } from 'react-native-paper';
9
+ import PropTypes from "prop-types";
10
+ import FontIcon from "$ecomponents/Icon/Font";
11
+ import theme, {StyleProp} from "$theme";
12
+
13
+ const ANIMATION_DURATION = 100;
14
+
15
+ const CheckboxWeb = ({
16
+ status,
17
+ theme: themeOverrides,
18
+ disabled,
19
+ onPress,
20
+ testID,
21
+ rippleColor,
22
+ color,
23
+ ...rest
24
+ }) => {
25
+ const { current: scaleAnim } = React.useRef(
26
+ new Animated.Value(1)
27
+ );
28
+ const isFirstRendering = React.useRef(true);
29
+
30
+ const {
31
+ animation: { scale },
32
+ } = theme;
33
+
34
+ React.useEffect(() => {
35
+ // Do not run animation on very first rendering
36
+ if (isFirstRendering.current) {
37
+ isFirstRendering.current = false;
38
+ return;
39
+ }
40
+
41
+ const checked = status === 'checked';
42
+
43
+ Animated.sequence([
44
+ Animated.timing(scaleAnim, {
45
+ toValue: 0.85,
46
+ duration: checked ? ANIMATION_DURATION * scale : 0,
47
+ useNativeDriver: false,
48
+ }),
49
+ Animated.timing(scaleAnim, {
50
+ toValue: 1,
51
+ duration: checked
52
+ ? ANIMATION_DURATION * scale
53
+ : ANIMATION_DURATION * scale * 1.75,
54
+ useNativeDriver: false,
55
+ }),
56
+ ]).start();
57
+ }, [status, scaleAnim, scale]);
58
+
59
+ const checked = status === 'checked';
60
+ const indeterminate = status === 'indeterminate';
61
+
62
+ const borderWidth = scaleAnim.interpolate({
63
+ inputRange: [0.8, 1],
64
+ outputRange: [7, 0],
65
+ });
66
+
67
+ const icon = indeterminate
68
+ ? 'minus-box'
69
+ : checked
70
+ ? 'checkbox-marked'
71
+ : 'checkbox-blank-outline';
72
+ const selectionControlColor = theme.Colors.isValid(color)? color : theme.colors.primary;
73
+ return (
74
+ <TouchableRipple
75
+ {...rest}
76
+ borderless
77
+ rippleColor={rippleColor}
78
+ onPress={onPress}
79
+ disabled={disabled}
80
+ accessibilityRole="checkbox"
81
+ accessibilityState={{ disabled, checked }}
82
+ accessibilityLiveRegion="polite"
83
+ style={styles.container}
84
+ testID={testID}
85
+ theme={theme}
86
+ >
87
+ <Animated.View style={{ transform: [{ scale: scaleAnim }] }}>
88
+ <FontIcon
89
+ allowFontScaling={false}
90
+ name={icon}
91
+ size={24}
92
+ color={selectionControlColor}
93
+ direction="ltr"
94
+ />
95
+ <View style={[StyleSheet.absoluteFill, styles.fillContainer]}>
96
+ <Animated.View
97
+ style={[
98
+ styles.fill,
99
+ { borderColor: selectionControlColor },
100
+ { borderWidth },
101
+ ]}
102
+ />
103
+ </View>
104
+ </Animated.View>
105
+ </TouchableRipple>
106
+ );
107
+ };
108
+
109
+ CheckboxWeb.displayName = 'Checkbox.Android';
110
+
111
+ const styles = StyleSheet.create({
112
+ container: {
113
+ borderRadius: 18,
114
+ width: 36,
115
+ height: 36,
116
+ padding: 6,
117
+ },
118
+ fillContainer: {
119
+ alignItems: 'center',
120
+ justifyContent: 'center',
121
+ },
122
+ fill: {
123
+ height: 14,
124
+ width: 14,
125
+ },
126
+ });
127
+
128
+ export default CheckboxWeb;
129
+
130
+ CheckboxWeb.propTypes = {
131
+ status: PropTypes.oneOf(['checked','unchecked','indeterminate']),
132
+ /**
133
+ * Whether checkbox is disabled.
134
+ */
135
+ disabled : PropTypes.bool,
136
+ /**
137
+ * Label to be displayed on the item.
138
+ */
139
+ label: PropTypes.string,
140
+ /**
141
+ * Function to execute on press.
142
+ */
143
+ onPress : PropTypes.func,//(e) => void;
144
+ /**
145
+ * Function to execute on long press.
146
+ */
147
+ onLongPress : PropTypes.func,//(e) => void;
148
+ /**
149
+ * Type of background drawabale to display the feedback (Android).
150
+ * https://reactnative.dev/docs/pressable#rippleconfig
151
+ */
152
+ background: PropTypes.any,
153
+ accessibilityLabel : PropTypes.string,
154
+ /**
155
+ * Custom color for unchecked checkbox.
156
+ */
157
+ uncheckedColor : PropTypes.string,
158
+ /**
159
+ * Custom color for checkbox.
160
+ */
161
+ color : PropTypes.string,
162
+ /**
163
+ * Color of the ripple effect.
164
+ */
165
+ rippleColor : PropTypes.string,
166
+ /**
167
+ * Additional styles for container View.
168
+ */
169
+ style : StyleProp,
170
+ /**
171
+ * Specifies the largest possible scale a label font can reach.
172
+ */
173
+ labelMaxFontSizeMultiplier : PropTypes.number,
174
+ /**
175
+ * Style that is passed to Label element.
176
+ */
177
+ labelStyle : StyleProp,
178
+ testID : PropTypes.string,
179
+ /**
180
+ * Checkbox control position.
181
+ */
182
+ position : PropTypes.string,
183
+ }
@@ -0,0 +1,168 @@
1
+ import * as React from 'react';
2
+ import PropTypes from "prop-types";
3
+ import {
4
+ StyleSheet,
5
+ View,
6
+ } from 'react-native';
7
+ import { StyleProp } from '$theme';
8
+ import theme from "$theme";
9
+ import Checkbox from './Checkbox';
10
+ import { TouchableRipple,Text } from 'react-native-paper';
11
+
12
+ const CheckboxItem = ({
13
+ style,
14
+ status,
15
+ label,
16
+ onPress,
17
+ onLongPress,
18
+ labelStyle,
19
+ theme: themeOverrides,
20
+ testID,
21
+ mode,
22
+ position = 'trailing',
23
+ accessibilityLabel = label,
24
+ disabled,
25
+ labelVariant = 'bodyLarge',
26
+ labelMaxFontSizeMultiplier = 1.5,
27
+ rippleColor,
28
+ background,
29
+ ...props
30
+ }) => {
31
+ const checkboxProps = { ...props, status, theme, disabled };
32
+ const isLeading = position === 'leading';
33
+ const checkbox = <Checkbox {...checkboxProps} />
34
+
35
+ const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text;
36
+ const disabledTextColor = theme.isV3
37
+ ? theme.colors.onSurfaceDisabled
38
+ : theme.colors.disabled;
39
+ const textAlign = isLeading ? 'right' : 'left';
40
+
41
+ const computedStyle = {
42
+ color: disabled ? disabledTextColor : textColor,
43
+ textAlign,
44
+ }
45
+
46
+ return (
47
+ <TouchableRipple
48
+ accessibilityLabel={accessibilityLabel}
49
+ accessibilityRole="checkbox"
50
+ accessibilityState={{
51
+ checked: status === 'checked',
52
+ disabled,
53
+ }}
54
+ onPress={onPress}
55
+ onLongPress={onLongPress}
56
+ testID={testID}
57
+ disabled={disabled}
58
+ rippleColor={rippleColor}
59
+ theme={theme}
60
+ background={background}
61
+ >
62
+ <View
63
+ style={[styles.container, style]}
64
+ pointerEvents="none"
65
+ importantForAccessibility="no-hide-descendants"
66
+ >
67
+ {isLeading && checkbox}
68
+ <Text
69
+ variant={labelVariant}
70
+ testID={`${testID}-text`}
71
+ maxFontSizeMultiplier={labelMaxFontSizeMultiplier}
72
+ style={[
73
+ styles.label,
74
+ !theme.isV3 && styles.font,
75
+ computedStyle,
76
+ labelStyle,
77
+ ]}
78
+ >
79
+ {label}
80
+ </Text>
81
+ {!isLeading && checkbox}
82
+ </View>
83
+ </TouchableRipple>
84
+ );
85
+ };
86
+
87
+ CheckboxItem.displayName = 'Checkbox.Item';
88
+
89
+ export default CheckboxItem;
90
+
91
+ // @component-docs ignore-next-line
92
+ export { CheckboxItem };
93
+
94
+ const styles = StyleSheet.create({
95
+ container: {
96
+ flexDirection: 'row',
97
+ alignItems: 'center',
98
+ justifyContent: 'space-between',
99
+ paddingVertical: 8,
100
+ paddingHorizontal: 16,
101
+ },
102
+ label: {
103
+ flexShrink: 1,
104
+ flexGrow: 1,
105
+ },
106
+ font: {
107
+ fontSize: 16,
108
+ },
109
+ });
110
+ CheckboxItem.propTypes = {
111
+ status: PropTypes.oneOf(['checked','unchecked','indeterminate']),
112
+ /**
113
+ * Whether checkbox is disabled.
114
+ */
115
+ disabled : PropTypes.bool,
116
+ /**
117
+ * Label to be displayed on the item.
118
+ */
119
+ label: PropTypes.string,
120
+ /**
121
+ * Function to execute on press.
122
+ */
123
+ onPress : PropTypes.func,//(e) => void;
124
+ /**
125
+ * Function to execute on long press.
126
+ */
127
+ onLongPress : PropTypes.func,//(e) => void;
128
+ /**
129
+ * Type of background drawabale to display the feedback (Android).
130
+ * https://reactnative.dev/docs/pressable#rippleconfig
131
+ */
132
+ background: PropTypes.any,
133
+ accessibilityLabel : PropTypes.string,
134
+ /**
135
+ * Custom color for unchecked checkbox.
136
+ */
137
+ uncheckedColor : PropTypes.string,
138
+ /**
139
+ * Custom color for checkbox.
140
+ */
141
+ color : PropTypes.string,
142
+ /**
143
+ * Color of the ripple effect.
144
+ */
145
+ rippleColor : PropTypes.string,
146
+ /**
147
+ * Additional styles for container View.
148
+ */
149
+ style : StyleProp,
150
+ /**
151
+ * Specifies the largest possible scale a label font can reach.
152
+ */
153
+ labelMaxFontSizeMultiplier : PropTypes.number,
154
+ /**
155
+ * Style that is passed to Label element.
156
+ */
157
+ labelStyle : StyleProp,
158
+ testID : PropTypes.string,
159
+ /**
160
+ * Checkbox control position.
161
+ */
162
+ position : PropTypes.string,
163
+ /**
164
+ * Whether `<Checkbox.Android />` or `<Checkbox.IOS />` should be used.
165
+ * Left undefined `<Checkbox />` will be used.
166
+ */
167
+ mode : PropTypes.oneOf(['android','ios'])
168
+ }
@@ -0,0 +1,13 @@
1
+ import { Checkbox } from "react-native-paper";
2
+ import {forwardRef} from "react";
3
+
4
+ const CheckboxItemComponent = forwardRef((props,ref)=>{
5
+ return <Checkbox.Item
6
+ ref = {ref}
7
+ {...props}
8
+ />
9
+ });
10
+
11
+ export default CheckboxItemComponent;
12
+
13
+ CheckboxItemComponent.displayName = "CheckboxItemComponent";
@@ -2,9 +2,11 @@ import { Checkbox } from 'react-native-paper';
2
2
  import View from "$ecomponents/View";
3
3
  import React from "$react";
4
4
  import {isUndefined,defaultObj,defaultVal,defaultStr} from "$cutils";
5
- import {isIos,isAndroid} from "$cplatform";
5
+ import {isIos,isAndroid,isMobileNative} from "$cplatform";
6
6
  import theme,{Colors,DISABLED_OPACITY,ALPHA_OPACITY} from "$theme";
7
7
  import { StyleSheet } from 'react-native';
8
+ import CheckboxItem from "./Item";
9
+
8
10
  export const checkedStatus = 'checked';
9
11
  export const uncheckedStatus = 'unchecked';
10
12
  import PropTypes from "prop-types";
@@ -13,6 +15,7 @@ import HelperText from "$ecomponents/HelperText";
13
15
  export const leftPosition = 'leading';
14
16
  export const rightPosition = "trailing";
15
17
 
18
+
16
19
  export const CHECKED_ICON_NAME = isIos()? 'check':'check';
17
20
 
18
21
  export const UNCHECKED_ICON_NAME = isIos() ?'' : ''
@@ -119,8 +122,8 @@ const CheckboxComponent = React.forwardRef((props,ref)=>{
119
122
  testID = defaultStr(testID,"RN_CheckboxComponent");
120
123
  return <View testID={testID+"_Container"} {...containerProps} style={[containerProps.style,disabledStyle]} pointerEvents={pointerEvents}>
121
124
  <Tooltip
122
- Component = {Checkbox.Item}
123
125
  {...p}
126
+ Component = {CheckboxItem}
124
127
  testID = {testID}
125
128
  disabled = {disabled}
126
129
  readOnly = {!isEditable}
@@ -309,7 +309,13 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
309
309
  return false;
310
310
  }}
311
311
  renderCustomPagination = {({context})=>{
312
- if(!canPaginate()) return null;
312
+ if(!canPaginate()) {
313
+ return <View testID={testID+"_PaginationLabel"}>
314
+ <Label textBold primary style={{fontSize:15}}>
315
+ {total.formatNumber()}
316
+ </Label>
317
+ </View>
318
+ }
313
319
  const page = pageRef.current, totalPages = getTotalPages(), prevPage = getPrevPage(),nextPage = getNextPage();
314
320
  const iconProp = {
315
321
  size : 25,
@@ -1,6 +1,6 @@
1
1
  import PropTypes from "prop-types";
2
2
  import KeyboardEventHandler from "../KeyboardEventHandler";
3
- import { addMediaQueryUpdateStyeSubscription } from "$context/hooks";
3
+ import { addMediaQueryUpdateStyeSubscription } from "$econtext/hooks";
4
4
  import Dimensions from "$cdimensions";
5
5
  const {getActions,getFormFields,Forms} = require("../utils")
6
6
  import TextField,{parseDecimal} from "$ecomponents/TextField";
@@ -58,7 +58,7 @@ export default function ImageComponent(props){
58
58
  onChange,draw,round,drawText,drawLabel,rounded,defaultSrc,
59
59
  createSignatureOnly,pickImageProps,width,height,cropProps,size,resizeProps,containerProps,
60
60
  menuProps,pickUri,drawProps,imageProps,length,testID,withLabel,...rest} = props;
61
- rest = defaultObj(rest);
61
+ const pickedImageRef = React.useRef(null);
62
62
  pickImageProps = defaultObj(pickImageProps);
63
63
  cropProps = defaultObj(cropProps);
64
64
  draw = defaultBool(draw,true);
@@ -144,6 +144,7 @@ export default function ImageComponent(props){
144
144
  setSrc(imageSrc)
145
145
  });
146
146
  }
147
+ pickedImageRef.current = image;
147
148
  setSrc(imageSrc);
148
149
  return image;
149
150
  }
@@ -184,11 +185,15 @@ export default function ImageComponent(props){
184
185
  },
185
186
  }
186
187
  React.useEffect(()=>{
187
- if(src === prevSrc)return;
188
+ if(src === prevSrc) {
189
+ pickedImageRef.current = null;
190
+ return;
191
+ }
188
192
  if(typeof onChange =='function'){
189
- onChange({context,src,deleted:src == null?true:false,dataURL:src,dataUrl:src})
193
+ onChange({context,...defaultObj(pickedImageRef.current),src,deleted:src == null?true:false,dataURL:src,dataUrl:src})
190
194
  }
191
- },[src])
195
+ pickedImageRef.current = null;
196
+ },[src]);
192
197
  React.useEffect(()=>{
193
198
  if(typeof onMount =='function'){
194
199
  onMount({context});
@@ -3,7 +3,7 @@ import PropTypes from "prop-types";
3
3
  import React from "$react";
4
4
  import {isMobileNative} from "$cplatform";
5
5
  import {debounce,isNumber,isNonNullString} from "$cutils";
6
- import {useMediaQueryUpdateStyle} from "$context/hooks";
6
+ import {useMediaQueryUpdateStyle} from "$econtext/hooks";
7
7
 
8
8
 
9
9
  const ViewComponent = React.forwardRef(({onRender,onLayoutTimeout,pointerEvents,onLayout,autoHeight,autoWidth,elevation,...props},ref)=>{
@@ -1,7 +1,7 @@
1
1
  import PermText from "./PermText";
2
2
  import React from "$react";
3
3
  import Expandable from "$ecomponents/Expandable";
4
- import {defaultObj,defaultStr,arrayValueExists,isNonNullString,defaultVal} from "$cutils";
4
+ import {defaultObj,defaultStr,isNonNullString,defaultVal} from "$cutils";
5
5
  import PropTypes from "prop-types";
6
6
  import {hasResource} from "./utils";
7
7
  import { StyleSheet } from "react-native";
@@ -55,12 +55,16 @@ const PermLine = ({text,cellProps,isUserMasterAdmin,withGrid,defaultActions,reso
55
55
  isUserMasterAdmin = !!isUserMasterAdmin;
56
56
  let checked = isUserMasterAdmin;
57
57
  const onToggleSingle = ({resource,checked,action})=>{
58
+ if(!resource){
59
+ console.error("Invalid resource toggle ",resource,checked,action);
60
+ return;
61
+ }
58
62
  if(isUserMasterAdmin || !isNonNullString(action) || !isNonNullString(resource) || !isNonNullString(allPerms[resource])){
59
63
  return;
60
64
  }
61
65
  const data = {...state.data};
62
66
  const allAction = defaultStr(allPerms[resource]);
63
- if(allAction == "all"){
67
+ if(allAction === "all"){
64
68
  if(checked){
65
69
  data[resource] = allAction;
66
70
  } else delete data[resource];
@@ -68,10 +72,10 @@ const PermLine = ({text,cellProps,isUserMasterAdmin,withGrid,defaultActions,reso
68
72
  data[resource] = defaultStr(data[resource]).toLowerCase();
69
73
  let spl = data[resource].split("2");
70
74
  if(checked){
71
- if(action !== 'read' && arrayValueExists(allAction.toLowerCase().split("2"),'read') && !arrayValueExists(spl,'read')){
75
+ if(action !== 'read' && allAction.toLowerCase().split("2").includes('read') && !spl.includes('read')){
72
76
  spl.push('read');
73
77
  }
74
- if(!arrayValueExists(spl,action,true)){
78
+ if(!spl.includes(action)){
75
79
  spl.push(action);
76
80
  }
77
81
  } else {
@@ -108,40 +112,43 @@ const PermLine = ({text,cellProps,isUserMasterAdmin,withGrid,defaultActions,reso
108
112
  onChange({data:state.data,resource,table});
109
113
  }
110
114
  },[state.data])
111
- const content = [];
112
- Object.map(perms,(perm,i)=>{
113
- const pText = defaultStr(perm.text,perm.label);
114
- if(!isObj(perm.actions)){
115
- if(!isNonNullString(pText)) return null;
116
- allPerms[i] = "all";
117
- checked = isUserMasterAdmin? true : isNonNullString(state.data[i]);
118
- if(!checked){
119
- allChecked = false;
120
- }
121
- content.push(<PermText isUserMasterAdmin={isUserMasterAdmin} key = {i} table={table} tooltip={defaultStr(perm.tooltip,perm.title,perm.desc)} onToggle={onToggleSingle} text={pText} checked ={checked} resource={i} action ={'all'}/>);
122
- return;
123
- }
124
- allPerms[i] = "";
125
- const splitP = defaultStr(state.data[i]).toLowerCase().split("2");
126
- const pContent = []
127
- const hasS = isNonNullString(text) && isNonNullString(pText) && pText.toLowerCase() != text.toLowerCase()
128
- Object.map(perm.actions,(p,j)=>{
129
- if(!isObj(p) || !isNonNullString(p.text)) return null;
130
- allPerms[i] = (isNonNullString(allPerms[i])?(allPerms[i]+"2"):"")+j;
131
- checked = isUserMasterAdmin? true : arrayValueExists(splitP,j,true);
132
- if(!checked){
133
- allChecked = false;
115
+ const content = React.useStableMemo(()=>{
116
+ const content = [];
117
+ Object.map(perms,(perm,i)=>{
118
+ const pText = defaultStr(perm.text,perm.label);
119
+ if(!isObj(perm.actions)){
120
+ if(!isNonNullString(pText)) return null;
121
+ allPerms[i] = "all";
122
+ checked = isUserMasterAdmin? true : isNonNullString(state.data[i]);
123
+ if(!checked){
124
+ allChecked = false;
125
+ }
126
+ content.push(<PermText isUserMasterAdmin={isUserMasterAdmin} key = {i} table={table} tooltip={defaultStr(perm.tooltip,perm.title,perm.desc)} onToggle={onToggleSingle} text={pText} checked ={checked} resource={i} action ={'all'}/>);
127
+ return;
128
+ }
129
+ allPerms[i] = "";
130
+ const splitP = defaultStr(state.data[i]).toLowerCase().split("2");
131
+ const pContent = []
132
+ const hasS = isNonNullString(text) && isNonNullString(pText) && pText.toLowerCase() != text.toLowerCase()
133
+ Object.map(perm.actions,(p,j)=>{
134
+ if(!isObj(p) || !isNonNullString(p.text)) return null;
135
+ allPerms[i] = (isNonNullString(allPerms[i])?(allPerms[i]+"2"):"")+j;
136
+ checked = isUserMasterAdmin? true : splitP.includes(j);
137
+ if(!checked){
138
+ allChecked = false;
139
+ }
140
+ pContent.push(<PermText labelStyle ={hasS? styles.permChildren : undefined} isUserMasterAdmin={isUserMasterAdmin} key={j} table={table} onToggle={onToggleSingle} tooltip={defaultStr(p.tooltip,p.title,p.desc)} text = {p.text} checked ={checked} actions={perm.actions} resource={i} action ={j}/>)
141
+ });
142
+ if(pContent.length){
143
+ content.push(<View key={i} style={{backgroundColor:theme.colors.surface}} testID={testID+"_Content_"+i}>
144
+ {hasS ? <Label testID={testID+'_Label'}>{pText}</Label> : null}
145
+ {pContent}
146
+ </View>)
134
147
  }
135
- pContent.push(<PermText labelStyle ={hasS? styles.permChildren : undefined} isUserMasterAdmin={isUserMasterAdmin} key={j} table={table} onToggle={onToggleSingle} tooltip={defaultStr(p.tooltip,p.title,p.desc)} text = {p.text} checked ={checked} actions={perm.actions} resource={i} action ={j}/>)
148
+
136
149
  });
137
- if(pContent.length){
138
- content.push(<View key={i} style={{backgroundColor:theme.colors.surface}} testID={testID+"_Content_"+i}>
139
- {hasS ? <Label testID={testID+'_Label'}>{pText}</Label> : null}
140
- {pContent}
141
- </View>)
142
- }
143
-
144
- });
150
+ return content;
151
+ },[perms,state.data,state.expanded]);
145
152
  if(!content.length) return null;
146
153
  return <Cell testID={testID+"_Cell"} tabletSize={6} desktopSize={4} phoneSize={12} {...cellProps}>
147
154
  <Expandable
@@ -162,7 +169,8 @@ const PermLine = ({text,cellProps,isUserMasterAdmin,withGrid,defaultActions,reso
162
169
  labelStyle = {false}
163
170
  checked = {allChecked}
164
171
  disabled = {disabled}
165
- resource={resource} action={allPerms[resource]}
172
+ resource={resource}
173
+ action={allPerms[resource]}
166
174
  text={text}
167
175
  testID = {testID+"_"+table}
168
176
  isUserMasterAdmin = {isUserMasterAdmin}
@@ -7,6 +7,10 @@ import theme from "$theme";
7
7
 
8
8
  const PermText = React.forwardRef(({isUserMasterAdmin,disabled,assignPerm,testID,text,title,label,checked,labelStyle,table,type,onToggle,actions,action,resource,tooltip,...props},ref)=>{
9
9
  testID = defaultStr(testID,"RN_AuthPermTextComponent");
10
+ if(!resource){
11
+ console.error("invalid resource for perm text : resource = ",resource,action,type,text,title," table = ",table,tooltip,props);
12
+ return null;
13
+ }
10
14
  return <Checkbox
11
15
  title = {tooltip || title}
12
16
  ref = {ref}
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  "@fto-consult/expo-ui": {
3
3
  "name": "@fto-consult/expo-ui",
4
- "version": "8.5.0",
4
+ "version": "8.14.5",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/borispipo/expo-ui.git"
@@ -34,7 +34,7 @@ module.exports = {
34
34
  "license": "MIT"
35
35
  },
36
36
  "@fto-consult/common": {
37
- "version": "4.11.1",
37
+ "version": "4.15.56",
38
38
  "url": "https://github.com/borispipo/common#readme",
39
39
  "license": "ISC"
40
40
  },
@@ -67,11 +67,6 @@ module.exports = {
67
67
  "url": "https://github.com/crypto-browserify/crypto-browserify",
68
68
  "license": "MIT"
69
69
  },
70
- "expo": {
71
- "version": "50.0.2",
72
- "url": "https://github.com/expo/expo/tree/main/packages/expo",
73
- "license": "MIT"
74
- },
75
70
  "file-saver": {
76
71
  "version": "2.0.5",
77
72
  "url": "https://github.com/eligrey/FileSaver.js#readme",
@@ -82,6 +77,11 @@ module.exports = {
82
77
  "url": "https://ruimarinho.github.io/google-libphonenumber/",
83
78
  "license": "(MIT AND Apache-2.0)"
84
79
  },
80
+ "html2canvas": {
81
+ "version": "1.4.1",
82
+ "url": "https://html2canvas.hertzen.com",
83
+ "license": "MIT"
84
+ },
85
85
  "htmlparser2-without-node-native": {
86
86
  "version": "3.9.2",
87
87
  "url": "git://github.com/fb55/htmlparser2.git",
@@ -95,6 +95,11 @@ module.exports = {
95
95
  "version": "3.7.6",
96
96
  "license": "BSD-3-Clause"
97
97
  },
98
+ "jsbarcode": {
99
+ "version": "3.11.6",
100
+ "url": "https://github.com/lindell/JsBarcode#readme",
101
+ "license": "MIT"
102
+ },
98
103
  "prop-types": {
99
104
  "version": "15.8.1",
100
105
  "url": "https://facebook.github.io/react/",
@@ -129,7 +134,7 @@ module.exports = {
129
134
  "license": "MIT"
130
135
  },
131
136
  "react-native-paper": {
132
- "version": "5.12.1",
137
+ "version": "5.12.3",
133
138
  "url": "https://callstack.github.io/react-native-paper",
134
139
  "license": "MIT"
135
140
  },