@fto-consult/expo-ui 6.52.0 → 6.52.2

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.
@@ -13,7 +13,7 @@ module.exports = (opts)=>{
13
13
  opts.withPouchDB = opts.withPouchDB !== false && opts.withPouchdb !== false ? true : false;
14
14
  delete opts.withPouchdb;
15
15
  const expoUI = require("./expo-ui-path")();
16
- const r = require(`"@fto-consult/common/babel.config.alias"`)(opts);
16
+ const r = require(`@fto-consult/common/babel.config.alias`)(opts);
17
17
  const expo = path.resolve(expoUI,"src");
18
18
  r.$edocs = path.resolve(expoUI,"docs");//l'alias de la documentation
19
19
  r["$edocs-components"] = path.resolve(r.$edocs,"components");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "6.52.0",
3
+ "version": "6.52.2",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "main": "main",
6
6
  "scripts": {
@@ -70,7 +70,7 @@
70
70
  "@expo/html-elements": "^0.5.1",
71
71
  "@expo/vector-icons": "^13.0.0",
72
72
  "@faker-js/faker": "^8.0.2",
73
- "@fto-consult/common": "^3.45.9",
73
+ "@fto-consult/common": "^3.45.10",
74
74
  "@pchmn/expo-material3-theme": "^1.3.1",
75
75
  "@react-native-async-storage/async-storage": "1.18.2",
76
76
  "@react-native-community/datetimepicker": "7.2.0",
@@ -7,7 +7,6 @@ import Filter from "$ecomponents/Filter";
7
7
 
8
8
  export default function FilterAccordionComponent({onChange,...props}){
9
9
  const valuesRefs = React.useRef({});
10
- console.log("rendering ",valuesRefs);
11
10
  return <Filter
12
11
  {...props}
13
12
  {...valuesRefs.current}
@@ -1209,8 +1209,12 @@ export default class CommonDatagridComponent extends AppComponent {
1209
1209
  toggleFilterColumnVisibility(field,visible){
1210
1210
  if(!isNonNullString(field)) return;
1211
1211
  const filteredColumns = {...this.state.filteredColumns};
1212
+ if(typeof visible !=='boolean'){
1213
+ visible = !!!filteredColumns[field];
1214
+ }
1212
1215
  filteredColumns[field] = visible;
1213
1216
  this.setSessionData("filteredColumns"+this.getSessionNameKey(),filteredColumns);
1217
+ this.trigger("toggleFilterColumnVisibility",{field,columnField:field,visible});
1214
1218
  return visible;
1215
1219
  }
1216
1220
 
@@ -2729,6 +2733,9 @@ export default class CommonDatagridComponent extends AppComponent {
2729
2733
  getPreparedColumns(){
2730
2734
  return this.preparedColumns;
2731
2735
  }
2736
+ getColumns(){
2737
+ return isObj(this.state.columns)? this.state.columns : {};
2738
+ }
2732
2739
  prepareData(args,cb){
2733
2740
  let {pagination,config,aggregatorFunction:customAggregatorFunction,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,sectionListCollapsedStates,updateFooters} = defaultObj(args);
2734
2741
  cb = typeof cb ==='function'? cb : typeof args.cb == 'function'? args.cb : undefined;
@@ -14,7 +14,7 @@ import DateLib from "$lib/date";
14
14
  import {getFetchOptions} from "$cutils/filters";
15
15
  import {setQueryParams} from "$cutils/uri";
16
16
  import {uniqid} from "$cutils";
17
- import { getFetcherOptions } from "$capi/fetch";
17
+ import apiFetch,{ getFetcherOptions } from "$capi/fetch";
18
18
  import Icon from "$ecomponents/Icon";
19
19
  import Label from "$ecomponents/Label";
20
20
  import { StyleSheet,View } from "react-native";
@@ -26,6 +26,7 @@ import PropTypes from "prop-types";
26
26
  import {Menu} from "$ecomponents/BottomSheet";
27
27
  import session from "$session";
28
28
  import useContext from "$econtext/hooks";
29
+ import notify from "$cnotify";
29
30
 
30
31
  export const getSessionKey = ()=>{
31
32
  return Auth.getSessionKey("swrDatagrid");
@@ -188,17 +189,13 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
188
189
  delete opts.page;
189
190
  delete opts.offset;
190
191
  }
192
+ if(showProgressRef.current ===false){
193
+ opts.showError = false;
194
+ }
191
195
  if(typeof fetcher =='function'){
192
196
  return fetcher(url,opts);
193
197
  }
194
- const {url:fUrl,fetcher:cFetcher,...rest} = getFetcherOptions(url,opts);
195
- if(showProgressRef.current ===false){
196
- rest.showError = false;
197
- }
198
- return cFetcher(fUrl,rest).catch((e)=>{
199
- console.log(e," is swr fetching data");
200
- throw e;
201
- });
198
+ return apiFetch(url,opts);
202
199
  },
203
200
  showError : false,
204
201
  swrOptions : getSWROptions(swrConfig.refreshTimeout)
@@ -232,7 +229,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
232
229
  },500);
233
230
  },[error]);
234
231
  const doRefresh = (showProgress)=>{
235
- showProgressRef.current = showProgress ? typeof showProgress ==='boolean' : false;
232
+ showProgressRef.current = showProgress ? typeof showProgress ==='boolean' : isLoading;
236
233
  refresh();
237
234
  }
238
235
  const canPaginate = ()=>{
@@ -1,7 +1,51 @@
1
1
  import React from "$react";
2
2
  import View from "$ecomponents/View";
3
3
  import Label from "$ecomponents/Label";
4
+ import { useDatagrid } from "./hooks";
5
+ import styles from "./styles";
6
+ import {defaultStr} from "$cutils";
7
+ import theme from "$theme";
8
+ import Filter, {canHandleFilter} from "$ecomponents/Filter";
9
+ import { getMenuStyle } from "./styles";
4
10
 
5
- export default function DatagridTableFilterComponent({}){
6
- return null;
11
+ export default function DatagridTableFilterComponent({columnField,label,onChange,text,testID,...rest}){
12
+ const {context,filteredColumns} = useDatagrid();
13
+ const [visible,setVisible] = React.useState(!!filteredColumns[columnField]);
14
+ testID = defaultStr(testID,"RN_DatagridTableFilterComponent");
15
+ React.useEffect(()=>{
16
+ if(typeof context?.on ==='function'){
17
+ const onToggleVisibility = ({columnField:cField,visible:nVisible})=>{
18
+ if(columnField === cField && visible !== nVisible){
19
+ console.log("toggle ",columnField,nVisible);
20
+ setVisible(nVisible);
21
+ }
22
+ }
23
+ context.on("toggleFilterColumnVisibility",onToggleVisibility);
24
+ return ()=>{
25
+ context.off("toggleFilterColumnVisibility",onToggleVisibility);
26
+ }
27
+ }
28
+ },[context]);
29
+ label = label || text;
30
+ return <View testID={testID+"_DatagridFilterTableContainer"} style={[styles.filter,getMenuStyle(),!visible && styles.hidden]}>
31
+ <View testID={testID+"_DatagridTableFilterContent"} style={[theme.styles.row,theme.styles.alignItemsCenter,theme.styles.justifyContentStart,!visible && styles.hidden]}>
32
+ {React.isValidElement(label,true) ? <Label numberOfLines={1} style={[styles.filterLabel]}>
33
+ {label}
34
+ Un label
35
+ </Label>:null}
36
+ <Filter
37
+ {...rest}
38
+ withLabel={false}
39
+ testID={testID+"_DatagridFilterComponent_"+columnField}
40
+ anchorProps = {{size:20,style:[theme.styles.noMargin,theme.styles.noPadding]}}
41
+ onChange = {(...args)=>{
42
+ if(!visible){
43
+ return;
44
+ }
45
+ console.log("calling on change ",args);
46
+ onChange && onChange(...args);
47
+ }}
48
+ />
49
+ </View>
50
+ </View>;
7
51
  }
@@ -6,48 +6,46 @@ import { StyleSheet,ScrollView } from "react-native";
6
6
  import Label from "$ecomponents/Label";
7
7
  import Filter from "./Filter";
8
8
  import FiltersMenu from "./FiltersMenu";
9
- import FilterMenu from "./FilterMenu";
10
9
  import {useDatagrid} from "./hooks";
11
10
 
12
11
  export default function DatagridTableFiltersComponent({orOperator,andOperator,testID}){
13
12
  testID = defaultStr(testID,"RN_DatagridTableFiltersComponent")
14
- const {visible,isLoading,visibleColumnsNames,filters,filteredColumns,context} = useDatagrid();
13
+ const {filters,filteredColumns,filterableColumnsNames} = useDatagrid();
14
+ const [visibleColumns,context,setVisibleColumns] = React.useState(filteredColumns);
15
15
  const valuesRefs = React.useRef({});
16
- const filteredRef = React.useRef({});
17
- const {content,colMenus} = React.useStableMemo(()=>{
16
+ React.useEffect(()=>{
17
+ if(typeof context?.on ==='function'){
18
+ const onToggleVisibility = ({columnField,visible})=>{
19
+ if(visibleColumns[columnField] !== visible){
20
+ setVisibleColumns({...visibleColumns,[columnField]:visible});
21
+ }
22
+ }
23
+ context.on("toggleFilterColumnVisibility",onToggleVisibility);
24
+ return ()=>{
25
+ context.off("toggleFilterColumnVisibility",onToggleVisibility);
26
+ }
27
+ }
28
+ },[context]);
29
+ const {content} = React.useStableMemo(()=>{
18
30
  const content = [];
19
31
  Object.map(filters,(filter,index)=>{
20
32
  if(isObj(filter)){
21
- const {onChange,filter:isFiltered,...rest} = filter;
33
+ const {filter:isFiltered,...rest} = filter;
22
34
  if(isFiltered === false) return null;
23
- const key = defaultStr(filter.key,filter.field,filter.columnField,filter.index,index+"");
35
+ const columnField = defaultStr(filter.field,filter.columnField,String(index));
36
+ if(!columnField || !visibleColumns[columnField]) return null;
24
37
  content.push(<Filter
25
38
  {...rest}
26
- {...(isObj(valuesRefs.current[key]) ? valuesRefs.current[key] : {})}
27
- dynamicRendered
39
+ //{...(isObj(valuesRefs.current[columnField]) ? valuesRefs.current[columnField] : {})}
40
+ columnField={columnField}
41
+ dynamicRendered={false}
28
42
  orOperator = {defaultBool(orOperator,filter.orOperator,true)}
29
43
  andOperator = {defaultBool(andOperator,filter.andOperator,true)}
30
- onChange = {(arg)=>{
31
- if(!arg.action && !arg.operator || !arg.field) return;
32
- const canHandle = canHandleFilter(arg);
33
- valuesRefs.current[key] = arg;
34
- if(filteredRef.current[key] !== canHandle){
35
- if(canHandle){
36
- canHandlerFilterRef.current++;
37
- } else {
38
- canHandlerFilterRef.current = Math.max(0,canHandlerFilterRef.current-1);
39
- }
40
- }
41
- filteredRef.current[key] = canHandle;
42
- if(onChange){
43
- onChange(arg);
44
- }
45
- }}
46
44
  />)
47
45
  }
48
46
  })
49
47
  return {content};
50
- },[filters])
48
+ },[visibleColumns])
51
49
  return <ScrollView horizontal testID={testID+"_FiltersScrollView"}>
52
50
  <View testID={testID} style = {[theme.styles.row,styles.container,theme.styles.rowWrap,theme.styles.justifyStart,theme.styles.alignItemsCenter]}>
53
51
  {<FiltersMenu/>}
@@ -7,36 +7,47 @@ import theme from "$theme";
7
7
  import Label from "$ecomponents/Label";
8
8
  import React from "$react";
9
9
  import { getMenuStyle } from "./styles";
10
+ import BottomSheetMenu from "$ecomponents/BottomSheet/Menu";
10
11
 
11
12
  export default function DatagridFiltersMenuComponent({testID,...props}){
12
- const {filteredColumns,filterableColumnsNames,...rest} = useDatagrid();
13
+ const {filteredColumns,columns,context,filterableColumnsNames} = useDatagrid();
14
+ const [visibleMenus,setVisibleMenus] = React.useState(filteredColumns);
13
15
  const isFiltered = !!Object.size(filteredColumns,true);
14
16
  testID = defaultStr(testID,"RN_DatagridFiltersMenuComponent")
15
- console.log(props," is props heeein");
16
17
  const items = React.useStableMemo(()=>{
17
18
  const items = [];
18
- console.log(rest," is ressss",filterableColumnsNames);
19
- Object.map(filterableColumnsNames,(field)=>{
20
-
19
+ if(!columns) return items;
20
+ Object.map(filterableColumnsNames,(field,i)=>{
21
+ const column = columns[field];
22
+ if(!isObj(column)) return;
23
+ const filterKey = defaultStr(column.field,column.name,i);
24
+ items.push({
25
+ ...column,
26
+ icon : !!visibleMenus[filterKey] ? "check":undefined,
27
+ items : undefined,
28
+ onPress : (e)=>{
29
+ const visible = !!visibleMenus[filterKey];
30
+ const nVisible = context?.toggleFilterColumnVisibility? context.toggleFilterColumnVisibility(filterKey,!!!visible) : visible;
31
+ if(nVisible !== visible){
32
+ setVisibleMenus({...visibleMenus,[filterKey]:nVisible});
33
+ }
34
+ }
35
+ })
21
36
  });
22
- return;
23
- colMenus.push(<FilterMenu
24
- key = {key}
25
- filterKey={key}
26
- {...filter}
27
- context={context}
28
- filteredColumns={filteredColumns}
29
- />)
30
- },[filterableColumnsNames]);
31
- return <Menu
37
+ return items;
38
+ },[filterableColumnsNames,visibleMenus]);
39
+ return <BottomSheetMenu
32
40
  testID={testID}
41
+ title = {"Filtres"}
33
42
  {...props}
43
+ items = {items}
34
44
  anchor={(p)=>{
35
45
  return <Pressable {...p} testID={testID+"_FilterPressableContainer"} style={[theme.styles.row,theme.styles.justifyContentStart,theme.styles.alignItemsCenter,getMenuStyle()]}>
36
46
  <Icon
37
47
  name={isFiltered?"filter-menu":"filter-plus"}
38
48
  primary = {isFiltered}
39
49
  size={20}
50
+ style={[theme.styles.noPadding,theme.styles.noMargin]}
40
51
  />
41
52
  <Label primary={isFiltered} textBold={isFiltered}>Filtres</Label>
42
53
  </Pressable>
@@ -4,5 +4,6 @@ export const useDatagrid = ()=>{
4
4
  const visible = context && typeof context?.canShowFilters =='function' && context.canShowFilters()|| false;
5
5
  const isLoading = context && context.isLoading() || false;
6
6
  const r = typeof context?.getPreparedColumns =='function'? context?.getPreparedColumns() : {};
7
- return {...r,visible,isLoading,context};
7
+ const columns = typeof context?.getColumns =='function' && context.getColumns() || {}
8
+ return {...r,visible,isLoading,context,columns};
8
9
  }
@@ -3,14 +3,20 @@ import theme from '$theme';
3
3
 
4
4
  const styles = StyleSheet.create({
5
5
  menuItem : {
6
- borderRadius : 10,
6
+ borderRadius : 7,
7
+ margin : 5,
8
+ paddingHorizontal : 10,
9
+ paddingVertical : 2,
10
+ },
11
+ hidden : {
12
+ display : "none",
13
+ opacity : 0,
14
+ },
15
+ filterLabel : {
16
+ fontSize:11,
7
17
  }
8
18
  });
9
19
 
10
- export const getMenuStyle = (style)=>([
11
- styles.menuItem,
12
- {backgroundColor:theme.surfaceBackground},
13
- style,
14
- ]);
20
+ export const getMenuStyle = (style)=>([styles.menuItem,{backgroundColor:theme.colors.surface},style]);
15
21
 
16
22
  export default styles;
@@ -222,7 +222,7 @@ export default class Filter extends AppComponent {
222
222
  }
223
223
  }
224
224
  }
225
- this.props.onChange({...this.getStateValues(),value,field:this.props.field,action,operator,selector,originAction,context:this});
225
+ this.props.onChange({...this.getStateValues(),value,field:this.props.field,columnField:this.props.field,action,operator,selector,originAction,context:this});
226
226
  }
227
227
  }
228
228
  componentDidUpdate (){
@@ -1,6 +1,6 @@
1
1
  import React from "$react";
2
2
  import Divider from "$ecomponents/Divider";
3
- import {isObj,isNonNullString,defaultStr,defaultObj} from "$utils";
3
+ import {isObj,isNonNullString,defaultStr,defaultObj} from "$cutils";
4
4
  import {flattenStyle,Colors} from "$theme";
5
5
  import FieldContent from "./FieldContent";
6
6
 
@@ -4,7 +4,7 @@
4
4
  @see : https://github.com/gorhom/react-native-portal
5
5
  */
6
6
  import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
7
- import {uniqid} from "$utils";
7
+ import {uniqid} from "$cutils";
8
8
  import { usePortal } from './hooks';
9
9
 
10
10
  const PortalComponent = ({
@@ -1,4 +1,4 @@
1
- import {isNonNullString,isObj,extendObj,defaultObj,defaultStr} from "$utils";
1
+ import {isNonNullString,isObj,extendObj} from "$cutils";
2
2
  import { useQuery as useRQuery, useMutation as RQUseMutation, useQueryClient } from "@tanstack/react-query";
3
3
  import { getFetcherOptions as apiGetFetcherOptions } from '$capi';
4
4
 
@@ -425,7 +425,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
425
425
  if(hasTabs){
426
426
  if(isMobOrTab){
427
427
  renderingTabsProps.firstTab = <Tab.Item testID={testID+"_MainTab"} label={"Principal"} {...firstTabProps} key={tabKey}>
428
- <View testID={testID+"_MainTab_Content"} {...contentProps} style={[styles.noMarging,contentProps.style,styles.h100,styles.noPadding]}>
428
+ <View testID={testID+"_MainTab_Content"} {...contentProps} style={[styles.noMargin,contentProps.style,styles.h100,styles.noPadding]}>
429
429
  {header}
430
430
  {content}
431
431
  </View>
@@ -435,7 +435,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
435
435
  }
436
436
  const ct = renderTabsContent(renderingTabsProps);
437
437
  if(isMobOrTab && ct){
438
- contentProps.style = [contentProps.style,styles.noMarging,styles.noPadding,styles.content]
438
+ contentProps.style = [contentProps.style,styles.noMargin,styles.noPadding,styles.content]
439
439
  mainContent = ct;
440
440
  } else {
441
441
  mainContent = <View {...contentProps} testID={testID+"_ContentContainer"} style={[styles.container,styles.noPadding,contentProps.style]}>
@@ -907,7 +907,7 @@ const styles = StyleSheet.create({
907
907
  paddingHorizontal : 0,
908
908
  paddingVertical : 0,
909
909
  },
910
- noMarging : {
910
+ noMargin : {
911
911
  margin : 0,
912
912
  marginVertical : 0,
913
913
  marginHorizontal : 0,
@@ -13,7 +13,7 @@ const PermText = React.forwardRef(({isUserMasterAdmin,disabled,assignPerm,testID
13
13
  testID = {testID}
14
14
  disabled = {disabled || isUserMasterAdmin}
15
15
  defaultValue = {checked || isUserMasterAdmin?1 : 0}
16
- style = {[theme.styles.noPadding,theme.styles.noMarging,labelStyle !== false && styles.checkbox]}
16
+ style = {[theme.styles.noPadding,theme.styles.noMargin,labelStyle !== false && styles.checkbox]}
17
17
  labelStyle = {[labelStyle !== false && styles.label,labelStyle && labelStyle]}
18
18
  label = {defaultVal(label,text)}
19
19
  onPress = {(args)=>{