1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict'
|
7 |
|
8 | import React, {PropTypes as types} from 'react'
|
9 | import {shallowEqual} from 'asobj'
|
10 | import {isProduction} from 'asenv'
|
11 | import classnames from 'classnames'
|
12 |
|
13 | let assertCache = {}
|
14 | let notfoundCache = []
|
15 |
|
16 | const ASSERT_DELAY = 400
|
17 |
|
18 |
|
19 | const ApIcon = React.createClass({
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | propTypes: {},
|
26 |
|
27 | mixins: [],
|
28 |
|
29 | statics: {
|
30 | |
31 |
|
32 |
|
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(', ')}.
|
56 | You 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 |
|
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 |
|
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 |
|
157 |
|
158 |
|
159 | _assertTimer: -1
|
160 | })
|
161 |
|
162 | export default ApIcon
|