UNPKG

@nativescript/core

Version:

A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.

118 lines 5.29 kB
/* Copyright (c) 2014, Yahoo! Inc. All rights reserved. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. */ // https://github.com/ericf/css-mediaquery import { Trace } from '../trace'; import { Length } from '../ui/styling/style-properties'; // ----------------------------------------------------------------------------- const RE_MEDIA_QUERY = /^(?:(only|not)?\s*([_a-z][_a-z0-9-]*)|(\([^\)]+\)))(?:\s*and\s*(.*))?$/i, RE_MQ_EXPRESSION = /^\(\s*([_a-z-][_a-z0-9-]*)\s*(?:\:\s*([^\)]+))?\s*\)$/, RE_MQ_FEATURE = /^(?:(min|max)-)?(.+)/, RE_LENGTH_UNIT = /(em|rem|px|cm|mm|in|pt|pc)?\s*$/, RE_RESOLUTION_UNIT = /(dpi|dpcm|dppx)?\s*$/; export var MediaQueryType; (function (MediaQueryType) { MediaQueryType["all"] = "all"; MediaQueryType["print"] = "print"; MediaQueryType["screen"] = "screen"; })(MediaQueryType || (MediaQueryType = {})); export function matchQuery(mediaQuery, values) { const expressions = parseQuery(mediaQuery); return expressions.some((query) => { const { type, inverse, features } = query; // Either the parsed or specified `type` is "all", or the types must be // equal for a match. const typeMatch = query.type === 'all' || values.type === query.type; // Quit early when `type` doesn't match, but take "not" into account if ((typeMatch && inverse) || !(typeMatch || inverse)) { return false; } const expressionsMatch = features.every((feature) => { const value = values[feature.property]; // Missing or falsy values don't match if (!value && value !== 0) { return false; } switch (feature.property) { case 'orientation': case 'prefers-color-scheme': if (typeof value !== 'string') { return false; } return value.toLowerCase() === feature.value.toLowerCase(); default: { // Numeric properties let numVal; if (typeof value !== 'number') { Trace.write(`Unknown CSS media query feature property: '${feature.property}' on '${query}'`, Trace.categories.MediaQuery, Trace.messageType.warn); return false; } switch (feature.property) { case 'width': case 'height': case 'device-width': case 'device-height': { numVal = Length.toDevicePixels(Length.parse(feature.value), 0); break; } default: Trace.write(`Unknown CSS media query feature property: '${feature.property}' on '${query}'`, Trace.categories.MediaQuery, Trace.messageType.warn); break; } switch (feature.modifier) { case 'min': return value >= numVal; case 'max': return value <= numVal; default: return value === numVal; } break; } } }); return (expressionsMatch && !inverse) || (!expressionsMatch && inverse); }); } export function parseQuery(mediaQuery) { const mediaQueryStrings = mediaQuery.split(','); return mediaQueryStrings.map((query) => { query = query.trim(); const captures = query.match(RE_MEDIA_QUERY); // Media query must be valid if (!captures) { throw new SyntaxError(`Invalid CSS media query: '${query}'`); } const modifier = captures[1]; const type = captures[2]; const featureString = ((captures[3] || '') + (captures[4] || '')).trim(); const expression = { inverse: !!modifier && modifier.toLowerCase() === 'not', type: MediaQueryType[type ? type.toLowerCase() : 'all'] ?? 'all', features: [], }; // Check for media query features if (!featureString) { return expression; } // Split features string into a list const features = featureString.match(/\([^\)]+\)/g); // Media query must be valid if (!features) { throw new SyntaxError(`Invalid CSS media query features: '${featureString}' on '${query}'`); } for (const feature of features) { const captures = feature.match(RE_MQ_EXPRESSION); // Media query must be valid if (!captures) { throw new SyntaxError(`Invalid CSS media query feature: '${feature}' on '${query}'`); } const featureData = captures[1].toLowerCase().match(RE_MQ_FEATURE); expression.features.push({ modifier: featureData[1], property: featureData[2], value: captures[2], }); } return expression; }); } //# sourceMappingURL=index.js.map