diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..ea05f38 --- /dev/null +++ b/.babelrc @@ -0,0 +1,6 @@ +{ + "presets": ["@babel/env"], + "plugins": [ + "transform-react-jsx" + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0b886c1..f76c706 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,4 @@ -* -!.* -!*.js -!*.d.ts -!*.json -!*.md -!*.txt -.DS_Store \ No newline at end of file +.DS_Store +.idea +node_modules +dist/* diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4befed3 --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +.DS_Store +.idea diff --git a/build.js b/build.js index 57a2ea1..d013886 100644 --- a/build.js +++ b/build.js @@ -1,595 +1,44 @@ -/** - * This file is part of the @iconify/react package. - * - * (c) Vjacheslav Trushkin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +"use strict"; const fs = require('fs'); -const path = require('path'); -const tools = require('@iconify/json-tools'); +const babel = require('@babel/core'); -/* - Configuration - */ - -// Log progress -let log = true; - -// Cleanup -let doCleanup = true; - -// Validate prefix -let validatePrefix = true; - -// Ignore errors -let ignoreErrors = false; - -// Source directory -let sourceDir = null; - -// Target directory -let targetDir = __dirname; - -// List of allowed files. If null, directory will be scanned -let allowFiles = null; - -// List of prefixes to allow and skip -let allowSets = null, - skipSets = null; - -// True if .d.ts files should be added -let typeScript = true; - -/** - * Recursively create directory - * - * @param path - */ -const mkdir = path => { - let dirs = typeof path === 'string' ? path.split('/') : path, - dir; - - if (dirs.length) { - dir = ''; - dirs.forEach(part => { - dir += part; - if (dir.length) { - try { - fs.mkdirSync(dir, 0o755); - } catch (err) { - } - } - dir += '/'; - }); - } -}; - -/** - * Clean up directory - * - * @param {string} dir Directory to remove - * @param {boolean} [includeDir] True if directory should be removed as well - * @return {*} Error object or number of deleted files - */ -const cleanup = (dir, includeDir) => { - let counter = 0, - errors = []; - - function rec(extra) { - let ignored = false, - files; - - try { - files = fs.readdirSync(dir + extra); - } catch (err) { - errors.push({ - error: err, - filename: dir + extra, - type: 'readdir' - }); - return; - } - - files.forEach(file => { - let filename = dir + extra + '/' + file, - stats = fs.lstatSync(filename); - - if (stats.isDirectory()) { - if (rec(extra + '/' + file)) { - // true returned - directory has ignored files - ignored = true; - return; - } - - // Try to remove directory - try { - fs.rmdirSync(filename); - } catch (err) { - errors.push({ - error: err, - filename: filename, - type: 'dir' - }); - ignored = true; - } - return; - } - - if (stats.isFile() || stats.isSymbolicLink()) { - // Try to remove file - try { - fs.unlinkSync(filename); - counter ++; - } catch (err) { - errors.push({ - error: err, - filename: filename, - type: 'file' - }); - ignored = true; - } - return; - } - - errors.push({ - filename: filename, - type: 'unknown' - }); - }); - - return ignored; - } - - if (!rec('') && includeDir) { - try { - fs.rmdirSync(dir); - counter ++; - } catch (err) { - errors.push({ - error: err, - filename: dir, - type: 'dir' - }); - } - } - - return errors.length ? errors : counter; -}; - -/** - * Check if directory exists - * - * @param {string} dir - * @return {boolean} - */ -const isDir = dir => { +function fileExists(filename) { + let stats; try { - let stat = fs.statSync(dir); - return stat.isDirectory(); - } catch (err) { + stats = fs.statSync(filename); + } catch (e) { return false; } -}; - -/** - * Convert object to string - * - * @param data - * @return {string} - */ -const stringify = data => JSON.stringify(data, null, '\t'); - -/** - * Export collection - * - * @param collection - * @param dir - * @return {boolean} - */ -const exportCollection = (collection, dir) => { - let icons = 0, - aliases = 0; - - /** - * Export typescript file - * - * @param {string} filename - * @param {string} [name] - */ - const exportTS = (filename, name) => { - name = typeof name === 'string' ? name : 'data'; - fs.writeFileSync(filename + '.d.ts', 'declare const ' + name + ': object;\nexport default ' + name + ';\n'); - }; - - /** - * Export icon - * - * @param name - * @param data - */ - const exportIcon = (name, data) => { - if (data === null) { - throw new Error('Got null for icon ' + name); - } - - data = Object.assign(Object.create(null), data); - delete data.parent; - Object.keys(data).forEach(key => { - if (key.slice(0, 1) === '_') { - delete data[key]; - } - }); - - let content = stringify(data); - content = 'export default ' + content + ';\n'; - fs.writeFileSync(dir + '/' + name + '.js', content, 'utf8'); - if (typeScript) { - exportTS(dir + '/' + name); - } - }; - - /** - * Export alias - * - * @param name - * @param data - */ - const exportAlias = (name, data) => { - if (data === null) { - throw new Error('Got null for alias ' + name); - } - - data = Object.assign(Object.create(null), data); - - let parent = data.parent; - - const exportSimpleAlias = () => { - let content = 'import data from \'./' + parent + '\';\n'; - content += 'export default data;\n'; - fs.writeFileSync(dir + '/' + name + '.js', content, 'utf8'); - if (typeScript) { - exportTS(dir + '/' + name); - } - }; - - const exportComplexAlias = () => { - let content = 'import data from \'./' + parent + '\';\n'; - content += '\nlet alias = Object.assign(Object.create(null), data);\n'; - - let keys = Object.keys(data); - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - switch (key) { - case 'hFlip': - case 'vFlip': - content += 'alias.' + key + ' = !alias.' + key + ';\n'; - break; - case 'rotate': - content += 'alias.' + key + ' = (alias.' + key + ' ? alias.' + key + ' : 0) + ' + data[key] + ';\n'; - break; - - case 'width': - case 'height': - case 'left': - case 'top': - case 'inlineTop': - case 'inlineHeight': - case 'verticalAlign': - content += 'alias.' + key + ' = ' + data[key] + ';\n'; - break; - - default: - return false; - } - } - - content += '\nexport default alias;\n'; - fs.writeFileSync(dir + '/' + name + '.js', content, 'utf8'); - if (typeScript) { - exportTS(dir + '/' + name, 'alias'); - } - return true; - }; - - delete data.parent; - - if (!Object.keys(data).length) { - // Alias without modifications - exportSimpleAlias(); - return true; - } - - return exportComplexAlias(); - }; - - - // Export icons - Object.keys(collection.items.icons).forEach(icon => { - exportIcon(icon, collection.getIconData(icon, false)); - icons ++; - }); - - // Export aliases - if (collection.items.aliases !== void 0) { - Object.keys(collection.items.aliases).forEach(icon => { - if (!exportAlias(icon, collection.items.aliases[icon])) { - // Failed to export as alias - export as icon - exportIcon(icon, collection.getIconData(icon, false)); - } - aliases ++; - }); - } - - if (log) { - console.log('[' + collection.prefix() + '] Exported ' + icons + ' icons' + (aliases ? ', ' + aliases + ' aliases.' : '')); - } return true; -}; - -/* - Resolve command line parameters - */ -let args = process.argv.slice(2); -if (!args.length) { - // Use default build command - args = '--package @iconify/json --dir json --target {dir} --typescript'.split(' '); } -for (let i = 0; i < args.length; i++) { - let dir; - - switch (args[i]) { - case '--skip': - // Skip packages - if ((++ i) >= args.length) { - throw new Error('Missing list of prefixes for ' + args[i - 1] + '\nCorrect usage: node build ' + args[i - 1] + ' fa-brands,mdi-light,vaadin'); - } - args[i].toLowerCase().split(',').forEach(prefix => { - if (skipSets === null) { - skipSets = []; - } - skipSets.push(prefix.trim()); - }); - break; - - case '--filter': - case '--prefix': - case '--prefixes': - // Filter packages - if ((++ i) >= args.length) { - throw new Error('Missing list of prefixes for ' + args[i - 1] + '\nCorrect usage: node build ' + args[i - 1] + ' fa-solid,mdi-light,ant-design'); - } - args[i].toLowerCase().split(',').forEach(prefix => { - if (allowSets === null) { - allowSets = []; - } - allowSets.push(prefix.trim()); - }); - break; - - case '--file': - case '--files': - // Filter packages - if ((++ i) >= args.length) { - throw new Error('Missing list of files for ' + args[i - 1] + '\nCorrect usage: node build ' + args[i - 1] + ' fa.json,mdi.json'); - } - args[i].toLowerCase().split(',').forEach(file => { - if (allowFiles === null) { - allowFiles = []; - } - allowFiles.push(file.trim()); - }); - break; - - case '--package': - case '--module': - // Import from custom package instead of @iconify/json - if ((++ i) >= args.length) { - throw new Error('Missing package name for ' + args[i - 1] + '\nCorrect usage: node build ' + args[i - 1] + ' custom-package --dir json'); - } - - // Check if its a package name - let parts = args[i].split('/'); - if (parts.length === 1 || (parts.length === 2 && parts[0].slice(0, 1) === '@')) { - // Resolve package.json to find root directory of that package - sourceDir = path.dirname(require.resolve(args[i] + '/package.json')); - } else { - // Resolve as file, extract directory from it - sourceDir = path.dirname(require.resolve(args[i])); - - // Check if last parameter points to JSON file - if (parts[parts.length - 1].split('.').pop() === 'json') { - if (allowFiles === null) { - allowFiles = []; - } - allowFiles.push(parts[parts.length - 1]); - } - } - break; - - case '--dir': - case '--source': - // Import from directory inside package - // Should be added after --package - if ((++ i) >= args.length) { - throw new Error('Missing directory name for ' + args[i - 1] + '\nCorrect usage (for files from custom-package): node build --package custom-package ' + args[i - 1] + ' json\nCorrect usage (for files in current working directory): node build ' + args[i - 1] + ' json'); - } - if (sourceDir === null) { - // Use current working directory - sourceDir = ''; - } - dir = args[i].replace('{dir}', __dirname); - if (dir.slice(0, 1) === '/' && sourceDir !== '') { - dir = dir.slice(1); - } - if (dir.slice(-1) === '/') { - dir = dir.slice(0, dir.length - 1); - } - if (!dir.length) { - // Empty directory - throw new Error('Invalid directory name for ' + args[i - 1]); - } - sourceDir += (sourceDir === '' ? '' : '/') + dir; - break; - - case '--target': - // Target directory - if ((++ i) >= args.length) { - throw new Error('Missing directory name for ' + args[i - 1] + '\nCorrect usage: node build ' + args[i - 1] + ' output-dir'); - } - dir = args[i].replace('{dir}', __dirname); - if (dir.slice(-1) === '/') { - dir = dir.slice(0, dir.length - 1); - } - if (!dir.length) { - // Empty directory - throw new Error('Invalid directory name for ' + args[i - 1]); - } - targetDir = dir; - break; - - case '--no-cleanup': - doCleanup = false; - break; - - case '--cleanup': - doCleanup = true; - break; - - case '--ignore-prefix': - validatePrefix = false; - break; - - case '--validate-prefix': - validatePrefix = true; - break; - - case '--no-typescript': - typeScript = false; - break; - - case '--typescript': - typeScript = true; - break; - - case '--ignore-errors': - ignoreErrors = true; - break; +const rootDir = __dirname; +let presets = JSON.parse(fs.readFileSync(rootDir + '/.babelrc', 'utf8')); - case '--silent': - case '--no-log': - log = false; - break; +['icon'].forEach(filename => { + // Transpile .js file + let source = rootDir + '/src/' + filename + '.js', + target = rootDir + '/dist/' + filename + '.js'; - case '--verbose': - case '--log': - log = true; - break; + if (fileExists(source)) { + let code = fs.readFileSync(source), + result = babel.transform(code, presets); - default: - throw new Error('Unknown parameter ' + args[i]); + fs.writeFileSync(target, result.code, 'utf8'); + console.log('Transpiled', filename + '.js'); } -} - -if (sourceDir === null) { - // Missing source - throw new Error('Missing source.\nTo parse JSON files from Iconify JSON use: node build --package @iconify/json --dir json\nTo parse JSON files from custom directory use: node build --source ./path/to/directory'); -} - -/* - Find all icon sets - */ -let files = Object.create(null); -if (allowFiles !== null) { - // Use only allow files - allowFiles.forEach(file => { - let filename = path.resolve(sourceDir, file), - prefix = file.split('/').pop().split('.').shift(); - - try { - let stats = fs.lstatSync(filename); - if (!stats.isFile()) { - return; - } - } catch (err) { - // No such file? - return; - } - files[prefix] = filename; - }); -} else { - // Scan directory - fs.readdirSync(sourceDir).forEach(file => { - let parts = file.split('.'); - if (parts.length !== 2 || parts.pop() !== 'json') { - // File must be in prefix.json format - return; - } + // Copy optional files + ['.d.ts'].forEach(ext => { + let source = rootDir + '/src/' + filename + ext, + target = rootDir + '/dist/' + filename + ext; - let prefix = parts.shift(); - if (skipSets !== null && skipSets.indexOf(prefix) !== -1) { - // Skip - return; - } - if (allowSets !== null && allowSets.indexOf(prefix) === -1) { - // Not allowed - return; + if (fileExists(source)) { + fs.writeFileSync(target, fs.readFileSync(source, 'utf8'), 'utf8'); + console.log('Copied', filename + ext); } - - files[prefix] = sourceDir + '/' + file; }); -} - -if (!Object.keys(files).length) { - if (ignoreErrors) { - return; - } - throw new Error('No JSON files to parse.'); -} - -/* - Load and export all collections - */ -let parsed = Object.create(null); -Object.keys(files).forEach(prefix => { - let source = files[prefix], - collection = new tools.Collection(prefix); - - // Load collection - if (!collection.loadFromFile(source)) { - if (ignoreErrors) { - return; - } - throw new Error('Error loading collection from ' + source); - } - - if (collection.prefix() !== prefix) { - if (validatePrefix) { - if (ignoreErrors) { - return; - } - throw new Error('Collection loaded from ' + source + ' has prefix "' + collection.prefix() + '", expected "' + prefix + '"'); - } - prefix = collection.prefix(); - } - - // Clean up or create directory - let target = targetDir + '/' + prefix; - if (parsed[prefix] === void 0) { - parsed[prefix] = true; - if (doCleanup) { - if (isDir(target)) { - cleanup(target, false); - } - } - mkdir(target); - } +}); - // Write all files - exportCollection(collection, target); -}); \ No newline at end of file diff --git a/icon.js b/icon.js deleted file mode 100644 index 601defe..0000000 --- a/icon.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * This file is part of the @iconify/react package. - * - * (c) Vjacheslav Trushkin - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import React from 'react'; -import SVG from '@iconify/json-tools/src/svg'; -import normalize from '@iconify/json-tools/src/normalize'; - -const component = (props, inline) => { - if (typeof props.icon !== 'object') { - return null; - } - - // Split properties into SVG properties and icon properties - let split = SVG.splitAttributes(props), - iconProps = split.icon, - customAttributes = split.node; - - delete customAttributes.icon; - - // Set default inline value - if (iconProps.inline === void 0) { - iconProps.inline = inline; - } - - // Get SVG data - let svg = new SVG(normalize(props.icon)); - let iconData = svg.getAttributes(iconProps); - - // Set style - let style = { - transform: 'rotate(360deg)' - }; - - if (iconData.style['vertical-align'] !== void 0) { - style.verticalAlign = iconData.style['vertical-align']; - } - if (props.style !== void 0) { - style = Object.assign(style, props.style); - } - - // Generate element attributes - let attributes = Object.assign({ - xmlns: 'http://www.w3.org/2000/svg', - focusable: false, - style: style - }, customAttributes, iconData.attributes); - - attributes.dangerouslySetInnerHTML = {__html: iconData.body}; - - // Generate SVG - return React.createElement('svg', attributes, null); -}; - -export const Icon = props => component(props, false); -export const InlineIcon = props => component(props, true); - -export default Icon; diff --git a/package-lock.json b/package-lock.json index 976d586..37c056d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,991 @@ { "name": "@iconify/react", - "version": "1.0.8", + "version": "1.1.0-beta1", "lockfileVersion": 1, "requires": true, "dependencies": { - "@iconify/json": { - "version": "1.0.110", - "resolved": "https://registry.npmjs.org/@iconify/json/-/json-1.0.110.tgz", - "integrity": "sha512-wRi1ZZibPSQBcjKJsHoZURJFrWS6QRyyFoLhZYw6WCfDD53mkXUO0mb69e+52ORlDgcML3A17xhDvHm7tMIiwQ==" + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } }, - "@iconify/json-tools": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@iconify/json-tools/-/json-tools-1.0.6.tgz", - "integrity": "sha512-mBM+Zk1rodeQ+RdpHj4RWFBMErC0YTca5npOlNqJr/6TFjHN5qnY7GYWe4rf/poB6L9BYrJ73irz1hyeLE1CDA==" + "@babel/core": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-define-map": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } + }, + "@babel/helpers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", + "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.11" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", + "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", + "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", + "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", + "dev": true, + "requires": { + "regexp-tree": "^0.1.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", + "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", + "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", + "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", + "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } + }, + "@babel/preset-env": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", + "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.4.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.4.4", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.4.4", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-modules-systemjs": "^7.4.4", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.4.4", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-reserved-words": "^7.2.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + } + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "browserslist": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.1.tgz", + "integrity": "sha512-1MC18ooMPRG2UuVFJTHFIAkk6mpByJfxCrnUyvSlu/hyQSFHMrlhM02SzNuCV+quTP4CKmqtOMAIjrifrpBJXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000971", + "electron-to-chromium": "^1.3.137", + "node-releases": "^1.1.21" + } + }, + "caniuse-lite": { + "version": "1.0.30000973", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000973.tgz", + "integrity": "sha512-/F3t/Yo8LEdRSEPCmI15fLu5vepVh9UCg/9inJXF5AAfW7xRRJkbaM2ut52iRMQMnGCLQouLbFdbOA+VEFOIsg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "dev": true + }, + "core-js-compat": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.3.tgz", + "integrity": "sha512-EP018pVhgwsKHz3YoN1hTq49aRe+h017Kjz0NQz3nXV0cCRMvH3fLQl+vEPGr4r4J5sk4sU3tUC7U1aqTCeJeA==", + "dev": true, + "requires": { + "browserslist": "^4.6.0", + "core-js-pure": "3.1.3", + "semver": "^6.1.0" + }, + "dependencies": { + "semver": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "dev": true + } + } + }, + "core-js-pure": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.3.tgz", + "integrity": "sha512-k3JWTrcQBKqjkjI0bkfXS0lbpWPxYuHWfMMjC1VDmzU4Q58IwSbuXSo99YO/hUHlw/EB4AlfA2PVxOGkrIq6dA==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "electron-to-chromium": { + "version": "1.3.144", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.144.tgz", + "integrity": "sha512-jNRFJpfNrYm5uJ4x0q9oYMOfbL0JPOlkNli8GS/5zEmCjnE5jAtoCo4BYajHiqSPqEeAjtTdItL4p7EZw+jSfg==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -27,11 +994,44 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node-releases": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.22.tgz", + "integrity": "sha512-O6XpteBuntW1j86mw6LlovBIwTe+sO2+7vi9avQffNeIW4upgnaCVm6xrBWH+KATz7mNNRNNeEpuWB7dT6Cr3w==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, "prop-types": { "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", @@ -58,6 +1058,94 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", + "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, + "regexp-tree": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", + "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "dev": true + }, + "regexpu-core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "regjsgen": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "scheduler": { "version": "0.13.6", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", @@ -66,6 +1154,67 @@ "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "dev": true } } } diff --git a/package.json b/package.json index f889889..fdd8f6f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@iconify/react", "description": "Iconify icon component for React.", "author": "Vjacheslav Trushkin", - "version": "1.0.8", + "version": "1.1.0-beta1", "license": "MIT", "bugs": "https://github.com/iconify/iconify-react/issues", "homepage": "https://github.com/iconify/iconify-react", @@ -11,13 +11,16 @@ "url": "git+ssh://git@github.com/iconify/iconify-react.git" }, "scripts": { - "install": "node build" + "build": "node build" }, - "main": "icon.js", - "types": "icon.d.ts", + "main": "src/icon.js", + "types": "src/icon.d.ts", "dependencies": { - "@iconify/json": "^1.0.110", - "@iconify/json-tools": "^1.0.5", "react": "^16.8.3" + }, + "devDependencies": { + "@babel/core": "^7.4.5", + "@babel/preset-env": "^7.4.5", + "babel-plugin-transform-react-jsx": "^6.24.1" } } diff --git a/readme.md b/readme.md index a250c7a..9506c08 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ Iconify is a modern open source SVG alternative to glyph fonts. It is a unified framework, aimed to offer all popular icon sets with one easy to use syntax: Font Awesome, Material Design Icons, Jam Icons and several emoji sets: Noto Emoji, Twemoji, EmojiOne, Firefox OS Emoji. -You can use over 30,000 icons without installing multiple dependencies. It can also be used with custom and premium icon sets. No fonts, no massive packages. +You can use over 40,000 icons without installing multiple dependencies. It can also be used with custom and premium icon sets. No fonts, no massive packages. Iconify for React generates separate files for each icon, so when compiling your application only icons you use in project will be bundled. That means you can use FontAwesome, MDI, Vaadin, EmojiOne and other icons on same page without loading massive amounts of data. @@ -18,24 +18,17 @@ If you are using Yarn: yarn add @iconify/react ``` -Package does not include icons. Icons will be generated during installation. - -## Updating - -Unfortunately NPM and Yarn do not re-run installation script when updating dependencies. This makes it impossible to automatically keep icons up to date. - -To re-build icons you can either re-install @iconify/react (uninstall it then install it again) or run this after updating dependencies: -``` -node node_modules/@iconify/react/build -``` +Package does not include icons. Icons are split into separate packages that available at NPM. See below. ## Usage +Install `@iconify/react` and package for selected icons set, import Icon and/or InlineIcon from `@iconify/react` and icon data for icon you want to use: ``` import { Icon, InlineIcon } from "@iconify/react"; -import home from "@iconify/react/mdi-light/home"; -import faceWithMonocle from "@iconify/react/twemoji/face-with-monocle"; +import home from "@iconify/icons-mdi-light/home"; +import faceWithMonocle from "@iconify/icons-twemoji/face-with-monocle"; ``` +Then use Icon or InlineIcon component with icon data as "icon" parameter: ```

This is some text with

@@ -62,61 +55,113 @@ Custom properties: ## TypeScript -Iconify for React is compatible with TypeScript. By default build script generates .d.ts files for each icon. See build script command line options below. +Iconify for React is compatible with TypeScript. + +If you are using TypeScript, only attributes "id", "className" and "style" are passed to node. If you want to pass other custom attributes, edit dist/icon.d.ts file (or suggest a change by opening issue on @iconify/react repository). -If you are using TypeScript, only attributes "id", "className" and "style" are passed to node. If you want to pass other custom attributes, edit icon.d.ts file (or suggest a change by opening issue on @iconify/react repository). +## Icon packages -## Icons list +As of version 1.1.0 this package no longer includes icons. There are over 40k icons, each in its won file. That takes a lot of disc space. +Because of that icons were moved to multiple separate packages, one package per icon set. -See [Iconify icon sets page](https://iconify.design/icon-sets/) for list of available icons. +You can find all available icons at https://iconify.design/icon-sets/ -## Importing icons +Browse or search icons, click any icon and you will see "React" tab that will give you exact code for React component. -Import format for each icon is "@iconify/react/{prefix}/{icon}" where {prefix} is collection prefix, {icon} is icon name. +Import format for each icon is "@iconify/icon-{prefix}/{icon}" where {prefix} is collection prefix, {icon} is icon name. -Import imports JSON data for icon, to render it use Icon or InlineIcon component. +Usage examples for few popular icon packages: -Each icon is split in its own file, so only icons that you import are compiled when you build React application. -You can use any name for imported icon. For example: +### Material Design Icons + +Package: https://www.npmjs.com/package/@iconify/icons-mdi + +Icons list: https://iconify.design/icon-sets/mdi/ + +Installation: ``` -import notCat from "@iconify/react/noto-v1/dog"; +npm install @iconify/icons-mdi ``` +Usage: +``` +import { Icon, InlineIcon } from "@iconify/react"; +import home from "@iconify/icons-mdi/home"; +import accountCheck from "@iconify/icons-mdi/account-check"; +``` +``` + +

This is some text with

+``` + -## Build script +### Simple Icons (big collection of logos) -You can use build script with custom icon sets that have been converted to [Iconify JSON format](https://iconify.design/docs/json-icon-format/). +Package: https://www.npmjs.com/package/@iconify/icons-simple-icons -Add your own JSON files to directory "json", run build script from command line: +Icons list: https://iconify.design/icon-sets/simple-icons/ +Installation: +``` +npm install @iconify/icons-mdi +``` +Usage: +``` +import { Icon, InlineIcon } from "@iconify/react"; +import behanceIcon from "@iconify/icons-simple-icons/behance"; +import mozillafirefoxIcon from "@iconify/icons-simple-icons/mozillafirefox"; +``` ``` -node node_modules/@iconify/react/build --source json --target icons --typescript + +

Mozilla Firefox is the best browser!

``` -where "json" is directory where JSON files are, "icons" is directory where components will be exported. -There are more command line options: +### Font Awesome 5 Solid -* --skip foo,bar: list of prefixes to ignore. -* --filter foo,bar: list of prefixes to include. If set, all other prefixes will be ignored -* --file json/custom.json: file to parse -* --files json/custom.json,json/custom2.json: list of additional files to parse, separated by comma. -* --package @iconify/json: parse JSON files in installed package. Use in combination with --dir if files are in sub-directory (see package.json for example). -* --source json: directory where JSON files are located. -* --dir json: sub-directory where JSON files are located, used in combination with --package (see package.json for example). -* --target icons: directory where to save components. Build script will also create sub-directories with prefixes, so for example fa-home will be in icons/fa/home.js -* --typescript: export .d.ts files for each icon. This option doubles amount of files, but it is needed if you are using React with TypeScript. Enabled by default. -* --no-typescript: do not export .d.ts files. Use this if you are not using TypeScript to reduce amount of exported files. -* --no-cleanup: prevent build script from deleting old files. By default everything in target directory is removed to clean up old build data, this will prevent clean up. -* --silent: prevent build script from logging export process. -* --ignore-prefix: do not validate prefixes. By default build script requires filenames to match prefixes, so for example "fa-solid" should be in "fa-solid.json", adding this to command line will prevent that check. -* --ignore-errors: do not stop on error. This applies only to invalid json files. Script will throw errors even with --ignore-errors when there are bad command line parameters. +Package: https://www.npmjs.com/package/@iconify/icons-fa-solid -Examples: -```node node_modules/@iconify/react/build --source json --target icons -node node_modules/@iconify/react/build --module @iconify/json --dir json --target iconify-icons --filter fa-brands,logos,brandico -node node_modules/@iconify/react/build --module @iconify/json --dir json --target iconify-icons --skip fa-brands,logos,brandico --silent +Icons list: https://iconify.design/icon-sets/fa-solid/ + +Installation: +``` +npm install @iconify/icons-fa-solid +``` +Usage: +``` +import { Icon, InlineIcon } from "@iconify/react"; +import toggleOn from "@iconify/icons-fa-solid/toggle-on"; +import chartBar from "@iconify/icons-fa-solid/chart-bar"; +``` +``` + +

Click to toggle

+``` + +### Noto Emoji + +Package: https://www.npmjs.com/package/@iconify/icons-noto + +Icons list: https://iconify.design/icon-sets/noto/ + +Installation: +``` +npm install @iconify/icons-noto +``` +Usage: +``` +import { Icon, InlineIcon } from "@iconify/react"; +import greenApple from "@iconify/icons-noto/green-apple"; +import huggingFace from "@iconify/icons-noto/hugging-face"; +``` +``` + +

Its time for hugs !

``` +### Other icon sets + +There are over 50 icon sets. This readme shows only few examples. See [Iconify icon sets](http://iconify.design/icon-sets/) for list of available icon sets. Click any icon to see code. + ## License React component is released with MIT license. diff --git a/icon.d.ts b/src/icon.d.ts similarity index 100% rename from icon.d.ts rename to src/icon.d.ts diff --git a/src/icon.js b/src/icon.js new file mode 100644 index 0000000..d966470 --- /dev/null +++ b/src/icon.js @@ -0,0 +1,592 @@ +/** + * This file is part of the @iconify/react package. + * + * (c) Vjacheslav Trushkin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import React from 'react'; + +/** + * Unique id counter + * + * @type {number} + */ +let idCounter = 0; + +/** + * Regex used to split dimensions + * + * @type {RegExp} + * @private + */ +const unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g; +const unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g; + +/** + * Attributes used for icon + * + * @type {string[]} + */ +const iconAttributes = ['width', 'height', 'inline', 'hFlip', 'vFlip', 'flip', 'rotate', 'align', 'color', 'box']; + +/** + * Default attribute values + * + * @type {object} + */ +const defaultAttributes = { + left: 0, + top: 0, + width: 16, + height: 16, + rotate: 0, + hFlip: false, + vFlip: false +}; + +/** + * Add missing properties to icon + * + * Important: in PHP version of this library this function is part of Collection class: Collection::addMissingAttributes() + * + * JavaScript version uses separate file so this function could be used in React and other components without loading + * entire Collection class. + * + * @param {object} data + * @return {object} + */ +function normalize(data) { + let item = Object.assign(Object.create(null), defaultAttributes, data); + if (item.inlineTop === void 0) { + item.inlineTop = item.top; + } + if (item.inlineHeight === void 0) { + item.inlineHeight = item.height; + } + if (item.verticalAlign === void 0) { + // -0.143 if icon is designed for 14px height, + // otherwise assume icon is designed for 16px height + item.verticalAlign = item.height % 7 === 0 && item.height % 8 !== 0 ? -0.143 : -0.125; + } + return item; +} + +/** + * Get preserveAspectRatio attribute value + * + * @param {object} align + * @return {string} + * @private + */ +function getAlignment(align) { + let result; + switch (align.horizontal) { + case 'left': + result = 'xMin'; + break; + + case 'right': + result = 'xMax'; + break; + + default: + result = 'xMid'; + } + switch (align.vertical) { + case 'top': + result += 'YMin'; + break; + + case 'bottom': + result += 'YMax'; + break; + + default: + result += 'YMid'; + } + result += align.slice ? ' slice' : ' meet'; + return result; +} + +/** + * SVG class + * + * @see @iconify/json-tools/src/svg.js + */ +class SVG { + /** + * Constructor + * + * @param icon Icon data + * Use Collection.getIconData() to retrieve icon data + */ + constructor(icon) { + this._item = icon; + } + + /** + * Get SVG attributes + * + * @param {object} props Custom properties (same as query string in Iconify API) + * @returns {string} + */ + getAttributes(props) { + let item = this._item; + if (typeof props !== 'object') { + props = Object.create(null); + } + + // Set data + let align = { + horizontal: 'center', + vertical: 'middle', + slice: false + }; + let transform = { + rotate: item.rotate, + hFlip: item.hFlip, + vFlip: item.vFlip + }; + let style = Object.create(null); + + let attributes = Object.create(null); + + // Get width/height + let inline = props.inline === true || props.inline === 'true' || props.inline === '1'; + + let box = { + left: item.left, + top: inline ? item.inlineTop : item.top, + width: item.width, + height: inline ? item.inlineHeight : item.height + }; + + // Transformations + ['hFlip', 'vFlip'].forEach(key => { + if (props[key] !== void 0 && (props[key] === true || props[key] === 'true' || props[key] === '1')) { + transform[key] = !transform[key]; + } + }); + if (props.flip !== void 0) { + props.flip.toLowerCase().split(/[\s,]+/).forEach(value => { + switch (value) { + case 'horizontal': + transform.hFlip = !transform.hFlip; + break; + + case 'vertical': + transform.vFlip = !transform.vFlip; + } + }); + } + if (props.rotate !== void 0) { + let value = props.rotate; + if (typeof value === 'number') { + transform.rotate += value; + } else if (typeof value === 'string') { + let units = value.replace(/^-?[0-9.]*/, ''); + if (units === '') { + value = parseInt(value); + if (!isNaN(value)) { + transform.rotate += value; + } + } else if (units !== value) { + let split = false; + switch (units) { + case '%': + // 25% -> 1, 50% -> 2, ... + split = 25; + break; + + case 'deg': + // 90deg -> 1, 180deg -> 2, ... + split = 90; + } + if (split) { + value = parseInt(value.slice(0, value.length - units.length)); + if (!isNaN(value)) { + transform.rotate += Math.round(value / split); + } + } + } + } + } + + // Apply transformations to box + let transformations = [], + tempValue; + if (transform.hFlip) { + if (transform.vFlip) { + transform.rotate += 2; + } else { + // Horizontal flip + transformations.push('translate(' + (box.width + box.left) + ' ' + (0 - box.top) + ')'); + transformations.push('scale(-1 1)'); + box.top = box.left = 0; + } + } else if (transform.vFlip) { + // Vertical flip + transformations.push('translate(' + (0 - box.left) + ' ' + (box.height + box.top) + ')'); + transformations.push('scale(1 -1)'); + box.top = box.left = 0; + } + switch (transform.rotate % 4) { + case 1: + // 90deg + tempValue = box.height / 2 + box.top; + transformations.unshift('rotate(90 ' + tempValue + ' ' + tempValue + ')'); + // swap width/height and x/y + if (box.left !== 0 || box.top !== 0) { + tempValue = box.left; + box.left = box.top; + box.top = tempValue; + } + if (box.width !== box.height) { + tempValue = box.width; + box.width = box.height; + box.height = tempValue; + } + break; + + case 2: + // 180deg + transformations.unshift('rotate(180 ' + (box.width / 2 + box.left) + ' ' + (box.height / 2 + box.top) + ')'); + break; + + case 3: + // 270deg + tempValue = box.width / 2 + box.left; + transformations.unshift('rotate(-90 ' + tempValue + ' ' + tempValue + ')'); + // swap width/height and x/y + if (box.left !== 0 || box.top !== 0) { + tempValue = box.left; + box.left = box.top; + box.top = tempValue; + } + if (box.width !== box.height) { + tempValue = box.width; + box.width = box.height; + box.height = tempValue; + } + break; + } + + // Calculate dimensions + // Values for width/height: null = default, 'auto' = from svg, false = do not set + // Default: if both values aren't set, height defaults to '1em', width is calculated from height + let customWidth = props.width ? props.width : null; + let customHeight = props.height ? props.height : null; + + let width, height; + if (customWidth === null && customHeight === null) { + customHeight = '1em'; + } + if (customWidth !== null && customHeight !== null) { + width = customWidth; + height = customHeight; + } else if (customWidth !== null) { + width = customWidth; + height = SVG.calculateDimension(width, box.height / box.width); + } else { + height = customHeight; + width = SVG.calculateDimension(height, box.width / box.height); + } + + if (width !== false) { + attributes.width = width === 'auto' ? box.width : width; + } + if (height !== false) { + attributes.height = height === 'auto' ? box.height : height; + } + + // Add vertical-align for inline icon + if (inline && item.verticalAlign !== 0) { + style['vertical-align'] = item.verticalAlign + 'em'; + } + + // Check custom alignment + if (props.align !== void 0) { + props.align.toLowerCase().split(/[\s,]+/).forEach(value => { + switch (value) { + case 'left': + case 'right': + case 'center': + align.horizontal = value; + break; + + case 'top': + case 'bottom': + case 'middle': + align.vertical = value; + break; + + case 'crop': + align.slice = true; + break; + + case 'meet': + align.slice = false; + } + }); + } + + // Generate viewBox and preserveAspectRatio attributes + attributes.preserveAspectRatio = getAlignment(align); + attributes.viewBox = box.left + ' ' + box.top + ' ' + box.width + ' ' + box.height; + + // Generate body + let body = SVG.replaceIDs(item.body); + + if (props.color !== void 0) { + body = body.replace(/currentColor/g, props.color); + } + if (transformations.length) { + body = '' + body + ''; + } + if (props.box === true || props.box === 'true' || props.box === '1') { + // Add transparent bounding box + body += ''; + } + + return { + attributes: attributes, + body: body, + style: style + }; + } + + /** + * Generate SVG + * + * @param {object} props Custom properties (same as query string in Iconify API) + * @param {boolean} [addExtra] True if extra attributes should be added to SVG. + * Due to lack of functions in JavaScript for escaping attributes, it is your job to make sure key and value are both properly escaped. Default value is false. + * @returns {string} + */ + getSVG(props, addExtra) { + let attributes = SVG.splitAttributes(props), + data = this.getAttributes(attributes.icon); + + let svg = ' { + svg += ' ' + attr + '="' + attributes.node[attr] + '"'; + }); + } + + // Add SVG attributes + Object.keys(data.attributes).forEach(attr => { + svg += ' ' + attr + '="' + data.attributes[attr] + '"'; + }); + + // Add style with 360deg transformation to style to prevent subpixel rendering bug + svg += ' style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);'; + Object.keys(data.style).forEach(attr => { + svg += ' ' + attr + ': ' + data.style[attr] + ';'; + }); + if (props && props.style !== void 0) { + svg += props.style; + } + svg += '">'; + + svg += data.body + ''; + + return svg; + } + + /** + * Split attributes + * + * @param props + * @return {{icon: {}, node: {}}} + */ + static splitAttributes(props) { + let result = { + icon: Object.create(null), + node: Object.create(null) + }; + + Object.keys(props).forEach(name => { + result[iconAttributes.indexOf(name) === -1 ? 'node' : 'icon'][name] = props[name]; + }); + + return result; + } + + /** + * Calculate second dimension when only 1 dimension is set + * + * @param {string|number} size One dimension (such as width) + * @param {number} ratio Width/height ratio. + * If size == width, ratio = height/width + * If size == height, ratio = width/height + * @param {number} [precision] Floating number precision in result to minimize output. Default = 100 + * @return {string|number|null} Another dimension, null on error + */ + static calculateDimension(size, ratio, precision) { + if (ratio === 1) { + return size; + } + + precision = precision === void 0 ? 100 : precision; + if (typeof size === 'number') { + return Math.ceil(size * ratio * precision) / precision; + } + + // split code into sets of strings and numbers + let split = size.split(unitsSplit); + if (split === null || !split.length) { + return null; + } + let results = [], + code = split.shift(), + isNumber = unitsTest.test(code), + num; + + while (true) { + if (isNumber) { + num = parseFloat(code); + if (isNaN(num)) { + results.push(code); + } else { + results.push(Math.ceil(num * ratio * precision) / precision); + } + } else { + results.push(code); + } + + // next + code = split.shift(); + if (code === void 0) { + return results.join(''); + } + isNumber = !isNumber; + } + } + + /** + * Replace IDs in SVG output with unique IDs + * Fast replacement without parsing XML, assuming commonly used patterns. + * + * @param {string} body + * @return {string} + */ + static replaceIDs(body) { + let regex = /\sid="(\S+)"/g, + ids = [], + match, prefix; + + function strReplace(search, replace, subject) { + let pos = 0; + + while ((pos = subject.indexOf(search, pos)) !== -1) { + subject = subject.slice(0, pos) + replace + subject.slice(pos + search.length); + pos += replace.length; + } + + return subject; + } + + // Find all IDs + while (match = regex.exec(body)) { + ids.push(match[1]); + } + if (!ids.length) { + return body; + } + + prefix = 'IconifyId-' + Date.now().toString(16) + '-' + (Math.random() * 0x1000000 | 0).toString(16) + '-'; + + // Replace with unique ids + ids.forEach(function(id) { + let newID = prefix + idCounter; + idCounter ++; + body = strReplace('="' + id + '"', '="' + newID + '"', body); + body = strReplace('="#' + id + '"', '="#' + newID + '"', body); + body = strReplace('(#' + id + ')', '(#' + newID + ')', body); + }); + + return body; + } +} + +/** + * Create React component with SVG data + * + * @param {object} props + * @param {boolean} inline + * @return {null|React.Component} + */ +function component(props, inline) { + if (typeof props.icon !== 'object') { + return null; + } + + // Split properties into SVG properties and icon properties + let split = SVG.splitAttributes(props), + iconProps = split.icon, + customAttributes = split.node; + + delete customAttributes.icon; + + // Set default inline value + if (iconProps.inline === void 0) { + iconProps.inline = inline; + } + + // Get SVG data + let svg = new SVG(normalize(props.icon)); + let iconData = svg.getAttributes(iconProps); + + // Set style + let style = { + transform: 'rotate(360deg)' + }; + + if (iconData.style['vertical-align'] !== void 0) { + style.verticalAlign = iconData.style['vertical-align']; + } + if (props.style !== void 0) { + style = Object.assign(style, props.style); + } + + // Generate element attributes + let attributes = Object.assign({ + xmlns: 'http://www.w3.org/2000/svg', + focusable: false, + style: style + }, customAttributes, iconData.attributes); + + attributes.dangerouslySetInnerHTML = {__html: iconData.body}; + + // Generate SVG + return React.createElement('svg', attributes, null); +} + +/** + * Icon without vertical alignment + * + * @param {object} props + * @return {React.Component} + * @constructor + */ +export const Icon = props => component(props, false); + +/** + * Icon with vertical alignment + * + * @param {object} props + * @return {React.Component} + * @constructor + */ +export const InlineIcon = props => component(props, true); + +/** + * Default export + */ +export default Icon;