UNPKG

kepler.gl.geoiq

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

919 lines (814 loc) 89.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.OVERLAY_TYPE = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _colorUtils = require("../utils/color-utils"); var _window = require("global/window"); var _keymirror = _interopRequireDefault(require("keymirror")); var _defaultLayerIcon = _interopRequireDefault(require("./default-layer-icon")); var _defaultSettings = require("../constants/default-settings"); var _customColorRanges = require("../constants/custom-color-ranges"); var _layerFactory = require("./layer-factory"); var _utils = require("../utils/utils"); var _dataUtils = require("../utils/data-utils"); var _dataScaleUtils = require("../utils/data-scale-utils"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var _marked = /*#__PURE__*/ _regenerator["default"].mark(generateColor); /** * Approx. number of points to sample in a large data set * @type {number} */ var MAX_SAMPLE_SIZE = 5000; var OVERLAY_TYPE = (0, _keymirror["default"])({ deckgl: null, mapboxgl: null }); exports.OVERLAY_TYPE = OVERLAY_TYPE; var layerColors = Object.values(_customColorRanges.DataVizColors).map(_colorUtils.hexToRgb); function generateColor() { var index; return _regenerator["default"].wrap(function generateColor$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: index = 0; case 1: if (!(index < layerColors.length + 1)) { _context.next = 7; break; } if (index === layerColors.length) { index = 0; } _context.next = 5; return layerColors[index++]; case 5: _context.next = 1; break; case 7: case "end": return _context.stop(); } } }, _marked); } var colorMaker = generateColor(); var defaultGetFieldValue = function defaultGetFieldValue(field, d) { return d[field.tableFieldIndex - 1]; }; var Layer = /*#__PURE__*/ function () { function Layer() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck2["default"])(this, Layer); this.id = props.id || (0, _utils.generateHashId)(6); // meta this.meta = {}; // visConfigSettings this.visConfigSettings = {}; this.config = this.getDefaultLayerConfig(_objectSpread({ columns: this.getLayerColumns() }, props)); } (0, _createClass2["default"])(Layer, [{ key: "getDefaultLayerConfig", value: function getDefaultLayerConfig() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return { dataId: props.dataId || null, label: props.label || 'new layer', color: props.color || colorMaker.next().value, columns: props.columns || null, isVisible: props.isVisible || false, isConfigActive: props.isConfigActive || false, highlightColor: props.highlightColor || [252, 242, 26, 255], // TODO: refactor this into separate visual Channel config // color by field, domain is set by filters, field, scale type colorField: null, colorDomain: [0, 1], colorScale: 'quantile', // color by size, domain is set by filters, field, scale type sizeDomain: [0, 1], sizeScale: 'linear', sizeField: null, visConfig: {}, textLabel: { field: null, color: [255, 255, 255], size: 50, offset: [0, 0], anchor: 'middle' } }; } /** * Get the description of a visualChannel config * @param key * @returns {{label: string, measure: (string|string)}} */ }, { key: "getVisualChannelDescription", value: function getVisualChannelDescription(key) { // e.g. label: Color, measure: Vehicle Type return { label: this.visConfigSettings[this.visualChannels[key].range].label, measure: this.config[this.visualChannels[key].field] ? this.config[this.visualChannels[key].field].name : this.visualChannels[key].defaultMeasure }; } /** * Assign a field to layer column, return column config * @param key - Column Key * @param field - Selected field * @returns {{}} - Column config */ }, { key: "assignColumn", value: function assignColumn(key, field) { // field value could be null for optional columns var update = field ? { value: field.name, fieldIdx: field.tableFieldIndex - 1 } : { value: null, fieldIdx: -1 }; return _objectSpread({}, this.config.columns, (0, _defineProperty2["default"])({}, key, _objectSpread({}, this.config.columns[key], {}, update))); } /** * Assign a field pair to column config, return column config * @param key - Column Key * @param pair - field Pair * @returns {{}} - Column config */ }, { key: "assignColumnPairs", value: function assignColumnPairs(key, pair) { var _objectSpread3; if (!this.columnPairs || !this.columnPairs[key]) { // should not end in this state return this.config.columns; } var _this$columnPairs$key = this.columnPairs[key], partnerKey = _this$columnPairs$key.pair, fieldPairKey = _this$columnPairs$key.fieldPairKey; var partnerFieldPairKey = this.columnPairs[partnerKey].fieldPairKey; return _objectSpread({}, this.config.columns, (_objectSpread3 = {}, (0, _defineProperty2["default"])(_objectSpread3, key, pair[fieldPairKey]), (0, _defineProperty2["default"])(_objectSpread3, partnerKey, pair[partnerFieldPairKey]), _objectSpread3)); } /** * Calculate a radius zoom multiplier to render points, so they are visible in all zoom level * @param mapState * @param mapState.zoom - actual zoom * @param mapState.zoomOffset - zoomOffset when render in the plot container for export image * @returns {number} */ }, { key: "getZoomFactor", value: function getZoomFactor(_ref) { var zoom = _ref.zoom, _ref$zoomOffset = _ref.zoomOffset, zoomOffset = _ref$zoomOffset === void 0 ? 0 : _ref$zoomOffset; return Math.pow(2, Math.max(14 - zoom + zoomOffset, 0)); } /** * Calculate a elevation zoom multiplier to render points, so they are visible in all zoom level * @param mapState * @param mapState.zoom - actual zoom * @param mapState.zoomOffset - zoomOffset when render in the plot container for export image * @returns {number} */ }, { key: "getElevationZoomFactor", value: function getElevationZoomFactor(_ref2) { var zoom = _ref2.zoom, _ref2$zoomOffset = _ref2.zoomOffset, zoomOffset = _ref2$zoomOffset === void 0 ? 0 : _ref2$zoomOffset; return Math.pow(2, Math.max(8 - zoom + zoomOffset, 0)); } }, { key: "formatLayerData", value: function formatLayerData(data, allData, filteredIndex) { return {}; } }, { key: "axiosApiCall", value: function axiosApiCall() { return {}; } }, { key: "renderLayer", value: function renderLayer() { return []; } }, { key: "getHoverData", value: function getHoverData(object) { if (!object) { return null; } // by default, each entry of layerData should have a data property points // to the original item in the allData array // each layer can implement its own getHoverData method return object.data; } /** * When change layer type, try to copy over layer configs as much as possible * @param configToCopy - config to copy over * @param visConfigSettings - visConfig settings of config to copy */ }, { key: "assignConfigToLayer", value: function assignConfigToLayer(configToCopy, visConfigSettings) { var _this = this; // don't deep merge visualChannel field var notToDeepMerge = Object.values(this.visualChannels).map(function (v) { return v.field; }); // don't deep merge color range, reversed: is not a key by default notToDeepMerge.push('colorRange'); // don't copy over domain var notToCopy = Object.values(this.visualChannels).map(function (v) { return v.domain; }); // if range is for the same property group copy it, otherwise, not to copy Object.values(this.visualChannels).forEach(function (v) { if (configToCopy.visConfig[v.range] && visConfigSettings[v.range].group !== _this.visConfigSettings[v.range].group) { notToCopy.push(v.range); } }); // don't copy over visualChannel range var currentConfig = this.config; var copied = this.copyLayerConfig(currentConfig, configToCopy, { notToDeepMerge: notToDeepMerge, notToCopy: notToCopy }); this.updateLayerConfig(copied); // validate visualChannel field type and scale types Object.keys(this.visualChannels).forEach(function (channel) { _this.validateVisualChannel(channel); }); } /* * Recursively copy config over to an empty layer * when received saved config, or copy config over from a different layer type * make sure to only copy over value to existing keys * @param {object} currentConfig - existing config to be override * @param {object} configToCopy - new Config to copy over * @param {string[]} notToDeepMerge - array of properties to not to be deep copied * @param {string[]} notToCopy - array of properties not to copy * @returns {object} - copied config */ }, { key: "copyLayerConfig", value: function copyLayerConfig(currentConfig, configToCopy) { var _this2 = this; var _ref3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref3$notToDeepMerge = _ref3.notToDeepMerge, notToDeepMerge = _ref3$notToDeepMerge === void 0 ? [] : _ref3$notToDeepMerge, _ref3$notToCopy = _ref3.notToCopy, notToCopy = _ref3$notToCopy === void 0 ? [] : _ref3$notToCopy; var copied = {}; Object.keys(currentConfig).forEach(function (key) { if ((0, _utils.isPlainObject)(currentConfig[key]) && (0, _utils.isPlainObject)(configToCopy[key]) && !notToDeepMerge.includes(key) && !notToCopy.includes(key)) { // recursively assign object value copied[key] = _this2.copyLayerConfig(currentConfig[key], configToCopy[key], { notToDeepMerge: notToDeepMerge, notToCopy: notToCopy }); } else if ((0, _utils.notNullorUndefined)(configToCopy[key]) && !notToCopy.includes(key)) { // copy copied[key] = configToCopy[key]; } else { // keep existing copied[key] = currentConfig[key]; } }); return copied; } }, { key: "registerVisConfig", value: function registerVisConfig(layerVisConfigs) { var _this3 = this; Object.keys(layerVisConfigs).forEach(function (item) { if (typeof item === 'string' && _layerFactory.LAYER_VIS_CONFIGS[layerVisConfigs[item]]) { // if assigned one of default LAYER_CONFIGS _this3.config.visConfig[item] = _layerFactory.LAYER_VIS_CONFIGS[layerVisConfigs[item]].defaultValue; _this3.visConfigSettings[item] = _layerFactory.LAYER_VIS_CONFIGS[layerVisConfigs[item]]; } else if (['type', 'defaultValue'].every(function (p) { return layerVisConfigs[item][p]; })) { // if provided customized visConfig, and has type && defaultValue // TODO: further check if customized visConfig is valid _this3.config.visConfig[item] = layerVisConfigs[item].defaultValue; _this3.visConfigSettings[item] = layerVisConfigs[item]; } }); } }, { key: "getLayerColumns", value: function getLayerColumns() { var required = this.requiredLayerColumns.reduce(function (accu, key) { return _objectSpread({}, accu, (0, _defineProperty2["default"])({}, key, { value: null, fieldIdx: -1 })); }, {}); var optional = this.optionalColumns.reduce(function (accu, key) { return _objectSpread({}, accu, (0, _defineProperty2["default"])({}, key, { value: null, fieldIdx: -1, optional: true })); }, {}); return _objectSpread({}, required, {}, optional); } }, { key: "updateLayerConfig", value: function updateLayerConfig(newConfig) { this.config = _objectSpread({}, this.config, {}, newConfig); return this; } }, { key: "updateLayerVisConfig", value: function updateLayerVisConfig(newVisConfig) { this.config.visConfig = _objectSpread({}, this.config.visConfig, {}, newVisConfig); return this; } /** * Check whether layer has all columns * * @param {object} layer * @returns {boolean} yes or no */ }, { key: "hasAllColumns", value: function hasAllColumns() { var columns = this.config.columns; return columns && Object.values(columns).every(function (v) { return Boolean(v.optional || v.value && v.fieldIdx > -1); }); } /** * Check whether layer has data * * @param {object} layer * @param {Array | Object} layerData * @returns {boolean} yes or no */ }, { key: "hasLayerData", value: function hasLayerData(layerData) { if (!layerData) { return false; } return Boolean(layerData.data && layerData.data.length); } }, { key: "isValidToSave", value: function isValidToSave() { return this.type && this.hasAllColumns(); } }, { key: "shouldRenderLayer", value: function shouldRenderLayer(data) { return this.type && this.hasAllColumns() && this.config.isVisible && this.hasLayerData(data); } }, { key: "getVisChannelScale", value: function getVisChannelScale(scale, domain, range, fixed) { return _defaultSettings.SCALE_FUNC[fixed ? 'linear' : scale]().domain(domain).range(fixed ? domain : range); } }, { key: "getPointsBounds", value: function getPointsBounds(allData, getPosition) { // no need to loop through the entire dataset // get a sample of data to calculate bounds var sampleData = allData.length > MAX_SAMPLE_SIZE ? (0, _dataUtils.getSampleData)(allData, MAX_SAMPLE_SIZE) : allData; var points = sampleData.map(getPosition); var latBounds = (0, _dataUtils.getLatLngBounds)(points, 1, [-90, 90]); var lngBounds = (0, _dataUtils.getLatLngBounds)(points, 0, [-180, 180]); if (!latBounds || !lngBounds) { return null; } return [lngBounds[0], latBounds[0], lngBounds[1], latBounds[1]]; } }, { key: "getLightSettingsFromBounds", value: function getLightSettingsFromBounds(bounds) { return Array.isArray(bounds) && bounds.length >= 4 ? _objectSpread({}, _defaultSettings.DEFAULT_LIGHT_SETTINGS, { lightsPosition: [].concat((0, _toConsumableArray2["default"])(bounds.slice(0, 2)), [_defaultSettings.DEFAULT_LIGHT_SETTINGS.lightsPosition[2]], (0, _toConsumableArray2["default"])(bounds.slice(2, 4)), [_defaultSettings.DEFAULT_LIGHT_SETTINGS.lightsPosition[5]]) }) : _defaultSettings.DEFAULT_LIGHT_SETTINGS; } }, { key: "getEncodedChannelValue", value: function getEncodedChannelValue(scale, data, field) { var defaultValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _defaultSettings.NO_VALUE_COLOR; var getValue = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : defaultGetFieldValue; var type = field.type; var value = getValue(field, data); var attributeValue; if (type === _defaultSettings.ALL_FIELD_TYPES.timestamp) { // shouldn't need to convert here // scale Function should take care of it attributeValue = scale(new Date(value)); } else { attributeValue = scale(value); } if (!attributeValue) { attributeValue = defaultValue; } return attributeValue; } }, { key: "updateMeta", value: function updateMeta(meta) { this.meta = _objectSpread({}, this.meta, {}, meta); } /** * helper function to update one layer domain when state.data changed * if state.data change is due ot update filter, newFiler will be passed * called by updateAllLayerDomainData * @param {Object} dataset * @param {Object} newFilter * @returns {object} layer * @returns {object} widget */ }, { key: "updateLayerDomain", value: function updateLayerDomain(dataset, newFilter) { var _this4 = this; Object.values(this.visualChannels).forEach(function (channel) { var scale = channel.scale; var scaleType = _this4.config[scale]; // ordinal domain is based on allData, if only filter changed // no need to update ordinal domain if (!newFilter || scaleType !== _defaultSettings.SCALE_TYPES.ordinal) { var domain = channel.domain; var updatedDomain = _this4.calculateLayerDomain(dataset, channel); _this4.updateLayerConfig((0, _defineProperty2["default"])({}, domain, updatedDomain)); } }); return this; } /** * Validate visual channel field and scales based on supported field & scale type * @param channel */ }, { key: "validateVisualChannel", value: function validateVisualChannel(channel) { this.validateFieldType(channel); this.validateScale(channel); } /** * Validate field type based on channelScaleType */ }, { key: "validateFieldType", value: function validateFieldType(channel) { var visualChannel = this.visualChannels[channel]; var field = visualChannel.field, channelScaleType = visualChannel.channelScaleType, supportedFieldTypes = visualChannel.supportedFieldTypes; if (this.config[field]) { // if field is selected, check if field type is supported var channelSupportedFieldTypes = supportedFieldTypes || _defaultSettings.CHANNEL_SCALE_SUPPORTED_FIELDS[channelScaleType]; if (!channelSupportedFieldTypes.includes(this.config[field].type)) { // field type is not supported, set it back to null // set scale back to default this.updateLayerConfig((0, _defineProperty2["default"])({}, field, null)); } } } /** * Validate scale type based on aggregation */ }, { key: "validateScale", value: function validateScale(channel) { var visualChannel = this.visualChannels[channel]; var scale = visualChannel.scale; if (!scale) { // visualChannel doesn't have scale return; } var scaleOptions = this.getScaleOptions(channel); // check if current selected scale is // supported, if not, change to default if (!scaleOptions.includes(this.config[scale])) { this.updateLayerConfig((0, _defineProperty2["default"])({}, scale, scaleOptions[0])); } } /** * Get scale options based on current field * @param {string} channel * @returns {string[]} */ }, { key: "getScaleOptions", value: function getScaleOptions(channel) { var visualChannel = this.visualChannels[channel]; var field = visualChannel.field, scale = visualChannel.scale, channelScaleType = visualChannel.channelScaleType; return this.config[field] ? _defaultSettings.FIELD_OPTS[this.config[field].type].scale[channelScaleType] : [this.getDefaultLayerConfig()[scale]]; } }, { key: "updateLayerVisualChannel", value: function updateLayerVisualChannel(dataset, channel) { var visualChannel = this.visualChannels[channel]; this.validateVisualChannel(channel); // calculate layer channel domain var updatedDomain = this.calculateLayerDomain(dataset, visualChannel); this.updateLayerConfig((0, _defineProperty2["default"])({}, visualChannel.domain, updatedDomain)); } }, { key: "calculateLayerDomain", value: function calculateLayerDomain(dataset, visualChannel) { var allData = dataset.allData, filteredIndexForDomain = dataset.filteredIndexForDomain; var defaultDomain = [0, 1]; var scale = visualChannel.scale; var scaleType = this.config[scale]; var field = this.config[visualChannel.field]; if (!field) { // if colorField or sizeField were set back to null return defaultDomain; } if (!_defaultSettings.SCALE_TYPES[scaleType]) { _window.console.error("scale type ".concat(scaleType, " not supported")); return defaultDomain; } // TODO: refactor to add valueAccessor to field var fieldIdx = field.tableFieldIndex - 1; var isTime = field.type === _defaultSettings.ALL_FIELD_TYPES.timestamp; var valueAccessor = _dataUtils.maybeToDate.bind(null, isTime, fieldIdx, field.format); var indexValueAccessor = function indexValueAccessor(i) { return valueAccessor(allData[i]); }; var sortFunction = (0, _dataUtils.getSortingFunction)(field.type); switch (scaleType) { case _defaultSettings.SCALE_TYPES.ordinal: case _defaultSettings.SCALE_TYPES.point: // do not recalculate ordinal domain based on filtered data // don't need to update ordinal domain every time return (0, _dataScaleUtils.getOrdinalDomain)(allData, valueAccessor); case _defaultSettings.SCALE_TYPES.quantile: return (0, _dataScaleUtils.getQuantileDomain)(filteredIndexForDomain, indexValueAccessor, sortFunction); case _defaultSettings.SCALE_TYPES.quantize: case _defaultSettings.SCALE_TYPES.linear: case _defaultSettings.SCALE_TYPES.sqrt: default: return (0, _dataScaleUtils.getLinearDomain)(filteredIndexForDomain, indexValueAccessor); } } }, { key: "isLayerHovered", value: function isLayerHovered(objectInfo) { return objectInfo && objectInfo.layer && objectInfo.picked && objectInfo.layer.props.id === this.id; } }, { key: "getRadiusScaleByZoom", value: function getRadiusScaleByZoom(mapState, fixedRadius) { var radiusChannel = Object.values(this.visualChannels).find(function (vc) { return vc.property === 'radius'; }); if (!radiusChannel) { return 1; } var field = radiusChannel.field; var fixed = fixedRadius === undefined ? this.config.visConfig.fixedRadius : fixedRadius; var radius = this.config.visConfig.radius; return fixed ? 1 : (this.config[field] ? 1 : radius) * this.getZoomFactor(mapState); } }, { key: "shouldCalculateLayerData", value: function shouldCalculateLayerData(props) { var _this5 = this; return props.some(function (p) { return !_this5.noneLayerDataAffectingProps.includes(p); }); } }, { key: "axiosApiCall", value: function axiosApiCall() { return null; } }, { key: "layerIcon", get: function get() { return _defaultLayerIcon["default"]; } }, { key: "overlayType", get: function get() { return OVERLAY_TYPE.deckgl; } }, { key: "type", get: function get() { return null; } }, { key: "name", get: function get() { return this.type; } }, { key: "isAggregated", get: function get() { return false; } }, { key: "requiredLayerColumns", get: function get() { return []; } }, { key: "optionalColumns", get: function get() { return []; } }, { key: "noneLayerDataAffectingProps", get: function get() { return ['label', 'opacity', 'thickness', 'isVisible']; } }, { key: "visualChannels", get: function get() { return { color: { property: 'color', field: 'colorField', scale: 'colorScale', domain: 'colorDomain', range: 'colorRange', key: 'color', channelScaleType: _defaultSettings.CHANNEL_SCALES.color }, size: { property: 'size', field: 'sizeField', scale: 'sizeScale', domain: 'sizeDomain', range: 'sizeRange', key: 'size', channelScaleType: _defaultSettings.CHANNEL_SCALES.size } }; } /* * Column pairs maps layer column to a specific field pairs, * By default, it is set to null */ }, { key: "columnPairs", get: function get() { return null; } /* * Default point column pairs, can be used for point based layers: point, icon etc. */ }, { key: "defaultPointColumnPairs", get: function get() { return { lat: { pair: 'lng', fieldPairKey: 'lat' }, lng: { pair: 'lat', fieldPairKey: 'lng' } }; } /* * Default link column pairs, can be used for link based layers: arc, line etc */ }, { key: "defaultLinkColumnPairs", get: function get() { return { lat0: { pair: 'lng0', fieldPairKey: 'lat' }, lng0: { pair: 'lat0', fieldPairKey: 'lng' }, lat1: { pair: 'lng1', fieldPairKey: 'lat' }, lng1: { pair: 'lat1', fieldPairKey: 'lng' } }; } /** * Return a React component for to render layer instructions in a modal * @returns {object} - an object * @example * return { * id: 'iconInfo', * template: IconInfoModal, * modalProps: { * title: 'How to draw icons' * }; * } */ }, { key: "layerInfoModal", get: function get() { return null; } /* * Given a dataset, automatically create layers based on it * and return the props * By default, no layers will be found */ }], [{ key: "findDefaultLayerProps", value: function findDefaultLayerProps(fieldPairs, dataId) { return null; } /** * Given a array of preset required column names * found field that has the same name to set as layer column * * @param {object[]} defaultFields * @param {object[]} allFields * @returns {object[] | null} all possible required layer column pairs */ }, { key: "findDefaultColumnField", value: function findDefaultColumnField(defaultFields, allFields) { // find all matched fields for each required col var requiredColumns = Object.keys(defaultFields).reduce(function (prev, key) { var requiredFields = allFields.filter(function (f) { return f.name === defaultFields[key] || defaultFields[key].includes(f.name); }); prev[key] = requiredFields.length ? requiredFields.map(function (f) { return { value: f.name, fieldIdx: f.tableFieldIndex - 1 }; }) : null; return prev; }, {}); if (!Object.values(requiredColumns).every(Boolean)) { // if any field missing, return null return null; } return this.getAllPossibleColumnPairs(requiredColumns); } }, { key: "getAllPossibleColumnPairs", value: function getAllPossibleColumnPairs(requiredColumns) { // for multiple matched field for one required column, return multiple // combinations, e. g. if column a has 2 matched, column b has 3 matched // 6 possible column pairs will be returned var allKeys = Object.keys(requiredColumns); var pointers = allKeys.map(function (k, i) { return i === allKeys.length - 1 ? -1 : 0; }); var countPerKey = allKeys.map(function (k) { return requiredColumns[k].length; }); var pairs = []; /* eslint-disable no-loop-func */ while (incrementPointers(pointers, countPerKey, pointers.length - 1)) { var newPair = pointers.reduce(function (prev, cuur, i) { prev[allKeys[i]] = requiredColumns[allKeys[i]][cuur]; return prev; }, {}); pairs.push(newPair); } /* eslint-enable no-loop-func */ // recursively increment pointers function incrementPointers(pts, counts, index) { if (index === 0 && pts[0] === counts[0] - 1) { // nothing to increment return false; } if (pts[index] + 1 < counts[index]) { pts[index] = pts[index] + 1; return true; } pts[index] = 0; return incrementPointers(pts, counts, index - 1); } return pairs; } }, { key: "hexToRgb", value: function hexToRgb(c) { return (0, _colorUtils.hexToRgb)(c); } }]); return Layer; }(); exports["default"] = Layer; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sYXllcnMvYmFzZS1sYXllci5qcyJdLCJuYW1lcyI6WyJnZW5lcmF0ZUNvbG9yIiwiTUFYX1NBTVBMRV9TSVpFIiwiT1ZFUkxBWV9UWVBFIiwiZGVja2dsIiwibWFwYm94Z2wiLCJsYXllckNvbG9ycyIsIk9iamVjdCIsInZhbHVlcyIsIkRhdGFWaXpDb2xvcnMiLCJtYXAiLCJoZXhUb1JnYiIsImluZGV4IiwibGVuZ3RoIiwiY29sb3JNYWtlciIsImRlZmF1bHRHZXRGaWVsZFZhbHVlIiwiZmllbGQiLCJkIiwidGFibGVGaWVsZEluZGV4IiwiTGF5ZXIiLCJwcm9wcyIsImlkIiwibWV0YSIsInZpc0NvbmZpZ1NldHRpbmdzIiwiY29uZmlnIiwiZ2V0RGVmYXVsdExheWVyQ29uZmlnIiwiY29sdW1ucyIsImdldExheWVyQ29sdW1ucyIsImRhdGFJZCIsImxhYmVsIiwiY29sb3IiLCJuZXh0IiwidmFsdWUiLCJpc1Zpc2libGUiLCJpc0NvbmZpZ0FjdGl2ZSIsImhpZ2hsaWdodENvbG9yIiwiY29sb3JGaWVsZCIsImNvbG9yRG9tYWluIiwiY29sb3JTY2FsZSIsInNpemVEb21haW4iLCJzaXplU2NhbGUiLCJzaXplRmllbGQiLCJ2aXNDb25maWciLCJ0ZXh0TGFiZWwiLCJzaXplIiwib2Zmc2V0IiwiYW5jaG9yIiwia2V5IiwidmlzdWFsQ2hhbm5lbHMiLCJyYW5nZSIsIm1lYXN1cmUiLCJuYW1lIiwiZGVmYXVsdE1lYXN1cmUiLCJ1cGRhdGUiLCJmaWVsZElkeCIsInBhaXIiLCJjb2x1bW5QYWlycyIsInBhcnRuZXJLZXkiLCJmaWVsZFBhaXJLZXkiLCJwYXJ0bmVyRmllbGRQYWlyS2V5Iiwiem9vbSIsInpvb21PZmZzZXQiLCJNYXRoIiwicG93IiwibWF4IiwiZGF0YSIsImFsbERhdGEiLCJmaWx0ZXJlZEluZGV4Iiwib2JqZWN0IiwiY29uZmlnVG9Db3B5Iiwibm90VG9EZWVwTWVyZ2UiLCJ2IiwicHVzaCIsIm5vdFRvQ29weSIsImRvbWFpbiIsImZvckVhY2giLCJncm91cCIsImN1cnJlbnRDb25maWciLCJjb3BpZWQiLCJjb3B5TGF5ZXJDb25maWciLCJ1cGRhdGVMYXllckNvbmZpZyIsImtleXMiLCJjaGFubmVsIiwidmFsaWRhdGVWaXN1YWxDaGFubmVsIiwiaW5jbHVkZXMiLCJsYXllclZpc0NvbmZpZ3MiLCJpdGVtIiwiTEFZRVJfVklTX0NPTkZJR1MiLCJkZWZhdWx0VmFsdWUiLCJldmVyeSIsInAiLCJyZXF1aXJlZCIsInJlcXVpcmVkTGF5ZXJDb2x1bW5zIiwicmVkdWNlIiwiYWNjdSIsIm9wdGlvbmFsIiwib3B0aW9uYWxDb2x1bW5zIiwibmV3Q29uZmlnIiwibmV3VmlzQ29uZmlnIiwiQm9vbGVhbiIsImxheWVyRGF0YSIsInR5cGUiLCJoYXNBbGxDb2x1bW5zIiwiaGFzTGF5ZXJEYXRhIiwic2NhbGUiLCJmaXhlZCIsIlNDQUxFX0ZVTkMiLCJnZXRQb3NpdGlvbiIsInNhbXBsZURhdGEiLCJwb2ludHMiLCJsYXRCb3VuZHMiLCJsbmdCb3VuZHMiLCJib3VuZHMiLCJBcnJheSIsImlzQXJyYXkiLCJERUZBVUxUX0xJR0hUX1NFVFRJTkdTIiwibGlnaHRzUG9zaXRpb24iLCJzbGljZSIsIk5PX1ZBTFVFX0NPTE9SIiwiZ2V0VmFsdWUiLCJhdHRyaWJ1dGVWYWx1ZSIsIkFMTF9GSUVMRF9UWVBFUyIsInRpbWVzdGFtcCIsIkRhdGUiLCJkYXRhc2V0IiwibmV3RmlsdGVyIiwic2NhbGVUeXBlIiwiU0NBTEVfVFlQRVMiLCJvcmRpbmFsIiwidXBkYXRlZERvbWFpbiIsImNhbGN1bGF0ZUxheWVyRG9tYWluIiwidmFsaWRhdGVGaWVsZFR5cGUiLCJ2YWxpZGF0ZVNjYWxlIiwidmlzdWFsQ2hhbm5lbCIsImNoYW5uZWxTY2FsZVR5cGUiLCJzdXBwb3J0ZWRGaWVsZFR5cGVzIiwiY2hhbm5lbFN1cHBvcnRlZEZpZWxkVHlwZXMiLCJDSEFOTkVMX1NDQUxFX1NVUFBPUlRFRF9GSUVMRFMiLCJzY2FsZU9wdGlvbnMiLCJnZXRTY2FsZU9wdGlvbnMiLCJGSUVMRF9PUFRTIiwiZmlsdGVyZWRJbmRleEZvckRvbWFpbiIsImRlZmF1bHREb21haW4iLCJDb25zb2xlIiwiZXJyb3IiLCJpc1RpbWUiLCJ2YWx1ZUFjY2Vzc29yIiwibWF5YmVUb0RhdGUiLCJiaW5kIiwiZm9ybWF0IiwiaW5kZXhWYWx1ZUFjY2Vzc29yIiwiaSIsInNvcnRGdW5jdGlvbiIsInBvaW50IiwicXVhbnRpbGUiLCJxdWFudGl6ZSIsImxpbmVhciIsInNxcnQiLCJvYmplY3RJbmZvIiwibGF5ZXIiLCJwaWNrZWQiLCJtYXBTdGF0ZSIsImZpeGVkUmFkaXVzIiwicmFkaXVzQ2hhbm5lbCIsImZpbmQiLCJ2YyIsInByb3BlcnR5IiwidW5kZWZpbmVkIiwicmFkaXVzIiwiZ2V0Wm9vbUZhY3RvciIsInNvbWUiLCJub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMiLCJEZWZhdWx0TGF5ZXJJY29uIiwiQ0hBTk5FTF9TQ0FMRVMiLCJsYXQiLCJsbmciLCJsYXQwIiwibG5nMCIsImxhdDEiLCJsbmcxIiwiZmllbGRQYWlycyIsImRlZmF1bHRGaWVsZHMiLCJhbGxGaWVsZHMiLCJyZXF1aXJlZENvbHVtbnMiLCJwcmV2IiwicmVxdWlyZWRGaWVsZHMiLCJmaWx0ZXIiLCJmIiwiZ2V0QWxsUG9zc2libGVDb2x1bW5QYWlycyIsImFsbEtleXMiLCJwb2ludGVycyIsImsiLCJjb3VudFBlcktleSIsInBhaXJzIiwiaW5jcmVtZW50UG9pbnRlcnMiLCJuZXdQYWlyIiwiY3V1ciIsInB0cyIsImNvdW50cyIsImMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBVUE7O0FBQ0E7O0FBRUE7O0FBRUE7O0FBT0E7Ozs7Ozs7OzZCQWtCVUEsYTs7QUFaVjs7OztBQUlBLElBQU1DLGVBQWUsR0FBRyxJQUF4QjtBQUVPLElBQU1DLFlBQVksR0FBRywyQkFBVTtBQUNwQ0MsRUFBQUEsTUFBTSxFQUFFLElBRDRCO0FBRXBD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