@fto-consult/expo-ui
Version:
Bibliothèque de composants UI Expo,react-native
175 lines (161 loc) • 5.44 kB
JavaScript
import React, { useMemo,forwardRef,useEffect,defaultNumber,useRef,useMergeRefs} from '$react';
import PropTypes from 'prop-types';
import barcodes from 'jsbarcode/src/barcodes';
import theme,{StyleProp} from "$theme";
import {defaultStr,defaultObj,isNonNullString,extendObj,uniqid,isDataURL} from "$cutils";
import Generator from "./Generator";
import {isMobileNative} from "$cplatform";
import { defaultBarcodeFormat,barcodeFormats,toDataURL,jsbarcodePropTypes,encode } from './utils';
import Label from "$ecomponents/Label";
export * from "./utils";
const BarcodeGenerator = forwardRef(({
value = '',
as,
width = 2,
height = 100,
format,
lineColor,
children,
testID,
style:cStyle,
onError,
autoConvertToDataURL,
onConvertToDataURL,
maxWidth,
background,
dataURLOptions,
id,
onReady,
displayValue,
...rest
},ref) => {
dataURLOptions = defaultObj(dataURLOptions);
testID = defaultStr(testID,"RNBarcodeGenerator");
const innerRef = useRef(null);
const style = theme.flattenStyle(cStyle);
const idRef = useRef(defaultStr(id,uniqid("bar-code-generator-web")));
background = theme.Colors.isValid(background) ? background : style.backgroundColor = theme.Colors.isValid(style.backgroundColor)? style.backgroundColor : '#ffffff';
lineColor = theme.Colors.isValid(lineColor)? lineColor : '#000000';
if(!isNonNullString(format)){
format = defaultBarcodeFormat;
} else if(!barcodeFormats.includes(format)){
console.warn(`Format de code bar [${format}] est invalide, il sera remplacé par le format [${defaultBarcodeFormat}]. Vous devez spécifier un format parmi la liste : [${barcodeFormats.join(",")}]`,children,rest)
format = defaultBarcodeFormat;
}
const drawRect = (x, y, width, height) => {
return `M${x},${y}h${width}v${height}h-${width}z`;
};
const drawSvgBarCode = (encoded) => {
const rects = [];
const { data: binary } = encoded;
const barCodeWidth = binary.length * width;
const singleBarWidth =
typeof maxWidth === 'number' && barCodeWidth > maxWidth
? maxWidth / binary.length
: width;
let barWidth = 0;
let x = 0;
let yFrom = 0;
for (let b = 0; b < binary.length; b++) {
x = b * singleBarWidth;
if (binary[b] === '1') {
barWidth++;
} else if (barWidth > 0) {
rects[rects.length] = drawRect(
x - singleBarWidth * barWidth,
yFrom,
singleBarWidth * barWidth,
height,
);
barWidth = 0;
}
}
if (barWidth > 0) {
rects[rects.length] = drawRect(
x - singleBarWidth * (barWidth - 1),
yFrom,
singleBarWidth * barWidth,
height,
);
}
return rects;
};
const { bars, barCodeWidth,error } = useMemo(() => {
try {
if(!value){
throw new Error(`Valeur du code barre invalide!!\n Merci de spécifier une valeur non nulle`)
}
const encoded = encode({value,width,height,format,lineColor,maxWidth});
if(!encoded){
throw new Error(`code barre ${value} invalide pour le format sélectionné ${format}`);
}
const barCodeWidth = encoded.data.length * width;
return {
bars: drawSvgBarCode(encoded),
error : false,
barCodeWidth:
typeof maxWidth === 'number' && barCodeWidth > maxWidth
? maxWidth
: barCodeWidth,
};
} catch (error) {
if (onError) {
onError(error);
}
return {
bars: [],
barCodeWidth: 0,
error,
};
}
}, [value, width, height, format, lineColor, maxWidth]);
const _toDataURL = ()=>{
return toDataURL(innerRef.current,{
onConvertToDataURL,dataURLOptions,
});
}
useEffect(()=>{
if(autoConvertToDataURL === true){
_toDataURL();
}
},[format,value,width,height,lineColor])
return (<Generator
{...rest}
as={as}
displayValue = {typeof displayValue =='boolean'? displayValue : typeof displayValue !=='undefined'? !!displayValue : true}
errorText = {error ? <Label style={{textAlign:'center'}} error fontSize={15} textBold>
{error?.toString()}
</Label>: null}
id = {idRef.current}
onReady = {()=>{
if(typeof onReady =="function"){
return onReady({toDataURL:_toDataURL});
}
}}
value = {value}
bars = {bars}
format = {format}
error = {error}
testID = {testID}
background = {background}
width = {isMobileNative()?barCodeWidth:width}
height = {height}
lineColor = {lineColor}
ref = {(element)=>{
innerRef.current = element;
React.setRef(ref,{element,toDataURL});
}}
/>);
});
BarcodeGenerator.propTypes = {
value: PropTypes.string,
...jsbarcodePropTypes,
dataURLOptions : PropTypes.object,//les options à utiliser pour la convertion en data url
onConvertToDataURL : PropTypes.func,//lorsque la valeur est converti au format data url
maxWidth: PropTypes.number,
style: StyleProp,
onError: PropTypes.func,
autoConvertToDataURL : PropTypes.bool,//si la valeur sera auto converti en url lorsque le composant sera monté
};
export default BarcodeGenerator;
BarcodeGenerator.displayName = "BarcodeGeneratorComponent";