@glitz/core
Advanced tools
Comparing version 1.1.0-beta.10 to 1.1.0-beta.11
@@ -214,50 +214,38 @@ 'use strict'; | ||
var FONT_FAMILY = 'fontFamily'; | ||
var NON_ATOMIC_KEY = '$'; | ||
var Base = /** @class */ (function () { | ||
function Base(injector, transformer, atomic) { | ||
var walk = function (style, rules, media, pseudo) { | ||
for (var property in style) { | ||
var resolve = function (style, result, media, pseudo) { | ||
if (result === void 0) { result = {}; } | ||
var properties = Object.keys(style); | ||
for (var i = properties.length - 1; i >= 0; i--) { | ||
var property = properties[i]; | ||
var value = style[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
var declarations = getIndex(rules, media, pseudo); | ||
if (isPrimitive(value)) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (typeof value === 'object') { | ||
{ | ||
var isEmpty = true; | ||
for (var x in value) { | ||
isEmpty = false; | ||
break; | ||
} | ||
if (isEmpty) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
{ | ||
if (typeof value !== 'object') { | ||
console.error('The style property `%s` was has to be a string, number or object, was %O', property, value); | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
var combinedPseudo = (pseudo || '') + property; | ||
walk(value, rules, media, combinedPseudo); | ||
continue; | ||
else if (Object.keys(value).length === 0) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (property.indexOf('@media') === 0) { | ||
var combinedMedia = (media ? media + " and " : '') + property.slice(7); | ||
walk(value, rules, combinedMedia, pseudo); | ||
continue; | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
var declarations = getIndex(rules, media, pseudo); | ||
if (ANIMATION_NAME in declarations) { | ||
continue; | ||
} | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(ANIMATION_NAME in declarations)) { | ||
var name = injector().injectKeyframesRule(value); | ||
declarations[ANIMATION_NAME] = name; | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
var declarations = getIndex(rules, media, pseudo); | ||
if (FONT_FAMILY in declarations) { | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(FONT_FAMILY in declarations)) { | ||
var names = ''; | ||
@@ -273,55 +261,60 @@ var families = Array.isArray(value) ? value : [value]; | ||
declarations[FONT_FAMILY] = names; | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
getIndex(rules, media, pseudo)[property] = value; | ||
continue; | ||
continue; | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
var combinedPseudo = (pseudo || '') + property; | ||
resolve(value, result, media, combinedPseudo); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
resolve(value, result, property, pseudo); | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
} | ||
// Shorthand objects | ||
var isValid = true; | ||
var longhandDeclarations = {}; | ||
for (var extension in value) { | ||
{ | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
continue; | ||
} | ||
// Shorthand objects | ||
var isValid = true; | ||
var longhandDeclarations = {}; | ||
for (var extension in value) { | ||
{ | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
var longhandValue = value[extension]; | ||
var typeOfValue = typeof longhandValue; | ||
if (typeOfValue === 'string' || | ||
typeOfValue === 'number' || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeOfValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
} | ||
var longhandValue = value[extension]; | ||
if (isPrimitive(longhandValue) || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeof longhandValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
{ | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
isValid = false; | ||
break; | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
continue; | ||
} | ||
if (isValid) { | ||
{ | ||
for (var longhandProperty in longhandDeclarations) { | ||
if (longhandProperty in style) { | ||
console.warn('A property in shorthand object %O resolved to `%s` that already exists in %O. The last one in order will be ignored.', value, longhandProperty, style); | ||
} | ||
} | ||
} | ||
walk(longhandDeclarations, rules, media, pseudo); | ||
{ | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
} | ||
isValid = false; | ||
break; | ||
} | ||
if (isValid) { | ||
resolve(longhandDeclarations, result, media, pseudo); | ||
continue; | ||
@@ -333,3 +326,3 @@ } | ||
} | ||
return rules; | ||
return result; | ||
}; | ||
@@ -339,16 +332,50 @@ var injectClassName = function (declarations, media, pseudo) { | ||
}; | ||
var cache = createIndex(); | ||
var cache = {}; | ||
var inject = | ||
// Atomic as default | ||
atomic === false | ||
? function (declarations, media, pseudo) { | ||
return ' ' + injectClassName(declarations, media, pseudo); | ||
? function (style, media, pseudo) { | ||
var classNames = ''; | ||
var properties = Object.keys(style); | ||
var blocks = {}; | ||
for (var i = properties.length - 1; i >= 0; i--) { | ||
var property = properties[i]; | ||
var value = style[property]; | ||
if (property[0] === ':' || property[0] === '@') { | ||
blocks[property] = value; | ||
continue; | ||
} | ||
var block = (blocks[NON_ATOMIC_KEY] = blocks[NON_ATOMIC_KEY] || {}); | ||
block[property] = value; | ||
} | ||
for (var rule in blocks) { | ||
if (rule === NON_ATOMIC_KEY) { | ||
classNames += ' ' + injectClassName(blocks[rule], media, pseudo); | ||
} | ||
else { | ||
classNames += inject(blocks[rule], rule[0] === '@' ? rule.slice(7) : media, rule[0] === ':' ? rule : pseudo); | ||
} | ||
} | ||
return classNames; | ||
} | ||
: function (declarations, media, pseudo) { | ||
: function (style, media, pseudo) { | ||
var classNames = ''; | ||
for (var property in declarations) { | ||
var value = declarations[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
var properties = Object.keys(style); | ||
var index = getIndex(cache, media, pseudo); | ||
for (var i = properties.length - 1; i >= 0; i--) { | ||
var property = properties[i]; | ||
var value = style[property]; | ||
// Pseudo | ||
if (property[0] === ':') { | ||
classNames += inject(value, media, property); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
classNames += inject(value, property.slice(7), pseudo); | ||
continue; | ||
} | ||
var declaration = (_a = {}, _a[property] = value, _a); | ||
if (isPrimitive(value)) { | ||
// Only supports caching of primitive values | ||
var index = getIndex(cache, media, pseudo); | ||
var cachedValues = (index[property] = index[property] || {}); | ||
@@ -359,3 +386,3 @@ if (value in cachedValues) { | ||
} | ||
var className = injectClassName((_a = {}, _a[property] = value, _a), media, pseudo); | ||
var className = injectClassName(declaration, media, pseudo); | ||
if (className) { | ||
@@ -367,34 +394,16 @@ cachedValues[value] = className; | ||
} | ||
if (Array.isArray(value)) { | ||
classNames += ' ' + injectClassName((_b = {}, _b[property] = value, _b), media, pseudo); | ||
continue; | ||
} | ||
// Array | ||
classNames += ' ' + injectClassName(declaration, media, pseudo); | ||
} | ||
return classNames; | ||
var _a, _b; | ||
var _a; | ||
}; | ||
var reducer = function (result, style) { return resolve(style, result); }; | ||
this.injectStyle = function (styles) { | ||
var rules = createIndex(); | ||
if (Array.isArray(styles)) { | ||
for (var i = styles.length; i >= 0; i--) { | ||
walk(styles[i], rules); | ||
} | ||
} | ||
else { | ||
walk(styles, rules); | ||
} | ||
var classNames = inject(rules[0]); | ||
for (var pseudo in rules[1]) { | ||
classNames += inject(rules[1][pseudo], undefined, pseudo); | ||
} | ||
for (var media in rules[2]) { | ||
classNames += inject(rules[2][media], media); | ||
} | ||
for (var media in rules[3]) { | ||
for (var pseudo in rules[3][media]) { | ||
classNames += inject(rules[3][media][pseudo], media, pseudo); | ||
} | ||
} | ||
var result = Array.isArray(styles) | ||
? styles.length > 1 ? styles.reduceRight(reducer, {}) : resolve(styles[0] || {}) | ||
: resolve(styles); | ||
var classNames = inject(result); | ||
{ | ||
validateMixingShorthandLonghand(rules, classNames); | ||
validateMixingShorthandLonghand(result, classNames); | ||
} | ||
@@ -406,18 +415,17 @@ return classNames.slice(1); | ||
}()); | ||
function createIndex() { | ||
return [{}, {}, {}, {}]; | ||
} | ||
function getIndex(rules, media, pseudo) { | ||
if (media && pseudo) { | ||
var pseudos = (rules[3][media] = rules[3][media] || {}); | ||
return (pseudos[pseudo] = pseudos[pseudo] || {}); | ||
function getIndex(indexes, media, pseudo) { | ||
var index = indexes; | ||
if (media) { | ||
index = (index[media] = index[media] || {}); | ||
} | ||
else if (media) { | ||
return (rules[2][media] = rules[2][media] || {}); | ||
if (pseudo) { | ||
return (index[pseudo] = index[pseudo] || {}); | ||
} | ||
else if (pseudo) { | ||
return (rules[1][pseudo] = rules[1][pseudo] || {}); | ||
else { | ||
return index; | ||
} | ||
return rules[0]; | ||
} | ||
function isPrimitive(value) { | ||
return typeof value === 'string' || typeof value === 'number'; | ||
} | ||
@@ -424,0 +432,0 @@ function injectSheetRule(styleElement, rule) { |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,n){r.__proto__=n}||function(r,n){for(var e in n)n.hasOwnProperty(e)&&(r[e]=n[e])};function n(n,e){function t(){this.constructor=n}r(n,e),n.prototype=null===e?Object.create(e):(t.prototype=e.prototype,new t)}var e=Object.assign||function(r){for(var n,e=1,t=arguments.length;e<t;e++)for(var i in n=arguments[e])Object.prototype.hasOwnProperty.call(n,i)&&(r[i]=n[i]);return r};function t(r){var n,e="";for(n in r){var t=r[n];if("object"==typeof t)for(var o=0,a=t;o<a.length;o++){var f=a[o];e&&(e+=";"),e+=i(n,f)}else e&&(e+=";"),e+=i(n,t)}return e}function i(r,n){return"string"==typeof n||"number"==typeof n?u(r)+":"+n:""}var o=/[A-Z]/g,a=/^(ms|moz|webkit)/,f={};function u(r){return r in f?f[r]:f[r]=r.replace(o,"-$&").replace(a,"-$&").toLowerCase()}var c="__glitz__",s="animationName",v="fontFamily",l=function(){return function(r,n,e){var t=function(n,e,i,o){for(var a in n){var f=n[a];if("string"!=typeof f&&"number"!=typeof f)if("object"!=typeof f);else{if(":"===a[0]){t(f,e,i,(o||"")+a);continue}if(0===a.indexOf("@media")){var u=(i?i+" and ":"")+a.slice(7);t(f,e,u,o);continue}if("@keyframes"===a||a===s){var c=y(e,i,o);if(s in c)continue;var l=r().injectKeyframesRule(f);c[s]=l;continue}if("@font-face"===a||a===v){if(c=y(e,i,o),v in c)continue;for(var p="",m=0,d=Array.isArray(f)?f:[f];m<d.length;m++){var g=d[m];p&&(p+=","),p+="string"==typeof g?g:r().injectFontFaceRule(g)}c[v]=p;continue}if(Array.isArray(f)){y(e,i,o)[a]=f;continue}var h=!0,x={};for(var j in f){var b=f[j],_=typeof b;if(!("string"===_||"number"===_||Array.isArray(b)||"object"===_&&"animation"===a&&"name"===j||"font"===a&&"family"===j)){h=!1;break}"x"!==j?"y"!==j?x[a+j[0].toUpperCase()+j.slice(1)]=b:(x[a+"Top"]=b,x[a+"Bottom"]=b):(x[a+"Left"]=b,x[a+"Right"]=b)}h&&t(x,e,i,o)}else a in(c=y(e,i,o))||(c[a]=f)}return e},i=function(e,t,i){return r(t).injectClassRule(n?n(e):e,i)},o=[{},{},{},{}],a=!1===e?function(r,n,e){return" "+i(r,n,e)}:function(r,n,e){var t,a,f="";for(var u in r){var c=r[u];if("string"!=typeof c&&"number"!=typeof c)Array.isArray(c)&&(f+=" "+i(((a={})[u]=c,a),n,e));else{var s=y(o,n,e),v=s[u]=s[u]||{};if(c in v){f+=" "+v[c];continue}var l=i(((t={})[u]=c,t),n,e);l&&(v[c]=l),f+=" "+l}}return f};this.injectStyle=function(r){var n=[{},{},{},{}];if(Array.isArray(r))for(var e=r.length;e>=0;e--)t(r[e],n);else t(r,n);var i=a(n[0]);for(var o in n[1])i+=a(n[1][o],void 0,o);for(var f in n[2])i+=a(n[2][f],f);for(var f in n[3])for(var o in n[3][f])i+=a(n[3][f][o],f,o);return i.slice(1)}}}();function y(r,n,e){if(n&&e){var t=r[3][n]=r[3][n]||{};return t[e]=t[e]||{}}return n?r[2][n]=r[2][n]||{}:e?r[1][e]=r[1][e]||{}:r[0]}function p(r,n){var e=r.sheet;e.insertRule(n,e.cssRules.length)}function m(r){var n=document.createElement("style");return r&&(n.media=r),n}function d(r,n){return document.head.insertBefore(r,n),r}function g(r){void 0===r&&(r="");var n=0,e=10,t=35,i=1,o=function(){var a=n+e;return a===t&&(e+=9*(t+1),t=Math.pow(36,++i)-1),n++,373===a?o():r+a.toString(36)};return o}function h(r,n){return r+"{"+n+"}"}var x=/\.([a-z0-9])(:[^{]+)?\{([^}]+)\}/g,j=/@keyframes ([a-z0-9])\{((?:[a-z0-9%]+\{[^}]+\})+)\}/g,b=/@font-face \{([^}]+)\}/g,_=/;?font-family:([^;}]+)/,O=function(r){function e(n,e,t,i){var o={},a={},f={},u={},c={},s=n.textContent;if(s){for(var v=void 0;v=x.exec(s);){if(e(),v[2])(a[v[2]]=a[v[2]]||{})[v[3]]=v[1];else o[v[3]]=v[1]}for(;v=j.exec(s);)t(),f[v[2]]=v[1];for(;v=b.exec(s);){var l=_.exec(v[1]);i(),l&&(u[v[1]]=l[1],c[v[1].replace(_,"")]=l[1])}}return r.call(this,o,a,f,u,c,e,t,i,function(r,e,t){var i=function(r,n,e){return void 0===e&&(e=""),"."+h(r+e,n)}(r,e,t);p(n,i)},function(r,e){var t=function(r,n){return"@keyframes "+h(r,n)}(r,e);p(n,t)},function(r){var e=function(r){return"@font-face {"+r+"}"}(r);p(n,e)})||this}return n(e,r),e}(function(){return function(r,n,i,o,a,f,u,c,s,v,l){this.injectClassRule=function(e,i){var o=t(e);if(o){var a=i?n[i]=n[i]||{}:r,u=a[o];if(u)return u;var c=f();return a[o]=c,s&&s(c,o,i),c}return""},this.injectKeyframesRule=function(r){var n="";for(var e in r)n+=h(e,t(r[e]));if(n){var o=i[n];if(o)return o;var a=u();return i[n]=a,v&&v(a,n),a}return""},this.injectFontFaceRule=function(r){delete r.fontFamily;var n=t(r);if(n){var i=a[n];if(i)return i;var f=c(),u=t(e({},r,{fontFamily:f}));return o[u]=a[n]=f,l&&l(u),f}return""}}}()),A=function(r){function e(n,e){void 0===e&&(e={});var t,i,o=e.prefix,a=g(o),f=g(o),u=g(o),s=e.mediaOrder,v={},l=null,y={};if(t=r.call(this,function(r){if(r){if(y[r])return y[r];var n=v[r]=m(r),e=null;if(s){var t=Object.keys(v).sort(s);l=v[t[0]],e=v[t[t.indexOf(r)+1]]||null}return d(n,e),y[r]=new O(n,a,f,u)}if(i)return i;n=d(m(r),l);return i=new O(n,a,f,u)},e.transformer,e.atomic)||this,"auto"===n&&(n=document.getElementsByClassName(c)),n)for(var p=0,h=n;p<h.length;p++){var x=h[p],j=x.media;j?(l||(l=x),v[j]=x,y[j]=new O(x,a,f,u)):i=new O(x,a,f,u)}return t}return n(e,r),e}(l);function w(r){var n,e="";for(n in r){e&&(e+=" and ");var t=r[n];e+=!0===t?"("+u(n)+")":"("+u(n)+": "+("string"==typeof t?t:R(n,"h")||R(n,"t")?t+"px":R(n,"n")?t+"dpi":t)+")"}return e}function R(r,n){return r.indexOf(n)===r.length-1}exports.default=A,exports.media=function(r,n){return(e={})["@media "+("string"==typeof r?r:w(r))]=n,e;var e},exports.query=w,exports.pseudo=function(r,n){return(e={})[r]=n,e;var e},exports.compose=function(){for(var r=[],n=0;n<arguments.length;n++)r[n]=arguments[n];return r.reduceRight(function(r,n){return function(e){return n(r(e))}})}; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,e){r.__proto__=e}||function(r,e){for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n])};function e(e,n){function t(){this.constructor=e}r(e,n),e.prototype=null===n?Object.create(n):(t.prototype=n.prototype,new t)}var n=Object.assign||function(r){for(var e,n=1,t=arguments.length;n<t;n++)for(var i in e=arguments[n])Object.prototype.hasOwnProperty.call(e,i)&&(r[i]=e[i]);return r};function t(r){var e,n="";for(e in r){var t=r[e];if("object"==typeof t)for(var o=0,f=t;o<f.length;o++){var a=f[o];n&&(n+=";"),n+=i(e,a)}else n&&(n+=";"),n+=i(e,t)}return n}function i(r,e){return"string"==typeof e||"number"==typeof e?u(r)+":"+e:""}var o=/[A-Z]/g,f=/^(ms|moz|webkit)/,a={};function u(r){return r in a?a[r]:a[r]=r.replace(o,"-$&").replace(f,"-$&").toLowerCase()}var c="__glitz__",s="animationName",v="fontFamily",l="$",y=function(){return function(r,e,n){var t=function(e,n,i,o){void 0===n&&(n={});for(var f=Object.keys(e),a=f.length-1;a>=0;a--){var u=f[a],c=e[u];if(m(c)){if(!(u in(d=p(n,i,o)))){d[u]=c;continue}}else if("@keyframes"!==u&&u!==s)if("@font-face"!==u&&u!==v)if(":"!==u[0])if("@"!==u[0])if(Array.isArray(c))u in(d=p(n,i,o))||(d[u]=c);else{var l=!0,y={};for(var h in c){var g=c[h];if(!(m(g)||Array.isArray(g)||"object"==typeof g&&"animation"===u&&"name"===h||"font"===u&&"family"===h)){l=!1;break}"x"!==h?"y"!==h?y[u+h[0].toUpperCase()+h.slice(1)]=g:(y[u+"Top"]=g,y[u+"Bottom"]=g):(y[u+"Left"]=g,y[u+"Right"]=g)}l&&t(y,n,i,o)}else t(c,n,u,o);else t(c,n,i,(o||"")+u);else{var d=p(n,i,o);if(!(v in d)){for(var j="",x=0,b=Array.isArray(c)?c:[c];x<b.length;x++){var O=b[x];j&&(j+=","),j+="string"==typeof O?O:r().injectFontFaceRule(O)}d[v]=j}}else{var d=p(n,i,o);if(!(s in d)){var _=r().injectKeyframesRule(c);d[s]=_}}}return n},i=function(n,t,i){return r(t).injectClassRule(e?e(n):n,i)},o={},f=!1===n?function(r,e,n){for(var t="",o=Object.keys(r),a={},u=o.length-1;u>=0;u--){var c=o[u],s=r[c];":"!==c[0]&&"@"!==c[0]?(a[l]=a[l]||{})[c]=s:a[c]=s}for(var v in a)t+=v===l?" "+i(a[v],e,n):f(a[v],"@"===v[0]?v.slice(7):e,":"===v[0]?v:n);return t}:function(r,e,n){for(var t,a="",u=Object.keys(r),c=p(o,e,n),s=u.length-1;s>=0;s--){var v=u[s],l=r[v];if(":"!==v[0])if("@"!==v[0]){var y=((t={})[v]=l,t);if(m(l)){var h=c[v]=c[v]||{};if(l in h){a+=" "+h[l];continue}var g=i(y,e,n);g&&(h[l]=g),a+=" "+g}else a+=" "+i(y,e,n)}else a+=f(l,v.slice(7),n);else a+=f(l,e,v)}return a},a=function(r,e){return t(e,r)};this.injectStyle=function(r){var e=Array.isArray(r)?r.length>1?r.reduceRight(a,{}):t(r[0]||{}):t(r);return f(e).slice(1)}}}();function p(r,e,n){var t=r;return e&&(t=t[e]=t[e]||{}),n?t[n]=t[n]||{}:t}function m(r){return"string"==typeof r||"number"==typeof r}function h(r,e){var n=r.sheet;n.insertRule(e,n.cssRules.length)}function g(r){var e=document.createElement("style");return r&&(e.media=r),e}function d(r,e){return document.head.insertBefore(r,e),r}function j(r){void 0===r&&(r="");var e=0,n=10,t=35,i=1,o=function(){var f=e+n;return f===t&&(n+=9*(t+1),t=Math.pow(36,++i)-1),e++,373===f?o():r+f.toString(36)};return o}function x(r,e){return r+"{"+e+"}"}var b=/\.([a-z0-9])(:[^{]+)?\{([^}]+)\}/g,O=/@keyframes ([a-z0-9])\{((?:[a-z0-9%]+\{[^}]+\})+)\}/g,_=/@font-face \{([^}]+)\}/g,R=/;?font-family:([^;}]+)/,w=function(r){function n(e,n,t,i){var o={},f={},a={},u={},c={},s=e.textContent;if(s){for(var v=void 0;v=b.exec(s);){if(n(),v[2])(f[v[2]]=f[v[2]]||{})[v[3]]=v[1];else o[v[3]]=v[1]}for(;v=O.exec(s);)t(),a[v[2]]=v[1];for(;v=_.exec(s);){var l=R.exec(v[1]);i(),l&&(u[v[1]]=l[1],c[v[1].replace(R,"")]=l[1])}}return r.call(this,o,f,a,u,c,n,t,i,function(r,n,t){var i=function(r,e,n){return void 0===n&&(n=""),"."+x(r+n,e)}(r,n,t);h(e,i)},function(r,n){var t=function(r,e){return"@keyframes "+x(r,e)}(r,n);h(e,t)},function(r){var n=function(r){return"@font-face {"+r+"}"}(r);h(e,n)})||this}return e(n,r),n}(function(){return function(r,e,i,o,f,a,u,c,s,v,l){this.injectClassRule=function(n,i){var o=t(n);if(o){var f=i?e[i]=e[i]||{}:r,u=f[o];if(u)return u;var c=a();return f[o]=c,s&&s(c,o,i),c}return""},this.injectKeyframesRule=function(r){var e="";for(var n in r)e+=x(n,t(r[n]));if(e){var o=i[e];if(o)return o;var f=u();return i[e]=f,v&&v(f,e),f}return""},this.injectFontFaceRule=function(r){delete r.fontFamily;var e=t(r);if(e){var i=f[e];if(i)return i;var a=c(),u=t(n({},r,{fontFamily:a}));return o[u]=f[e]=a,l&&l(u),a}return""}}}()),A=function(r){function n(e,n){void 0===n&&(n={});var t,i,o=n.prefix,f=j(o),a=j(o),u=j(o),s=n.mediaOrder,v={},l=null,y={};if(t=r.call(this,function(r){if(r){if(y[r])return y[r];var e=v[r]=g(r),n=null;if(s){var t=Object.keys(v).sort(s);l=v[t[0]],n=v[t[t.indexOf(r)+1]]||null}return d(e,n),y[r]=new w(e,f,a,u)}if(i)return i;e=d(g(r),l);return i=new w(e,f,a,u)},n.transformer,n.atomic)||this,"auto"===e&&(e=document.getElementsByClassName(c)),e)for(var p=0,m=e;p<m.length;p++){var h=m[p],x=h.media;x?(l||(l=h),v[x]=h,y[x]=new w(h,f,a,u)):i=new w(h,f,a,u)}return t}return e(n,r),n}(y);function k(r){var e,n="";for(e in r){n&&(n+=" and ");var t=r[e];n+=!0===t?"("+u(e)+")":"("+u(e)+": "+("string"==typeof t?t:F(e,"h")||F(e,"t")?t+"px":F(e,"n")?t+"dpi":t)+")"}return n}function F(r,e){return r.indexOf(e)===r.length-1}exports.default=A,exports.media=function(r,e){return(n={})["@media "+("string"==typeof r?r:k(r))]=e,n;var n},exports.query=k,exports.pseudo=function(r,e){return(n={})[r]=e,n;var n},exports.compose=function(){for(var r=[],e=0;e<arguments.length;e++)r[e]=arguments[e];return r.reduceRight(function(r,e){return function(n){return e(r(n))}})}; |
@@ -214,50 +214,38 @@ 'use strict'; | ||
var FONT_FAMILY = 'fontFamily'; | ||
var NON_ATOMIC_KEY = '$'; | ||
var Base = /** @class */ (function () { | ||
function Base(injector, transformer, atomic) { | ||
var walk = function (style, rules, media, pseudo) { | ||
for (var property in style) { | ||
var resolve = function (style, result, media, pseudo) { | ||
if (result === void 0) { result = {}; } | ||
var properties = Object.keys(style); | ||
for (var i = properties.length - 1; i >= 0; i--) { | ||
var property = properties[i]; | ||
var value = style[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
var declarations = getIndex(rules, media, pseudo); | ||
if (isPrimitive(value)) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (typeof value === 'object') { | ||
if (process.env.NODE_ENV !== 'production') { | ||
var isEmpty = true; | ||
for (var x in value) { | ||
isEmpty = false; | ||
break; | ||
} | ||
if (isEmpty) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (typeof value !== 'object') { | ||
console.error('The style property `%s` was has to be a string, number or object, was %O', property, value); | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
var combinedPseudo = (pseudo || '') + property; | ||
walk(value, rules, media, combinedPseudo); | ||
continue; | ||
else if (Object.keys(value).length === 0) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (property.indexOf('@media') === 0) { | ||
var combinedMedia = (media ? media + " and " : '') + property.slice(7); | ||
walk(value, rules, combinedMedia, pseudo); | ||
continue; | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
var declarations = getIndex(rules, media, pseudo); | ||
if (ANIMATION_NAME in declarations) { | ||
continue; | ||
} | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(ANIMATION_NAME in declarations)) { | ||
var name = injector().injectKeyframesRule(value); | ||
declarations[ANIMATION_NAME] = name; | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
var declarations = getIndex(rules, media, pseudo); | ||
if (FONT_FAMILY in declarations) { | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(FONT_FAMILY in declarations)) { | ||
var names = ''; | ||
@@ -273,55 +261,60 @@ var families = Array.isArray(value) ? value : [value]; | ||
declarations[FONT_FAMILY] = names; | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
getIndex(rules, media, pseudo)[property] = value; | ||
continue; | ||
continue; | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
var combinedPseudo = (pseudo || '') + property; | ||
resolve(value, result, media, combinedPseudo); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
resolve(value, result, property, pseudo); | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
var declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
} | ||
// Shorthand objects | ||
var isValid = true; | ||
var longhandDeclarations = {}; | ||
for (var extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
continue; | ||
} | ||
// Shorthand objects | ||
var isValid = true; | ||
var longhandDeclarations = {}; | ||
for (var extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
var longhandValue = value[extension]; | ||
var typeOfValue = typeof longhandValue; | ||
if (typeOfValue === 'string' || | ||
typeOfValue === 'number' || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeOfValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
} | ||
var longhandValue = value[extension]; | ||
if (isPrimitive(longhandValue) || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeof longhandValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
isValid = false; | ||
break; | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
continue; | ||
} | ||
if (isValid) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
for (var longhandProperty in longhandDeclarations) { | ||
if (longhandProperty in style) { | ||
console.warn('A property in shorthand object %O resolved to `%s` that already exists in %O. The last one in order will be ignored.', value, longhandProperty, style); | ||
} | ||
} | ||
} | ||
walk(longhandDeclarations, rules, media, pseudo); | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
} | ||
isValid = false; | ||
break; | ||
} | ||
if (isValid) { | ||
resolve(longhandDeclarations, result, media, pseudo); | ||
continue; | ||
@@ -333,3 +326,3 @@ } | ||
} | ||
return rules; | ||
return result; | ||
}; | ||
@@ -339,16 +332,50 @@ var injectClassName = function (declarations, media, pseudo) { | ||
}; | ||
var cache = createIndex(); | ||
var cache = {}; | ||
var inject = | ||
// Atomic as default | ||
atomic === false | ||
? function (declarations, media, pseudo) { | ||
return ' ' + injectClassName(declarations, media, pseudo); | ||
? function (style, media, pseudo) { | ||
var classNames = ''; | ||
var properties = Object.keys(style); | ||
var blocks = {}; | ||
for (var i = properties.length - 1; i >= 0; i--) { | ||
var property = properties[i]; | ||
var value = style[property]; | ||
if (property[0] === ':' || property[0] === '@') { | ||
blocks[property] = value; | ||
continue; | ||
} | ||
var block = (blocks[NON_ATOMIC_KEY] = blocks[NON_ATOMIC_KEY] || {}); | ||
block[property] = value; | ||
} | ||
for (var rule in blocks) { | ||
if (rule === NON_ATOMIC_KEY) { | ||
classNames += ' ' + injectClassName(blocks[rule], media, pseudo); | ||
} | ||
else { | ||
classNames += inject(blocks[rule], rule[0] === '@' ? rule.slice(7) : media, rule[0] === ':' ? rule : pseudo); | ||
} | ||
} | ||
return classNames; | ||
} | ||
: function (declarations, media, pseudo) { | ||
: function (style, media, pseudo) { | ||
var classNames = ''; | ||
for (var property in declarations) { | ||
var value = declarations[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
var properties = Object.keys(style); | ||
var index = getIndex(cache, media, pseudo); | ||
for (var i = properties.length - 1; i >= 0; i--) { | ||
var property = properties[i]; | ||
var value = style[property]; | ||
// Pseudo | ||
if (property[0] === ':') { | ||
classNames += inject(value, media, property); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
classNames += inject(value, property.slice(7), pseudo); | ||
continue; | ||
} | ||
var declaration = (_a = {}, _a[property] = value, _a); | ||
if (isPrimitive(value)) { | ||
// Only supports caching of primitive values | ||
var index = getIndex(cache, media, pseudo); | ||
var cachedValues = (index[property] = index[property] || {}); | ||
@@ -359,3 +386,3 @@ if (value in cachedValues) { | ||
} | ||
var className = injectClassName((_a = {}, _a[property] = value, _a), media, pseudo); | ||
var className = injectClassName(declaration, media, pseudo); | ||
if (className) { | ||
@@ -367,34 +394,16 @@ cachedValues[value] = className; | ||
} | ||
if (Array.isArray(value)) { | ||
classNames += ' ' + injectClassName((_b = {}, _b[property] = value, _b), media, pseudo); | ||
continue; | ||
} | ||
// Array | ||
classNames += ' ' + injectClassName(declaration, media, pseudo); | ||
} | ||
return classNames; | ||
var _a, _b; | ||
var _a; | ||
}; | ||
var reducer = function (result, style) { return resolve(style, result); }; | ||
this.injectStyle = function (styles) { | ||
var rules = createIndex(); | ||
if (Array.isArray(styles)) { | ||
for (var i = styles.length; i >= 0; i--) { | ||
walk(styles[i], rules); | ||
} | ||
} | ||
else { | ||
walk(styles, rules); | ||
} | ||
var classNames = inject(rules[0]); | ||
for (var pseudo in rules[1]) { | ||
classNames += inject(rules[1][pseudo], undefined, pseudo); | ||
} | ||
for (var media in rules[2]) { | ||
classNames += inject(rules[2][media], media); | ||
} | ||
for (var media in rules[3]) { | ||
for (var pseudo in rules[3][media]) { | ||
classNames += inject(rules[3][media][pseudo], media, pseudo); | ||
} | ||
} | ||
var result = Array.isArray(styles) | ||
? styles.length > 1 ? styles.reduceRight(reducer, {}) : resolve(styles[0] || {}) | ||
: resolve(styles); | ||
var classNames = inject(result); | ||
if (process.env.NODE_ENV !== 'production') { | ||
validateMixingShorthandLonghand(rules, classNames); | ||
validateMixingShorthandLonghand(result, classNames); | ||
} | ||
@@ -406,18 +415,17 @@ return classNames.slice(1); | ||
}()); | ||
function createIndex() { | ||
return [{}, {}, {}, {}]; | ||
} | ||
function getIndex(rules, media, pseudo) { | ||
if (media && pseudo) { | ||
var pseudos = (rules[3][media] = rules[3][media] || {}); | ||
return (pseudos[pseudo] = pseudos[pseudo] || {}); | ||
function getIndex(indexes, media, pseudo) { | ||
var index = indexes; | ||
if (media) { | ||
index = (index[media] = index[media] || {}); | ||
} | ||
else if (media) { | ||
return (rules[2][media] = rules[2][media] || {}); | ||
if (pseudo) { | ||
return (index[pseudo] = index[pseudo] || {}); | ||
} | ||
else if (pseudo) { | ||
return (rules[1][pseudo] = rules[1][pseudo] || {}); | ||
else { | ||
return index; | ||
} | ||
return rules[0]; | ||
} | ||
function isPrimitive(value) { | ||
return typeof value === 'string' || typeof value === 'number'; | ||
} | ||
@@ -424,0 +432,0 @@ function createHashCounter(prefix) { |
@@ -5,52 +5,37 @@ import { validateMixingShorthandLonghand } from '../utils/mixing-shorthand-longhand'; | ||
const FONT_FAMILY = 'fontFamily'; | ||
const NON_ATOMIC_KEY = '$'; | ||
export default class Base { | ||
constructor(injector, transformer, atomic) { | ||
const walk = (style, rules, media, pseudo) => { | ||
for (const property in style) { | ||
const resolve = (style, result = {}, media, pseudo) => { | ||
const properties = Object.keys(style); | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (isPrimitive(value)) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (typeof value === 'object') { | ||
if (process.env.NODE_ENV !== 'production') { | ||
let isEmpty = true; | ||
for (const x in value) { | ||
isEmpty = false; | ||
// tslint:disable-next-line no-unused-expression | ||
x; | ||
break; | ||
} | ||
if (isEmpty) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (typeof value !== 'object') { | ||
console.error('The style property `%s` was has to be a string, number or object, was %O', property, value); | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
const combinedPseudo = (pseudo || '') + property; | ||
walk(value, rules, media, combinedPseudo); | ||
continue; | ||
else if (Object.keys(value).length === 0) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (property.indexOf('@media') === 0) { | ||
const combinedMedia = (media ? `${media} and ` : '') + property.slice(7); | ||
walk(value, rules, combinedMedia, pseudo); | ||
continue; | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (ANIMATION_NAME in declarations) { | ||
continue; | ||
} | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(ANIMATION_NAME in declarations)) { | ||
const name = injector().injectKeyframesRule(value); | ||
declarations[ANIMATION_NAME] = name; | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (FONT_FAMILY in declarations) { | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(FONT_FAMILY in declarations)) { | ||
let names = ''; | ||
@@ -65,55 +50,60 @@ const families = Array.isArray(value) ? value : [value]; | ||
declarations[FONT_FAMILY] = names; | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
getIndex(rules, media, pseudo)[property] = value; | ||
continue; | ||
continue; | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
const combinedPseudo = (pseudo || '') + property; | ||
resolve(value, result, media, combinedPseudo); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
resolve(value, result, property, pseudo); | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
} | ||
// Shorthand objects | ||
let isValid = true; | ||
const longhandDeclarations = {}; | ||
for (const extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
continue; | ||
} | ||
// Shorthand objects | ||
let isValid = true; | ||
const longhandDeclarations = {}; | ||
for (const extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
const longhandValue = value[extension]; | ||
const typeOfValue = typeof longhandValue; | ||
if (typeOfValue === 'string' || | ||
typeOfValue === 'number' || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeOfValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
} | ||
const longhandValue = value[extension]; | ||
if (isPrimitive(longhandValue) || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeof longhandValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
isValid = false; | ||
break; | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
continue; | ||
} | ||
if (isValid) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
for (const longhandProperty in longhandDeclarations) { | ||
if (longhandProperty in style) { | ||
console.warn('A property in shorthand object %O resolved to `%s` that already exists in %O. The last one in order will be ignored.', value, longhandProperty, style); | ||
} | ||
} | ||
} | ||
walk(longhandDeclarations, rules, media, pseudo); | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
} | ||
isValid = false; | ||
break; | ||
} | ||
if (isValid) { | ||
resolve(longhandDeclarations, result, media, pseudo); | ||
continue; | ||
@@ -125,19 +115,53 @@ } | ||
} | ||
return rules; | ||
return result; | ||
}; | ||
const injectClassName = (declarations, media, pseudo) => injector(media).injectClassRule(transformer ? transformer(declarations) : declarations, pseudo); | ||
const cache = createIndex(); | ||
const cache = {}; | ||
const inject = | ||
// Atomic as default | ||
atomic === false | ||
? (declarations, media, pseudo) => { | ||
return ' ' + injectClassName(declarations, media, pseudo); | ||
? (style, media, pseudo) => { | ||
let classNames = ''; | ||
const properties = Object.keys(style); | ||
const blocks = {}; | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
if (property[0] === ':' || property[0] === '@') { | ||
blocks[property] = value; | ||
continue; | ||
} | ||
const block = (blocks[NON_ATOMIC_KEY] = blocks[NON_ATOMIC_KEY] || {}); | ||
block[property] = value; | ||
} | ||
for (const rule in blocks) { | ||
if (rule === NON_ATOMIC_KEY) { | ||
classNames += ' ' + injectClassName(blocks[rule], media, pseudo); | ||
} | ||
else { | ||
classNames += inject(blocks[rule], rule[0] === '@' ? rule.slice(7) : media, rule[0] === ':' ? rule : pseudo); | ||
} | ||
} | ||
return classNames; | ||
} | ||
: (declarations, media, pseudo) => { | ||
: (style, media, pseudo) => { | ||
let classNames = ''; | ||
for (const property in declarations) { | ||
const value = declarations[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
const properties = Object.keys(style); | ||
const index = getIndex(cache, media, pseudo); | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
// Pseudo | ||
if (property[0] === ':') { | ||
classNames += inject(value, media, property); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
classNames += inject(value, property.slice(7), pseudo); | ||
continue; | ||
} | ||
const declaration = { [property]: value }; | ||
if (isPrimitive(value)) { | ||
// Only supports caching of primitive values | ||
const index = getIndex(cache, media, pseudo); | ||
const cachedValues = (index[property] = index[property] || {}); | ||
@@ -148,3 +172,3 @@ if (value in cachedValues) { | ||
} | ||
const className = injectClassName({ [property]: value }, media, pseudo); | ||
const className = injectClassName(declaration, media, pseudo); | ||
if (className) { | ||
@@ -156,33 +180,15 @@ cachedValues[value] = className; | ||
} | ||
if (Array.isArray(value)) { | ||
classNames += ' ' + injectClassName({ [property]: value }, media, pseudo); | ||
continue; | ||
} | ||
// Array | ||
classNames += ' ' + injectClassName(declaration, media, pseudo); | ||
} | ||
return classNames; | ||
}; | ||
const reducer = (result, style) => resolve(style, result); | ||
this.injectStyle = (styles) => { | ||
const rules = createIndex(); | ||
if (Array.isArray(styles)) { | ||
for (let i = styles.length; i >= 0; i--) { | ||
walk(styles[i], rules); | ||
} | ||
} | ||
else { | ||
walk(styles, rules); | ||
} | ||
let classNames = inject(rules[0]); | ||
for (const pseudo in rules[1]) { | ||
classNames += inject(rules[1][pseudo], undefined, pseudo); | ||
} | ||
for (const media in rules[2]) { | ||
classNames += inject(rules[2][media], media); | ||
} | ||
for (const media in rules[3]) { | ||
for (const pseudo in rules[3][media]) { | ||
classNames += inject(rules[3][media][pseudo], media, pseudo); | ||
} | ||
} | ||
const result = Array.isArray(styles) | ||
? styles.length > 1 ? styles.reduceRight(reducer, {}) : resolve(styles[0] || {}) | ||
: resolve(styles); | ||
const classNames = inject(result); | ||
if (process.env.NODE_ENV !== 'production') { | ||
validateMixingShorthandLonghand(rules, classNames); | ||
validateMixingShorthandLonghand(result, classNames); | ||
} | ||
@@ -193,17 +199,16 @@ return classNames.slice(1); | ||
} | ||
function createIndex() { | ||
return [{}, {}, {}, {}]; | ||
} | ||
function getIndex(rules, media, pseudo) { | ||
if (media && pseudo) { | ||
const pseudos = (rules[3][media] = rules[3][media] || {}); | ||
return (pseudos[pseudo] = pseudos[pseudo] || {}); | ||
function getIndex(indexes, media, pseudo) { | ||
let index = indexes; | ||
if (media) { | ||
index = (index[media] = index[media] || {}); | ||
} | ||
else if (media) { | ||
return (rules[2][media] = rules[2][media] || {}); | ||
if (pseudo) { | ||
return (index[pseudo] = index[pseudo] || {}); | ||
} | ||
else if (pseudo) { | ||
return (rules[1][pseudo] = rules[1][pseudo] || {}); | ||
else { | ||
return index; | ||
} | ||
return rules[0]; | ||
} | ||
function isPrimitive(value) { | ||
return typeof value === 'string' || typeof value === 'number'; | ||
} |
263
jsm/index.js
@@ -174,50 +174,37 @@ function parseDeclarationBlock(declarations) { | ||
const FONT_FAMILY = 'fontFamily'; | ||
const NON_ATOMIC_KEY = '$'; | ||
class Base { | ||
constructor(injector, transformer, atomic) { | ||
const walk = (style, rules, media, pseudo) => { | ||
for (const property in style) { | ||
const resolve = (style, result = {}, media, pseudo) => { | ||
const properties = Object.keys(style); | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (isPrimitive(value)) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (typeof value === 'object') { | ||
if (process.env.NODE_ENV !== 'production') { | ||
let isEmpty = true; | ||
for (const x in value) { | ||
isEmpty = false; | ||
break; | ||
} | ||
if (isEmpty) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (typeof value !== 'object') { | ||
console.error('The style property `%s` was has to be a string, number or object, was %O', property, value); | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
const combinedPseudo = (pseudo || '') + property; | ||
walk(value, rules, media, combinedPseudo); | ||
continue; | ||
else if (Object.keys(value).length === 0) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (property.indexOf('@media') === 0) { | ||
const combinedMedia = (media ? `${media} and ` : '') + property.slice(7); | ||
walk(value, rules, combinedMedia, pseudo); | ||
continue; | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (ANIMATION_NAME in declarations) { | ||
continue; | ||
} | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(ANIMATION_NAME in declarations)) { | ||
const name = injector().injectKeyframesRule(value); | ||
declarations[ANIMATION_NAME] = name; | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (FONT_FAMILY in declarations) { | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(FONT_FAMILY in declarations)) { | ||
let names = ''; | ||
@@ -232,55 +219,60 @@ const families = Array.isArray(value) ? value : [value]; | ||
declarations[FONT_FAMILY] = names; | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
getIndex(rules, media, pseudo)[property] = value; | ||
continue; | ||
continue; | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
const combinedPseudo = (pseudo || '') + property; | ||
resolve(value, result, media, combinedPseudo); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
resolve(value, result, property, pseudo); | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
} | ||
// Shorthand objects | ||
let isValid = true; | ||
const longhandDeclarations = {}; | ||
for (const extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
continue; | ||
} | ||
// Shorthand objects | ||
let isValid = true; | ||
const longhandDeclarations = {}; | ||
for (const extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
const longhandValue = value[extension]; | ||
const typeOfValue = typeof longhandValue; | ||
if (typeOfValue === 'string' || | ||
typeOfValue === 'number' || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeOfValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
} | ||
const longhandValue = value[extension]; | ||
if (isPrimitive(longhandValue) || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeof longhandValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
isValid = false; | ||
break; | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
continue; | ||
} | ||
if (isValid) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
for (const longhandProperty in longhandDeclarations) { | ||
if (longhandProperty in style) { | ||
console.warn('A property in shorthand object %O resolved to `%s` that already exists in %O. The last one in order will be ignored.', value, longhandProperty, style); | ||
} | ||
} | ||
} | ||
walk(longhandDeclarations, rules, media, pseudo); | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
} | ||
isValid = false; | ||
break; | ||
} | ||
if (isValid) { | ||
resolve(longhandDeclarations, result, media, pseudo); | ||
continue; | ||
@@ -292,19 +284,53 @@ } | ||
} | ||
return rules; | ||
return result; | ||
}; | ||
const injectClassName = (declarations, media, pseudo) => injector(media).injectClassRule(transformer ? transformer(declarations) : declarations, pseudo); | ||
const cache = createIndex(); | ||
const cache = {}; | ||
const inject = | ||
// Atomic as default | ||
atomic === false | ||
? (declarations, media, pseudo) => { | ||
return ' ' + injectClassName(declarations, media, pseudo); | ||
? (style, media, pseudo) => { | ||
let classNames = ''; | ||
const properties = Object.keys(style); | ||
const blocks = {}; | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
if (property[0] === ':' || property[0] === '@') { | ||
blocks[property] = value; | ||
continue; | ||
} | ||
const block = (blocks[NON_ATOMIC_KEY] = blocks[NON_ATOMIC_KEY] || {}); | ||
block[property] = value; | ||
} | ||
for (const rule in blocks) { | ||
if (rule === NON_ATOMIC_KEY) { | ||
classNames += ' ' + injectClassName(blocks[rule], media, pseudo); | ||
} | ||
else { | ||
classNames += inject(blocks[rule], rule[0] === '@' ? rule.slice(7) : media, rule[0] === ':' ? rule : pseudo); | ||
} | ||
} | ||
return classNames; | ||
} | ||
: (declarations, media, pseudo) => { | ||
: (style, media, pseudo) => { | ||
let classNames = ''; | ||
for (const property in declarations) { | ||
const value = declarations[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
const properties = Object.keys(style); | ||
const index = getIndex(cache, media, pseudo); | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
// Pseudo | ||
if (property[0] === ':') { | ||
classNames += inject(value, media, property); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
classNames += inject(value, property.slice(7), pseudo); | ||
continue; | ||
} | ||
const declaration = { [property]: value }; | ||
if (isPrimitive(value)) { | ||
// Only supports caching of primitive values | ||
const index = getIndex(cache, media, pseudo); | ||
const cachedValues = (index[property] = index[property] || {}); | ||
@@ -315,3 +341,3 @@ if (value in cachedValues) { | ||
} | ||
const className = injectClassName({ [property]: value }, media, pseudo); | ||
const className = injectClassName(declaration, media, pseudo); | ||
if (className) { | ||
@@ -323,33 +349,15 @@ cachedValues[value] = className; | ||
} | ||
if (Array.isArray(value)) { | ||
classNames += ' ' + injectClassName({ [property]: value }, media, pseudo); | ||
continue; | ||
} | ||
// Array | ||
classNames += ' ' + injectClassName(declaration, media, pseudo); | ||
} | ||
return classNames; | ||
}; | ||
const reducer = (result, style) => resolve(style, result); | ||
this.injectStyle = (styles) => { | ||
const rules = createIndex(); | ||
if (Array.isArray(styles)) { | ||
for (let i = styles.length; i >= 0; i--) { | ||
walk(styles[i], rules); | ||
} | ||
} | ||
else { | ||
walk(styles, rules); | ||
} | ||
let classNames = inject(rules[0]); | ||
for (const pseudo in rules[1]) { | ||
classNames += inject(rules[1][pseudo], undefined, pseudo); | ||
} | ||
for (const media in rules[2]) { | ||
classNames += inject(rules[2][media], media); | ||
} | ||
for (const media in rules[3]) { | ||
for (const pseudo in rules[3][media]) { | ||
classNames += inject(rules[3][media][pseudo], media, pseudo); | ||
} | ||
} | ||
const result = Array.isArray(styles) | ||
? styles.length > 1 ? styles.reduceRight(reducer, {}) : resolve(styles[0] || {}) | ||
: resolve(styles); | ||
const classNames = inject(result); | ||
if (process.env.NODE_ENV !== 'production') { | ||
validateMixingShorthandLonghand(rules, classNames); | ||
validateMixingShorthandLonghand(result, classNames); | ||
} | ||
@@ -360,18 +368,17 @@ return classNames.slice(1); | ||
} | ||
function createIndex() { | ||
return [{}, {}, {}, {}]; | ||
} | ||
function getIndex(rules, media, pseudo) { | ||
if (media && pseudo) { | ||
const pseudos = (rules[3][media] = rules[3][media] || {}); | ||
return (pseudos[pseudo] = pseudos[pseudo] || {}); | ||
function getIndex(indexes, media, pseudo) { | ||
let index = indexes; | ||
if (media) { | ||
index = (index[media] = index[media] || {}); | ||
} | ||
else if (media) { | ||
return (rules[2][media] = rules[2][media] || {}); | ||
if (pseudo) { | ||
return (index[pseudo] = index[pseudo] || {}); | ||
} | ||
else if (pseudo) { | ||
return (rules[1][pseudo] = rules[1][pseudo] || {}); | ||
else { | ||
return index; | ||
} | ||
return rules[0]; | ||
} | ||
function isPrimitive(value) { | ||
return typeof value === 'string' || typeof value === 'number'; | ||
} | ||
@@ -378,0 +385,0 @@ function injectSheetRule(styleElement, rule) { |
@@ -174,50 +174,37 @@ function parseDeclarationBlock(declarations) { | ||
const FONT_FAMILY = 'fontFamily'; | ||
const NON_ATOMIC_KEY = '$'; | ||
class Base { | ||
constructor(injector, transformer, atomic) { | ||
const walk = (style, rules, media, pseudo) => { | ||
for (const property in style) { | ||
const resolve = (style, result = {}, media, pseudo) => { | ||
const properties = Object.keys(style); | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (isPrimitive(value)) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (typeof value === 'object') { | ||
if (process.env.NODE_ENV !== 'production') { | ||
let isEmpty = true; | ||
for (const x in value) { | ||
isEmpty = false; | ||
break; | ||
} | ||
if (isEmpty) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (typeof value !== 'object') { | ||
console.error('The style property `%s` was has to be a string, number or object, was %O', property, value); | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
const combinedPseudo = (pseudo || '') + property; | ||
walk(value, rules, media, combinedPseudo); | ||
continue; | ||
else if (Object.keys(value).length === 0) { | ||
console.error('The style property `%s` was an empty %s and should be removed because it can cause unexpected behavior', property, Array.isArray(value) ? 'array' : 'object'); | ||
} | ||
if (property.indexOf('@media') === 0) { | ||
const combinedMedia = (media ? `${media} and ` : '') + property.slice(7); | ||
walk(value, rules, combinedMedia, pseudo); | ||
continue; | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (ANIMATION_NAME in declarations) { | ||
continue; | ||
} | ||
} | ||
if (property === '@keyframes' || property === ANIMATION_NAME) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(ANIMATION_NAME in declarations)) { | ||
const name = injector().injectKeyframesRule(value); | ||
declarations[ANIMATION_NAME] = name; | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
const declarations = getIndex(rules, media, pseudo); | ||
if (FONT_FAMILY in declarations) { | ||
continue; | ||
} | ||
continue; | ||
} | ||
if (property === '@font-face' || property === FONT_FAMILY) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(FONT_FAMILY in declarations)) { | ||
let names = ''; | ||
@@ -232,55 +219,60 @@ const families = Array.isArray(value) ? value : [value]; | ||
declarations[FONT_FAMILY] = names; | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
getIndex(rules, media, pseudo)[property] = value; | ||
continue; | ||
continue; | ||
} | ||
// Pseudo | ||
if (property[0] === ':') { | ||
const combinedPseudo = (pseudo || '') + property; | ||
resolve(value, result, media, combinedPseudo); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
resolve(value, result, property, pseudo); | ||
continue; | ||
} | ||
if (Array.isArray(value)) { | ||
const declarations = getIndex(result, media, pseudo); | ||
if (!(property in declarations)) { | ||
declarations[property] = value; | ||
} | ||
// Shorthand objects | ||
let isValid = true; | ||
const longhandDeclarations = {}; | ||
for (const extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
continue; | ||
} | ||
// Shorthand objects | ||
let isValid = true; | ||
const longhandDeclarations = {}; | ||
for (const extension in value) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!/^[a-z]+$/i.test(extension)) { | ||
console.error("The property `%s['%s']` in %O isn't a valid shorthand extension and will likely cause a failure", property, extension, value); | ||
} | ||
const longhandValue = value[extension]; | ||
const typeOfValue = typeof longhandValue; | ||
if (typeOfValue === 'string' || | ||
typeOfValue === 'number' || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeOfValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
} | ||
const longhandValue = value[extension]; | ||
if (isPrimitive(longhandValue) || | ||
Array.isArray(longhandValue) || | ||
// Objects are only valid for `animation.name` and `font.family` | ||
((typeof longhandValue === 'object' && (property === 'animation' && extension === 'name')) || | ||
(property === 'font' && extension === 'family'))) { | ||
if (extension === 'x') { | ||
longhandDeclarations[property + 'Left'] = longhandValue; | ||
longhandDeclarations[property + 'Right'] = longhandValue; | ||
continue; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
if (extension === 'y') { | ||
longhandDeclarations[property + 'Top'] = longhandValue; | ||
longhandDeclarations[property + 'Bottom'] = longhandValue; | ||
continue; | ||
} | ||
isValid = false; | ||
break; | ||
// Convert to camel cased CSS property due to cache | ||
longhandDeclarations[property + extension[0].toUpperCase() + extension.slice(1)] = longhandValue; | ||
continue; | ||
} | ||
if (isValid) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
for (const longhandProperty in longhandDeclarations) { | ||
if (longhandProperty in style) { | ||
console.warn('A property in shorthand object %O resolved to `%s` that already exists in %O. The last one in order will be ignored.', value, longhandProperty, style); | ||
} | ||
} | ||
} | ||
walk(longhandDeclarations, rules, media, pseudo); | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error("The object of `%s` isn't a valid shorthand object and will be ignored because property `%s['%s']` wasn't a string, number or array of values, was %O", property, property, extension, value); | ||
} | ||
isValid = false; | ||
break; | ||
} | ||
if (isValid) { | ||
resolve(longhandDeclarations, result, media, pseudo); | ||
continue; | ||
@@ -292,19 +284,53 @@ } | ||
} | ||
return rules; | ||
return result; | ||
}; | ||
const injectClassName = (declarations, media, pseudo) => injector(media).injectClassRule(transformer ? transformer(declarations) : declarations, pseudo); | ||
const cache = createIndex(); | ||
const cache = {}; | ||
const inject = | ||
// Atomic as default | ||
atomic === false | ||
? (declarations, media, pseudo) => { | ||
return ' ' + injectClassName(declarations, media, pseudo); | ||
? (style, media, pseudo) => { | ||
let classNames = ''; | ||
const properties = Object.keys(style); | ||
const blocks = {}; | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
if (property[0] === ':' || property[0] === '@') { | ||
blocks[property] = value; | ||
continue; | ||
} | ||
const block = (blocks[NON_ATOMIC_KEY] = blocks[NON_ATOMIC_KEY] || {}); | ||
block[property] = value; | ||
} | ||
for (const rule in blocks) { | ||
if (rule === NON_ATOMIC_KEY) { | ||
classNames += ' ' + injectClassName(blocks[rule], media, pseudo); | ||
} | ||
else { | ||
classNames += inject(blocks[rule], rule[0] === '@' ? rule.slice(7) : media, rule[0] === ':' ? rule : pseudo); | ||
} | ||
} | ||
return classNames; | ||
} | ||
: (declarations, media, pseudo) => { | ||
: (style, media, pseudo) => { | ||
let classNames = ''; | ||
for (const property in declarations) { | ||
const value = declarations[property]; | ||
if (typeof value === 'string' || typeof value === 'number') { | ||
const properties = Object.keys(style); | ||
const index = getIndex(cache, media, pseudo); | ||
for (let i = properties.length - 1; i >= 0; i--) { | ||
const property = properties[i]; | ||
const value = style[property]; | ||
// Pseudo | ||
if (property[0] === ':') { | ||
classNames += inject(value, media, property); | ||
continue; | ||
} | ||
// Media | ||
if (property[0] === '@') { | ||
classNames += inject(value, property.slice(7), pseudo); | ||
continue; | ||
} | ||
const declaration = { [property]: value }; | ||
if (isPrimitive(value)) { | ||
// Only supports caching of primitive values | ||
const index = getIndex(cache, media, pseudo); | ||
const cachedValues = (index[property] = index[property] || {}); | ||
@@ -315,3 +341,3 @@ if (value in cachedValues) { | ||
} | ||
const className = injectClassName({ [property]: value }, media, pseudo); | ||
const className = injectClassName(declaration, media, pseudo); | ||
if (className) { | ||
@@ -323,33 +349,15 @@ cachedValues[value] = className; | ||
} | ||
if (Array.isArray(value)) { | ||
classNames += ' ' + injectClassName({ [property]: value }, media, pseudo); | ||
continue; | ||
} | ||
// Array | ||
classNames += ' ' + injectClassName(declaration, media, pseudo); | ||
} | ||
return classNames; | ||
}; | ||
const reducer = (result, style) => resolve(style, result); | ||
this.injectStyle = (styles) => { | ||
const rules = createIndex(); | ||
if (Array.isArray(styles)) { | ||
for (let i = styles.length; i >= 0; i--) { | ||
walk(styles[i], rules); | ||
} | ||
} | ||
else { | ||
walk(styles, rules); | ||
} | ||
let classNames = inject(rules[0]); | ||
for (const pseudo in rules[1]) { | ||
classNames += inject(rules[1][pseudo], undefined, pseudo); | ||
} | ||
for (const media in rules[2]) { | ||
classNames += inject(rules[2][media], media); | ||
} | ||
for (const media in rules[3]) { | ||
for (const pseudo in rules[3][media]) { | ||
classNames += inject(rules[3][media][pseudo], media, pseudo); | ||
} | ||
} | ||
const result = Array.isArray(styles) | ||
? styles.length > 1 ? styles.reduceRight(reducer, {}) : resolve(styles[0] || {}) | ||
: resolve(styles); | ||
const classNames = inject(result); | ||
if (process.env.NODE_ENV !== 'production') { | ||
validateMixingShorthandLonghand(rules, classNames); | ||
validateMixingShorthandLonghand(result, classNames); | ||
} | ||
@@ -360,18 +368,17 @@ return classNames.slice(1); | ||
} | ||
function createIndex() { | ||
return [{}, {}, {}, {}]; | ||
} | ||
function getIndex(rules, media, pseudo) { | ||
if (media && pseudo) { | ||
const pseudos = (rules[3][media] = rules[3][media] || {}); | ||
return (pseudos[pseudo] = pseudos[pseudo] || {}); | ||
function getIndex(indexes, media, pseudo) { | ||
let index = indexes; | ||
if (media) { | ||
index = (index[media] = index[media] || {}); | ||
} | ||
else if (media) { | ||
return (rules[2][media] = rules[2][media] || {}); | ||
if (pseudo) { | ||
return (index[pseudo] = index[pseudo] || {}); | ||
} | ||
else if (pseudo) { | ||
return (rules[1][pseudo] = rules[1][pseudo] || {}); | ||
else { | ||
return index; | ||
} | ||
return rules[0]; | ||
} | ||
function isPrimitive(value) { | ||
return typeof value === 'string' || typeof value === 'number'; | ||
} | ||
@@ -378,0 +385,0 @@ function createHashCounter(prefix = '') { |
{ | ||
"name": "@glitz/core", | ||
"version": "1.1.0-beta.10", | ||
"version": "1.1.0-beta.11", | ||
"main": "./cjs/index.js", | ||
@@ -14,3 +14,3 @@ "module": "./jsm/index.js", | ||
"dependencies": { | ||
"@glitz/type": "^1.1.0-beta.10" | ||
"@glitz/type": "^1.1.0-beta.11" | ||
}, | ||
@@ -17,0 +17,0 @@ "scripts": { |
171209
3591
12
Updated@glitz/type@^1.1.0-beta.11