@fto-consult/expo-ui 8.73.0 → 8.74.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.
@@ -127,6 +127,27 @@ export default function AppMainEntry(){
127
127
  ({object})=><{object}>, la fonction permettant de muter les props du composant Fab, affiché dans les écrans par défaut
128
128
  */
129
129
  fabPropsMutator : (props)=>props,
130
+ /****
131
+ les props personnalisés à passer au composant ProfilAvatar
132
+ @param {
133
+ user <Object>, l'objet en rapport à l'utilisateur connecté
134
+ canSignOut <boolean>, renseigne si l'utilisateur peut se déconnecté. est à false lorsque la gestion de l'authentification est désactivé,
135
+ renderedOnAppBar <boolean>, renseigne si l'avatar est rendu sur l'AppBar où sur le drawer
136
+ closeDrawer : (callback<function>)=><any>, la fonction permettant de fermer le drawer, lorsque celui-ci est en mode temporaire
137
+ navigateToPreferences : <func>, la fonction permettant de naviguer vers les préférences utilisateurs,
138
+ signOut <func>, la fonction permetant de déconnecter l'utilisateur
139
+ ...rest,
140
+ },
141
+ @return <object> {
142
+ pseudo <string>, le pseudo à utiliser pour l'affichage du profil avatar
143
+ label <string>, le label, le sous nom à afficher juste en bas du pseudo
144
+ ...imageProps <object>, les props à utilser pour le rendu de l'avatar, idem au props du composant image,
145
+ menuItems : <array | object>, les items supplémentaires à afficher pour le rendu du menu,
146
+ preferencesMenuItem : <boolean>, si l'items préférence sera rendu dans les items du menu
147
+ signOutMenuItem : <boolean>, si l'item Déconnection sera rendu des les items de menu
148
+ }
149
+ */
150
+ profilAvatarProps : ({user,renderedOnAppBar,closeDrawer,canSignOut})=>({}),
130
151
  }}
131
152
  /*** //for application initialization
132
153
  @param {
@@ -145,6 +166,14 @@ export default function AppMainEntry(){
145
166
  beforeExit = {()=>Promise.resolve(true)}
146
167
 
147
168
  handleHelpScreen ={true} //si l'écran d'aide sera pris en compte, l'écran d'aide ainsi que les écrans des termes d'utilisations et autres
169
+ /***
170
+ Les filtres vers les icons Set
171
+ @param {object} font, l'objet font parmis la liste des fonts icons supportés : voir : https://icons.expo.fyi/Index
172
+ @param {string} fontName, le nom de la font
173
+ @param {string} fontNameLower, le nom de la font en lowerCase
174
+ @return {boolean}, si true, l'icon set sera pris en compte
175
+ */
176
+ FontsIconsFilter ={(font,fontName,fontNameLower)=>false}
148
177
  />
149
178
  }
