@fto-consult/expo-ui 2.16.3 → 2.16.6

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.
@@ -1,19 +1,20 @@
1
- import { Component } from "react";
2
1
  import {isNativeMobile} from "$cplatform";
3
2
  import View from "$ecomponents/View";
4
3
  import React from "$react";
5
4
  import theme,{remToPixel,Colors,flattenStyle} from '$theme';
6
5
  import {StyleSheet} from "react-native";
7
- import {defaultStr} from "$utils";
6
+ import {defaultStr,defaultObj,defaultNumber} from "$utils";
8
7
  import LogoComponent from "$logoComponent";
9
8
 
10
9
  export const height = 150;
11
10
  export const width = undefined;//300;
12
- export default class Logo extends Component {
13
- render(props){
14
- let {icon,color,style,testID,logo,text} = this.props;
11
+ export default function Logo (props) {
12
+ let {icon,color,style,testID,containerProps,smallStyle,largeStyle,mediumStyle,height:customHeight,withImage,withText} = props;
15
13
  testID = defaultStr(testID,"RN_LogoComponent");
16
- const styles = getStyle(style,color);
14
+ containerProps = defaultObj(containerProps);
15
+ customHeight =defaultNumber(customHeight,height);
16
+ const hasHeight = customHeight && customHeight != height? true : false;
17
+ const styles = getStyle({style,color,height:hasHeight?customHeight:undefined,smallStyle,largeStyle,mediumStyle});
17
18
  let logoImage = null,img,txt=null,hasTwice = false;
18
19
  if(LogoComponent){
19
20
  hasTwice = React.isComponent(LogoComponent.Image) && React.isComponent(LogoComponent.Text);
@@ -23,26 +24,30 @@ export default class Logo extends Component {
23
24
  img = icon !== false ? <View testID={testID+"_ContentContainer"} style={styles.logoImage}>
24
25
  <LogoComponent.Image styles={styles}/>
25
26
  </View> : null;
26
- txt = text !== false ? <LogoComponent.Text style={styles.logoContent} styles={styles}/> : null;
27
+ txt = withText !== false && React.isComponent(LogoComponent.Text) ? <LogoComponent.Text style={styles.logoContent} styles={styles}/> : null;
27
28
  }
28
29
  }
29
- return <View testID={testID} style={styles.container}>
30
- {hasTwice ? img : null}
30
+ return <View testID={testID} style={[styles.container,hasHeight && {height:customHeight}]}>
31
+ {hasTwice && withImage !== false ? img : null}
31
32
  {hasTwice? txt : null}
32
33
  {!hasTwice ? logoImage : null}
33
34
  </View>
34
- }
35
-
36
- }
35
+ }
37
36
 
