UNPKG

3.51 kBJSXView Raw
1/**
2 * apeman react package for icon components.
3 * @class ApIcon
4 */
5
6'use strict'
7
8import React, {PropTypes as types} from 'react'
9import {shallowEqual} from 'asobj'
10import {isProduction} from 'asenv'
11import classnames from 'classnames'
12
13let assertCache = {}
14let notfoundCache = []
15
16const ASSERT_DELAY = 400
17
18/** @lends ApIcon */
19const ApIcon = React.createClass({
20
21 // --------------------
22 // Specs
23 // --------------------
24
25 propTypes: {},
26
27 mixins: [],
28
29 statics: {
30 /**
31 * Check if has style.
32 * @param className
33 */
34 hasStyleWithClass (className) {
35 let styleSheets = document.styleSheets || []
36 for (let i = 0; i < styleSheets.length; i++) {
37 let styleSheet = styleSheets[ i ]
38 let rules = styleSheet.rules || styleSheet.cssRules || []
39 for (let j = 0; j < rules.length; j++) {
40 let rule = rules[ j ]
41 let selectorText = rule.selectorText
42 let hit = selectorText && new RegExp(`\.${className}`).test(selectorText)
43 if (hit) {
44 return true
45 }
46 }
47 }
48 return false
49 },
50
51 warnNotFound () {
52 setTimeout(() => {
53 if (notfoundCache.length > 0) {
54 console.warn(
55 `[ApIcon] No style found for class ${notfoundCache.map((notFound) => `"${notFound}"`).join(', ')}.
56You seeing this warning either because of:
57 1. Misspelling the name or missing some stylesheets.
58 2. Using stylesheets from another domain.`
59 )
60 notfoundCache = []
61 }
62 }, 100)
63 },
64 ASSERT_DELAY
65 },
66
67 getInitialState () {
68 return {}
69 },
70
71 getDefaultProps () {
72 return {}
73 },
74
75 render () {
76 const s = this
77 let { props } = s
78
79 return (
80 <i className={ classnames('ap-icon', props.className) }
81 style={Object.assign({}, props.style)}
82 aria-hidden='true'
83 >
84 </i>
85 )
86 },
87
88 // --------------------
89 // Lifecycle
90 // --------------------
91
92 shouldComponentUpdate (nextProps, nextState) {
93 const s = this
94 let { props, state } = s
95 return !shallowEqual(props, nextProps) || shallowEqual(state, nextState)
96 },
97
98 componentDidMount () {
99 const s = this
100 s.mounted = true
101 let { props } = s
102 if (!isProduction()) {
103 s.assertClassName(props.className, { delay: 1200 })
104 }
105 },
106
107 componentWillReceiveProps (nextProps) {
108 const s = this
109 if (!isProduction()) {
110 if (nextProps.hasOwnProperty('className')) {
111 s.assertClassName(nextProps.className)
112 }
113 }
114 },
115
116 componentWillUnmount () {
117 const s = this
118 clearTimeout(s._assertTimer)
119 },
120
121 // ------------------
122 // Helper
123 // ------------------
124
125 assertClassName (className, options = {}) {
126 if (!className) {
127 return
128 }
129 const s = this
130 clearTimeout(s._assertTimer)
131 s._assertTimer = setTimeout(() => {
132 if (!s.mounted) {
133 return
134 }
135 className.split(/\s/g).forEach((className) => {
136 if (!className) {
137 return
138 }
139 if (assertCache.hasOwnProperty(className)) {
140 return
141 }
142 if (/^ap/.test(className)) {
143 return
144 }
145 let valid = ApIcon.hasStyleWithClass(className)
146 if (!valid) {
147 notfoundCache.push(className)
148 }
149 assertCache[ className ] = valid
150 })
151 ApIcon.warnNotFound()
152 }, options.delay || ASSERT_DELAY)
153 },
154
155 // ------------------
156 // Private
157 // ------------------
158
159 _assertTimer: -1
160})
161
162export default ApIcon