react-native-css-media-query-processor
Version:
Match style objects containing CSS Media Queries with React Native
164 lines (127 loc) • 3.54 kB
JavaScript
/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/
;
exports.match = match; // -----------------------------------------------------------------------------
var RE_LENGTH_UNIT = /(em|rem|px|cm|mm|in|pt|pc)?\s*$/,
RE_RESOLUTION_UNIT = /(dpi|dpcm|dppx)?\s*$/;
function match(parsed, values) {
if (!parsed) {
return false;
}
if (parsed.length === 1) {
return matchQuery(parsed[0], values);
}
return parsed.some(function (mq) {
return matchQuery(mq, values);
});
}
function matchQuery(query, values) {
var inverse = query.inverse; // Either the parsed or specified `type` is "all", or the types must be
// equal for a match.
var typeMatch = query.type === "all" || values.type === query.type;
if (query.expressions.length === 0) {
// Quit early when `type` doesn't match, but take "not" into account.
if (typeMatch && inverse || !(typeMatch || inverse)) {
return false;
}
}
var expressionsMatch = query.expressions.every(function (expression) {
var feature = expression.feature,
modifier = expression.modifier,
expValue = expression.value,
value = values[feature]; // Missing or falsy values don't match.
if (!value) {
return false;
}
switch (feature) {
case "orientation":
case "scan":
return value.toLowerCase() === expValue.toLowerCase();
case "width":
case "height":
case "device-width":
case "device-height":
expValue = toPx(expValue);
value = toPx(value);
break;
case "resolution":
expValue = toDpi(expValue);
value = toDpi(value);
break;
case "aspect-ratio":
case "device-aspect-ratio":
case
/* Deprecated */
"device-pixel-ratio":
expValue = toDecimal(expValue);
value = toDecimal(value);
break;
case "grid":
case "color":
case "color-index":
case "monochrome":
expValue = parseInt(expValue, 10) || 1;
value = parseInt(value, 10) || 0;
break;
}
switch (modifier) {
case "min":
return value >= expValue;
case "max":
return value <= expValue;
default:
return value === expValue;
}
});
var isMatch = typeMatch && expressionsMatch;
if (inverse) {
return !isMatch;
}
return isMatch;
} // -- Utilities ----------------------------------------------------------------
function toDecimal(ratio) {
var decimal = Number(ratio),
numbers;
if (!decimal) {
numbers = ratio.match(/^(\d+)\s*\/\s*(\d+)$/);
decimal = numbers[1] / numbers[2];
}
return decimal;
}
function toDpi(resolution) {
var value = parseFloat(resolution),
units = String(resolution).match(RE_RESOLUTION_UNIT)[1];
switch (units) {
case "dpcm":
return value / 2.54;
case "dppx":
return value * 96;
default:
return value;
}
}
function toPx(length) {
var value = parseFloat(length),
units = String(length).match(RE_LENGTH_UNIT)[1];
switch (units) {
case "em":
return value * 16;
case "rem":
return value * 16;
case "cm":
return value * 96 / 2.54;
case "mm":
return value * 96 / 2.54 / 10;
case "in":
return value * 96;
case "pt":
return value * 72;
case "pc":
return value * 72 / 12;
default:
return value;
}
}