38
- const getStyle = (style,color)=>{
39
- const cColor = flattenStyle([{color:Colors.isValid(color)? color : theme.colors.primary}]);
37
+ const getStyle = ({style,color,height:customHeight,smallStyle,mediumStyle,largeStyle})=>{
38
+ const cColor = flattenStyle([{color:Colors.isValid(color)? color : theme.colors.primaryOnSurface}]);
39
+ let size = 5;
40
+ if(typeof customHeight =='number' && customHeight <= customHeight){
41
+ const divider = Math.min(size,Math.max(Math.ceil(height/customHeight),2));
42
+ size = divider <= 2 ? 2 : divider;
43
+ }
44
+ let smallSize = size/2, medium = (3/4)*size;
40
45
  return {
41
46
  ...styles,
42
- container : flattenStyle([styles.container,cColor,style]),
43
- firstText : flattenStyle([styles.medium,cColor]),
44
- large : flattenStyle([styles.medium,styles.large,cColor]),
45
- small : flattenStyle([styles.medium,cColor,styles.small]),
47
+ container : flattenStyle([styles.container,style]),
48
+ large : flattenStyle([styles.large,styles.large,{color:theme.colors.secondaryOnSurface,fontSize:remToPixel(size)},largeStyle]),
49
+ medium : flattenStyle([styles.medium,cColor,{fontSize:remToPixel(medium)},mediumStyle]),
50
+ small : flattenStyle([styles.small,cColor,styles.small,{fontSize:remToPixel(smallSize)},smallStyle]),
46
51
  };
47
52
  }
48
53
 
@@ -74,7 +79,7 @@ const styles = StyleSheet.create({
74
79
  },
75
80
  small : {
76
81
  fontSize:remToPixel(2.5),
77
- marginLeft:isNativeMobile()? -25 : -20
82
+ marginLeft:isNativeMobile()? -15 : -10
78
83
  },
79
84
  medium : {
80
85
  fontSize:remToPixel(3),
@@ -88,4 +93,5 @@ const styles = StyleSheet.create({
88
93
  })
89
94
 
90
95
  Logo.height = height;
91
- Logo.width = width;
96
+ Logo.width = width;
97
+ Logo.displayName = "ExpoLogoComponent";
@@ -59,7 +59,7 @@ export default function DatabaseStatisticContainer (props){
59
59
  left = {(aProps)=>{
60
60
  return <Avatar suffix={index} {...aProps} icon= {icon} size={40} label={title}/>
61
61
  }}
62
- title = {<Label splitText numberOfLines={1} primary style={[{fontSize:15}]}>{title}</Label>}
62
+ title = {<Label splitText numberOfLines={1} color={theme.colors.primaryOnSurface} style={[{fontSize:15}]}>{title}</Label>}
63
63
  titleProps = {{primary : true}}
64
64
  description = {isLoading?<View style={[theme.styles.justifyContentFlexStart,theme.styles.alignItemsFlexStart]}>
65
65
  <ActivityIndicator color={theme.colors.primary}/>
@@ -0,0 +1,200 @@
1
+ import {defaultObj} from "$utils";
2
+ import i18n from "$i18n"
3
+ import Auth from "$cauth";
4
+ import Menu from "$ecomponents/Menu";
5
+ import React from "$react";
6
+ import { screenName } from "$escreens/Auth/utils";
7
+ import Image from "$ecomponents/Image";
8
+ import { StyleSheet,View,Pressable} from "react-native";
9
+ import avatarProps from "$eauth/avatarProps";
10
+ import Button from "$ecomponents/Button";
11
+ import Label from "$ecomponents/Label";
12
+ import Icon from "$ecomponents/Icon";
13
+ import {navigate} from "$cnavigation";
14
+ import theme from "$theme";
15
+ import {isMobileNative} from "$cplatform";
16
+ import appConfig from "$capp/config";
17
+ import Preloader from "$preloader";
18
+ import {defaultNumber} from "$utils";
19
+ import Tooltip from "$ecomponents/Tooltip";
20
+ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps:customChevronIconProps,size,withLabel,...props},ref)=>{
21
+ let u = defaultObj(Auth.getLoggedUser());
22
+ const deviceNameRef = React.useRef(null);
23
+ const deviceName = appConfig.deviceName;
24
+ customChevronIconProps = defaultObj(customChevronIconProps);
25
+ props = defaultObj(props);
26
+ const closeDrawer = cb => {
27
+ if(drawerRef && drawerRef.current && drawerRef.current.close){
28
+ return drawerRef && drawerRef.current && drawerRef.current.close(cb);
29
+ }
30
+ return typeof cb =='function'? cb() : null;
31
+ }
32
+ if(withLabel === undefined){
33
+ withLabel = theme.showProfilAvatarOnDrawer;
34
+ }
35
+ withLabel = withLabel !== false ? true : false;
36
+ props.src = u.avatar;
37
+ size = defaultNumber(size,!withLabel?40:40);
38
+ const userPseudo = Auth.getUserPseudo();
39
+ const pseudo = defaultStr(userPseudo,Auth.getUserEmail(),Auth.getUserCode());
40
+ const label = defaultStr(Auth.getUserFullName(),userPseudo);
41
+ const onLongPress = ()=>{
42
+ appConfig.setDeviceId().then((r)=>{
43
+ if(deviceNameRef.current && deviceNameRef.current.update){
44
+ deviceNameRef.current.update(r?("["+r+"]"):"");
45
+ }
46
+ });
47
+ };
48
+ const tooltip = "Pressez longtemps pour définir un identifiant unique pour l'appareil";
49
+ const children = <View style={[styles.labelContainer,!withLabel && theme.styles.justifyContentCenter]}>
50
+ <Label splitText numberOfLines={1} style={{color:theme.colors.primaryOnSurface,fontSize:15}}>{pseudo}</Label>
51
+ <Label splitText numberOfLines={1} style={{fontSize:12,color:theme.colors.secondaryOnSurface,marginTop:6}}>
52
+ {label}
53
+ </Label>
54
+ {deviceName && <Label.withRef textBold splitText title={"Identifiant unique de l'application, installé sur cet appareil"} ref={deviceNameRef} secondary style={{fontSize:10}}>
55
+ [{deviceName}]
56
+ </Label.withRef> || null}
57
+ </View>
58
+ const menItems = [
59
+ !withLabel && {
60
+ text : <Tooltip tooltip={tooltip} Component={Pressable} onLongPress={onLongPress} testID={"RNProfilAvatar_ContainerMenu"}>
61
+ {children}
62
+ </Tooltip>,
63
+ closeOnPress : false,
64
+ divider : true,
65
+ },
66
+ {
67
+ label : i18n.lang("preferences",'Préférences'),
68
+ icon : "account-cog",
69
+ onPress : (a)=>{
70
+ closeDrawer(()=>{
71
+ return navigate({
72
+ routeName : screenName,
73
+ params : {
74
+ user : u,
75
+ }
76
+ })
77
+ });
78
+ }
79
+ },
80
+ {
81
+ label : i18n.lang("logout",'Déconnexion'),
82
+ icon : "logout",
83
+ onPress : (a)=>{
84
+ closeDrawer(()=>{
85
+ Preloader.open("Déconnexion en cours...");
86
+ Auth.signOut().finally(Preloader.close)
87
+ });
88
+ }
89
+ }
90
+ ];
91
+
92
+ const onChangeAvatar = ({dataURL})=>{
93
+ if(u.avatar === dataURL) {
94
+ return;
95
+ }
96
+ if(!dataURL){
97
+ u.avatar = null;
98
+ } else {
99
+ u.avatar = dataURL;
100
+ }
101
+ Auth.upsertUser({...u,avatar:u.avatar},false);
102
+ }
103
+
104
+ return <View ref ={ref}>
105
+ <Menu
106
+ anchor = { (aProps)=>{
107
+ const chevronIconProps = {
108
+ size : 20,
109
+ icon : "chevron-down",
110
+ secondary : true,
111
+ ...customChevronIconProps,
112
+ ...aProps,
113
+ style : [styles.icon,withLabel=== false && {color:theme.colors.primaryText},customChevronIconProps.style],
114
+ }
115
+ if(!withLabel){
116
+ return <View testID={"RNProfilAvatar_AvatarContainer"} style={[theme.styles.row,theme.styles.alignItemsCenter]}>
117
+ <Image
118
+ {...props}
119
+ {...aProps}
120
+ size={size}
121
+ style = {styles.itemLeft}
122
+ testID = {"RN_ProfilAvatar_Avatar"}
123
+ editable
124
+ defaultSource ={avatarProps.defaultSrc}
125
+ onChange = {onChangeAvatar}
126
+ />
127
+ <Icon
128
+ {...chevronIconProps}
129
+ {...aProps}
130
+ style = {[chevronIconProps.style,{marginLeft:-5}]}
131
+ />
132
+ </View>
133
+ }
134
+ return <Button
135
+ normal
136
+ upperCase = {false}
137
+ disableRipple
138
+ title = {tooltip}
139
+ {...aProps}
140
+ style = {[styles.container]}
141
+ surfaceProps = {{style:[theme.styles.noMargin,theme.styles.noPadding]}}
142
+ onLongPress = {onLongPress}
143
+ left={props1 => <Image
144
+ {...props}
145
+ {...props1}
146
+ size={size}
147
+ style = {styles.itemLeft}
148
+ testID = {"RN_ProfilAvatar_AvatarImage"}
149
+ editable
150
+ defaultSource ={avatarProps.defaultSrc}
151
+ onChange = {onChangeAvatar}
152
+ />}
153
+ right = {(p)=>{
154
+ return <Icon
155
+ {...p}
156
+ {...chevronIconProps}
157
+ />
158
+ }}
159
+ >
160
+ {children}
161
+ </Button>
162
+ } }
163
+ items={menItems}
164
+ />
165
+ </View>
166
+ });
167
+
168
+ const styles = StyleSheet.create({
169
+ itemLeft : {
170
+ marginHorizontal : 5,
171
+ marginTop : isMobileNative()? 10 : 0,
172
+ },
173
+ container : {
174
+ marginLeft : 0,
175
+ marginVertical : 10,
176
+ },
177
+ labelContainer : {
178
+ flexDirection : 'column',
179
+ paddingRight : 5,
180
+ maxWidth : 150,
181
+ minWidth : 100,
182
+ },
183
+ pseudo : {
184
+ flexDirection : "row",
185
+ justifyContent : "center",
186
+ alignItems : "center"
187
+ },
188
+ appName : {
189
+ marginLeft : 5,
190
+ fontWeight : "bold",
191
+ },
192
+ icon : {
193
+ marginHorizontal:0,
194
+ paddingHorizontal : 0,
195
+ }
196
+ })
197
+
198
+ export default UserProfileAvatarComponent;
199
+
200
+ UserProfileAvatarComponent.displayName = "UserProfileAvatarComponent";
@@ -4,10 +4,14 @@
4
4
 
5
5
  import Container from "$cauth/Container";
6
6
  import ScreenWithOrWithoutAuthContainer from "./ScreenWithOrWithoutAuthContainer";
7
+ import ProfilAvatar from "$elayouts/ProfilAvatar";
7
8
 
8
9
  export default function MainScreenComponent(props){
9
10
  return <ScreenWithOrWithoutAuthContainer
10
11
  {...props}
12
+ renderProfilAvatar = {(props)=>{
13
+ return <ProfilAvatar withLabel = {false} {...props} />
14
+ }}
11
15
  renderChildren = {({containerProps,children})=>{
12
16
  return <Container {...containerProps}>
13
17
  {children}
@@ -51,12 +51,18 @@ export default function MainScreenScreenWithOrWithoutAuthContainer(props) {
51
51
  screenName,
52
52
  containerProps,
53
53
  testID,
54
+ profilAvatarProps,
55
+ profilAvatarContainerProps,
56
+ withProfilAvatarOnAppBar:cWithPorilAvatarOnAppbar,
54
57
  renderChildren,
58
+ renderProfilAvatar,
55
59
  ...rest
56
60
  } = getScreenProps(props);
57
61
  const insets = useSafeAreaInsets();
58
62
  testID = defaultStr(testID,"RN_MainScreenScreenWithOrWithoutAuthContainer")
59
63
  containerProps = defaultObj(containerProps);
64
+ profilAvatarContainerProps = defaultObj(profilAvatarContainerProps);
65
+ profilAvatarProps = defaultObj(profilAvatarProps);
60
66
  const backgroundColor = theme.colors.background;
61
67
  const containerStyle = [
62
68
  styles.container,
@@ -83,6 +89,7 @@ export default function MainScreenScreenWithOrWithoutAuthContainer(props) {
83
89
  if(authRequired === false){
84
90
  withFab = false;
85
91
  }
92
+ const withProfilAvatarOnAppBar = cWithPorilAvatarOnAppbar !== false && withDrawer && !theme.showProfilAvatarOnDrawer ? true : false;
86
93
  React.useEffect(() => {
87
94
  if((title||subtitle) && navigation && navigation.setOptions){
88
95
  const appName = APP.getName().toUpperCase();
@@ -107,11 +114,22 @@ export default function MainScreenScreenWithOrWithoutAuthContainer(props) {
107
114
  {...fabProps}
108
115
  screenName={screenName}
109
116
  /> : null;
117
+ const profilAvatar = typeof renderProfilAvatar =='function'? renderProfilAvatar(profilAvatarProps) : null;
110
118
  const child = <>
111
119
  {withStatusBar !== false ? <StatusBar/> : null}
112
120
  <ErrorBoundary testID={testID+"_ScreenLayoutErrorBoundary"}>
113
121
  <View testID={testID} {...containerProps} style={[styles.container,{backgroundColor},modal && styles.modal]}>
114
- {appBar === false ? null : React.isValidElement(appBar)? state.AppBar : <AppBar testID={testID+'_AppBar'} {...appBarProps} backAction = {defaultVal(appBarProps.backAction,backAction)} elevation={defaultNumber(appBarProps.elevation,elevation)} withDrawer={withDrawer} options={options} ref={appBarRef} title={title} subtitle={subtitle}/>}
122
+ {appBar === false ? null : React.isValidElement(appBar)? state.AppBar : <AppBar
123
+ testID={testID+'_AppBar'} {...appBarProps}
124
+ backAction = {defaultVal(appBarProps.backAction,backAction)}
125
+ elevation={defaultNumber(appBarProps.elevation,elevation)}
126
+ withDrawer={withDrawer} options={options}
127
+ ref={appBarRef} title={title}
128
+ subtitle={subtitle}
129
+ right = {withProfilAvatarOnAppBar && <View testID={testID+"_ProfilAvatar_Container"} {...profilAvatarContainerProps} style={[profilAvatarContainerProps.style,styles.profilAvatarContainer]} >
130
+ {React.isValidElement(profilAvatar) && profilAvatar || null}
131
+ </View> || null}
132
+ />}
115
133
  {withScrollView !== false ? (
116
134
  <ScrollView
117
135
  testID = {testID+'_ScreenContentScrollView'}
@@ -1,17 +1,23 @@
1
1
  import Drawer,{DrawerItems} from "$ecomponents/Drawer";
2
- import ProfilAvatar from "./ProfilAvatar";
2
+ import ProfilAvatar from "$elayouts/ProfilAvatar";
3
3
  import React from "$react";
4
4
  import items,{isItemActive,refresh as refreshItems} from "./items";
5
5
  import APP from "$capp/instance";
6
6
  import Auth from "$cauth";
7
7
  import Login from "$eauth/Login";
8
8
  import {navigate} from "$cnavigation";
9
+ import theme from "$theme";
10
+ import Logo from "$ecomponents/Logo";
9
11
 
10
12
  const DrawerNavigator = React.forwardRef(({content,children,state,...props},ref)=>{
11
13
  const drawerRef = React.useRef(null);
12
14
  const mergedRefs = React.useMergeRefs(drawerRef,ref);
13
15
  const headerCB = ({isMinimized})=>{
14
- return isMinimized ? null : <ProfilAvatar ref={uProfileRef} drawerRef={drawerRef}/>;
16
+ if(isMinimized) return null;
17
+ if(!theme.showProfilAvatarOnDrawer){
18
+ return <Logo height = {70} withImage = {false} style={[theme.styles.justifyContentFlexStart,{maxWidth:220,overflow:'hidden'}]}/>
19
+ }
20
+ return <ProfilAvatar ref={uProfileRef} drawerRef={drawerRef}/>;
15
21
  };
16
22
  const isAuthLoggedIn = Auth.isLoggedIn();
17
23
  const [isLoggedIn,setIsLoggedIn] = React.useState(isAuthLoggedIn);
@@ -9,9 +9,10 @@ import APP from "$capp";
9
9
  ///les items du drawer
10
10
  import items from "$drawerItems";
11
11
  import { screenName as aboutScreenName} from "$escreens/Help/About";
12
+ import theme from "$theme";
12
13
 
13
14
  export const getItems = (force)=>{
14
- const name = APP.getName();
15
+ const name = !theme.showProfilAvatarOnDrawer ? 'Dashboard' : APP.getName();
15
16
  const itx = typeof items === "function" ? items() : items;
16
17
  const handleHelp = appConfig.get("handleHelpScreen") !== false ? true : false;
17
18
  const r = [
@@ -38,7 +39,7 @@ export const getItems = (force)=>{
38
39
  items : [
39
40
  {
40
41
  icon : 'help',
41
- label : 'A propos de '+name,
42
+ label : 'A propos de '+APP.getName(),
42
43
  routeName : aboutScreenName,
43
44
  }
44
45
  ]
@@ -8,7 +8,7 @@ import {SignIn2SignOut} from "$cauth";
8
8
  import React from "$react";
9
9
  import avatarProps from "$eauth/avatarProps";
10
10
 
11
- export const screenName = "UserProfile";
11
+ import {screenName} from "./utils";
12
12
 
13
13
  export default function UserProfileScreen(prs){
14
14
  const props = getScreenProps(prs);
@@ -2,4 +2,6 @@ import APP from "$capp/instance";
2
2
  import i18n from "$i18n";
3
3
 
4
4
  export const getTitle = x => APP.name+" "+APP.version+"/"+i18n.lang("login");
5
- export const title = getTitle();
5
+ export const title = getTitle();
6
+
7
+ export const screenName = "UserProfile";
@@ -1,141 +0,0 @@
1
- // Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
2
- // Use of this source code is governed by a BSD-style
3
- // license that can be found in the LICENSE file.
4
-
5
- import { lightColors,darkColors,primary as defaultPrimary,secondary as defaultSecondary} from "$theme/defaultTheme";
6
- import {modesObject} from "$ecomponents/TextField/utils";
7
-
8
- export const fields = {
9
- name : {
10
- type : 'text',
11
- maxLength : 30,
12
- text : 'Nom du thème',
13
- required : true,
14
- upper : true,
15
- },
16
- dark : {
17
- type : 'switch',
18
- checkedValue : true,
19
- uncheckedValue : false,
20
- label : 'Mode Sombre',
21
- checkedTooltip : 'Mode sombre actif',
22
- uncheckedTooltip : 'Mode sombre inactif',
23
- onChange : ({value,checked,context})=>{
24
- if(checked === undefined) return;
25
- if(context && context.getField){
26
- const darkFields = checked ? darkColors : lightColors;
27
- Object.map(darkFields,(dF,i)=>{
28
- const dFContext = context.getField(i);
29
- if(dFContext && dFContext.setValue){
30
- dFContext.validate({value:dF});
31
- }
32
- })
33
- }
34
- }
35
- },
36
- textFieldMode : {
37
- type : 'select',
38
- items : {...modesObject,none:{code:'',label:'Dynamique'}},
39
- text : 'Mode d\'affichage des champs de texte'
40
- },
41
- primary : {
42
- type : 'color',
43
- text : 'Couleur principale [primary]',
44
- required : true,
45
- onChange : ({value,context})=>{
46
- if(context && context.getField){
47
- const pOnSurface = context.getField("primaryOnSurface");
48
- if(pOnSurface){
49
- pOnSurface.setValue(value);
50
- }
51
- }
52
- }
53
- },
54
- primaryText : {
55
- type :'color',
56
- text :'Texte sur couleur principale [primaryText]',
57
- required : true,
58
- },
59
- secondary : {
60
- type : 'color',
61
- text : ' Couleur secondaire [secondary]',
62
- required : true,
63
- onChange : ({value,context})=>{
64
- if(context && context.getField){
65
- const sOnSurface = context.getField("secondaryOnSurface");
66
- if(sOnSurface){
67
- sOnSurface.setValue(value);
68
- }
69
- }
70
- }
71
- },
72
- secondaryText : {
73
- type :'color',
74
- text :'Texte sur couleur secondaire [secondaryText]',
75
- required : true,
76
- },
77
- text : {
78
- type :'color',
79
- text : 'Couleur de texte [text]',
80
- required : true,
81
- },
82
- disabled : {
83
- type :'color',
84
- text :'Texte Inactif [disabeld]'
85
- },
86
- divider : {
87
- type : 'color',
88
- text : 'Couleur|Soulignement [divider]'
89
- },
90
- background : {
91
- type : 'color',
92
- text : 'Couleur d\'arrière plan [background]',
93
- },
94
- surface : {
95
- type :'color',
96
- text :'Couleur de surface [surface]',
97
- },
98
- surfaceText : {
99
- type :'color',
100
- text :'Texte sur surface [surfaceText]',
101
- },
102
- primaryOnSurface : {
103
- type :'color',
104
- text :'Couleur principale sur surface [primaryOnSurface]',
105
- },
106
- secondaryOnSurface : {
107
- type :'color',
108
- text :'Couleur secondaire sur surface [secondaryOnSurface]',
109
- },
110
- info : {
111
- type :'color',
112
- text :'Notification|info [info]'
113
- },
114
- success : {
115
- type :'color',
116
- text :'Notification|Succès [success]'
117
- },
118
- warning : {
119
- type :'color',
120
- text :'Notification|Alerte [warning]'
121
- },
122
- error : {
123
- type :'color',
124
- text :'Notification|Erreur [error]'
125
- },
126
- };
127
- export const getThemeData = (value)=>{
128
- const theme = {name:value.name,colors:{}};
129
- const validValue = {};
130
- Object.map(fields,(f,i)=>{
131
- if(!f) return;
132
- if(f.type =='color'){
133
- const fText = i+"Color";
134
- theme.colors[i] = value[i] || value[fText];
135
- } else {
136
- theme[i] = value[i];
137
- }
138
- validValue[i] = value[i];
139
- });
140
- return {theme,value:validValue};
141
- }