@fto-consult/expo-ui 8.70.6 → 8.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "8.70.6",
3
+ "version": "8.72.0",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "react-native-paper-doc": "https://github.com/callstack/react-native-paper/tree/main/docs/docs/guides",
6
6
  "scripts": {
@@ -28,7 +28,7 @@ const ButtonStatusComponent = React.forwardRef(({status,withIcon,color,backgroun
28
28
  left = typeof left =='function'? left(rP) : left;
29
29
  right = typeof right =='function'? right(rP) : right;
30
30
  const icProps = {color,size:15,...iconProps,style:[theme.styles.noMargin,theme.styles.noPadding,iconProps.style],onPress}
31
- return <Pressable ref={ref} onPres={onPress} testID={`${testID}_Container`} {...containerProps} style={[{borderRadius:15,paddingVertical:4,paddingHorizontal:10,alignSelf: 'flex-start'},theme.styles.row,theme.styles.flexWrap,backgroundColor && {backgroundColor},style]}>
31
+ return <Pressable ref={ref} onPres={onPress} testID={`${testID}_Container`} {...containerProps} style={[styles.button,theme.styles.row,theme.styles.flexWrap,backgroundColor && {backgroundColor},style]}>
32
32
  {React.isValidElement(left)? left : null}
33
33
  {withIcon !== false && React.isValidElement(icon,true) ? <Icon {...icProps} icon={icon} />:null}
34
34
  {label ? <Label testID={`${testID}_Label`} {...labelProps} style={[color && {color},{fontSize:13},labelProps.style]}>{label}</Label> : null}
@@ -46,6 +46,15 @@ ButtonStatusComponent.defaultProps = {
46
46
  editable : false,
47
47
  }
48
48
 
49
+ const styles = StyleSheet.create({
50
+ button : {
51
+ borderRadius:15,
52
+ paddingVertical:4,
53
+ paddingHorizontal:10,
54
+ alignSelf: 'flex-start',
55
+ }
56
+ });
57
+
49
58
  ButtonStatusComponent.propTypes = {
50
59
  label : PropTypes.oneOfType([ //le libelé à faire figurer sur le status
51
60
  PropTypes.node,
@@ -2,7 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
4
  import DateLib from "$date";
5
- import React from "$react";
5
+ import React,{useState} from "$react";
6
6
  import {defaultObj,isNonNullString} from "$cutils";
7
7
  import SimpleSelect from "$ecomponents/SimpleSelect";
8
8
  import Provider from "$ecomponents/Dialog/Provider";
@@ -14,7 +14,9 @@ import { View } from "react-native";
14
14
  import Icon from "$ecomponents/Icon";
15
15
 
16
16
  const DateFormatSelector = React.forwardRef((props,ref)=>{
17
- return <SimpleSelect ref={ref} {...selectDateFormatFieldProps(props)}/>
17
+ return <SimpleSelect
18
+ ref={ref} {...selectDateFormatFieldProps(props)}
19
+ />
18
20
  });
19
21
 
20
22
  DateFormatSelector.displayName = "DateFormatSelector";
@@ -70,6 +72,9 @@ export const selectDateFormatFieldProps = ({onAdd:customOnAdd,onAddCustomFormat,
70
72
  if(typeof customOnAdd =='function'){
71
73
  customOnAdd(valueRef.current);
72
74
  }
75
+ if(typeof onAddCustomFormat =="function"){
76
+ onAddCustomFormat(valueRef.current);
77
+ }
73
78
  Provider.close();
74
79
  }
75
80
  }],
@@ -77,11 +82,11 @@ export const selectDateFormatFieldProps = ({onAdd:customOnAdd,onAddCustomFormat,
77
82
  };
78
83
  inputProps = defaultObj(props.inputProps);
79
84
  return {
80
- items : getDateFormatSelectorItems(),
81
85
  getItemValue : ({item})=>item.code,
82
86
  renderItem : dateFormatSelectorRenderItem,
83
87
  showAdd : true,
84
88
  label : "Format de date",
89
+ items : getDateFormatSelectorItems(props),
85
90
  ...props,
86
91
  inputProps : {
87
92
  enableCopy:false,...inputProps,
@@ -93,8 +98,6 @@ export const selectDateFormatFieldProps = ({onAdd:customOnAdd,onAddCustomFormat,
93
98
  },
94
99
  defaultValue : defaultStr(props.defaultValue,props.format),
95
100
  onAdd,
96
- onAdd : undefined,
97
- showAdd : false,
98
101
  }
99
102
  }
100
103
  export const getDateFormatSelectorItems = x=> Object.map(DateLib.sortedFormats,(format)=>{
@@ -2,31 +2,135 @@ import Button from "$ecomponents/Button";
2
2
  import React from "$react";
3
3
  import PropTypes from "prop-types";
4
4
  import { pickDocument } from "$emedia/document";
5
+ import { StyleSheet } from "react-native";
6
+ import {isObj,isNonNullString,extendObj,defaultObj,defaultBool} from "$cutils";
7
+ import Label from "$ecomponents/Label";
8
+ import theme from "$theme";
5
9
 
6
- const DocumentPickerComponent = React.forwardRef(({pickOptions,onSuccess,onCancel,onPress,...props},ref)=>{
7
- return <Button
10
+
11
+ const DocumentPickerComponent = React.forwardRef(({pickOptions,label,error,left,errorText,labelProps,containerProps,text:cText,onChange,onCancel,style,onPress,...props},ref)=>{
12
+ const [assets,setAssets] = React.useState([]);
13
+ label = React.isValidElement(label,true) && label || React.isValidElement(cText,true) && cText || null;
14
+ const changedRef = React.useRef(null);
15
+ labelProps = defaultObj(labelProps);
16
+ containerProps = defaultObj(containerProps);
17
+ const multiple = defaultBool(pickOptions?.multiple,props.multiple);
18
+ const {text,tooltip} = React.useMemo(()=>{
19
+ let text = ``,tooltip = "";
20
+ let counter = 0;
21
+ let breakCounter = 0;
22
+ (Array.isArray(assets) ?assets:[assets]).map((a)=>{
23
+ if(!isObj(a) || !isNonNullString(a.name)) return;
24
+ tooltip+=`${tooltip?",":""}${a.name}`
25
+ if(counter < 1){
26
+ text+=`${text?",":""}${a.name}`
27
+ } else {
28
+ breakCounter++;
29
+ }
30
+ counter++;
31
+ });
32
+ return {
33
+ text : text+(breakCounter> 0?` et ${breakCounter.formatNumber()} de plus`:""),
34
+ tooltip,
35
+ }
36
+ },[assets]);
37
+ React.useEffect(()=>{
38
+ if(!isObj(changedRef.current)) return;
39
+ const args = changedRef.current;
40
+ changedRef.current = null;
41
+ if(typeof onChange =="function"){
42
+ onChange({...args,value:assets});
43
+ }
44
+ },[assets]);
45
+ const textColor = error? theme.colors.error : theme.colors.text;
46
+ const textFieldMode = theme.textFieldMode;
47
+ const borderColor = theme.colors[error?"error":"divider"];
48
+ const isFlatMode = textFieldMode == "flat";
49
+ const containerStyle = isFlatMode ? {} : {paddingHorizontal : 10}
50
+ const labelColor = error ? theme.colors.error : theme.Colors.setAlpha(theme.colors.text,theme.ALPHA);
51
+ const rStyle = isFlatMode ? {borderWidth:0,borderBottomWidth:1,borderBottomColor:borderColor} : {
52
+ borderWidth : 1,
53
+ borderRadius:15,
54
+ borderColor,
55
+ };
56
+ const btn = <Button
8
57
  onPress = {(...r)=>{
9
58
  if(typeof onPress =="function" && onPress(...r) === false) return;
10
- pickDocument(pickOptions).then((r)=>{
11
- if(typeof onSuccess =="function"){
12
- onSuccess(r);
59
+ pickDocument(extendObj({},pickOptions,{multiple})).then((r)=>{
60
+ r.assets = Array.isArray(r.assets)? r.assets : [];
61
+ if(!multiple){
62
+ r.assets = r.assets[0];
13
63
  }
64
+ changedRef.current = r;
65
+ setAssets(r.assets);
14
66
  }).catch((r)=>{
15
67
  if(typeof onCancel =="function"){
16
68
  onCancel(r);
17
69
  }
18
70
  });
19
71
  }}
20
- ref={ref} {...props}/>
72
+ left = {(props)=>{
73
+ const c = typeof left =="function"? left(props) : React.isValidElement(left)? left : null;
74
+ const lL = <Label children={`Choisir ${multiple ? "des fichiers":"un fichier" }`} style={[styles.leftLabel,{color:textColor,borderRightColor:theme.colors.divider}]}/>;
75
+ return React.isValidElement(c)? <>
76
+ {c}{lL}
77
+ </> : lL;
78
+ }}
79
+ style = {[styles.button,style]}
80
+ upperCase ={false}
81
+ ref={ref} {...props}
82
+ children = {text || "Aucun fichier choisit"}
83
+ tooltip = {tooltip}
84
+ title = {tooltip}
85
+ labelProps = {{style:styles.label,splitText:true,numberOfLines : 1,color:textColor}}
86
+ containerProps = {{...containerProps,style:[styles.container,containerStyle,rStyle,containerProps.style]}}
87
+ />;
88
+ return <>
89
+ {label?<Label {...labelProps} style={[{color:labelColor},labelProps.style]} children={label}/> : null}
90
+ {btn}
91
+ {errorText? <Label error children={errorText}/>:null}
92
+ </>
21
93
  });
22
94
 
23
95
  DocumentPickerComponent.displayName = "DocumentPickerComponent";
24
96
 
25
97
  export default DocumentPickerComponent;
26
98
 
99
+ const styles = StyleSheet.create({
100
+ button : {
101
+ alignSelf: 'flex-start',
102
+ },
103
+ leftLabel : {
104
+ paddingVertical : 12,
105
+ borderRightWidth : 1,
106
+ textWrap : "nowrap",
107
+ paddingRight : 7,
108
+ },
109
+ label : {
110
+ paddingHorizontal : 5,
111
+ textWrap : "wrap",
112
+ textAlign : "left",
113
+ },
114
+ container : {
115
+ marginTop : 5,
116
+ }
117
+ });
118
+
27
119
  DocumentPickerComponent.propTypes = {
120
+ label : PropTypes.oneOfType([
121
+ PropTypes.node,
122
+ PropTypes.element,
123
+ PropTypes.string,
124
+ PropTypes.number,
125
+ ]),
126
+ text : PropTypes.oneOfType([
127
+ PropTypes.node,
128
+ PropTypes.element,
129
+ PropTypes.string,
130
+ PropTypes.number,
131
+ ]),
28
132
  ...Object.assign({},Button.propTypes),
29
- onSuccess : PropTypes.func,
133
+ onChange : PropTypes.func,
30
134
  onCancel : PropTypes.func,
31
135
  /*** @see : https://docs.expo.dev/versions/latest/sdk/document-picker/#documentpickeroptions */
32
136
  pickOptions : PropTypes.shape({
@@ -0,0 +1,63 @@
1
+ import Field from "./Field";
2
+ import DocumentPicker from "$ecomponents/DocumentPicker";
3
+ import {isObj,defaultObj} from "$cutils";
4
+ export default class FormFieldDocumentPicker extends Field {
5
+ canFocus(){
6
+ return false;
7
+ }
8
+ isValid(){
9
+ return true;
10
+ }
11
+ compareAssets(assets){
12
+ if(Array.isArray(assets)){
13
+ const previousValue = this.getPreviousValue();
14
+ const allPrev = Array.isArray(previousValue)? previousValue : [previousValue];
15
+ for(let i in assets){
16
+ let hasFound = false;
17
+ for(let j in allPrev){
18
+ if(this.compareSingleAssets(assets[i],allPrev[j])) {
19
+ hasFound = true;
20
+ }
21
+ if(hasFound) break;
22
+ }
23
+ if(!hasFound) return false;
24
+ }
25
+ return true;
26
+ }
27
+ return this.compareSingleAssets(assets,this.getPreviousValue());
28
+ }
29
+ compareSingleAssets(assets,previousValue){
30
+ if(!isObj(assets) || !isObj(previousValue)) return false;
31
+ return previousValue.lastModified === assets.lastModified && previousValue.mimeType == assets.mimeType && previousValue.name === assets.name && previousValue.size == assets.size && previousValue.uri == assets.uri;
32
+ }
33
+ onChange(args){
34
+ const assets = Array.isArray(args.assets) ? args.assets : [args.assets];
35
+ const value = this.props.multiple ? assets:assets[0];
36
+ if(this.compareAssets(value)){
37
+ return ;
38
+ }
39
+ this.validate({...args,value,context:this});
40
+ }
41
+ getComponent(){
42
+ return DocumentPicker;
43
+ }
44
+ _render({pickOptions,...props}){
45
+ pickOptions = defaultObj(pickOptions,props);
46
+ if(typeof this.props.multiple =="boolean"){
47
+ pickOptions.multiple = this.props.multiple;
48
+ }
49
+ return <DocumentPicker
50
+ {...props}
51
+ pickOptions = {pickOptions}
52
+ onChange = {this.onChange.bind(this)}
53
+ />
54
+ }
55
+ isTextField(){
56
+ return false;
57
+ }
58
+ }
59
+
60
+ FormFieldDocumentPicker.propTypes = {
61
+ ...Field.propTypes,
62
+ ...DocumentPicker.propTypes,
63
+ }
@@ -251,8 +251,7 @@ export default class Field extends AppComponent {
251
251
  }
252
252
  this.validatingValue = value;
253
253
  this.INITIAL_STATE._lastValidatingValue = value;
254
- this.setState ({validValue:value,validatingValue:value,previousValue:this.state.validValue,errorText:"",error:false},()=>{
255
- this._previousValue = this.state.validValue;
254
+ this.setState ({validValue:value,previousValidatedValue:this.state.validValue,validatingValue:value,previousValue:this.state.validValue,errorText:"",error:false},()=>{
256
255
  const fields = getFormFields(this.formName);
257
256
  let canEnable = true;
258
257
  for(var k in fields){
@@ -405,7 +404,7 @@ export default class Field extends AppComponent {
405
404
  return this.formName;
406
405
  }
407
406
  getOldValue () {
408
- return this._previousValue;
407
+ return this.state.previousValidatedValue;
409
408
  }
410
409
  /*** la valeur qui a été validée
411
410
  * @param : l'ensemble des données du formulaire à retourner
@@ -517,7 +516,7 @@ export default class Field extends AppComponent {
517
516
  return false;
518
517
  }
519
518
  getPreviousValue (){
520
- return this._previousValue;
519
+ return this.state.previousValidatedValue;
521
520
  }
522
521
  hasValueChanged(value){
523
522
  return (stableHash(this.state.validatingValue) === stableHash(value))? false : true;
@@ -541,9 +540,8 @@ export default class Field extends AppComponent {
541
540
  this.__hasAlreadyValidated = true;
542
541
  this.validatingValue = value;
543
542
  if(((!this.canValidate()) && !this.isSelectField()) || this.isFilter()){
544
- this._previousValue = this.state.validValue;
545
543
  this.trigger("validate",{...defaultObj(rest),context:this,value,event,oldValue:this.INITIAL_STATE._lastValidatingValue},(results)=>{
546
- this.setState({validValue:value,validatingValue:value,sk:!this.state.sk,previousValue:this.state.validatingValue},()=>{
544
+ this.setState({validValue:value,previousValidatedValue:this.state.validValue,validatingValue:value,sk:!this.state.sk,previousValue:this.state.validatingValue},()=>{
547
545
  if(isFunction(this.props.onValidate)){
548
546
  this.props.onValidate({...defaultObj(rest),props:this.props,name:this.name,field:this.name,value,event,context:this,oldValue:this.INITIAL_STATE._lastValidatingValue});
549
547
  }
@@ -23,19 +23,15 @@ export default class FormFieldImage extends Field {
23
23
  return ;
24
24
  }
25
25
  this.validate({...args,value:dataUrl,context:this});
26
- /*if(isFunction(this.props.onChange)){
27
- this.props.onChange({dataUrl,src:dataUrl,dataURL:dataUrl,previousSrc:previousValue});
28
- }*/
29
26
  }
30
27
  getComponent(){
31
28
  return Image;
32
29
  }
33
- _render(props){
34
- let {dbName,onChange,...p} = props;
35
- p.onChange = this.onChange.bind(this);
30
+ _render({onChange,...p}){
36
31
  return <Image
37
32
  {...p}
38
33
  src={defaultVal(p.src,p.defaultValue)}
34
+ onChange={this.onChange.bind(this)}
39
35
  />
40
36
  }
41
37
  isTextField(){
@@ -46,20 +42,5 @@ export default class FormFieldImage extends Field {
46
42
  FormFieldImage.propTypes = {
47
43
  width : PropTypes.number,
48
44
  height : PropTypes.number,
49
- /*** le nom du champ qu'on valide
50
- * si fieldName est définie, alors, il est utilisé pour la validation du champ.
51
- * lorsque la valeur est mise à jour, on recherche en base toutes les objets ayant pour valeur ladite valeur
52
- * Si est trouvé, alors une erreur est retournée.
53
- * Dans le cas où fieldName est définie, alors, l'id n'est pas utilisé pour la validation
54
- *
55
- */
56
- fieldName : PropTypes.string,
57
- ...Field.propTypes,
58
- /*** le nom de la table dans laquelle l'idField est enreigistré */
59
- table : PropTypes.string,
60
- tableName : PropTypes.string, //idem à table
61
- /*** le nom de la bd où l'id field est enregistré */
62
- dbName : PropTypes.string,
63
- //la longueur maximale du champ
64
- maxLength:PropTypes.number
45
+ ...Field.propTypes
65
46
  }
@@ -1,6 +1,5 @@
1
1
  import SelectField from "./SelectField";
2
2
  import {selectDateFormatFieldProps,getDateFormatSelectorItems} from "$ecomponents/Date/FormatSelector";
3
- import DateLib from "$date";
4
3
 
5
4
  export default class FormFieldSelectDateFormat extends SelectField{
6
5
  constructor(props){
@@ -19,7 +19,8 @@ import "$cutils";
19
19
  import React from "$react";
20
20
  import SelectDateFormat from "./SelectDateFormat";
21
21
  import CurrencyFormat from "./CurrencyFormat";
22
- import SelectFontIcon from "./SelectFontIcon"
22
+ import SelectFontIcon from "./SelectFontIcon";
23
+ import DocumentPicker from "./DocumentPicker";
23
24
 
24
25
  const defFormFields = {
25
26
  Field,
@@ -43,6 +44,7 @@ const defFormFields = {
43
44
  ,SelectDateFormat
44
45
  ,Html
45
46
  ,SelectFontIcon,
47
+ DocumentPicker,
46
48
  }
47
49
 
48
50
  export default defFormFields;
@@ -30,6 +30,7 @@ export const getComponentTypes = ()=>{
30
30
  scheduler : Fields.Scheduler,
31
31
  default : Fields.TextField,
32
32
  selecticon : Fields.SelectFontIcon,
33
+ documentpicker : Fields.DocumentPicker,
33
34
  ...Fields,
34
35
  };
35
36
  }
@@ -20,11 +20,16 @@ import TouchableRipple from "$ecomponents/TouchableRipple";
20
20
  dans le champ isStructData
21
21
  */
22
22
  const TableLinKComponent = React.forwardRef(({containerProps,children,labelProps,...props},ref)=>{
23
- const {testID,onPressLink,disabled,readOnly,fetchData,navigate,isAllowed:checkIfAllowed,Component,...rest} = usePrepareProps(props);
23
+ const {testID,onPressLink,disabled,readOnly,fetchData,navigate,isAllowed:checkIfAllowed,onLongPres,Component,...rest} = usePrepareProps(props);
24
24
  containerProps = defaultObj(containerProps);
25
25
  labelProps = defaultObj(labelProps);
26
26
  const CP = disabled || readOnly ? View : TouchableRipple;
27
- return <CP testID={testID} onLongPres={(e)=>React.stopEventPropagation(e)} {...containerProps} onPress={disabled || readOnly? undefined : onPressLink} style={[styles.container,containerProps.style]}>
27
+ return <CP testID={testID} onLongPres={(e,...rest)=>{
28
+ React.stopEventPropagation(e);
29
+ if(typeof onLongPres =="function"){
30
+ onLongPres(e,...rest);
31
+ }
32
+ }} {...containerProps} onPress={disabled || readOnly? undefined : onPressLink} style={[styles.container,containerProps.style]}>
28
33
  <Tooltip testID={testID+"_Tooltip"} {...rest} style={[rest.style,{pointerEvents: disabled || readOnly ? 'none' : 'auto'}]} Component={Component} onPress={disabled || readOnly?undefined:onPressLink} ref={ref} readOnly={readOnly} disabled = {disabled}>
29
34
  <Label testID={testID+"_Label"} underlined primary {...labelProps} style={[_styles.lh15,labelProps.style]} disabled={disabled} readOnly={readOnly}>{children}</Label>
30
35
  </Tooltip>
@@ -90,7 +95,7 @@ TableLinKComponent.propTypes = {
90
95
  ///les props à utiliser pour afficher la table de données en cas de click sur le lien
91
96
  triggerProps : PropTypes.object,
92
97
  /*** l'id de la données à récupérer en cas de clic sur le lien */
93
- id : PropTypes.oneOfType([PropTypes.number,PropTypes.string]),
98
+ id : PropTypes.oneOfType([PropTypes.number,PropTypes.string,PropTypes.array,PropTypes.object]),
94
99
  routeName : PropTypes.string,///la route via laquelle on devra naviguer
95
100
  routeParam : PropTypes.object,///les props à passer à la route en question
96
101
  children : PropTypes.node
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  "@fto-consult/expo-ui": {
3
- "version": "8.70.3",
3
+ "version": "8.71.0",
4
4
  "url": "https://github.com/borispipo/expo-ui#readme",
5
5
  "license": "ISC"
6
6
  },
@@ -39,16 +39,6 @@ module.exports = {
39
39
  "url": "https://github.com/pchmn/expo-material3-theme#readme",
40
40
  "license": "MIT"
41
41
  },
42
- "@react-native-async-storage/async-storage": {
43
- "version": "1.21.0",
44
- "url": "https://github.com/react-native-async-storage/async-storage#readme",
45
- "license": "MIT"
46
- },
47
- "@react-native-community/datetimepicker": {
48
- "version": "7.6.1",
49
- "url": "https://github.com/react-native-community/datetimepicker#readme",
50
- "license": "MIT"
51
- },
52
42
  "@react-native-community/netinfo": {
53
43
  "version": "11.1.0",
54
44
  "url": "https://github.com/react-native-netinfo/react-native-netinfo#readme",
@@ -109,6 +99,11 @@ module.exports = {
109
99
  "url": "https://docs.expo.dev/versions/latest/sdk/clipboard",
110
100
  "license": "MIT"
111
101
  },
102
+ "expo-document-picker": {
103
+ "version": "11.10.1",
104
+ "url": "https://docs.expo.dev/versions/latest/sdk/document-picker/",
105
+ "license": "MIT"
106
+ },
112
107
  "expo-font": {
113
108
  "version": "11.10.3",
114
109
  "url": "https://docs.expo.dev/versions/latest/sdk/font/",
@@ -194,6 +189,11 @@ module.exports = {
194
189
  "url": "https://github.com/react-native-community/react-native-svg",
195
190
  "license": "MIT"
196
191
  },
192
+ "react-native-view-shot": {
193
+ "version": "3.8.0",
194
+ "url": "https://github.com/gre/react-native-view-shot",
195
+ "license": "MIT"
196
+ },
197
197
  "react-native-webview": {
198
198
  "version": "13.6.4",
199
199
  "url": "https://github.com/react-native-webview/react-native-webview#readme",
@@ -208,5 +208,10 @@ module.exports = {
208
208
  "version": "3.0.0",
209
209
  "url": "https://github.com/browserify/stream-browserify",
210
210
  "license": "MIT"
211
+ },
212
+ "vm": {
213
+ "version": "0.1.0",
214
+ "url": "https://github.com/DiegoRBaquero/node-vm#readme",
215
+ "license": "MIT"
211
216
  }
212
217
  };
File without changes
File without changes