UNPKG

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