@fto-consult/expo-ui
Version:
Bibliothèque de composants UI Expo,react-native
145 lines (139 loc) • 5.52 kB
JavaScript
import Button from "$ecomponents/Button";
import React from "$react";
import PropTypes from "prop-types";
import { pickDocument } from "$emedia/document";
import { StyleSheet } from "react-native";
import {isObj,isNonNullString,extendObj,defaultObj,defaultBool} from "$cutils";
import Label from "$ecomponents/Label";
import theme from "$theme";
const DocumentPickerComponent = React.forwardRef(({pickOptions,label,error,left,errorText,labelProps,containerProps,text:cText,onChange,onCancel,style,onPress,...props},ref)=>{
const [assets,setAssets] = React.useState([]);
label = React.isValidElement(label,true) && label || React.isValidElement(cText,true) && cText || null;
const changedRef = React.useRef(null);
labelProps = defaultObj(labelProps);
containerProps = defaultObj(containerProps);
const multiple = defaultBool(pickOptions?.multiple,props.multiple);
const {text,tooltip} = React.useMemo(()=>{
let text = ``,tooltip = "";
let counter = 0;
let breakCounter = 0;
(Array.isArray(assets) ?assets:[assets]).map((a)=>{
if(!isObj(a) || !isNonNullString(a.name)) return;
tooltip+=`${tooltip?",":""}${a.name}`
if(counter < 1){
text+=`${text?",":""}${a.name}`
} else {
breakCounter++;
}
counter++;
});
return {
text : text+(breakCounter> 0?` et ${breakCounter.formatNumber()} de plus`:""),
tooltip,
}
},[assets]);
React.useEffect(()=>{
if(!isObj(changedRef.current)) return;
const args = changedRef.current;
changedRef.current = null;
if(typeof onChange =="function"){
onChange({...args,value:assets});
}
},[assets]);
const textColor = error? theme.colors.error : theme.colors.text;
const textFieldMode = theme.textFieldMode;
const borderColor = theme.colors[error?"error":"divider"];
const isFlatMode = textFieldMode == "flat";
const containerStyle = isFlatMode ? {} : {paddingHorizontal : 10}
const labelColor = error ? theme.colors.error : theme.Colors.setAlpha(theme.colors.text,theme.ALPHA);
const rStyle = isFlatMode ? {borderWidth:0,borderBottomWidth:1,borderBottomColor:borderColor} : {
borderWidth : 1,
borderRadius:15,
borderColor,
};
const btn = <Button
onPress = {(...r)=>{
if(typeof onPress =="function" && onPress(...r) === false) return;
pickDocument(extendObj({},pickOptions,{multiple})).then((r)=>{
r.assets = Array.isArray(r.assets)? r.assets : [];
if(!multiple){
r.assets = r.assets[0];
}
changedRef.current = r;
setAssets(r.assets);
}).catch((r)=>{
if(typeof onCancel =="function"){
onCancel(r);
}
});
}}
left = {(props)=>{
const c = typeof left =="function"? left(props) : React.isValidElement(left)? left : null;
const lL = <Label children={`Choisir ${multiple ? "des fichiers":"un fichier" }`} style={[styles.leftLabel,{color:textColor,borderRightColor:theme.colors.divider}]}/>;
return React.isValidElement(c)? <>
{c}{lL}
</> : lL;
}}
style = {[styles.button,style]}
upperCase ={false}
ref={ref} {...props}
children = {text || "Aucun fichier choisit"}
tooltip = {tooltip}
title = {tooltip}
labelProps = {{style:styles.label,splitText:true,numberOfLines : 1,color:textColor}}
containerProps = {{...containerProps,style:[styles.container,containerStyle,rStyle,containerProps.style]}}
/>;
return <>
{label?<Label {...labelProps} style={[{color:labelColor},labelProps.style]} children={label}/> : null}
{btn}
{errorText? <Label error children={errorText}/>:null}
</>
});
DocumentPickerComponent.displayName = "DocumentPickerComponent";
export default DocumentPickerComponent;
const styles = StyleSheet.create({
button : {
alignSelf: 'flex-start',
},
leftLabel : {
paddingVertical : 12,
borderRightWidth : 1,
textWrap : "nowrap",
paddingRight : 7,
},
label : {
paddingHorizontal : 5,
textWrap : "wrap",
textAlign : "left",
},
container : {
marginTop : 5,
}
});
DocumentPickerComponent.propTypes = {
label : PropTypes.oneOfType([
PropTypes.node,
PropTypes.element,
PropTypes.string,
PropTypes.number,
]),
text : PropTypes.oneOfType([
PropTypes.node,
PropTypes.element,
PropTypes.string,
PropTypes.number,
]),
...Object.assign({},Button.propTypes),
onChange : PropTypes.func,
onCancel : PropTypes.func,
/*** @see : https://docs.expo.dev/versions/latest/sdk/document-picker/#documentpickeroptions */
pickOptions : PropTypes.shape({
copyToCacheDirectory : PropTypes.bool,
multiple : PropTypes.bool,
/*** @seee : https://en.wikipedia.org/wiki/Media_type */
type : PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
])
}),
}