150
179
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "8.73.0",
3
+ "version": "8.74.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": {
@@ -70,7 +70,8 @@
70
70
  "dependencies": {
71
71
  "@emotion/react": "^11.11.1",
72
72
  "@faker-js/faker": "^8.0.2",
73
- "@fto-consult/common": "^4.44.3",
73
+ "@fto-consult/common": "^4.45.0",
74
+ "@fto-consult/expo-ui": "^8.73.1",
74
75
  "apexcharts": "^3.48.0",
75
76
  "file-saver": "^2.0.5",
76
77
  "google-libphonenumber": "^3.2.34",
@@ -59,7 +59,6 @@ const BottomSheetComponent = React.forwardRef((props,ref)=> {
59
59
  modalProps,
60
60
  titleProps : _titleProps,
61
61
  withScrollView,
62
- bindResizeEvent,
63
62
  scrollViewProps : _scrollViewProps,
64
63
  actionTitle,
65
64
  elevation:customElevation,
@@ -228,12 +227,8 @@ const BottomSheetComponent = React.forwardRef((props,ref)=> {
228
227
 
229
228
  React.setRef(ref,{close:closeModal,open})
230
229
  React.useEffect(()=>{
231
- if(bindResizeEvent && false){
232
- APP.on(APP.EVENTS.RESIZE_PAGE,closeModal);
233
- }
234
230
  return ()=>{
235
231
  removeListeners();
236
- APP.off(APP.EVENTS.RESIZE_PAGE,closeModal);
237
232
  React.setRef(ref,null);
238
233
  }
239
234
  },[]);
@@ -326,7 +321,6 @@ BottomSheetComponent.propTypes = {
326
321
 
327
322
  BottomSheetComponent.defaultProps = {
328
323
  withScrollView : PropTypes.bool,
329
- bindResizeEvent : PropTypes.bool,
330
324
  animationType: isNativeMobile ? "slide" : "fade",//Background animation ("none", "fade", "slide")
331
325
  height:undefined,//Height of Bottom Sheet
332
326
  minClosingHeight: 0,//Minimum height of Bottom Sheet before close
@@ -21,8 +21,8 @@ import BackToTop from "$ecomponents/BackToTop";
21
21
  import FiltersAccordionComponent from "./Filters";
22
22
  import RenderType from "../RenderType";
23
23
  import { flatMode} from "$ecomponents/TextField";
24
- //import List from "$ecomponents/Table/List";
25
- import List from "$ecomponents/List/FlashList";
24
+ import List from "$ecomponents/Table/List";
25
+ //import List from "$ecomponents/List/FlashList";
26
26
  import theme,{Colors} from "$theme";
27
27
  import {styles as rStyles} from "../utils";
28
28
  import Avatar from "$ecomponents/Avatar";
@@ -19,6 +19,7 @@ import MaterialIcons from "@expo/vector-icons/MaterialIcons";
19
19
  import Octicons from "@expo/vector-icons/Octicons";
20
20
  import SimpleLineIcons from "@expo/vector-icons/SimpleLineIcons";
21
21
  import Zocial from "@expo/vector-icons/Zocial";
22
+ import Colors from "$theme/colors";
22
23
 
23
24
  /*** @see : https://icons.expo.fyi/ popur tous les icons supportés*/
24
25
  /*** L'iconSet par défaut est le MaterialCommunityIcon qui ne nécessite pas de préfixer les noms des icones
@@ -67,6 +67,7 @@ Object.map(Utils,(v,i)=>{
67
67
  fabPropsMutator : ({object})=><{object}>, la fonction permettant de muter les props du composant Fab, affiché dans les écrans par défaut,
68
68
  TableDataScreen | TableDataScreenItem : {ReactComponent}, le composant TableDataScreenItem, à utiliser pour le rendu des écrans
69
69
  TableDataScreenList | TableDataListScreen {ReactComponent}, le composant TableDataList à utiliser pour le rendu des écrans listants les éléments du table data
70
+ profilAvatarProps : {function | object}, si fonction, ({user,size,renderedOnAppBar,})=>{pseudo,label,size,menuItems,...rest}
70
71
  },
71
72
 
72
73
  navigation : {
@@ -16,13 +16,31 @@ import appConfig from "$capp/config";
16
16
  import Preloader from "$preloader";
17
17
  import {defaultNumber} from "$cutils";
18
18
  import Tooltip from "$ecomponents/Tooltip";
19
+ import PropTypes from "prop-types";
20
+ import { useContext } from "$econtext/hooks";
19
21
 
20
- const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps:customChevronIconProps,size,withLabel,...props},ref)=>{
22
+ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,renderedOnAppBar,chevronIconProps:customChevronIconProps,size,withLabel,menuItems,...props},ref)=>{
21
23
  let u = defaultObj(Auth.getLoggedUser());
22
24
  const deviceNameRef = React.useRef(null);
23
25
  const deviceName = appConfig.deviceName;
24
26
  customChevronIconProps = defaultObj(customChevronIconProps);
25
27
  props = defaultObj(props);
28
+ const navigateToPreferences = (a)=>{
29
+ closeDrawer(()=>{
30
+ return navigate({
31
+ routeName : screenName,
32
+ params : {
33
+ user : u,
34
+ }
35
+ })
36
+ });
37
+ };
38
+ const signOut = (a)=>{
39
+ closeDrawer(()=>{
40
+ Preloader.open("Déconnexion en cours...");
41
+ Auth.signOut().finally(Preloader.close)
42
+ });
43
+ };
26
44
  const closeDrawer = cb => {
27
45
  if(drawerRef && drawerRef.current && drawerRef.current.close){
28
46
  return drawerRef && drawerRef.current && drawerRef.current.close(cb);
@@ -37,8 +55,15 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
37
55
  size = defaultNumber(size,!withLabel?40:40);
38
56
  const userPseudo = Auth.getUserPseudo();
39
57
  const defaultPseudo = "Default User";
40
- const pseudo = defaultStr(userPseudo,Auth.getUserCode(),Auth.getUserEmail(),appConfig.authDefaultUsername,defaultPseudo);
41
- const label = defaultStr(Auth.getUserFullName(),userPseudo);
58
+ const canSignOut = Auth.canSignOut();
59
+ const {components:{profilAvatarProps}} = useContext();
60
+ const customProps = Object.assign({},typeof profilAvatarProps =='function'? profilAvatarProps({...props,signOut,navigateToPreferences,canSignOut,closeDrawer,user:u,size,close:closeDrawer,setDeviceId:onLongPress,renderedOnAppBar,}) : profilAvatarProps);
61
+ if(typeof customProps.size =="number"){
62
+ size = customProps.size;
63
+ }
64
+ const pseudo = defaultStr(customProps.pseudo,userPseudo,Auth.getUserCode(),Auth.getUserEmail(),appConfig.authDefaultUsername,defaultPseudo);
65
+ const label = defaultStr(customProps.label,Auth.getUserFullName(),userPseudo);
66
+ delete customProps.label;
42
67
  const onLongPress = ()=>{
43
68
  appConfig.setDeviceId().then((r)=>{
44
69
  if(deviceNameRef.current && deviceNameRef.current.update){
@@ -48,15 +73,16 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
48
73
  };
49
74
  const pseudoTooltip = (pseudo == defaultPseudo ? `Pour modifier la valeur du pseudo actuel, définissez dans le fichier package.json, la propriété : authDefaultUsername de type chaine de caractère`:"");
50
75
  const tooltip = "Pressez longtemps pour définir un identifiant unique pour l'appareil";
51
- const pseudoContent = <Label splitText numberOfLines={1} style={{color:theme.colors.primaryOnSurface,fontSize:15}}>{pseudo}</Label>;
52
- const children = <View style={[styles.labelContainer,!withLabel && theme.styles.justifyContentCenter]}>
76
+ const testID = defaultStr(customProps.testID,props.testID,"RN_ProfilAvatar")
77
+ const pseudoContent = <Label testID={testID+"_PseudoContent"} splitText numberOfLines={1} style={{color:theme.colors.primaryOnSurface,fontSize:15}}>{pseudo}</Label>;
78
+ const children = <View testID={testID+"_AnchorContainer"} style={[styles.labelContainer,!withLabel && theme.styles.justifyContentCenter]}>
53
79
  {pseudoTooltip?<Tooltip title={pseudoTooltip}>
54
80
  {pseudoContent}
55
81
  </Tooltip>:pseudoContent}
56
- <Label splitText numberOfLines={1} style={[{fontSize:12,color:theme.colors.secondaryOnSurface,marginTop:6},!withLabel && {textAlign:'center'}]}>
82
+ {label != pseudo ? <Label testID={testID+"_ProfilAvatarLabel"} splitText numberOfLines={1} style={[{fontSize:12,color:theme.colors.secondaryOnSurface,marginTop:6},!withLabel && styles.withNotLabel]}>
57
83
  {label}
58
- </Label>
59
- {deviceName && <Label.withRef textBold splitText title={"Identifiant unique de l'application, installé sur cet appareil"} ref={deviceNameRef} secondary style={{fontSize:10}}>
84
+ </Label>:null}
85
+ {deviceName && <Label.withRef testID={testID+"_ProfilAvatarDeviceName"} textBold splitText title={"Identifiant unique de l'application, installé sur cet appareil"} ref={deviceNameRef} secondary style={{fontSize:10}}>
60
86
  [{deviceName}]
61
87
  </Label.withRef> || null}
62
88
  </View>
@@ -68,30 +94,22 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
68
94
  closeOnPress : false,
69
95
  divider : true,
70
96
  },
71
- {
97
+ ...(Array.isArray(menuItems)? menuItems : isObj(menuItems)? Object.keys(menuItems).map(k=>{
98
+ return menuItems[k];
99
+ }) : []),
100
+ ...(Array.isArray(customProps.menuItems)? customProps.menuItems : isObj(customProps.menuItems)? Object.keys(customProps.menuItems).map(k=>{
101
+ return customProps.menuItems[k];
102
+ }) : []),
103
+ customProps.preferencesMenuItem != false && {
72
104
  label : i18n.lang("preferences",'Préférences'),
73
105
  icon : "account-cog",
74
- onPress : (a)=>{
75
- closeDrawer(()=>{
76
- return navigate({
77
- routeName : screenName,
78
- params : {
79
- user : u,
80
- }
81
- })
82
- });
83
- }
106
+ onPress : navigateToPreferences,
84
107
  },
85
- Auth.canSignOut() && {
108
+ canSignOut && customProps.signOutMenuItem !== false && {
86
109
  label : i18n.lang("logout",'Déconnexion'),
87
110
  icon : "logout",
88
- onPress : (a)=>{
89
- closeDrawer(()=>{
90
- Preloader.open("Déconnexion en cours...");
91
- Auth.signOut().finally(Preloader.close)
92
- });
93
- }
94
- }
111
+ onPress : signOut,
112
+ },
95
113
  ];
96
114
 
97
115
  const onChangeAvatar = ({dataURL})=>{
@@ -105,7 +123,7 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
105
123
  }
106
124
  Auth.upsertUser({...u,avatar:u.avatar},false);
107
125
  }
108
- return <View ref ={ref}>
126
+ return <View ref ={ref} testID={testID+"_ProfilAvatarWrapper"}>
109
127
  <Menu
110
128
  anchor = { (aProps)=>{
111
129
  const chevronIconProps = {
@@ -117,19 +135,21 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
117
135
  style : [styles.icon,withLabel=== false && {color:theme.colors.onPrimary},customChevronIconProps.style],
118
136
  }
119
137
  if(!withLabel){
120
- return <View testID={"RNProfilAvatar_AvatarContainer"} style={[theme.styles.row,theme.styles.alignItemsCenter]}>
138
+ return <View testID={testID+"_AvatarContainer"} style={[theme.styles.row,theme.styles.alignItemsCenter,theme.styles.pr1]}>
121
139
  <Image
122
140
  pickImageProps = {{quality:0.4}}
123
141
  {...props}
124
142
  {...aProps}
143
+ {...customProps}
125
144
  size={size}
126
145
  style = {styles.itemLeft}
127
- testID = {"RN_ProfilAvatar_Avatar"}
146
+ testID = {testID+"_Avatar"}
128
147
  readOnly = {false}
129
148
  defaultSource ={avatarProps.defaultSrc}
130
149
  onChange = {onChangeAvatar}
131
150
  />
132
- <Icon
151
+ <Icon.Font
152
+ testID={testID+"_ChevronIcon"}
133
153
  {...chevronIconProps}
134
154
  {...aProps}
135
155
  style = {[chevronIconProps.style,{marginLeft:-5}]}
@@ -137,6 +157,7 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
137
157
  </View>
138
158
  }
139
159
  return <Pressable
160
+ testID={testID+"_ProfilAvatarContainer"}
140
161
  normal
141
162
  upperCase = {false}
142
163
  disableRipple
@@ -148,15 +169,17 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
148
169
  >
149
170
  <Image
150
171
  {...props}
172
+ {...customProps}
151
173
  size={size}
152
174
  style = {styles.itemLeft}
153
- testID = {"RN_ProfilAvatar_AvatarImage"}
175
+ testID = {testID+"_Avatar"}
154
176
  readOnly = {false}
155
177
  defaultSource ={avatarProps.defaultSrc}
156
178
  onChange = {onChangeAvatar}
157
179
  />
158
180
  {children}
159
181
  <Icon
182
+ testID={testID+"_ChevronIcon"}
160
183
  {...chevronIconProps}
161
184
  />
162
185
  </Pressable>
@@ -185,6 +208,9 @@ const styles = StyleSheet.create({
185
208
  maxWidth : 140,
186
209
  minWidth : 100,
187
210
  },
211
+ withNotLabel : {
212
+ textAlign : "center",
213
+ },
188
214
  pseudo : {
189
215
  flexDirection : "row",
190
216
  justifyContent : "center",
@@ -197,9 +223,35 @@ const styles = StyleSheet.create({
197
223
  icon : {
198
224
  marginHorizontal:0,
199
225
  paddingHorizontal : 0,
200
- }
201
- })
226
+ },
227
+ notLabelHeader : {
228
+ textAlign : "left",
229
+ alignSelf :"flex-start"
230
+ },
231
+ });
202
232
 
203
233
  export default UserProfileAvatarComponent;
204
234
 
205
- UserProfileAvatarComponent.displayName = "UserProfileAvatarComponent";
235
+ UserProfileAvatarComponent.displayName = "UserProfileAvatarComponent";
236
+
237
+ UserProfileAvatarComponent.propTypes = {
238
+ renderedOnAppBar : PropTypes.bool,//spécifie si le profil avatar est rendu si true sur l'appBar, si false sur le drawer
239
+ ...Object.assign({},Image.propTypes), //par défaut les props de l'image qui est utilisée pour le rendu de l'avatar
240
+ withLabel : PropTypes.bool, //si le label sera affiché, ie, le nom où pseudo de l'utilisateur
241
+ menuItems : PropTypes.oneOfType([
242
+ PropTypes.array,
243
+ PropTypes.object,
244
+ ]),
245
+ /****
246
+ La props customProps issue de la propriété {component:profilAvatarProps} de useContext, prend les propriétés suivatnes :
247
+ il peut s'agir d'une fonction où d'un objet. s'il s'agit d'une fonction alors la dite fonction est de la forme :
248
+ ({canSignOut<boolean>,renderedOnAppBar<boolean>,user<object>,....rest})=> <CustomAvatarProps>
249
+ <CustomAvatarProps> : {
250
+ ...Image.propTypes,
251
+ size <number>,
252
+ pseudo <string>, le pseudo à afficher
253
+ label <string>, la chaine de caractère à afficher pour le rendu du label/FullName,
254
+ menuItems : <Array<object> | object<object>>, les menu items personnalisés à utiliser pour l'affichage
255
+ }
256
+ */
257
+ }
@@ -6,10 +6,10 @@ import Container from "$cauth/Container";
6
6
  import ScreenWithoutAuthContainer from "./ScreenWithoutAuthContainer";
7
7
  import ProfilAvatar from "$elayouts/ProfilAvatar";
8
8
  import {defaultObj,defaultBool} from "$cutils";
9
- import View from "$ecomponents/View";
10
9
  import theme from "$theme";
10
+ import React from "$react";
11
11
 
12
- export default function MainScreenComponent({profilAvatarProps,withDrawer,allowDrawer,profilAvatarContainerProps,withProfilAvatarOnAppBar:cWithPorilAvatarOnAppbar,authProps,authRequired,...props}){
12
+ export default function MainScreenComponent({profilAvatarProps,appBarProps,testID,withDrawer,allowDrawer,profilAvatarContainerProps,withProfilAvatarOnAppBar:cWithPorilAvatarOnAppbar,authProps,authRequired,...props}){
13
13
  authProps = Object.assign({},authProps),
14
14
  profilAvatarContainerProps = defaultObj(profilAvatarContainerProps);
15
15
  profilAvatarProps = defaultObj(profilAvatarProps);
@@ -18,16 +18,26 @@ export default function MainScreenComponent({profilAvatarProps,withDrawer,allowD
18
18
  if(allowDrawer === false){
19
19
  withDrawer = false;
20
20
  }
21
+ testID = defaultStr(testID,"RN_MainScreenComponent");
21
22
  const withProfilAvatarOnAppBar = cWithPorilAvatarOnAppbar !== false && withDrawer && !theme.showProfilAvatarOnDrawer ? true : false;
22
- return <Container authProps={authProps} required={authRequired}>
23
+ appBarProps = defaultObj(appBarProps);
24
+ const {right} = appBarProps;
25
+ if(withProfilAvatarOnAppBar){
26
+ appBarProps.right = (...p)=>{
27
+ const r = typeof right =='function'? right(p) : right;
28
+ return <>
29
+ <ProfilAvatar renderedOnAppBar withLabel={false} size={40} {...profilAvatarProps}/>
30
+ {React.isValidElement(r)? r : null}
31
+ </>
32
+ }
33
+ }
34
+ return <Container authProps={authProps} required={authRequired} testID={testID}>
23
35
  <ScreenWithoutAuthContainer
24
36
  {...props}
25
37
  withDrawer={withDrawer}
26
38
  allowDrawer={allowDrawer}
27
39
  authRequired = {authRequired}
28
- right = {withProfilAvatarOnAppBar && <View testID={testID+"_ProfilAvatar_Container"} {...profilAvatarContainerProps} style={[profilAvatarContainerProps.style,styles.profilAvatarContainer]} >
29
- {<ProfilAvatar withLabel={false} {...profilAvatarProps}/>}
30
- </View> || null}
40
+ appBarProps={appBarProps}
31
41
  />
32
42
  </Container>
33
43
  }
@@ -37,7 +37,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
37
37
  contentContainerStyle,
38
38
  options,
39
39
  backAction,
40
- appBarProps,
40
+ appBarProps:cAppbarProps,
41
41
  elevation,
42
42
  withFab,
43
43
  withNotifications,
@@ -63,7 +63,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
63
63
  containerProps = defaultObj(containerProps);
64
64
  backgroundColor = theme.Colors.isValid(backgroundColor)? backgroundColor : theme.colors.background;
65
65
  options = defaultObj(options);
66
- appBarProps = defaultObj(appBarProps);
66
+ const {right,left,...appBarProps} = defaultObj(cAppbarProps);
67
67
  title = defaultVal(title,appBarProps.title);
68
68
  subtitle = defaultVal(subtitle,appBarProps.subtitle);
69
69
  notificationsProps = {...Object.assign({},notificationsProps),...Object.assign({},appBarProps.notificationsProps)};
@@ -117,6 +117,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
117
117
  {appBar === false ? null : React.isValidElement(appBar)? AppBar : <AppBar
118
118
  testID={testID+'_AppBar'}
119
119
  {...appBarProps}
120
+ left = {left}
120
121
  backAction = {defaultVal(appBarProps.backAction,backAction)}
121
122
  elevation={defaultNumber(appBarProps.elevation,elevation)}
122
123
  notificationsProps = {notificationsProps}
@@ -124,6 +125,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
124
125
  ref={appBarRef} title={title}
125
126
  subtitle={subtitle}
126
127
  withNotifications = {withNotifications}
128
+ right = {right}
127
129
  />}
128
130
  {withScrollView !== false ? (
129
131
  <ScrollView
@@ -0,0 +1,6 @@
1
+ export default function(){
2
+ return null;
3
+ }
4
+
5
+ export const open = ()=>{
6
+ };
@@ -1,178 +1,21 @@
1
- /**@see : https://github.com/pipwerks/PDFObject#readme */
2
- let {Dialog} = require("$ecomponents/Dialog")
3
- let Icon = require("$ecomponents/Icon")
4
- require("./styles.css")
5
- let PDFObject = require("pdfobject")
6
- let {MenuButton} = require("$ui")
7
- let isMSE = //checkEdge ? false :
8
- window.navigator && typeof window.navigator.msSaveOrOpenBlob == "function" ? true : false;
9
- class PDFViewer extends APP.Component {
10
- constructor(props){
11
- super(props);
12
- APP.extend(this._events,{
13
- resize : this.resetPos.bind(this)
14
- })
15
- this.autobind();
16
- }
1
+ import React from "$react";
2
+ import DialogProvider from "$ecomponents/Dialog/Provider";
17
3
 
18
- componentDidMount(){
19
- super.componentDidMount();
20
- this.updatePdfContent();
21
- window.addEventListener('resize',this._events.resize, true)
22
- this.resetPos();
23
- }
24
- resetPos (){
25
- if(!this._isMounted()) return;
26
- let pdfWrap = document.getElementById(this.pdfViewerWrapperDomId);
27
- if(isDOMElement(pdfWrap)){
28
- let parent = pdfWrap.parentNode;
29
- let mP = pdfWrap.closest(".dialog.md-dialog-container");
30
- if(isDOMElement(parent) && isDOMElement(mP)){
31
- let maxHeight = mezr.height(parent);
32
- let maxH2 = mezr.height(mP);
33
- let min = Math.min(maxHeight,maxH2);
34
- if(min == 0){
35
- min = "100%";
36
- } else min = min+"px";
37
- pdfWrap.style.height = min;
38
- }
39
- }
40
- }
4
+ let dialogRef = null;
41
5
 
42
- componentDidUpdate(){
43
- super.componentDidUpdate();
44
- if(this.dialogRef && this.dialogRef.open){
45
- this.dialogRef.open();
46
- }
47
- this.updatePdfContent()
48
- this.resetPos();
49
- }
50
- componentWillUnmount(){
51
- super.componentWillUnmount();
52
- this.dialogRef = undefined;
53
- window.removeEventListener('resize',this._events.resize, true)
54
- this.clearEvents();
55
- }
56
- viewCapacitor (){
57
- let f = window.PreviewAnyFile || (cordova && cordova.plugins.PreviewAnyFile);
58
- if(f && f.preview){
59
- f = f.preview;
60
- let {file} = this.props;
61
- APP.FILE.getCapacitorPDFromDataURL({content:file,fileName:this.props.fileName,success:({path})=>{
62
- if(isFunction(f)){
63
- f(
64
- path,
65
- function(win){},
66
- function(err){
67
- console.log(err," pdf viewer in cap android ios")
68
- }
69
- )
70
- }
71
- }})
72
- }
73
- }
74
- updatePdfContent(){
75
- let file = this.props.file;
76
- if (isMSE) {
77
- let b64 = dataURLToBase64(file);
78
- if(b64){
79
- var byteCharacters = atob(b64);
80
- var byteNumbers = new Array(byteCharacters.length);
81
- for (var i = 0; i < byteCharacters.length; i++) {
82
- byteNumbers[i] = byteCharacters.charCodeAt(i);
83
- }
84
- var byteArray = new Uint8Array(byteNumbers);
85
- var blob = new Blob([byteArray], {
86
- type: 'application/pdf'
87
- });
88
- return window.navigator.msSaveOrOpenBlob(blob, defaultStr(this.props.title,'données-impr')+".pdf");
89
- }
90
- return null;
91
- }
92
- if(isElectron()){
93
- return ELECTRON.PRINTER.preview({
94
- content:this.props.file,
95
- fileName : this.props.fileName,
96
- fileExtension : 'pdf',
97
- });
98
- }
99
- if(isCapacitor(true)){
100
- return this.viewCapacitor();
101
- }
102
- let dom = document.getElementById(this.pdfViewerWrapperDomId);
103
- if(isDOMElement(dom)){
104
- try {
105
- this.pdfInstance = PDFObject.embed(file,dom);
106
- } catch (e){
107
- console.log(e,' error on loading pdf file')
108
- }
109
- }
110
- }
111
- UNSAFE_componentWillReceiveProps(nexProps,prevProps){
112
- if(nexProps.file && nexProps.file != this.state.file){
113
- this._pageNumber = 1;
114
- }
115
- }
116
- onPrint (args){
117
- console.log(args,' was printed');
118
- }
119
- getPrintSettings(){
120
- return defaultObj(this.props.printProps,this.props.printOptions);
121
- }
122
- render (){
123
- if(isMSE || isElectron() || isCapacitor(true)) return null;
124
- let {file,dialogProps,title,onPrint,printProps,printOptions,fileName,...rest} = this.props;
125
- dialogProps = defaultObj(dialogProps);
126
- dialogProps.contentProps = defaultObj(dialogProps.contentProps)
127
- dialogProps.contentProps.id = defaultStr(dialogProps.contentProps.id,this.dialogWrapperParentId,uniqid('dialog-content-wrp-par'))
128
- this.dialogWrapperParentId = dialogProps.contentProps.id;
129
- dialogProps.contentProps.className = classNames(dialogProps.contentProps.className,'no-padding pdf-viewer-dialog-content')
130
- dialogProps.className = classNames(dialogProps.className,'pdf-viewer-dialog')
131
- dialogProps.title = defaultStr(dialogProps.title,title)
132
- rest = defaultObj(rest)
133
- let {actions} = dialogProps;
134
- let acts = []
135
- let mIts = []
136
- if(mIts.length > 0){
137
- acts.push(
138
- <MenuButton
139
- menuItems = {mIts}
140
- flat
141
- id = {uniqid("view-page-id-butt")}
142
- >
143
- {<Icon name="material-more_vert" title={"pages"}/>}
144
- </MenuButton>
145
- )
146
- }
147
- Object.map(actions,(a,i)=>{
148
- if(!a) return;
149
- acts.push(a);
150
- })
151
- this.pdfViewerWrapperDomId = defaultStr(this.pdfViewerWrapperDomId,uniqid("pdf-viewer-wrapper-id"))
152
- return (
153
- <Dialog
154
- key = {_uniqid("dialog-pdf-viewer-key-id")}
155
- {...dialogProps}
156
- ref = {(el)=>{
157
- if(el){
158
- this.dialogRef = el;
159
- }
160
- }}
161
- fullPage
162
- visible
163
- actions = {acts}
164
- >
165
- <div className="pdf-viewer-wrapper w100 h100" id={this.pdfViewerWrapperDomId}></div>
166
- </Dialog>
167
- );
168
- }
6
+ export default function WebPDFReader(){
7
+ dialogRef = React.useRef(null);
8
+ return <>
9
+ <DialogProvider
10
+ ref = {dialogRef}
11
+ responsive = {false}
12
+ />
13
+ </>
169
14
  }
170
15
 
171
- module.exports = PDFViewer;
172
- PDFViewer.PDFObject = PDFObject;
173
-
174
- PDFViewer.propTypes = {
175
- ...Document.propTypes,
176
- /*** méthode appelée lorsque le document est imprimé */
177
- onPrint : PropTypes.func,
16
+ export const open = (props)=>{
17
+ if(!dialogRef || !dialogRef?.current) return;
18
+ DialogProvider.open({
19
+ ...props,
20
+ },dialogRef.current);
178
21
  }