UNPKG

rn-custom-style-sheet

Version:

React Native component to select a specific value from a range of values.

206 lines (197 loc) 6.89 kB
'use strict'; import { between, down, not, only, up } from '../../../BreakPoint'; import { toPx } from '../../../Core'; import { makeQuery } from '../../Hooks'; const RE_MEDIA_QUERY = // eslint-disable-next-line no-useless-escape /^(?:(only|not)?\s*([_a-z][_a-z0-9-]*)|(\([^\)]+\)))(?:\s*and\s*(.*))?$/i; const RE_MQ_EXPRESSION = // eslint-disable-next-line no-useless-escape /^\(\s*([_a-z-][_a-z0-9-]*)\s*(?:\:\s*([^\)]+))?\s*\)$/; const RE_MQ_FEATURE = /^(?:(min|max|up|down|between|only|not)-)?(.+)/; const RE_LENGTH_UNIT = /(em|rem|px|cm|mm|in|pt|pc)?\s*$/; const RE_RESOLUTION_UNIT = /(dpi|dpcm|dppx)?\s*$/; const RE_COMMENTS = /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi; function matchQuery(mediaQuery, values, guideLineBreakpoint) { return parseQuery(mediaQuery).some(function (query) { const inverse = query.inverse; //const only: boolean = query.only || false; // 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. //only !== (values.only ?? false) if (typeMatch && inverse || !(typeMatch || inverse)) { return false; } const expressionsMatch = query.expressions.every(function (expression) { const feature = expression.feature; const modifier = expression.modifier; let expValue = expression.value; //@ts-ignore let value = values[feature]; // Missing or falsy values don't match. if (!value && value !== 0 && feature !== 'breakpoint') { return false; } switch (feature) { case 'orientation': case 'scan': return value.toLowerCase() === expValue.toLowerCase(); case 'width': case 'height': case 'device-width': case 'device-height': expValue = convertPx(expValue); value = convertPx(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 '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; case 'breakpoint': { switch (modifier) { case 'up': return matchQuery(makeQuery({ query: up(expValue, guideLineBreakpoint) }), values, guideLineBreakpoint); case 'down': return matchQuery(makeQuery({ query: down(expValue, guideLineBreakpoint) }), values, guideLineBreakpoint); case 'between': const range = expValue.replaceAll('[', '').replaceAll(']', '').split(',').map(item => item.trim()); return matchQuery(makeQuery({ query: between(range[0], range[1], guideLineBreakpoint) }), values, guideLineBreakpoint); case 'only': return matchQuery(makeQuery({ query: only(expValue, guideLineBreakpoint) }), values, guideLineBreakpoint); case 'not': return matchQuery(makeQuery({ query: not(expValue, guideLineBreakpoint) }), values, guideLineBreakpoint); default: return value === expValue; } } default: //any } switch (modifier) { case 'min': return value >= expValue; case 'max': return value <= expValue; default: return value === expValue; } }); return expressionsMatch && !inverse || !expressionsMatch && inverse; }); } function parseQuery(mediaQuery) { return mediaQuery.split('#').map(function (query) { // Remove comments first query = query.replace(RE_COMMENTS, ''); 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] ?? '').trim(); const type = (captures[2] ?? '').trim(); const expressions = ((captures[3] ?? '') + (captures[4] ?? '')).trim(); const parsed = { only: false, inverse: false, type: '', expressions: [] }; parsed.only = !!modifier && modifier.toLowerCase() === 'only'; parsed.inverse = !!modifier && modifier.toLowerCase() === 'not'; parsed.type = type ? type.toLowerCase() : 'all'; // Check for media query expressions. if (!expressions) { parsed.expressions = []; return parsed; } // Split expressions into a list. const expressionList = // eslint-disable-next-line no-useless-escape expressions.match(/\([^\)]+\)/g); // Media Query must be valid. if (!expressionList) { throw new SyntaxError('Invalid CSS media query :- "' + expressions + '"'); } parsed.expressions = expressionList.map(function (expression) { const capturesInner = expression.match(RE_MQ_EXPRESSION); // Media Query must be valid. if (!capturesInner) { throw new SyntaxError('Invalid CSS media query := "' + expression + '"'); } const feature = capturesInner?.[1]?.toLowerCase()?.match(RE_MQ_FEATURE); return { modifier: feature?.[1] ?? '', feature: feature?.[2] ?? '', value: capturesInner?.[2] ?? '' }; }); return parsed; }); } function toDecimal(ratio) { let decimal = Number(ratio); let numbers; if (!decimal) { numbers = ratio.match(/^(\d+)\s*\/\s*(\d+)$/); decimal = numbers[1] / numbers[2]; } return decimal; } function toDpi(resolution) { const value = parseFloat(resolution); const 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 convertPx(length) { const value = parseFloat(length); const units = String(length).match(RE_LENGTH_UNIT)?.[1] ?? ''; return toPx(value, units); } function matchMedia(query, values, guideLineBreakpoint) { const isMatches = matchQuery(query, values, guideLineBreakpoint); const media = query; return { isMatches, media }; } export default matchMedia; //# sourceMappingURL=MatchMediaQuery.js.map