UNPKG

12 kBJavaScriptView Raw
1var canUseDOM = !!(
2 typeof window !== 'undefined' &&
3 window.document &&
4 window.document.createElement
5);
6var styleElement;
7if (
8 typeof module !== 'undefined' &&
9 module.hot &&
10 typeof module.hot.addDisposeHandler === 'function'
11) {
12 // gross
13 var hot = module.hot;
14 if (typeof hot.data === 'object') {
15 styleElement = hot.data.styleElement;
16 }
17 hot.addDisposeHandler(function(data) {
18 data.styleElement = styleElement;
19 });
20}
21if (canUseDOM && !styleElement) {
22 styleElement = document.createElement('style');
23 styleElement.type = 'text/css';
24 styleElement.appendChild(document.createTextNode('/* jsxstyle */'));
25 document.head.appendChild(styleElement);
26}
27function addStyleToHead(rule) {
28 if (styleElement) {
29 var sheet = styleElement.sheet;
30 try {
31 sheet.insertRule(rule, sheet.cssRules.length);
32 } catch (insertError) {
33 // insertRule will fail for rules with pseudoelements the browser doesn't support.
34 // see: https://github.com/smyte/jsxstyle/issues/75
35 if (process.env.NODE_ENV !== 'production') {
36 console.error(
37 '[jsxstyle] Could not insert rule at position ' +
38 sheet.cssRules.length +
39 ': `' +
40 rule +
41 '`'
42 );
43 }
44 }
45 }
46}
47
48var componentStyles = {
49 Block: { display: 'block' },
50 Box: null,
51 Col: { display: 'flex', flexDirection: 'column' },
52 Grid: { display: 'grid' },
53 Inline: { display: 'inline' },
54 InlineBlock: { display: 'inline-block' },
55 Row: { display: 'flex', flexDirection: 'row' },
56};
57
58/**
59 * Copyright 2013-present, Facebook, Inc.
60 * All rights reserved.
61 *
62 * This source code is licensed under the BSD-style license found in the
63 * LICENSE file in the root directory of this source tree. An additional grant
64 * of patent rights can be found in the PATENTS file in the same directory.
65 *
66 */
67var isUnitlessNumber = {
68 animationIterationCount: true,
69 borderImageOutset: true,
70 borderImageSlice: true,
71 borderImageWidth: true,
72 boxFlex: true,
73 boxFlexGroup: true,
74 boxOrdinalGroup: true,
75 columnCount: true,
76 columns: true,
77 flex: true,
78 flexGrow: true,
79 flexNegative: true,
80 flexOrder: true,
81 flexPositive: true,
82 flexShrink: true,
83 fontWeight: true,
84 gridColumn: true,
85 gridColumnEnd: true,
86 gridColumnSpan: true,
87 gridColumnStart: true,
88 gridRow: true,
89 gridRowEnd: true,
90 gridRowSpan: true,
91 gridRowStart: true,
92 lineClamp: true,
93 lineHeight: true,
94 opacity: true,
95 order: true,
96 orphans: true,
97 tabSize: true,
98 widows: true,
99 zIndex: true,
100 zoom: true,
101 // SVG-related properties
102 fillOpacity: true,
103 floodOpacity: true,
104 stopOpacity: true,
105 strokeDasharray: true,
106 strokeDashoffset: true,
107 strokeMiterlimit: true,
108 strokeOpacity: true,
109 strokeWidth: true,
110};
111function prefixKey(prefix, key) {
112 return prefix + key.charAt(0).toUpperCase() + key.substring(1);
113}
114var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
115Object.keys(isUnitlessNumber).forEach(function(prop) {
116 prefixes.forEach(function(prefix) {
117 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
118 });
119});
120function dangerousStyleValue(name, value) {
121 var isEmpty = value == null || typeof value === 'boolean' || value === '';
122 if (isEmpty) {
123 return '';
124 }
125 if (
126 typeof value === 'number' &&
127 value !== 0 &&
128 !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])
129 ) {
130 if (value > -1 && value < 1) {
131 return Math.round(value * 1e6) / 1e4 + '%';
132 }
133 return value + 'px';
134 }
135 return ('' + value).trim();
136}
137
138var uppercasePattern = /([A-Z])/g;
139var msPattern = /^ms-/;
140var hyphenateCache = {};
141function hyphenateStyleName(styleName) {
142 if (hyphenateCache.hasOwnProperty(styleName)) {
143 return hyphenateCache[styleName];
144 }
145 var hyphenatedString = styleName
146 .replace(uppercasePattern, '-$1')
147 .toLowerCase()
148 .replace(msPattern, '-ms-');
149 hyphenateCache[styleName] = hyphenatedString;
150 return hyphenateCache[styleName];
151}
152
153// global flag makes subsequent calls of capRegex.test advance to the next match
154var capRegex = /[A-Z]/g;
155var pseudoelements = {
156 after: true,
157 before: true,
158 placeholder: true,
159 selection: true,
160};
161var pseudoclasses = {
162 active: true,
163 checked: true,
164 disabled: true,
165 empty: true,
166 enabled: true,
167 focus: true,
168 hover: true,
169 invalid: true,
170 required: true,
171 target: true,
172 valid: true,
173};
174var specialCaseProps = {
175 children: true,
176 class: true,
177 className: true,
178 component: true,
179 mediaQueries: true,
180 props: true,
181 style: true,
182};
183function getStyleKeysForProps(props, pretty) {
184 if (pretty === void 0) {
185 pretty = false;
186 }
187 if (typeof props !== 'object' || props === null) {
188 return null;
189 }
190 var propKeys = Object.keys(props).sort();
191 var keyCount = propKeys.length;
192 if (keyCount === 0) {
193 return null;
194 }
195 var mediaQueries = props.mediaQueries;
196 var hasMediaQueries = typeof mediaQueries === 'object';
197 var usesMediaQueries = false;
198 var styleKeyObj = {};
199 var classNameKey = '';
200 var seenMQs = {};
201 var mqSortKeys = {};
202 if (hasMediaQueries) {
203 var idx = -1;
204 for (var k in mediaQueries) {
205 mqSortKeys[k] = '@' + (1000 + ++idx);
206 }
207 }
208 for (var idx = -1; ++idx < keyCount; ) {
209 var originalPropName = propKeys[idx];
210 if (
211 specialCaseProps.hasOwnProperty(originalPropName) ||
212 !props.hasOwnProperty(originalPropName)
213 ) {
214 continue;
215 }
216 var propName = originalPropName;
217 var propSansMQ = void 0;
218 var pseudoelement = void 0;
219 var pseudoclass = void 0;
220 var mqKey = void 0;
221 capRegex.lastIndex = 0;
222 var splitIndex = 0;
223 var prefix =
224 capRegex.test(originalPropName) &&
225 capRegex.lastIndex > 1 &&
226 originalPropName.slice(0, capRegex.lastIndex - 1);
227 // check for media query prefix
228 if (prefix && hasMediaQueries && mediaQueries.hasOwnProperty(prefix)) {
229 usesMediaQueries = true;
230 mqKey = prefix;
231 splitIndex = capRegex.lastIndex - 1;
232 propSansMQ =
233 originalPropName[splitIndex].toLowerCase() +
234 originalPropName.slice(splitIndex + 1);
235 prefix =
236 capRegex.test(originalPropName) &&
237 propSansMQ.slice(0, capRegex.lastIndex - splitIndex - 1);
238 }
239 // check for pseudoelement prefix
240 if (prefix && pseudoelements.hasOwnProperty(prefix)) {
241 pseudoelement = prefix;
242 splitIndex = capRegex.lastIndex - 1;
243 prefix =
244 capRegex.test(originalPropName) &&
245 originalPropName[splitIndex].toLowerCase() +
246 originalPropName.slice(splitIndex + 1, capRegex.lastIndex - 1);
247 }
248 // check for pseudoclass prefix
249 if (prefix && pseudoclasses.hasOwnProperty(prefix)) {
250 pseudoclass = prefix;
251 splitIndex = capRegex.lastIndex - 1;
252 }
253 // trim prefixes off propName
254 if (splitIndex > 0) {
255 propName =
256 originalPropName[splitIndex].toLowerCase() +
257 originalPropName.slice(splitIndex + 1);
258 }
259 var styleValue = dangerousStyleValue(propName, props[originalPropName]);
260 if (styleValue === '') {
261 continue;
262 }
263 var mediaQuery = mqKey && mediaQueries[mqKey];
264 var mqSortKey = mqKey && mqSortKeys[mqKey];
265 var key =
266 '.' +
267 (mqSortKey || '') +
268 (pseudoclass ? ':' + pseudoclass : '') +
269 (pseudoelement ? '::' + pseudoelement : '');
270 if (!styleKeyObj.hasOwnProperty(key)) {
271 styleKeyObj[key] = { styles: pretty ? '\n' : '' };
272 if (mediaQuery) {
273 styleKeyObj[key].mediaQuery = mediaQuery;
274 }
275 if (pseudoclass) {
276 styleKeyObj[key].pseudoclass = pseudoclass;
277 }
278 if (pseudoelement) {
279 styleKeyObj[key].pseudoelement = pseudoelement;
280 }
281 }
282 if (mediaQuery) {
283 seenMQs[mediaQuery] = seenMQs[mediaQuery] || '';
284 seenMQs[mediaQuery] += propSansMQ + ':' + styleValue + ';';
285 } else {
286 classNameKey += originalPropName + ':' + styleValue + ';';
287 }
288 styleKeyObj[key].styles +=
289 (pretty ? ' ' : '') +
290 hyphenateStyleName(propName) +
291 (pretty ? ': ' : ':') +
292 styleValue +
293 (pretty ? ';\n' : ';');
294 }
295 // append media query key
296 if (usesMediaQueries) {
297 var mqKeys = Object.keys(seenMQs).sort();
298 for (var idx = -1, len = mqKeys.length; ++idx < len; ) {
299 var mediaQuery = mqKeys[idx];
300 classNameKey += '@' + mediaQuery + '~' + seenMQs[mediaQuery];
301 }
302 }
303 if (classNameKey === '') {
304 return null;
305 }
306 styleKeyObj.classNameKey = classNameKey;
307 return styleKeyObj;
308}
309
310/* tslint:disable no-bitwise */
311// thx darksky: https://git.io/v9kWO
312function stringHash(str) {
313 var hash = 5381;
314 var i = str.length;
315 while (i) {
316 hash = (hash * 33) ^ str.charCodeAt(--i);
317 }
318 /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
319 * integers. Since we want the results to be always positive, convert the
320 * signed int to an unsigned by doing an unsigned bitshift. */
321 return hash >>> 0;
322}
323
324function cannotInject() {
325 throw new Error(
326 'jsxstyle error: `injectOptions` must be called before any jsxstyle components mount.'
327 );
328}
329function alreadyInjected() {
330 throw new Error(
331 'jsxstyle error: `injectOptions` should be called once and only once.'
332 );
333}
334function getStringHash(key, props) {
335 return '_' + stringHash(key).toString(36);
336}
337function getStyleCache() {
338 var _classNameCache = {};
339 var getClassNameForKey = getStringHash;
340 var onInsertRule;
341 var pretty = false;
342 var styleCache = {
343 reset: function() {
344 _classNameCache = {};
345 },
346 injectOptions: function(options) {
347 if (options) {
348 if (options.getClassName) {
349 getClassNameForKey = options.getClassName;
350 }
351 if (options.onInsertRule) {
352 onInsertRule = options.onInsertRule;
353 }
354 if (options.pretty) {
355 pretty = options.pretty;
356 }
357 }
358 styleCache.injectOptions = alreadyInjected;
359 },
360 getClassName: function(props, classNameProp) {
361 styleCache.injectOptions = cannotInject;
362 var styleObj = getStyleKeysForProps(props, pretty);
363 if (typeof styleObj !== 'object' || styleObj === null) {
364 return classNameProp || null;
365 }
366 var key = styleObj.classNameKey;
367 if (key && !_classNameCache.hasOwnProperty(key)) {
368 _classNameCache[key] = getClassNameForKey(key, props);
369 delete styleObj.classNameKey;
370 Object.keys(styleObj)
371 .sort()
372 .forEach(function(k) {
373 var selector = '.' + _classNameCache[key];
374 // prettier-ignore
375 var _a = styleObj[k], pseudoclass = _a.pseudoclass, pseudoelement = _a.pseudoelement, mediaQuery = _a.mediaQuery, styles = _a.styles;
376 var rule =
377 selector +
378 (pseudoclass ? ':' + pseudoclass : '') +
379 (pseudoelement ? '::' + pseudoelement : '') +
380 (' {' + styles + '}');
381 if (mediaQuery) {
382 rule = '@media ' + mediaQuery + ' { ' + rule + ' }';
383 }
384 if (
385 onInsertRule &&
386 // if the function returns false, bail.
387 onInsertRule(rule, props) === false
388 ) {
389 return;
390 }
391 addStyleToHead(rule);
392 });
393 }
394 return _classNameCache[key] && classNameProp
395 ? classNameProp + ' ' + _classNameCache[key]
396 : _classNameCache[key] || classNameProp || null;
397 },
398 };
399 return styleCache;
400}
401
402export {
403 addStyleToHead,
404 componentStyles,
405 dangerousStyleValue,
406 getStyleCache,
407 getStyleKeysForProps,
408 pseudoelements,
409 pseudoclasses,
410 hyphenateStyleName,
411 stringHash,
412};