@fto-consult/expo-ui 8.8.3 → 8.9.1

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.8.3",
3
+ "version": "8.9.1",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "scripts": {
6
6
  "clear-npx-cache": "npx clear-npx-cache",
@@ -1,4 +1,4 @@
1
- import {useRef,useState,forwardRef,useMergeRefs,useEffect,useMemo} from "$react";
1
+ import React,{useRef,useState,forwardRef,useMergeRefs,useEffect,useMemo} from "$react";
2
2
  import Generator from "../Generator";
3
3
  import PropTypes from "prop-types";
4
4
  import View from "$ecomponents/View";
@@ -18,64 +18,77 @@ import Color from "$ecomponents/Color";
18
18
  import Expandable from "$ecomponents/Expandable";
19
19
  import session from "$session";
20
20
  const sessionKey = "appDesigner-sess"
21
+ import { encode } from "../Generator/utils";
21
22
 
22
23
  const fontOptionsKeys = ["bold","italic","bold italic"];
23
24
  const alignments = ["left","center","right"];
24
25
 
25
26
  const BarcodeDesigner = forwardRef(({
26
- format,testID,onReady,text,value,flat,width,height,displayValue,fontOptions,font,textAlign,textPosition,textMargin,fontSize,background,lineColor,margin,marginTop,marginBottom,marginLeft,marginRight,
27
+ format,testID,onReady,text,value,flat,onChange,width,height,displayValue,fontOptions,font,textAlign,textPosition,textMargin,fontSize,background,lineColor,margin,marginTop,marginBottom,marginLeft,marginRight,
27
28
  sessionName,
29
+ bottomContent,
30
+ leftContent,
31
+ rightContent,
32
+ topContent,
33
+ saveAction,
28
34
  ...rest
29
35
  },ref)=>{
30
36
  testID = defaultStr(testID,'RNBarcodeDesigner');
31
37
  const sKey = sessionName ? `${sessionKey}-${sessionName}` : null;
32
- const getSession = x=> !isNonNullString(sessionName)? {} : defaultObj(session.get(sKey));
33
- const sData = getSession();
38
+ const sData = !isNonNullString(sessionName)? {} : defaultObj(session.get(sKey));
34
39
  Dimensions.useWindowDimensions();
35
40
  const innerRef = useRef(null);
36
41
  const sFormat = !isNonNullString(format) || !barcodeFormats.includes(format) ? isNonNullString(sData.format) && barcodeFormats.includes(sData.format) ? sData.format : defaultBarcodeFormat : format;
37
42
  const sHeight = defaultNumber(height,sData.height,100), sWidth = defaultNumber(width,sData.w100,2), sDisplayValue = typeof displayValue =='boolean'? displayValue :sData.displayValue !== undefined ? sData.displayValue:true;
38
- const sFontOptions = isNonNullString(fontOptions) && fontOptionsKeys.includes(fontOptions) ? fontOptions : isNonNullString(sData.fontOptions) ? fontOptionsKeys.includes(sData?.fontOptions) : "bold";
43
+ const sFontOptions = isNonNullString(fontOptions) && fontOptionsKeys.includes(fontOptions) ? fontOptions : isNonNullString(sData.fontOptions) && fontOptionsKeys.includes(sData?.fontOptions) ? sData.fontOptions : "bold";
39
44
  const sTextAlign = isNonNullString(textAlign) && alignments.includes(textAlign)? textAlign : isNonNullString(sData.textAlign) && alignments.includes(sData.textAlign)? sData.textAlign : "center";
40
45
  const sTextPosition = isNonNullString(textPosition) && ["top","bottom"].includes(textPosition) ? textPosition : isNonNullString(sData.textPosition) && ["top","bottom"].includes(sData.textPosition) ? sData.textPosition : "bottom";
41
46
  const sFontSize = typeof fontSize ==='number'? fontSize : typeof sData.fontSize ==='number'? sData.fontSize : 20;
42
47
  const sLineColor = theme.Colors.isValid(lineColor)? lineColor : theme.Colors.isValid(sData.lineColor)? sData?.linceColor:"#000000";
43
48
  const sBackground = theme.Colors.isValid(background)? background : theme.Colors.isValid(sData.background)? sData.background : "#ffffff";
44
49
  const sTextMargin = typeof textMargin =='number'? textMargin : typeof sData.textMargin =='number'? sData.textMargin : 2;
50
+ const sValue = isNonNullString(value)? value : isNonNullString(sData.value)? sData.value : "";
45
51
  const sMargins = {};
46
52
  Object.map({marginTop,marginBottom,marginLeft,marginRight},(val,k)=>{
47
53
  sMargins[k] = typeof v =='number'? v : typeof sData[k] == null ? sData[k] : 10;
48
54
  });
49
55
  const marginKeys = Object.keys(sMargins);
50
56
  const [state,setState] = useState({
51
- format : sFormat,height:sHeight,width : sWidth,value,displayValue :sDisplayValue,fontOptions : sFontOptions,textAlign:sTextAlign,
57
+ format : sFormat,height:sHeight,width : sWidth,value:sValue,displayValue :sDisplayValue,fontOptions : sFontOptions,textAlign:sTextAlign,
52
58
  textPosition : sTextPosition,fontSize : sFontSize,lineColor:sLineColor,background:sBackground,textMargin:sTextMargin,...sMargins
53
59
  });
54
60
  useEffect(()=>{
55
61
  if(sessionName){
56
62
  session.set(sKey,state);
57
63
  }
64
+ if(typeof onChange =='function'){
65
+ onChange({data:state,state,setState});
66
+ }
58
67
  },[state]);
68
+ const isValid = encode(state)!==null;
69
+ const args = {state,setState,sessionName,isValid,isMobile,isTablet,isDesktop,getState:()=>state,getData:()=>state};
70
+ leftContent = typeof leftContent =='function'? leftContent(args) : leftContent;
71
+ rightContent = typeof rightContent =='function'? rightContent(args) : rightContent;
72
+ bottomContent = typeof bottomContent =='function'? bottomContent(args) : bottomContent;
73
+ topContent = typeof topContent =='function'? topContent(args) : topContent;
74
+ saveAction = typeof saveAction =='function'? saveAction(args) : saveAction;
59
75
  const isMobile = Dimensions.isMobileMedia(),isTablet= Dimensions.isTabletMedia(),isDesktop= Dimensions.isDesktopMedia();
60
76
  const cellProps = {}
61
- const inputProps = {mode:"flat",style:{width:"100%"},containerProps:{style:[]}}
77
+ const inputProps = {mode:"flat",affix:false,style:{width:"100%",paddingLeft:10},labelProps:{style:{paddingLeft:10}},containerProps:{style:[]}}
62
78
  return <Surface {...rest} testID={testID} style={[theme.styles.w100,theme.styles.p2,rest.style]}>
63
79
  <View testID={testID+"SurfaceContent"} style={[isMobile || isTablet && {flexDirection:"column"},{justifyContent:"flex-start",alignItems:"flex-start"},isDesktop && {flexDirection:"row"}]}>
64
- <View elevation={isDesktop?5:0} testID={`${testID}_SettingsContainer`} style={[{paddingHorizontal:5},isDesktop? {width:400,marginRight:10,borderRightColor:theme.colors.divider,borderRightWidth:1}:{width:"100%"}]}>
65
- {false && isDesktop ? <View testID={`${testID}_DesignerOptions`} style={[theme.styles.w100]}>
80
+ <View elevation={isDesktop?5:0} testID={`${testID}_SettingsContainer`} style={[{paddingHorizontal:5},isDesktop? {width:400,marginRight:10,paddingBottom:20,borderColor:theme.colors.divider,borderWidth:1}:{width:"100%"}]}>
81
+ <Expandable defaultExpanded title={<View style={[theme.styles.row,theme.styles.flexWrap,theme.styles.alignItemsCenter,theme.styles.justifyContentSpaceBetween]}>
66
82
  <Label primary textBold fontSize={15} children={"Options du Designer"}/>
67
- <Divider style={[theme.styles.w100,{marginTop:5}]}/>
68
- </View>:null}
69
- <Expandable defaultExpanded title={<Label primary textBold fontSize={15} children={"Options du Designer"}/>}>
83
+ {React.isValidElement(saveAction)? saveAction : null}
84
+ </View>}>
70
85
  <View {...cellProps}>
71
86
  <TextField
72
87
  {...inputProps}
73
88
  label = {"Valeur de test"}
74
- defaultValue = {value}
89
+ defaultValue = {state.value}
75
90
  onChange = {({value})=>{
76
- if(value){
77
- setState({...state,value});
78
- }
91
+ setState({...state,value});
79
92
  }}
80
93
  />
81
94
  </View>
@@ -97,7 +110,7 @@ const BarcodeDesigner = forwardRef(({
97
110
  <View {...cellProps}>
98
111
  <TextField
99
112
  {...inputProps}
100
- label = {"Hauteur de la barre"}
113
+ label = {"Hauteur des barres"}
101
114
  type ="number"
102
115
  defaultValue = {state.height}
103
116
  onChange = {({value})=>{
@@ -109,7 +122,7 @@ const BarcodeDesigner = forwardRef(({
109
122
  <TextField
110
123
  {...inputProps}
111
124
  type ="number"
112
- label = {"Longueur de la barre"}
125
+ label = {"Longueur des barres"}
113
126
  defaultValue = {state.width}
114
127
  onChange = {({value})=>{
115
128
  setState({...state,width:value});
@@ -233,7 +246,9 @@ const BarcodeDesigner = forwardRef(({
233
246
  </Expandable>
234
247
  </View>
235
248
  <View testID={`${testID}_DesignerContainer`} style={[!isDesktop && {width:"100%"},{flexDirection:"column"},theme.styles.p1]}>
236
- <View testID={testID+"_DesignerContent"} style={[theme.styles.w100,theme.styles.justifyContentFlexStart,theme.styles.alignItemsFlexStart]}>
249
+ {React.isValidElement(topContent)? topContent : null}
250
+ <View testID={testID+"_DesignerContent"} style={[theme.styles.w100,theme.styles.row,theme.styles.justifyContentFlexStart,theme.styles.alignItemsFlexCenter]}>
251
+ {React.isValidElement(leftContent)? leftContent : null}
237
252
  <Generator
238
253
  {...state}
239
254
  displayValue = {!!state.displayValue}
@@ -243,12 +258,14 @@ const BarcodeDesigner = forwardRef(({
243
258
  }}
244
259
  ref = {useMergeRefs(ref,innerRef)}
245
260
  />
261
+ {React.isValidElement(rightContent) ?rightContent : null}
246
262
  </View>
263
+ {React.isValidElement(bottomContent) ? bottomContent : null}
247
264
  </View>
248
265
  </View>
249
266
  </Surface>
250
267
  });
251
-
268
+ const contentType = PropTypes.oneOfType([PropTypes.func,PropTypes.node]);
252
269
  export const barcodeSetingsFields = {
253
270
  sessionName : PropTypes.string,
254
271
  format : PropTypes.oneOf(barcodeFormats),
@@ -270,6 +287,12 @@ export const barcodeSetingsFields = {
270
287
  marginBottom : PropTypes.number,
271
288
  marginLeft : PropTypes.number,
272
289
  marginRight : PropTypes.number,
290
+ onChange : PropTypes.func,
291
+ topContent : contentType, //le contenu de l'élément à rendre en haut du Générateur
292
+ bottomContent : contentType,//le contenu de l'élément à rendre en haut du content
293
+ leftContent : contentType,
294
+ saveAction : contentType,
295
+ rightContent : contentType, //le contenu à render à droite du générateur
273
296
  }
274
297
 
275
298
  BarcodeDesigner.displayName = "BarcodeDesigner";
@@ -2,6 +2,7 @@ import React,{forwardRef,useRef,useEffect} from "$react";
2
2
  import {uniqid,defaultStr} from "$cutils";
3
3
  import JsBarcode from "jsbarcode";
4
4
  import {jsbarcodePropTypes } from "./utils";
5
+ import View from "$ecomponents/View";
5
6
 
6
7
  ///@see : https://lindell.me/JsBarcode/
7
8
  const BarcodeGeneratorComponent = forwardRef(({value,format,id,errorText,testID,onReady,text,flat,width,height,displayValue,fontOptions,font,textAlign,textPosition,textMargin,fontSize,background,lineColor,margin,marginTop,marginBottom,marginLeft,marginRight,valid},ref)=>{
@@ -34,7 +35,9 @@ const BarcodeGeneratorComponent = forwardRef(({value,format,id,errorText,testID,
34
35
  }
35
36
  });
36
37
  if(error) return error;
37
- return <svg {...jsProps} id={`${idRef.current}`} ref={ref} data-test-id={`${testID}`} className="bar-code-generator-svg"/>
38
+ return <View style={[{alignSelf:'center'}]} ref={ref}>
39
+ <svg {...jsProps} id={`${idRef.current}`} data-test-id={`${testID}`} className="bar-code-generator-svg"/>
40
+ </View>
38
41
  });
39
42
 
40
43
  BarcodeGeneratorComponent.displayName = "BarcodeGeneratorComponent";
@@ -5,7 +5,7 @@ import theme,{StyleProp} from "$theme";
5
5
  import {defaultStr,defaultObj,isNonNullString,extendObj,uniqid,isDataURL} from "$cutils";
6
6
  import Generator from "./Generator";
7
7
  import {isMobileNative} from "$cplatform";
8
- import { defaultBarcodeFormat,barcodeFormats,jsbarcodePropTypes,prepareOptions } from './utils';
8
+ import { defaultBarcodeFormat,barcodeFormats,jsbarcodePropTypes,encode } from './utils';
9
9
  import { captureRef } from '$expo-ui/view-shot';
10
10
  import Base64 from "$base64";
11
11
  import Label from "$ecomponents/Label";
@@ -127,21 +127,7 @@ const BarcodeGenerator = forwardRef(({
127
127
  },[format,value,width,height,lineColor])
128
128
  const toDataURL = ()=>{
129
129
  return new Promise((resolve,reject)=>{
130
- if(!isMobileNative() && typeof document !=="undefined" && typeof document?.querySelector =='function'){
131
- const element = document.querySelector(`#${idRef.current}`);
132
- if(element && window?.XMLSerializer){
133
- try {
134
- const xml = new XMLSerializer().serializeToString(element);
135
- const r = 'data:image/svg+xml;base64,' + Base64.encode(xml);
136
- if(isDataURL(r) && typeof onConvertToDataURL =="function"){
137
- onConvertToDataURL(r);
138
- }
139
- return resolve(r);
140
- } catch (e){
141
- }
142
- }
143
- }
144
- return innerRef.current?.measureInWindow((x, y, width, height) => {
130
+ const cb2 = (x, y, width, height) => {
145
131
  const cb = ()=>{
146
132
  return captureRef(innerRef.current,extendObj({},{
147
133
  quality: 1,
@@ -151,8 +137,9 @@ const BarcodeGenerator = forwardRef(({
151
137
  height,
152
138
  },dataURLOptions)).then((r)=>{
153
139
  if(isDataURL(r) && typeof onConvertToDataURL =="function"){
154
- onConvertToDataURL(r);
140
+ onConvertToDataURL({dataURL:r});
155
141
  }
142
+ resolve({dataURL:r,width,height});
156
143
  }).catch((e)=>{
157
144
  console.log(e," is capturing data url");
158
145
  reject(e);
@@ -162,10 +149,17 @@ const BarcodeGenerator = forwardRef(({
162
149
  return setTimeout(cb,50);
163
150
  }
164
151
  return cb();
165
- });
152
+ };
153
+ if(!isMobileNative() && typeof document !=="undefined" && typeof document?.querySelector =='function'){
154
+ const element = document.querySelector(`#${idRef.current}`);
155
+ if(element && typeof element?.getBoundingClientRect =='function'){
156
+ const {width,height} = element.getBoundingClientRect();
157
+ return cb2(undefined,undefined,width,height);
158
+ }
159
+ }
160
+ return innerRef.current?.measureInWindow(cb2);
166
161
  })
167
162
  }
168
- React.setRef(ref,toDataURL);
169
163
  return (<Generator
170
164
  {...rest}
171
165
  errorText = {error ? <Label style={{textAlign:'center'}} error fontSize={15} textBold>
@@ -182,48 +176,16 @@ const BarcodeGenerator = forwardRef(({
182
176
  width = {isMobileNative()?barCodeWidth:width}
183
177
  height = {height}
184
178
  lineColor = {lineColor}
185
- ref = {useMergeRefs(ref,innerRef)}
179
+ ref = {(el)=>{
180
+ if(el){
181
+ el.toDataURL = toDataURL;
182
+ }
183
+ innerRef.current = el;
184
+ React.setRef(ref,el);
185
+ }}
186
186
  />);
187
187
  });
188
188
 
189
- /****
190
- encode le barcode passé en paramètre
191
- @return {null|object}
192
- @param {string|object}
193
- si object alors : {
194
- value {string}, la valeur à vérifier
195
- format {string}, le code du format à vérifier
196
- }
197
- si string alors {value:{string}}, le format par défaut est le code128
198
- @param {string} format, si value est un objet alors le second paramètre peut être considéré comme le format
199
- */
200
- export const encode = (options,format)=>{
201
- if(isNonNullString(options)){
202
- options = {text:options};
203
- } else options = defaultObj(options);
204
- const {text:cText,value:cValue,format:cFormat,...rest} = options;
205
- const text = defaultStr(options.value,options.text);
206
- format = defaultStr(format,options.format);
207
- if(!isNonNullString(text)) return null;
208
- if(!isNonNullString(format) || !barcodeFormats.includes(format)){
209
- format = defaultBarcodeFormat
210
- }
211
- try {
212
- const encoder = new barcodes[format](text, {
213
- format,
214
- displayValue : true,
215
- flat: true,
216
- ...rest,
217
- });
218
- if (!encoder.valid()) {
219
- return null;
220
- }
221
- return encoder.encode();
222
- } catch (e){
223
- return null;
224
- }
225
- }
226
-
227
189
  BarcodeGenerator.propTypes = {
228
190
  value: PropTypes.string,
229
191
  ...jsbarcodePropTypes,
@@ -62,4 +62,42 @@ export const prepareOptions = ({textPosition,fontOptions,fontSize,textMargin,tex
62
62
  svgStyle,
63
63
  style,
64
64
  }
65
- }
65
+ }
66
+
67
+ /****
68
+ encode le barcode passé en paramètre
69
+ @return {null|object}
70
+ @param {string|object}
71
+ si object alors : {
72
+ value {string}, la valeur à vérifier
73
+ format {string}, le code du format à vérifier
74
+ }
75
+ si string alors {value:{string}}, le format par défaut est le code128
76
+ @param {string} format, si value est un objet alors le second paramètre peut être considéré comme le format
77
+ */
78
+ export const encode = (options,format)=>{
79
+ if(isNonNullString(options)){
80
+ options = {text:options};
81
+ } else options = defaultObj(options);
82
+ const {text:cText,value:cValue,format:cFormat,...rest} = options;
83
+ const text = defaultStr(options.value,options.text);
84
+ format = defaultStr(format,options.format);
85
+ if(!isNonNullString(text)) return null;
86
+ if(!isNonNullString(format) || !barcodeFormats.includes(format)){
87
+ format = defaultBarcodeFormat
88
+ }
89
+ try {
90
+ const encoder = new barcodes[format](text, {
91
+ format,
92
+ displayValue : true,
93
+ flat: true,
94
+ ...rest,
95
+ });
96
+ if (!encoder.valid()) {
97
+ return null;
98
+ }
99
+ return encoder.encode();
100
+ } catch (e){
101
+ return null;
102
+ }
103
+ }
package/src/pdf/index.js CHANGED
@@ -55,7 +55,7 @@ export const getFields = (config)=>{
55
55
  @paramm {multiple},
56
56
  @param {object} formDataProps, les prpops à passer au DialogProvider
57
57
  */
58
- export const getPrintSettings = ({multiple,sessionName,formDataProps,...rest})=>{
58
+ export const getPrintSettings = ({multiple,duplicateDocOnPage,pageBreakBeforeEachDoc,sessionName,formDataProps,...rest})=>{
59
59
  formDataProps = Object.assign({},formDataProps);
60
60
  const hasSession = isNonNullString(sessionName);
61
61
  if(hasSession){
@@ -66,7 +66,7 @@ export const getPrintSettings = ({multiple,sessionName,formDataProps,...rest})=>
66
66
  const sessionData = hasSession ? defaultObj(session.get(sessionName)) : {};
67
67
  const config = {...sessionData,...defaultObj(formDataProps.data)};
68
68
  const fields = extendObj(true,{},formDataProps.fields,{
69
- duplicateDocOnPage : {
69
+ duplicateDocOnPage : duplicateDocOnPage !== false ? {
70
70
  text :'Dupliquer le(s) document(s)',
71
71
  type : 'switch',
72
72
  defaultValue : 0,
@@ -90,8 +90,8 @@ export const getPrintSettings = ({multiple,sessionName,formDataProps,...rest})=>
90
90
  }
91
91
  }
92
92
  }
93
- },
94
- pageBreakBeforeEachDoc : {
93
+ } : undefined,
94
+ pageBreakBeforeEachDoc : pageBreakBeforeEachDoc !==false ? {
95
95
  text :'Saut de page par document',
96
96
  type : 'switch',
97
97
  defaultValue : 1,
@@ -105,8 +105,8 @@ export const getPrintSettings = ({multiple,sessionName,formDataProps,...rest})=>
105
105
  }
106
106
  return v;
107
107
  }
108
- },
109
- pageMarginAfterEachDoc : {
108
+ } : null,
109
+ pageMarginAfterEachDoc : duplicateDocOnPage !== false ? {
110
110
  text : "Marge après chaque document",
111
111
  tooltip : 'Spécifiez le nombre de ligne à ajouter comme marge après chaque document',
112
112
  defaultValue : 2,
@@ -121,7 +121,7 @@ export const getPrintSettings = ({multiple,sessionName,formDataProps,...rest})=>
121
121
  }
122
122
  return v;
123
123
  }
124
- },
124
+ } : undefined,
125
125
  },getFields(formDataProps.data))
126
126
  return new Promise((resolve,reject)=>{
127
127
  return DialogProvider.open({
@@ -39,18 +39,7 @@ export async function captureRef(view, options) {
39
39
  h2cOptions.y = options.y;
40
40
  }
41
41
  return html2canvas(view, h2cOptions).then((renderedCanvas)=>{
42
- if (false && options.width && options.height) {
43
- // Resize result
44
- const resizedCanvas = document.createElement('canvas');
45
- const resizedContext = resizedCanvas.getContext('2d');
46
- resizedCanvas.height = options.height;
47
- resizedCanvas.width = options.width;
48
- console.log(options.width," is dddd ",options);
49
- resizedContext.drawImage(renderedCanvas, 0, 0, resizedCanvas.width, resizedCanvas.height);
50
- renderedCanvas = resizedCanvas;
51
- }
52
42
  const dataUrl = renderedCanvas.toDataURL("image/" + options.format, options.quality);
53
- console.log(dataUrl," is ddddddddddd")
54
43
  if (options.result === "data-uri" || options.result === "tmpfile") return dataUrl;
55
44
  return dataUrl.replace(/data:image\/(\w+);base64,/, '');
56
45
  });