-
Notifications
You must be signed in to change notification settings - Fork 6
/
index.js
147 lines (113 loc) · 3.68 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'use strict';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Image, Platform, Dimensions, StyleSheet, TouchableOpacity } from 'react-native';
const IMG_CENTER_MODE = Platform.OS === 'ios' ? 'center' : 'contain';
export class Ikon extends Component {
constructor(props) {
super(props);
this.iconSet = __iconSet;
this.state = {
style: null,
resizeMode: null,
width: null,
height: null,
source: null,
}
}
componentWillReceiveProps(nextProps) {
this.updateProps(nextProps);
}
componentDidMount() {
this.updateProps(this.props);
}
updateProps(props) {
const {disabled, name, style} = props;
this.iconSet = __iconSet;
if(!this.iconSet) {
throw new Error( "[react-native-ikon] Have you forgotten to register your IconSet?" );
}
const resizeMode = props.resizeMode ? props.resizeMode : this.traverseIconSet(name, 'resizeMode');
const autoScale = props.autoScale ? props.autoScale : this.traverseIconSet(name, 'autoScale');
const doScale = (value) => {
return autoScale ? Ikon.__normalize(value) : value;
}
const width = doScale( props.width ? props.width : this.traverseIconSet(name, 'width') );
const height = doScale( props.height ? props.height : this.traverseIconSet(name, 'height') );
const source = props.source ? props.source : this.traverseIconSet(name, 'source');
let _style = style ? StyleSheet.flatten(style) : {};
_style = {..._style, width, height};
const transform = this.traverseIconSet(name, 'transform');
if(transform) {
_style = {..._style, transform};
}
if(!!disabled) {
let disabledStyle = this.traverseIconSet(name, '$disabled')
if(!disabledStyle) {
disabledStyle = {opacity: 0.5};
}
_style = [..._style, disabledStyle];
}
this.setState({
style: _style,
resizeMode: resizeMode ? resizeMode : IMG_CENTER_MODE,
width,
height,
source
})
}
// register an IconSet
static registerIconSet(iconSet) {
__iconSet = iconSet;
}
render() {
let {onPress, disabled} = this.props;
const icon = (
<Image resizeMode={this.state.resizeMode} width={this.state.width} height={this.state.height}
source={this.state.source} style={this.state.style}>
</Image>
)
if(typeof disabled === 'undefined') disabled = false;
if(onPress) {
return (
<TouchableOpacity onPress={onPress} disabled={disabled}>{icon}</TouchableOpacity>
)
}
return icon;
}
// try to find a value while traversing up the iconSet structure
traverseIconSet(name, property) {
let obj = Ikon.__resolvePropertyByKey(this.iconSet, name);
while(obj) {
if(obj[property]) {
return obj[property];
}
const p = name.lastIndexOf('.');
if(!p) return null;
name = name.substr(0, p);
obj = Ikon.__resolvePropertyByKey(this.iconSet, name);
}
return null;
}
// traverse down a nested object to resolve the 'path'
static __resolvePropertyByKey(obj, path) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : undefined
}, obj)
}
static __normalize(value : number) {
return Math.round(__scale * value);
}
}
const __scale = Dimensions ? Dimensions.get('window').width / 375 : 1;
// global iconSet
// assign your personal IconSet with Ikon.registerIconSet()
let __iconSet = null;
Ikon.propTypes = {
name: PropTypes.string.isRequired,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
resizeMode: PropTypes.string,
autoScale: PropTypes.bool,
}
Ikon.defaultProps = {
}