UNPKG

bidi-css-js

Version:

Logical, flow-ralative conversion for CSS in JS objects

671 lines (526 loc) 26.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.bidiCSSJS = factory()); }(this, (function () { 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); function isNumber(val) { return typeof val === 'number'; } function isNullOrUndefined(val) { return val === null || typeof val === 'undefined'; } function isObject(val) { return val && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object'; } function isString(val) { return typeof val === 'string'; } function includes(inclusive, inclusee) { return inclusive.indexOf(inclusee) !== -1; } /** * Flip the sign of a CSS value, possibly with a unit. * * We can't just negate the value with unary minus due to the units. * * @private * @param {String} value - the original value (for example 77%) * @return {String} the result (for example -77%) */ function flipSign(value) { if (parseFloat(value) === 0) { // Don't mangle zeroes return value; } if (value[0] === '-') { return value.slice(1); } return '-' + value; } function flipTransformSign(match, prefix, offset, suffix) { return prefix + flipSign(offset) + suffix; } /** * Takes a percentage for background position and inverts it. * This was copied and modified from CSSJanus: * https://github.com/cssjanus/cssjanus/blob/4245f834365f6cfb0239191a151432fb85abab23/src/cssjanus.js#L152-L175 * @param {String} value - the original value (for example 77%) * @return {String} the result (for example 23%) */ function calculateNewBackgroundPosition(value) { var idx = value.indexOf('.'); if (idx === -1) { value = 100 - parseFloat(value) + '%'; } else { // Two off, one for the "%" at the end, one for the dot itself var len = value.length - idx - 2; value = 100 - parseFloat(value); value = value.toFixed(len) + '%'; } return value; } /** * This takes a list of CSS values and converts it to an array * @param {String} value - something like `1px`, `1px 2em`, or `3pt rgb(150, 230, 550) 40px calc(100% - 5px)` * @return {Array} the split values (for example: `['3pt', 'rgb(150, 230, 550)', '40px', 'calc(100% - 5px)']`) */ function getValuesAsList(value) { return value.replace(/ +/g, ' ') // remove all extraneous spaces .split(' ').map(function (i) { return i.trim(); }) // get rid of extra space before/after each item .filter(Boolean) // get rid of empty strings // join items which are within parenthese // luckily `calc (100% - 5px)` is invalid syntax and it must be `calc(100% - 5px)`, otherwise this would be even more complex .reduce(function (_ref3, item) { var list = _ref3.list, state = _ref3.state; var openParansCount = (item.match(/\(/g) || []).length; var closedParansCount = (item.match(/\)/g) || []).length; if (state.parensDepth > 0) { list[list.length - 1] = list[list.length - 1] + ' ' + item; } else { list.push(item); } state.parensDepth += openParansCount - closedParansCount; return { list: list, state: state }; }, { list: [], state: { parensDepth: 0 } }).list; } /** * This is intended for properties that are `top right bottom left` and will switch them to `top left bottom right` * @param {String} value - `1px 2px 3px 4px` for example, but also handles cases where there are too few/too many and * simply returns the value in those cases (which is the correct behavior) * @return {String} the result - `1px 4px 3px 2px` for example. */ function handleQuartetValues(value) { var splitValues = getValuesAsList(value); if (splitValues.length <= 3 || splitValues.length > 4) { return value; } var _splitValues = slicedToArray(splitValues, 4), top = _splitValues[0], right = _splitValues[1], bottom = _splitValues[2], left = _splitValues[3]; return [top, left, bottom, right].join(' '); } // some values require a little fudging, that fudging goes here. var propertyValueConverters = { padding: function padding(_ref) { var value = _ref.value; if (isNumber(value)) { return value; } return handleQuartetValues(value); }, textShadow: function textShadow(_ref2) { var value = _ref2.value; // intentionally leaving off the `g` flag here because we only want to change the first number (which is the offset-x) return value.replace(/(-*)([.|\d]+)/, function (match, negative, number) { if (number === '0') { return match; } var doubleNegative = negative === '' ? '-' : ''; return '' + doubleNegative + number; }); }, borderColor: function borderColor(_ref3) { var value = _ref3.value; return handleQuartetValues(value); }, borderRadius: function borderRadius(_ref4) { var value = _ref4.value; if (isNumber(value)) { return value; } if (includes(value, '/')) { var _value$split = value.split('/'), _value$split2 = slicedToArray(_value$split, 2), radius1 = _value$split2[0], radius2 = _value$split2[1]; var convertedRadius1 = propertyValueConverters.borderRadius({ value: radius1.trim() }); var convertedRadius2 = propertyValueConverters.borderRadius({ value: radius2.trim() }); return convertedRadius1 + ' / ' + convertedRadius2; } var splitValues = getValuesAsList(value); switch (splitValues.length) { case 2: { return splitValues.reverse().join(' '); } case 4: { var _splitValues = slicedToArray(splitValues, 4), topLeft = _splitValues[0], topRight = _splitValues[1], bottomRight = _splitValues[2], bottomLeft = _splitValues[3]; return [topRight, topLeft, bottomLeft, bottomRight].join(' '); } default: { return value; } } }, background: function background(_ref5) { var value = _ref5.value, valuesToConvert = _ref5.valuesToConvert, isRtl = _ref5.isRtl, bgImgDirectionRegex = _ref5.bgImgDirectionRegex, bgPosDirectionRegex = _ref5.bgPosDirectionRegex; // Yeah, this is in need of a refactor 🙃... // but this property is a tough cookie 🍪 // get the backgroundPosition out of the string by removing everything that couldn't be the backgroundPosition value var backgroundPositionValue = value.replace(/(url\(.*?\))|(rgba?\(.*?\))|(hsl\(.*?\))|(#[a-fA-F0-9]+)|((^| )(\D)+( |$))/g, '').trim(); // replace that backgroundPosition value with the converted version value = value.replace(backgroundPositionValue, propertyValueConverters.backgroundPosition({ value: backgroundPositionValue, valuesToConvert: valuesToConvert, isRtl: isRtl, bgPosDirectionRegex: bgPosDirectionRegex })); // do the backgroundImage value replacing on the whole value (because why not?) return propertyValueConverters.backgroundImage({ value: value, valuesToConvert: valuesToConvert, bgImgDirectionRegex: bgImgDirectionRegex }); }, backgroundImage: function backgroundImage(_ref6) { var value = _ref6.value, valuesToConvert = _ref6.valuesToConvert, bgImgDirectionRegex = _ref6.bgImgDirectionRegex; if (!includes(value, 'url(') && !includes(value, 'linear-gradient(')) { return value; } return value.replace(bgImgDirectionRegex, function (match, g1, group2) { return match.replace(group2, valuesToConvert[group2]); }); }, backgroundPosition: function backgroundPosition(_ref7) { var value = _ref7.value, valuesToConvert = _ref7.valuesToConvert, isRtl = _ref7.isRtl, bgPosDirectionRegex = _ref7.bgPosDirectionRegex; return value // intentionally only grabbing the first instance of this because that represents `left` .replace(isRtl ? /^((-|\d|\.)+%)/ : null, function (match, group) { return calculateNewBackgroundPosition(group); }).replace(bgPosDirectionRegex, function (match) { return valuesToConvert[match]; }); }, backgroundPositionX: function backgroundPositionX(_ref8) { var value = _ref8.value, valuesToConvert = _ref8.valuesToConvert, isRtl = _ref8.isRtl, bgPosDirectionRegex = _ref8.bgPosDirectionRegex; if (isNumber(value)) { return value; } return propertyValueConverters.backgroundPosition({ value: value, valuesToConvert: valuesToConvert, isRtl: isRtl, bgPosDirectionRegex: bgPosDirectionRegex }); }, transform: function transform(_ref9) { var value = _ref9.value; // This was copied and modified from CSSJanus: // https://github.com/cssjanus/cssjanus/blob/4a40f001b1ba35567112d8b8e1d9d95eda4234c3/src/cssjanus.js#L152-L153 var nonAsciiPattern = '[^\\u0020-\\u007e]'; var escapePattern = '(?:' + '(?:(?:\\[0-9a-f]{1,6})(?:\\r\\n|\\s)?)' + '|\\\\[^\\r\\n\\f0-9a-f])'; var signedQuantPattern = '((?:-?' + ('(?:[0-9]*\\.[0-9]+|[0-9]+)' + '(?:\\s*' + '(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)' + '|' + ('-?' + ('(?:[_a-z]|' + nonAsciiPattern + '|' + escapePattern + ')') + ('(?:[_a-z0-9-]|' + nonAsciiPattern + '|' + escapePattern + ')') + '*') + ')?') + ')|(?:inherit|auto))'; var translateXRegExp = new RegExp('(translateX\\s*\\(\\s*)' + signedQuantPattern + '(\\s*\\))', 'gi'); var translateRegExp = new RegExp('(translate\\s*\\(\\s*)' + signedQuantPattern + '((?:\\s*,\\s*' + signedQuantPattern + '){0,1}\\s*\\))', 'gi'); var translate3dRegExp = new RegExp('(translate3d\\s*\\(\\s*)' + signedQuantPattern + '((?:\\s*,\\s*' + signedQuantPattern + '){0,2}\\s*\\))', 'gi'); var rotateRegExp = new RegExp('(rotate[ZY]?\\s*\\(\\s*)' + signedQuantPattern + '(\\s*\\))', 'gi'); return value.replace(translateXRegExp, flipTransformSign).replace(translateRegExp, flipTransformSign).replace(translate3dRegExp, flipTransformSign).replace(rotateRegExp, flipTransformSign); } }; propertyValueConverters.margin = propertyValueConverters.padding; propertyValueConverters.borderWidth = propertyValueConverters.padding; propertyValueConverters.boxShadow = propertyValueConverters.textShadow; propertyValueConverters.webkitBoxShadow = propertyValueConverters.boxShadow; propertyValueConverters.mozBoxShadow = propertyValueConverters.boxShadow; propertyValueConverters.WebkitBoxShadow = propertyValueConverters.boxShadow; propertyValueConverters.MozBoxShadow = propertyValueConverters.boxShadow; propertyValueConverters.borderStyle = propertyValueConverters.borderColor; propertyValueConverters.webkitTransform = propertyValueConverters.transform; propertyValueConverters.mozTransform = propertyValueConverters.transform; propertyValueConverters.WebkitTransform = propertyValueConverters.transform; propertyValueConverters.MozTransform = propertyValueConverters.transform; propertyValueConverters.transformOrigin = propertyValueConverters.backgroundPosition; propertyValueConverters.webkitTransformOrigin = propertyValueConverters.transformOrigin; propertyValueConverters.mozTransformOrigin = propertyValueConverters.transformOrigin; propertyValueConverters.WebkitTransformOrigin = propertyValueConverters.transformOrigin; propertyValueConverters.MozTransformOrigin = propertyValueConverters.transformOrigin; // kebab-case versions propertyValueConverters['text-shadow'] = propertyValueConverters.textShadow; propertyValueConverters['border-color'] = propertyValueConverters.borderColor; propertyValueConverters['border-radius'] = propertyValueConverters.borderRadius; propertyValueConverters['background-image'] = propertyValueConverters.backgroundImage; propertyValueConverters['background-position'] = propertyValueConverters.backgroundPosition; propertyValueConverters['background-position-x'] = propertyValueConverters.backgroundPositionX; propertyValueConverters['border-width'] = propertyValueConverters.padding; propertyValueConverters['box-shadow'] = propertyValueConverters.textShadow; propertyValueConverters['-webkit-box-shadow'] = propertyValueConverters.textShadow; propertyValueConverters['-moz-box-shadow'] = propertyValueConverters.textShadow; propertyValueConverters['border-style'] = propertyValueConverters.borderColor; propertyValueConverters['-webkit-transform'] = propertyValueConverters.transform; propertyValueConverters['-moz-transform'] = propertyValueConverters.transform; propertyValueConverters['transform-origin'] = propertyValueConverters.transformOrigin; propertyValueConverters['-webkit-transform-origin'] = propertyValueConverters.transformOrigin; propertyValueConverters['-moz-transform-origin'] = propertyValueConverters.transformOrigin; /* eslint import/no-unresolved:0 */ // this file just makes it easier to import dist/core var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var slicedToArray$1 = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // this will be an object of properties that map to their corresponding rtl property (their doppelganger) var propertiesToConvert = flowRelativeDirectionMapper(['paddingStart', 'paddingLeft', 'paddingRight'], ['paddingEnd', 'paddingRight', 'paddingLeft'], ['marginStart', 'marginLeft', 'marginRight'], ['marginEnd', 'marginRight', 'marginLeft'], ['paddingInlineStart', 'paddingLeft', 'paddingRight'], ['paddingInlineEnd', 'paddingRight', 'paddingLeft'], ['marginInlineStart', 'marginLeft', 'marginRight'], ['marginInlineEnd', 'marginRight', 'marginLeft'], ['insetInlineStart', 'left', 'right'], ['insetInlineEnd', 'right', 'left'], ['start', 'left', 'right'], ['end', 'right', 'left'], ['borderStart', 'borderLeft', 'borderRight'], ['borderEnd', 'borderRight', 'borderLeft'], ['borderStartColor', 'borderLeftColor', 'borderRightColor'], ['borderEndColor', 'borderRightColor', 'borderLeftColor'], ['borderStartStyle', 'borderLeftStyle', 'borderRightStyle'], ['borderEndStyle', 'borderRightStyle', 'borderLeftStyle'], ['borderStartWidth', 'borderLeftWidth', 'borderRightWidth'], ['borderEndWidth', 'borderRightWidth', 'borderLeftWidth'], ['borderInlineStart', 'borderLeft', 'borderRight'], ['borderInlineEnd', 'borderRight', 'borderLeft'], ['borderInlineStartColor', 'borderLeftColor', 'borderRightColor'], ['borderInlineEndColor', 'borderRightColor', 'borderLeftColor'], ['borderInlineStartStyle', 'borderLeftStyle', 'borderRightStyle'], ['borderInlineEndStyle', 'borderRightStyle', 'borderLeftStyle'], ['borderInlineStartWidth', 'borderLeftWidth', 'borderRightWidth'], ['borderInlineEndWidth', 'borderRightWidth', 'borderLeftWidth'], ['borderTopStartRadius', 'borderTopLeftRadius', 'borderTopRightRadius'], ['borderTopEndRadius', 'borderTopRightRadius', 'borderTopLeftRadius'], ['borderBottomStartRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'], ['borderBottomEndRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius'], ['borderStartStartRadius', 'borderTopLeftRadius', 'borderTopRightRadius'], ['borderStartEndRadius', 'borderTopRightRadius', 'borderTopLeftRadius'], ['borderEndStartRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'], ['borderEndEndRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius']); // The properties in this list either natively support flow-relative authoring // or should just not be touched (I'm looking at you `content`) var propertiesToIgnore = ['justifyContent', 'justifyItems', 'justifySelf', 'alignContent', 'alignItems', 'alignSelf', 'grid', 'gridColumnStart', 'gridColumnEnd', 'gridRowStart', 'gridRowEnd', 'gridColumn', 'gridRow', 'gridArea', 'gridTemplateColumns', 'gridTemplateRows', 'gridTemplate', 'gridTemplateAreas', 'content']; // this is the same as the propertiesToConvert except for values var valuesToConvert = flowRelativeDirectionMapper(['ste', 'ltr', 'rtl'], ['ets', 'rtl', 'ltr'], ['start', 'left', 'right'], ['end', 'right', 'left'], ['inline-start', 'left', 'right'], ['inline-end', 'right', 'left'], ['start-resize', 'w-resize', 'e-resize'], ['end-resize', 'e-resize', 'w-resize'], ['bottomstart-resize', 'sw-resize', 'se-resize'], ['bottomend-resize', 'se-resize', 'sw-resize'], ['topstart-resize', 'nw-resize', 'ne-resize'], ['topend-resize', 'ne-resize', 'nw-resize']); var canHaveLogical = ['background', 'backgroundImage', 'backgroundPosition', 'backgroundPositionX', 'borderColor', 'borderRadius', 'borderStyle', 'borderWidth', 'boxShadow', 'mozBoxShadow', 'webkitBoxShadow', 'MozBoxShadow', 'WebkitBoxShadow', 'margin', 'padding', 'textShadow', 'transform', 'mozTransform', 'webkitTransform', 'MozTransform', 'WebkitTransform', 'transformOrigin', 'mozTransformOrigin', 'webkitTransformOrigin', 'MozTransformOrigin', 'WebkitTransformOrigin']; // This regex is used to replace _every_ instance of `ste`, `ets`, `start`, // and `end` in `backgroundimage` with the corresponding logical value, // based on the flow direction. // A situation we're accepting here: // url('/start/end/ste/ets.png') will be changed to // url('/left/right/ltr/rtl.png') when in `ltr` mode var bgImgDirectionRegex = new RegExp('(^|\\W|_)((ste)|(ets)|(start)|(end))(\\W|_|$)', 'g'); var bgPosDirectionRegex = new RegExp('(start)|(end)'); /** * Logically converts properties and values in the CSS in JS object * based on the flow direction context. * @param {Object} object The CSS in JS object * @param {'rtl'|'ltr'} flowDirection The logical flow direction * @return {Object} The converted CSS in JS object */ function convert(object, flowDirection) { var isRtl = typeof flowDirection === 'string' && flowDirection.toLowerCase() === 'rtl'; var isLtr = typeof flowDirection === 'string' && flowDirection.toLowerCase() === 'ltr'; if (!isRtl && !isLtr) { throw new Error('"flowDirection" must either be "rtl" or "ltr", you are trying to pass "' + flowDirection + '"'); } return Object.keys(object).reduce(function (newObj, originalKey) { var originalValue = object[originalKey]; if (isString(originalValue)) { // you're welcome to later code 😺 originalValue = originalValue.trim(); } // Don't touch values that shouldn't be transformed. if (propertiesToIgnore.includes(originalKey)) { return _extends({}, newObj, defineProperty({}, originalKey, originalValue)); } // Try to convert otherwise var _convertProperty = convertProperty(originalKey, originalValue, isRtl), key = _convertProperty.key, value = _convertProperty.value; newObj[key] = value; return newObj; }, {}); } /** * Logically converts a property and its value based on the flow direction context * @param {String} originalKey the original property key * @param {Number|String|Object} originalValue the original css property value * @param {Boolean} isRtl Should conversion happen in RTL context? * @return {Object} the new {key, value} pair */ function convertProperty(originalKey, originalValue, isRtl) { var key = getPropertyDoppelganger(originalKey, isRtl); var value = getValueDoppelganger(key, originalValue, isRtl); return { key: key, value: value }; } /** * Logically gets the direction of the given property based on the flow direction context * @param {String} property the name of the property * @param {Boolean} isRtl Should conversion happen in RTL context? * @return {String} the name of the RTL property */ function getPropertyDoppelganger(property, isRtl) { var convertedProperty = isRtl ? propertiesToConvert.rtl[property] : propertiesToConvert.ltr[property]; return convertedProperty || property; } // let's try to keep the complexity down... // If we have to do this much more, let's break this up /* eslint-disable complexity */ /** * Logically converts the given value to the correct version based on the key and flow direction context * @param {String} key this is the key (note: this should be the RTL version of the originalKey) * @param {String|Number|Object} originalValue the original css property value. If it's an object, then we'll convert that as well * @param {Boolean} isRtl Should conversion happen in RTL context? * @return {String|Number|Object} the converted value */ function getValueDoppelganger(key, originalValue, isRtl) { if (isNullOrUndefined(originalValue)) { return originalValue; } var flowDirection = isRtl ? 'rtl' : 'ltr'; if (isObject(originalValue)) { return convert(originalValue, flowDirection); // recurssion 🌀 } var _analyzeOriginalValue = analyzeOriginalValue(originalValue), isLogical = _analyzeOriginalValue.isLogical, logicallessValue = _analyzeOriginalValue.logicallessValue, isImportant = _analyzeOriginalValue.isImportant, importantlessValue = _analyzeOriginalValue.importantlessValue; if (canHaveLogical.includes(key) && !isLogical) { return originalValue; } var isFourDirectionalShorthand = includes(['margin', 'padding', 'borderColor', 'borderRadius', 'borderStyle', 'borderWidth'], key); if (isLogical && !isRtl && !isFourDirectionalShorthand && !key.match(/(background)|((t|T)ransformOrigin)/)) { return logicallessValue; } var conversionMap = valuesToConvert[flowDirection]; // The logical props and values changes the default way you write four-directional shorhands // so that the order of values is `block-start`, `inline-start`, `block-end` and `inline-end`, which, // for the `inline-*` sides, is the opposite of how they are written without the `logical` keyword if (isLogical && isFourDirectionalShorthand) { return isRtl ? logicallessValue : convertValues(key, importantlessValue, conversionMap, isImportant, // Reversing `isRtl` like this is crooked, but for the time being, it is the easiest way to // address how values of four-directional shorthand properties with the `logical` keyword // should be handled according to the spec. !isRtl); } return convertValues(key, importantlessValue, conversionMap, isImportant, isRtl); } /* eslint-enable complexity */ function analyzeOriginalValue(originalValue) { var isNum = isNumber(originalValue); var logicallessValue = isNum ? originalValue : originalValue.replace(/^\s*logical\s*/i, ''); var isLogical = !isNum && logicallessValue.length !== originalValue.length; var importantlessValue = isNum ? logicallessValue : logicallessValue.replace(/\s*!important.*?$/, ''); var isImportant = !isNum && importantlessValue.length !== logicallessValue.length; return { isLogical: isLogical, logicallessValue: logicallessValue, isImportant: isImportant, importantlessValue: importantlessValue }; } function convertValues(key, value, conversionMap, isImportant, isRtl) { var valueConverter = propertyValueConverters[key]; var newValue = valueConverter ? valueConverter({ value: value, valuesToConvert: conversionMap, isRtl: isRtl, bgImgDirectionRegex: bgImgDirectionRegex, bgPosDirectionRegex: bgPosDirectionRegex }) : conversionMap[value] || value; return isImportant ? newValue + ' !important' : newValue; } function flowRelativeDirectionMapper() { for (var _len = arguments.length, logicanDirectionsMap = Array(_len), _key = 0; _key < _len; _key++) { logicanDirectionsMap[_key] = arguments[_key]; } return logicanDirectionsMap.reduce(function (all, _ref) { var _ref2 = slicedToArray$1(_ref, 3), origValue = _ref2[0], ltrValue = _ref2[1], rtlValue = _ref2[2]; return { ltr: _extends({}, all.ltr, defineProperty({}, origValue, ltrValue)), rtl: _extends({}, all.rtl, defineProperty({}, origValue, rtlValue)) }; }, { ltr: {}, rtl: {} }); } return convert; })));