diff --git a/.eslintrc.js b/.eslintrc.js index 9f7da03674a7df..a4a1ec153e3b2d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,10 +38,22 @@ module.exports = { globals: { wp: 'off', }, + settings: { + jsdoc: { + mode: 'typescript', + }, + }, rules: { + 'jest/expect-expect': 'off', '@wordpress/dependency-group': 'error', '@wordpress/gutenberg-phase': 'error', '@wordpress/react-no-unsafe-timeout': 'error', + '@wordpress/i18n-text-domain': [ + 'error', + { + allowedTextDomain: 'default', + }, + ], 'no-restricted-syntax': [ 'error', // NOTE: We can't include the forward slash in our regex or @@ -67,29 +79,6 @@ module.exports = { message: 'Deprecated functions must be removed before releasing this version.', }, - { - selector: - 'CallExpression[callee.name=/^(__|_n|_nx|_x)$/]:not([arguments.0.type=/^Literal|BinaryExpression$/])', - message: - 'Translate function arguments must be string literals.', - }, - { - selector: - 'CallExpression[callee.name=/^(_n|_nx|_x)$/]:not([arguments.1.type=/^Literal|BinaryExpression$/])', - message: - 'Translate function arguments must be string literals.', - }, - { - selector: - 'CallExpression[callee.name=_nx]:not([arguments.3.type=/^Literal|BinaryExpression$/])', - message: - 'Translate function arguments must be string literals.', - }, - { - selector: - 'CallExpression[callee.name=/^(__|_x|_n|_nx)$/] Literal[value=/\\.{3}/]', - message: 'Use ellipsis character (…) in place of three dots', - }, { selector: 'ImportDeclaration[source.value="redux"] Identifier.imported[name="combineReducers"]', @@ -179,6 +168,9 @@ module.exports = { { files: [ 'packages/e2e-test*/**/*.js' ], extends: [ 'plugin:@wordpress/eslint-plugin/test-e2e' ], + rules: { + 'jest/expect-expect': 'off', + }, }, ], }; diff --git a/.gitignore b/.gitignore index fc31278c325ded..a3ebac937fc66c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build build-module build-style +build-types node_modules gutenberg.zip @@ -14,6 +15,7 @@ yarn.lock playground/dist .cache +*.tsbuildinfo # Report generated from jest-junit test/native/junit.xml diff --git a/.travis.yml b/.travis.yml index 8798f87bb55da5..baf9a3bb3d4318 100644 --- a/.travis.yml +++ b/.travis.yml @@ -91,7 +91,7 @@ install: fi - | if [[ "$INSTALL_COMPOSER" = "true" ]]; then - npm run env docker-run -- php composer install + npm run env docker-run -- php composer install --no-interaction fi - | if [[ "$E2E_ROLE" = "author" ]]; then @@ -114,6 +114,13 @@ jobs: script: - npx eslint --parser-options=ecmaVersion:5 --no-eslintrc --no-ignore ./build/**/*.js + - name: Typecheck + install: + - npm ci + script: + - npm run build:package-types + + - name: Build artifacts install: # A "full" install is executed, since `npm ci` does not always exit @@ -209,22 +216,5 @@ jobs: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 3' < ~/.jest-e2e-tests ) - - stage: deploy - if: (NOT type IN (pull_request)) AND (branch = master) - name: Deploy Playground - env: INSTALL_WORDPRESS=false - install: - - npm ci - before_deploy: - - npm run storybook:build - deploy: - provider: pages - skip_cleanup: true - github_token: $GITHUB_TOKEN - keep_history: true - local_dir: playground/dist - on: - branch: master - allow_failures: # nothing is allowed to fail at the moment diff --git a/bin/api-docs/are-api-docs-unstaged.js b/bin/api-docs/are-api-docs-unstaged.js new file mode 100644 index 00000000000000..b7d956b9e145c3 --- /dev/null +++ b/bin/api-docs/are-api-docs-unstaged.js @@ -0,0 +1,43 @@ +#!/usr/bin/env node + +/** + * Node dependencies. + */ +const { extname } = require( 'path' ); +const chalk = require( 'chalk' ); +const execSync = require( 'child_process' ).execSync; +const { readFile } = require( 'fs' ).promises; + +const getUnstagedFiles = () => + execSync( 'git diff --name-only', { encoding: 'utf8' } ) + .split( '\n' ) + .filter( Boolean ); + +const fileHasToken = async ( file ) => + ( await readFile( file, 'utf8' ) ).includes( ' + * // content within will be filled by docgen + * + * + * @example Delimiter tokens that use a specific source file: + * + * // content within will be filled by docgen + * + * + * @type {RegExp} + * @see DEFAULT_PATH + */ +const TOKEN_PATTERN = //g; + +/** + * Given an absolute file path, returns the package name. + * + * @param {string} file Absolute path. + * + * @return {string} Package name. + */ +function getFilePackage( file ) { + return relative( PACKAGES_DIR, file ).split( sep )[ 0 ]; +} + +/** + * Returns an appropriate glob pattern for the packages directory to match + * relevant documentation files for a given set of files. + * + * @param {string[]} files Set of files to match. Pass an empty set to match + * all packages. + * + * @return {string} Packages glob pattern. + */ +function getPackagePattern( files ) { + if ( ! files.length ) { + return '*'; + } + + // Since brace expansion doesn't work with a single package, special-case + // the pattern for the singular match. + const packages = Array.from( new Set( files.map( getFilePackage ) ) ); + return packages.length === 1 ? packages[ 0 ] : '{' + packages.join() + '}'; +} + +/** + * Returns the conventional store name of a given package. + * + * @param {string} packageName Package name. + * + * @return {string} Store name. + */ +function getPackageStoreName( packageName ) { + let storeName = 'core'; + if ( packageName !== 'core-data' ) { + storeName += '/' + packageName; + } + + return storeName; +} + +/** + * Returns the conventional documentation file name of a given package. + * + * @param {string} packageName Package name. + * + * @return {string} Documentation file name. + */ +function getDataDocumentationFile( packageName ) { + const storeName = getPackageStoreName( packageName ); + return `data-${ storeName.replace( '/', '-' ) }.md`; +} + +/** + * Returns an appropriate glob pattern for the data documentation directory to + * match relevant documentation files for a given set of files. + * + * @param {string[]} files Set of files to match. Pass an empty set to match + * all packages. + * + * @return {string} Packages glob pattern. + */ +function getDataDocumentationPattern( files ) { + if ( ! files.length ) { + return '*'; + } + + // Since brace expansion doesn't work with a single package, special-case + // the pattern for the singular match. + const filePackages = Array.from( new Set( files.map( getFilePackage ) ) ); + const docFiles = filePackages.map( getDataDocumentationFile ); + + return docFiles.length === 1 ? docFiles[ 0 ] : '{' + docFiles.join() + '}'; +} + +/** + * Stream transform which filters out README files to include only those + * containing matched token pattern, yielding a tuple of the file and its + * matched tokens. + * + * @type {Transform} + */ +const filterTokenTransform = new Transform( { + objectMode: true, + + async transform( file, _encoding, callback ) { + let content; + try { + content = await readFile( file, 'utf8' ); + } catch {} + + if ( content ) { + const tokens = []; + + for ( const match of content.matchAll( TOKEN_PATTERN ) ) { + const [ , token, path = DEFAULT_PATH ] = match; + tokens.push( [ token, path ] ); + } + + if ( tokens.length ) { + this.push( [ file, tokens ] ); + } + } + + callback(); + }, +} ); + +/** + * Optional process arguments for which to generate documentation. + * + * @type {string[]} + */ +const files = process.argv.slice( 2 ); + +glob.stream( [ + `${ PACKAGES_DIR }/${ getPackagePattern( files ) }/README.md`, + `${ DATA_DOCS_DIR }/${ getDataDocumentationPattern( files ) }`, +] ) + .pipe( filterTokenTransform ) + .on( 'data', async ( /** @type {WPReadmeFileData} */ data ) => { + const [ file, tokens ] = data; + const output = relative( ROOT_DIR, file ); + + // Each file can have more than one placeholder content to update, each + // represented by tokens. The docgen script updates one token at a time, + // so the tokens must be replaced in sequence to prevent the processes + // from overriding each other. + for ( const [ token, path ] of tokens ) { + await execa( + join( __dirname, '..', '..', 'node_modules', '.bin', 'docgen' ), + [ + relative( ROOT_DIR, resolve( dirname( file ), path ) ), + `--output ${ output }`, + '--to-token', + `--use-token "${ token }"`, + '--ignore "/unstable|experimental/i"', + ], + { shell: true } + ); + } + } ); diff --git a/bin/api-docs/update-readmes.js b/bin/api-docs/update-readmes.js deleted file mode 100755 index ab1805c3fdeccd..00000000000000 --- a/bin/api-docs/update-readmes.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Node dependencies. - */ -const { join } = require( 'path' ); -const spawnSync = require( 'child_process' ).spawnSync; - -/** - * Local dependencies. - */ -const getPackages = require( './packages' ); - -getPackages().forEach( ( entry ) => { - const [ packageName, targetFiles ] = entry; - - Object.entries( targetFiles ).forEach( ( [ token, path ] ) => { - // Each target operates over the same file, so it needs to be processed synchronously, - // as to make sure the processes don't overwrite each other. - const { status, stderr } = spawnSync( - join( - __dirname, - '..', - '..', - 'node_modules', - '.bin', - 'docgen' - ).replace( / /g, '\\ ' ), - [ - join( 'packages', packageName, path ), - `--output packages/${ packageName }/README.md`, - '--to-token', - `--use-token "${ token }"`, - '--ignore "/unstable|experimental/i"', - ], - { shell: true } - ); - - if ( status !== 0 ) { - process.stderr.write( `${ packageName } ${ stderr.toString() }\n` ); - process.exit( 1 ); - } - } ); -} ); diff --git a/bin/check-latest-npm.js b/bin/check-latest-npm.js new file mode 100644 index 00000000000000..030cff774f0fd7 --- /dev/null +++ b/bin/check-latest-npm.js @@ -0,0 +1,121 @@ +#!/usr/bin/env node + +/** + * External dependencies + */ +const { green, red, yellow } = require( 'chalk' ); +const { get } = require( 'https' ); +const { spawn } = require( 'child_process' ); + +/** + * Returns a promise resolving with the version number of the latest available + * version of NPM. + * + * @return {Promise} Promise resolving with latest NPM version. + */ +async function getLatestNPMVersion() { + return new Promise( ( resolve, reject ) => { + get( + 'https://registry.npmjs.org/npm', + { + headers: { + // By passing a specialized `Accept` header, the registry + // will return an abbreviated form of the package data which + // includes enough detail to determine the latest version. + // + // See: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md + Accept: 'application/vnd.npm.install-v1+json', + }, + }, + async ( response ) => { + if ( response.statusCode !== 200 ) { + return reject( + new Error( 'Package data for NPM not found' ) + ); + } + + let body = ''; + for await ( const chunk of response ) { + body += chunk.toString(); + } + + let data; + try { + data = JSON.parse( body ); + } catch { + return reject( + new Error( + 'Package data for NPM returned invalid response body' + ) + ); + } + + resolve( data[ 'dist-tags' ].latest ); + } + ).on( 'error', ( error ) => { + if ( + /** @type {NodeJS.ErrnoException} */ ( error ).code === + 'ENOTFOUND' + ) { + error = new Error( `Could not contact the NPM registry to determine latest version. + +This could be due to an intermittent outage of the service, or because you are not connected to the internet. + +Because it is important that \`package-lock.json\` files only be committed while running the latest version of NPM, this commit has been blocked. + +If you are certain of your changes and desire to commit anyways, you should either connect to the internet or bypass commit verification using ${ yellow( + 'git commit --no-verify' + ) } .` ); + } + + reject( error ); + } ); + } ); +} + +/** + * Returns a promise resolving with the version number of the local installed + * version of NPM. + * + * @return {Promise} Promise resolving with local installed NPM version. + */ +async function getLocalNPMVersion() { + return new Promise( async ( resolve ) => { + const childProcess = spawn( 'npm', [ '-v' ] ); + + let output = ''; + for await ( const chunk of childProcess.stdout ) { + output += chunk.toString(); + } + + resolve( output.trim() ); + } ); +} + +Promise.all( [ getLatestNPMVersion(), getLocalNPMVersion() ] ) + .then( ( [ latest, local ] ) => { + if ( latest !== local ) { + throw new Error( + `The local NPM version does not match the expected latest version. Expected ${ green( + latest + ) }, found ${ red( local ) }. + +It is required that you have the latest version of NPM installed in order to commit a change to the package-lock.json file. + +Run ${ yellow( + 'npm install --global npm@latest' + ) } to install the latest version of NPM. Before retrying your commit, run ${ yellow( + 'npm install' + ) } once more to ensure the package-lock.json contents are correct. If there are any changes to the file, they should be included in your commit.` + ); + } + } ) + .catch( ( error ) => { + // Disable reason: A failure should log to the terminal. + + // eslint-disable-next-line no-console + console.error( + 'Latest NPM check failed!\n\n' + error.toString() + '\n' + ); + process.exitCode = 1; + } ); diff --git a/bin/commander.js b/bin/commander.js index 788019da2148b8..54b31c7c360f80 100755 --- a/bin/commander.js +++ b/bin/commander.js @@ -16,7 +16,7 @@ const SimpleGit = require( 'simple-git/promise' ); const childProcess = require( 'child_process' ); const Octokit = require( '@octokit/rest' ); const os = require( 'os' ); -const uuid = require( 'uuid/v4' ); +const { v4: uuid } = require( 'uuid' ); // Config const gitRepoOwner = 'WordPress'; diff --git a/bin/packages/lint-staged-typecheck.js b/bin/packages/lint-staged-typecheck.js new file mode 100644 index 00000000000000..47116c6e99f920 --- /dev/null +++ b/bin/packages/lint-staged-typecheck.js @@ -0,0 +1,39 @@ +/** + * External dependencies + */ +const _ = require( 'lodash' ); +const path = require( 'path' ); +const fs = require( 'fs' ); +const execa = require( 'execa' ); + +/** + * Internal dependencies + */ +require( './validate-typescript-version' ); + +/* eslint-disable no-console */ + +const repoRoot = path.join( __dirname, '..', '..' ); +const tscPath = path.join( repoRoot, 'node_modules', '.bin', 'tsc' ); + +// lint-staged passes full paths to staged changes +const changedFiles = process.argv.slice( 2 ); + +// Transform changed files to package directories containing tsconfig.json +const changedPackages = _.uniq( + changedFiles.map( ( fullPath ) => { + const relativePath = path.relative( repoRoot, fullPath ); + return path.join( ...relativePath.split( path.sep ).slice( 0, 2 ) ); + } ) +).filter( ( packageRoot ) => + fs.existsSync( path.join( packageRoot, 'tsconfig.json' ) ) +); + +try { + execa.sync( tscPath, [ '--build', ...changedPackages ] ); +} catch ( err ) { + console.error( err.stdout ); + process.exitCode = 1; +} + +/* eslint-enable no-console */ diff --git a/bin/packages/validate-typescript-version.js b/bin/packages/validate-typescript-version.js new file mode 100644 index 00000000000000..1c8af56b14bca7 --- /dev/null +++ b/bin/packages/validate-typescript-version.js @@ -0,0 +1,28 @@ +/** + * External dependencies + */ +const tscDetectedVersion = require( 'typescript' ).version; + +/** + * Internal dependencies + */ +const tscDependencyVersion = require( '../../package.json' ).devDependencies + .typescript; + +/* eslint-disable no-console */ + +if ( tscDependencyVersion !== tscDetectedVersion ) { + console.error( + [ + 'TypeScript dependency out of date.', + '\tDetected: %o', + '\tRequired: %o', + 'Please ensure dependencies are up to date.', + ].join( require( 'os' ).EOL ), + tscDetectedVersion, + tscDependencyVersion + ); + process.exit( 1 ); +} + +/* eslint-enable no-console */ diff --git a/bin/tsconfig.json b/bin/tsconfig.json new file mode 100644 index 00000000000000..b65a74eeb1bfc1 --- /dev/null +++ b/bin/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "target": "ES6", + "lib": [ "ES6", "ES2020.string" ], + "rootDir": ".", + "declarationMap": false, + + // We're not interested in the output, but we must generate + // something as part of a composite project. Use the + // ignored `.cache` file to hide tsbuildinfo and d.ts files. + "outDir": ".cache" + }, + "files": [ + "./api-docs/update-api-docs.js", + "./check-latest-npm.js" + ] +} diff --git a/changelog.txt b/changelog.txt index 8aef29a0a6e458..d2002de99fb165 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,202 @@ == Changelog == += 7.9.0-rc.1 = + +### Features + +- Add gradients support to Group, Columns and Media & Text blocks. [21375](https://github.com/WordPress/gutenberg/pull/21375) +- Add line height support to the Paragraph block. [20775](https://github.com/WordPress/gutenberg/pull/20775) +- Add font size support to the Heading block. [21431](https://github.com/WordPress/gutenberg/pull/21431) +- Add line height support to the Heading block. [21215](https://github.com/WordPress/gutenberg/pull/21215) +- Add custom height unit support to the Cover block. [20888](https://github.com/WordPress/gutenberg/pull/20888) + +### Enhancements + +- New Patterns: + - Hero Two Columns [21128](https://github.com/WordPress/gutenberg/pull/21128) + - Numbered Features [21131](https://github.com/WordPress/gutenberg/pull/21131) + - It's Time [21132](https://github.com/WordPress/gutenberg/pull/21132) +- Add a new keyboard shortcut to toggle Fullscreen Mode. [21436](https://github.com/WordPress/gutenberg/pull/21436) +- Insert post title instead of URL, when adding a link to an existing post [21240](https://github.com/WordPress/gutenberg/pull/21240) +- Social links block: + - Update tumblr icon [21329](https://github.com/WordPress/gutenberg/pull/21329) + - Update and massage social links colors. [21474](https://github.com/WordPress/gutenberg/pull/21474) +- Allow reusable block top and bottom paddings to collapse. [21472](https://github.com/WordPress/gutenberg/pull/21472) +- Update all block previews to use the auto-height behavior. [21014](https://github.com/WordPress/gutenberg/pull/21014) +- Disable autocomplete for custom class name inputs. [21110](https://github.com/WordPress/gutenberg/pull/21110) +- Several small tweaks to the new Block UI. [21476](https://github.com/WordPress/gutenberg/pull/21476) +- Unify the focus styles across the UI. [21141](https://github.com/WordPress/gutenberg/pull/21141) +- Improve block focus style. [21498](https://github.com/WordPress/gutenberg/pull/21498) +- Remove the post permalink UI from the post title. [21099](https://github.com/WordPress/gutenberg/pull/21099) +- Style the default toolbar buttons. [21252](https://github.com/WordPress/gutenberg/pull/21252) +- Style tweaks to the patterns library sidebar. [21263](https://github.com/WordPress/gutenberg/pull/21263) +- Smaller space between toolbar and block. [21166](https://github.com/WordPress/gutenberg/pull/21166) + +### Performance + +- Add block selection performance test. [21230](https://github.com/WordPress/gutenberg/pull/21230) +- Improve the performance of the block moving animation. [21231](https://github.com/WordPress/gutenberg/pull/21231) +- Render the patterns list asynchronously. [21322](https://github.com/WordPress/gutenberg/pull/21322) + +### Bug Fixes + +- Improve WordPress logo rendering for non-retina displays. [21217](https://github.com/WordPress/gutenberg/pull/21217) +- Fix inserter popover direction. [21556](https://github.com/WordPress/gutenberg/pull/21556) +- Fix Snackbar notice bottom margin. [18858](https://github.com/WordPress/gutenberg/pull/18858) +- Fix YouTube Embed block from flickering and crashing on Safari. [21225](https://github.com/WordPress/gutenberg/pull/21225) +- Fix sibling inserter being unclickable. [21232](https://github.com/WordPress/gutenberg/pull/21232) +- Fix block duplication using keyboard shortcut [21317](https://github.com/WordPress/gutenberg/pull/21317) +- Avoid creating an empty paragraph when selecting the parent's group block [21318](https://github.com/WordPress/gutenberg/pull/21318) +- Fix the Buttons block margins. [21376](https://github.com/WordPress/gutenberg/pull/21376) +- Prevent typing on a Popover from closing the block toolbar [21421](https://github.com/WordPress/gutenberg/pull/21421) +- Prevent copy/paste on number inputs from copying the post content. [21457](https://github.com/WordPress/gutenberg/pull/21457) +- Prevent scroll jumps when focusing long blocks. [21460](https://github.com/WordPress/gutenberg/pull/21460) +- Fix Separator block RTL styles. [21525](https://github.com/WordPress/gutenberg/pull/21525) +- Make dateI18n returns be affected by `gmt` parameter. [18982](https://github.com/WordPress/gutenberg/pull/18982) +- Fixes the read more link added by themes in the Latest Posts block. [20541](https://github.com/WordPress/gutenberg/pull/20541) +- Fix the Latest Posts block when `imageDimensions` is empty [21070](https://github.com/WordPress/gutenberg/pull/21070) +- Fix transparent images used as Cover block backgrounds. [20904](https://github.com/WordPress/gutenberg/pull/20904) +- IE11: fix focus on backspace. [21092](https://github.com/WordPress/gutenberg/pull/21092) +- Fix IE11 breakage when hitting Enter. [21361](https://github.com/WordPress/gutenberg/pull/21361) [21366](https://github.com/WordPress/gutenberg/pull/21366) +- Fix block movers on full-wide blocks. [21097](https://github.com/WordPress/gutenberg/pull/21097) +- Fix Annotations classNames. [21184](https://github.com/WordPress/gutenberg/pull/21184) +- RangeControl: Fix zero value handling with number input. [21187](https://github.com/WordPress/gutenberg/pull/21187) +- Fix reusable block horizontal padding regression. [21312](https://github.com/WordPress/gutenberg/pull/21312) +- Fix fullwide margins regression. [21201](https://github.com/WordPress/gutenberg/pull/21201) +- Prevent the Cover block from overriding the children blocks colors [21254](https://github.com/WordPress/gutenberg/pull/21254) +- Fix overly verbose aria-label in Social Link block [21369](https://github.com/WordPress/gutenberg/pull/21369) +- Fix container block appenders and sibling inserters. [21149](https://github.com/WordPress/gutenberg/pull/21149) [21142](https://github.com/WordPress/gutenberg/pull/21142) [21143](https://github.com/WordPress/gutenberg/pull/21143) + +### New APIs + +- @wordpress/i18n: Add create-i18n function. [21182](https://github.com/WordPress/gutenberg/pull/21182) +- @wordpress/interface: + - Add screen sidebar extensibility APIs. [20698](https://github.com/WordPress/gutenberg/pull/20698) [21260](https://github.com/WordPress/gutenberg/pull/21260) + - Prepare for npm release. [21417](https://github.com/WordPress/gutenberg/pull/21417) + - Add Fullscreen mode component. [21334](https://github.com/WordPress/gutenberg/pull/21334) + - Add InterfaceSkeleton component. [21335](https://github.com/WordPress/gutenberg/pull/21335) +- @wordpress/icons: Add new icons: tablet, mobile, desktop, font, share... [21261](https://github.com/WordPress/gutenberg/pull/21261) [21278](https://github.com/WordPress/gutenberg/pull/21278) +- Support changing the Group block's DOM element. [20218](https://github.com/WordPress/gutenberg/pull/20218) +- Block API: Add new utility to register block types from metadata in PHP [20794](https://github.com/WordPress/gutenberg/pull/20794) +- Add radio option to the ButtonGroup component. [20805](https://github.com/WordPress/gutenberg/pull/20805) + +### Experiments + +- Full site editing and Site Editor screen: + - Use the default post comments template for the Post Comments block. [21012](https://github.com/WordPress/gutenberg/pull/21012) + - Use slug as template part display label.[21161](https://github.com/WordPress/gutenberg/pull/21161) + - Remove duplicate queries fetching template parts [18878](https://github.com/WordPress/gutenberg/pull/18878) + - Preload the edited template to avoid the white page effect. [21214](https://github.com/WordPress/gutenberg/pull/21214) + - Move the menu item to the top level. [21273](https://github.com/WordPress/gutenberg/pull/21273) + - Add block breadcrumb; [21274](https://github.com/WordPress/gutenberg/pull/21274) + - Prevent template switcher jumpiness. [21280](https://github.com/WordPress/gutenberg/pull/21280) + - Increase the viewport width used for template previews. [21287](https://github.com/WordPress/gutenberg/pull/21287) + - Add top level inserter. [21328](https://github.com/WordPress/gutenberg/pull/21328) + - Apply the editor styles. [20982](https://github.com/WordPress/gutenberg/pull/20982) + - Update the multi-entity saving flow UI. [21159](https://github.com/WordPress/gutenberg/pull/21159) + - Small updates to template selector. [21202](https://github.com/WordPress/gutenberg/pull/21202) +- New navigation screen: + - Bootstrap the screen. [21036](https://github.com/WordPress/gutenberg/pull/21036) + - Implement the initial styling. [21314](https://github.com/WordPress/gutenberg/pull/21314) + - Add save shortcut. [21342](https://github.com/WordPress/gutenberg/pull/21342) + - Fix editor shortcuts. [21338](https://github.com/WordPress/gutenberg/pull/21338) + - Basic responsive styles. [21414](https://github.com/WordPress/gutenberg/pull/21414) +- Navigation block: + - Make the submenus usable on mobile. [21471](https://github.com/WordPress/gutenberg/pull/21471) + - Fix block for contributor users [18669](https://github.com/WordPress/gutenberg/pull/18669) + - Fix submenus being overlapped by wrapping top-level nav links. [21140](https://github.com/WordPress/gutenberg/pull/21140) + - Add vertical variation. [21296](https://github.com/WordPress/gutenberg/pull/21296) + - Show color controls in toolbar only. [20884](https://github.com/WordPress/gutenberg/pull/20884) + - Add capture toolbars prop to inner blocks. [21095](https://github.com/WordPress/gutenberg/pull/21095) +- Block API Support flags: + - Introduce a support key for support global style colors in blocks. [21021](https://github.com/WordPress/gutenberg/pull/21021) [21428](https://github.com/WordPress/gutenberg/pull/21428) + - Add the possibility to support gradients using the experimental color support flag; [21481](https://github.com/WordPress/gutenberg/pull/21481) + - Add a block support flag for font size. [21153](https://github.com/WordPress/gutenberg/pull/21153) +- Remove experimentalUIParts API. [20979](https://github.com/WordPress/gutenberg/pull/20979) +- Add experimental Text component. [21088](https://github.com/WordPress/gutenberg/pull/21088) + +### Documentation + +- Docs: Describe tools used in E2E testing. [21295](https://github.com/WordPress/gutenberg/pull/21295) +- WP-env: Add reference to docker log command to show error logs in terminal. [21308](https://github.com/WordPress/gutenberg/pull/21308) +- Docs: Add section in block RFC about register_block_type_from_metadata. [21501](https://github.com/WordPress/gutenberg/pull/21501) +- Update serverSideRender docs to include how to use from the wp global. [18722](https://github.com/WordPress/gutenberg/pull/18722) +- Prescribe latest NPM for development environment. [21017](https://github.com/WordPress/gutenberg/pull/21017) +- Update Documentation on how to update post meta values from a block. [21155](https://github.com/WordPress/gutenberg/pull/21155) +- Document getAnchorRect prop for Popover component. [17709](https://github.com/WordPress/gutenberg/pull/17709) +- Typos and tweaks: [21228](https://github.com/WordPress/gutenberg/pull/21228), [21364](https://github.com/WordPress/gutenberg/pull/21364), [21405](https://github.com/WordPress/gutenberg/pull/21405), [20660](https://github.com/WordPress/gutenberg/pull/20660), [21297](https://github.com/WordPress/gutenberg/pull/21297). + +### Code Quality + +- Add types to WordPress packages: + - @wordpress/element [21248](https://github.com/WordPress/gutenberg/pull/21248) + - @wordpress/primitives [21482](https://github.com/WordPress/gutenberg/pull/21482) + - @wordpress/icons [21487](https://github.com/WordPress/gutenberg/pull/21487) + - @wordpress/autop, @wordpress/escape-html and @wordpress/html-entities [20669](https://github.com/WordPress/gutenberg/pull/20669) + - @wordpress/i18n [21224](https://github.com/WordPress/gutenberg/pull/21224) + - @wordpress/prettier-config [21381](https://github.com/WordPress/gutenberg/pull/21381) [21053](https://github.com/WordPress/gutenberg/pull/21053) + - @wordpress/block-editor DOM utils. [21362](https://github.com/WordPress/gutenberg/pull/21362) +- Update the Buttons block to use the new color support flag. [21266](https://github.com/WordPress/gutenberg/pull/21266) +- Update the Paragraph block to use the colors support flag. [21037](https://github.com/WordPress/gutenberg/pull/21037) +- Update the Columns block to use the colors support flag. [21038](https://github.com/WordPress/gutenberg/pull/21038) +- Update the Heading block to use the colors support flag. [21039](https://github.com/WordPress/gutenberg/pull/21039) +- Update the Media & Text block to use the colors support flag. [21169](https://github.com/WordPress/gutenberg/pull/21169) +- Refactor env commands into separate files .[21353](https://github.com/WordPress/gutenberg/pull/21353) +- Remove the deprecated `request` dependency. [21398](https://github.com/WordPress/gutenberg/pull/21398) +- Move default styles to editor normalisation stylesheet. [19837](https://github.com/WordPress/gutenberg/pull/19837) +- Replace lodash.assign with vanilla JS. [21054](https://github.com/WordPress/gutenberg/pull/21054) +- Remove the old block preview implementation. [21096](https://github.com/WordPress/gutenberg/pull/21096) +- Make RichText window/document agnostic. [21105](https://github.com/WordPress/gutenberg/pull/21105) +- Polish a11y package. [21148](https://github.com/WordPress/gutenberg/pull/21148) +- Fix two typos in lib rest menu controller. [21418](https://github.com/WordPress/gutenberg/pull/21418) +- Global tips: Add period at the end of sentence. [20601](https://github.com/WordPress/gutenberg/pull/20601) +- Lighter block DOM: + - Verse block [20752](https://github.com/WordPress/gutenberg/pull/20752) + - Code block [21079](https://github.com/WordPress/gutenberg/pull/21079) + - Preformatted block [21146](https://github.com/WordPress/gutenberg/pull/21146) +- Update the padding values on the Card component to align with proposed spacing system. [21111](https://github.com/WordPress/gutenberg/pull/21111) +- Disable scroll in PlainText component. [21115](https://github.com/WordPress/gutenberg/pull/21115) +- Simplify inserter hasItems check. [21138](https://github.com/WordPress/gutenberg/pull/21138) +- Avoid string concatenation for the Latest Post block read more link. [21170](https://github.com/WordPress/gutenberg/pull/21170) + +### Various + +- Plugin: Bump tested up to info to WP 5.4 [21400](https://github.com/WordPress/gutenberg/pull/21400) +- Output package type declarations. [18942](https://github.com/WordPress/gutenberg/pull/18942) +- Exclude native files from type checking. [21491](https://github.com/WordPress/gutenberg/pull/21491) +- docgen: Optimize README update script. [18840](https://github.com/WordPress/gutenberg/pull/18840) +- Check Latest NPM on npm install. [21521](https://github.com/WordPress/gutenberg/pull/21521) +- E2E Tests: + - Improve stability of image block test [21174](https://github.com/WordPress/gutenberg/pull/21174) + - Improve Allowed Inner Blocks test stability [21175](https://github.com/WordPress/gutenberg/pull/21175) + - Use waitForSelector to wait for sidebar presence [21180](https://github.com/WordPress/gutenberg/pull/21180) +- Unit Tests: + - Fix @wordpress/env testPortNumberValidation unit test. [21394](https://github.com/WordPress/gutenberg/pull/21394) + - Introduce react-testing-library to some existing unit tests. [20428](https://github.com/WordPress/gutenberg/pull/20428) + - Components: Add SlotFill test. [21226](https://github.com/WordPress/gutenberg/pull/21226) + - Fail E2E when page displays warning notices [13452](https://github.com/WordPress/gutenberg/pull/13452) +- Project Management: Prompt user to link GitHub account to WordPress.org profile [21221](https://github.com/WordPress/gutenberg/pull/21221) [21384](https://github.com/WordPress/gutenberg/pull/21384) +- @wordpress/env: Bind "core" files to tests environment [21195](https://github.com/WordPress/gutenberg/pull/21195) +- ESLint Plugin: Continue considering unused variables after encountering exception [21354](https://github.com/WordPress/gutenberg/pull/21354) +- Enable prettier for JSX files [21151](https://github.com/WordPress/gutenberg/pull/21151) +- Increase severity of JSDoc linting to error. [20427](https://github.com/WordPress/gutenberg/pull/20427) +- Add I18N specific ESLint rules. [20555](https://github.com/WordPress/gutenberg/pull/20555) [20574](https://github.com/WordPress/gutenberg/pull/20574) +- Update uuid to v7.0.2. [21258](https://github.com/WordPress/gutenberg/pull/21258) +- Upgrade Reakit to version 1.0.0-rc.0; [21300](https://github.com/WordPress/gutenberg/pull/21300) +- Framework: Add package-lock precommit check for latest NPM. [21306](https://github.com/WordPress/gutenberg/pull/21306) +- Babel Preset: Update Babel version to 7.9.x. [21419](https://github.com/WordPress/gutenberg/pull/21419) +- ESLint Plugin: Update ESLint and related dependencies to 6.8.x. [21424](https://github.com/WordPress/gutenberg/pull/21424) +- Framework: Configure ESLint JSDoc plugin to target TypeScript mode. [18998](https://github.com/WordPress/gutenberg/pull/18998) +- Major version upgrade for Jest in all packages. [20766](https://github.com/WordPress/gutenberg/pull/20766) +- Storybook: + - Add TreeSelect component. [20496](https://github.com/WordPress/gutenberg/pull/20496) + - Update AnglePickerControl title. [21089](https://github.com/WordPress/gutenberg/pull/21089) +- Automated Testing: composer non-interactive flag for Travis. [21118](https://github.com/WordPress/gutenberg/pull/21118) +- REST API error message: Remove unnecessary space. [21178](https://github.com/WordPress/gutenberg/pull/21178) +- SlotFill: Guard property access to possibly-undefined slot. [21205](https://github.com/WordPress/gutenberg/pull/21205) +- Build: Add TypeScript version validation [21208](https://github.com/WordPress/gutenberg/pull/21208) + + = 7.8.1 = diff --git a/docs/contributors/coding-guidelines.md b/docs/contributors/coding-guidelines.md index a8f0698fa4a5c2..ba904db9cc9226 100644 --- a/docs/contributors/coding-guidelines.md +++ b/docs/contributors/coding-guidelines.md @@ -216,7 +216,7 @@ Custom types should be named as succinctly as possible, while still retaining cl /** * A block selection object. * - * @typedef {Object} WPBlockSelection + * @typedef WPBlockSelection * * @property {string} clientId A block client ID. * @property {string} attributeKey A block attribute key. @@ -225,6 +225,8 @@ Custom types should be named as succinctly as possible, while still retaining cl */ ``` +Note that there is no `{Object}` between `@typedef` and the type name. As `@property`s below tells us that it is a type for objects, it is recommend to not use `{Object}` when you want to define types for your objects. + Custom types can also be used to describe a set of predefined options. While the [type union](https://jsdoc.app/tags-type.html) can be used with literal values as an inline type, it can be difficult to align tags while still respecting a maximum line length of 80 characters. Using a custom type to define a union type can afford the opportunity to describe the purpose of these options, and helps to avoid these line length issues. ```js @@ -269,24 +271,26 @@ If you use a [TypeScript integration](https://github.com/Microsoft/TypeScript/wi For packages which do not distribute their own TypeScript types, you are welcomed to install and use the [DefinitelyTyped](http://definitelytyped.org/) community-maintained types definitions, if one exists. -### Record Types +### Generic Types When documenting a generic type such as `Object`, `Function`, `Promise`, etc., always include details about the expected record types. ```js -// Incorrect: +// Bad: /** @type {Object} */ /** @type {Function} */ /** @type {Promise} */ -// Correct: +// Good: -/** @type {Object} */ +/** @type {Record} */ /* or */ /** @type {{[setting:string]:any}} */ /** @type {(key:string)=>boolean} */ /** @type {Promise} */ ``` +When an object is used as a dictionary, you can define its type in 2 ways: indexable interface (`{[setting:string]:any}`) or `Record`. When the name of the key for an object provides hints for developers what to do like `setting`, use indexable interface. If not, use `Record`. + The function expression here uses TypeScript's syntax for function types, which can be useful in providing more detailed information about the names and types of the expected parameters. For more information, consult the [TypeScript `@type` tag function recommendations](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#type). In more advanced cases, you may define your own custom types as a generic type using the [TypeScript `@template` tag](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#template). @@ -312,7 +316,7 @@ Similar to the "Custom Types" advice concerning type unions and with literal val /** * Hash of breakpoint names with pixel width at which it becomes effective. * - * @type {Object} + * @type {Record} */ const BREAKPOINTS = { huge: 1440 /* , ... */ }; ``` @@ -409,7 +413,7 @@ When documenting an example, use the markdown \`\`\` code block to * select( 'my-shop' ).getPrice( 'hammer' ); * ``` * - * @return {Object} Object containing the store's + * @return {Record} Object containing the store's * selectors. */ ```` diff --git a/docs/contributors/getting-started.md b/docs/contributors/getting-started.md index 6236c404a71dbb..46938b11f75847 100644 --- a/docs/contributors/getting-started.md +++ b/docs/contributors/getting-started.md @@ -2,7 +2,7 @@ Gutenberg is a Node.js-based project, built primarily in JavaScript. -The first step is to install the [latest active LTS release](https://github.com/nodejs/Release#release-schedule) of Node. The easiest way (on macOS, Linux, or Windows 10 with the Linux Subsystem) is by installing and running [nvm]. Once `nvm` is installed, you can install the correct version of Node by running `nvm install` in the Gutenberg directory. +The first step is to install the [latest active LTS release](https://github.com/nodejs/Release#release-schedule) of Node, along with the latest version of [NPM](https://www.npmjs.com/). The easiest way (on macOS, Linux, or Windows 10 with the Linux Subsystem) is by installing and running [nvm]. Once `nvm` is installed, you can install the correct version of Node by running `nvm install --latest-npm` in the Gutenberg directory. Once you have Node installed, run these scripts from within your local Gutenberg repository: diff --git a/docs/contributors/testing-overview.md b/docs/contributors/testing-overview.md index 5d467ddf2f99a9..5c7d2a642b81b8 100644 --- a/docs/contributors/testing-overview.md +++ b/docs/contributors/testing-overview.md @@ -372,7 +372,9 @@ To locally run the tests in debug mode, follow these steps: 5. Click on the "Play" button to resume execution 6. Enjoy debugging the native mobile unit tests! -## End to end Testing +## End-to-end Testing + +End-to-end tests use [Puppeteer](https://github.com/puppeteer/puppeteer) as a headless Chromium driver, and are otherwise still run by a [Jest](https://jestjs.io/) test runner. If you're using the built-in [local environment](/docs/contributors/getting-started.md#local-environment), you can run the e2e tests locally using this command: diff --git a/docs/designers-developers/developers/data/data-core-annotations.md b/docs/designers-developers/developers/data/data-core-annotations.md index e71aefd27d2129..0b5840c617d1e4 100644 --- a/docs/designers-developers/developers/data/data-core-annotations.md +++ b/docs/designers-developers/developers/data/data-core-annotations.md @@ -4,17 +4,17 @@ Namespace: `core/annotations`. ## Selectors - + Nothing to document. - - + ## Actions - + Nothing to document. - + + diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index 1bd2c38e601a1e..e19a7cb52c12b1 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -4,7 +4,7 @@ Namespace: `core/block-editor`. ## Selectors - + # **canInsertBlockType** @@ -907,12 +907,11 @@ _Returns_ - `?boolean`: Whether the template is valid or not. - - + ## Actions - + # **clearSelectedBlock** @@ -1386,6 +1385,15 @@ _Returns_ # **updateSettings** -Undocumented declaration. +Returns an action object used in signalling that the block editor settings have been updated. + +_Parameters_ + +- _settings_ `Object`: Updated settings + +_Returns_ + +- `Object`: Action object + - + diff --git a/docs/designers-developers/developers/data/data-core-blocks.md b/docs/designers-developers/developers/data/data-core-blocks.md index 933c432cd93260..8d577f4fca040c 100644 --- a/docs/designers-developers/developers/data/data-core-blocks.md +++ b/docs/designers-developers/developers/data/data-core-blocks.md @@ -4,7 +4,7 @@ Namespace: `core/blocks`. ## Selectors - + # **getBlockStyles** @@ -231,12 +231,11 @@ _Returns_ - `Array`: Whether block type matches search term. - - + ## Actions - + # **addBlockCollection** @@ -417,4 +416,5 @@ _Returns_ - `Object`: Action object. - + + diff --git a/docs/designers-developers/developers/data/data-core-edit-post.md b/docs/designers-developers/developers/data/data-core-edit-post.md index 49801a69817be8..05714b83bcda7b 100644 --- a/docs/designers-developers/developers/data/data-core-edit-post.md +++ b/docs/designers-developers/developers/data/data-core-edit-post.md @@ -4,7 +4,7 @@ Namespace: `core/edit-post`. ## Selectors - + # **getActiveGeneralSidebarName** @@ -267,21 +267,16 @@ _Returns_ - `boolean`: Whether the metaboxes are being saved. - - + ## Actions - + # **closeGeneralSidebar** Returns an action object signalling that the user closed the sidebar. -_Returns_ - -- `Object`: Action object. - # **closeModal** Returns an action object signalling that the user closed a modal. @@ -326,11 +321,7 @@ Returns an action object used in signalling that the user opened an editor sideb _Parameters_ -- _name_ `string`: Sidebar name to be opened. - -_Returns_ - -- `Object`: Action object. +- _name_ `?string`: Sidebar name to be opened. # **openModal** @@ -472,4 +463,5 @@ _Returns_ - `Object`: Action object. - + + diff --git a/docs/designers-developers/developers/data/data-core-editor.md b/docs/designers-developers/developers/data/data-core-editor.md index ef0243465e9f3c..ffba8e67b9aa30 100644 --- a/docs/designers-developers/developers/data/data-core-editor.md +++ b/docs/designers-developers/developers/data/data-core-editor.md @@ -4,7 +4,7 @@ Namespace: `core/editor`. ## Selectors - + # **canInsertBlockType** @@ -1060,12 +1060,11 @@ _Related_ - isValidTemplate in core/block-editor store. - - + ## Actions - + # **autosave** @@ -1511,4 +1510,5 @@ _Returns_ - `Object`: Action object. - + + diff --git a/docs/designers-developers/developers/data/data-core-keyboard-shortcuts.md b/docs/designers-developers/developers/data/data-core-keyboard-shortcuts.md index 9db8ab7ce2d362..fefa8e189e2150 100644 --- a/docs/designers-developers/developers/data/data-core-keyboard-shortcuts.md +++ b/docs/designers-developers/developers/data/data-core-keyboard-shortcuts.md @@ -4,7 +4,7 @@ Namespace: `core/keyboard-shortcuts`. ## Selectors - + # **getAllShortcutRawKeyCombinations** @@ -85,12 +85,11 @@ _Returns_ - `?string`: Shortcut representation. - - + ## Actions - + # **registerShortcut** @@ -116,4 +115,5 @@ _Returns_ - `Object`: action. - + + diff --git a/docs/designers-developers/developers/data/data-core-notices.md b/docs/designers-developers/developers/data/data-core-notices.md index 876977576f69bd..54dfbdd8d84ed8 100644 --- a/docs/designers-developers/developers/data/data-core-notices.md +++ b/docs/designers-developers/developers/data/data-core-notices.md @@ -4,7 +4,7 @@ Namespace: `core/notices`. ## Selectors - + # **getNotices** @@ -20,12 +20,11 @@ _Returns_ - `Array`: Array of notices. - - + ## Actions - + # **createErrorNotice** @@ -132,4 +131,5 @@ _Returns_ - `Object`: Action object. - + + diff --git a/docs/designers-developers/developers/data/data-core-nux.md b/docs/designers-developers/developers/data/data-core-nux.md index 92dcf6be1d0ac2..ad0a93e2bde235 100644 --- a/docs/designers-developers/developers/data/data-core-nux.md +++ b/docs/designers-developers/developers/data/data-core-nux.md @@ -4,7 +4,7 @@ Namespace: `core/nux`. ## Selectors - + # **areTipsEnabled** @@ -47,12 +47,11 @@ _Returns_ - `boolean`: Whether or not the given tip is showing. - - + ## Actions - + # **disableTips** @@ -97,4 +96,5 @@ _Returns_ - `Object`: Action object. - + + diff --git a/docs/designers-developers/developers/data/data-core-viewport.md b/docs/designers-developers/developers/data/data-core-viewport.md index b8f133834ec594..4f776c53efbca7 100644 --- a/docs/designers-developers/developers/data/data-core-viewport.md +++ b/docs/designers-developers/developers/data/data-core-viewport.md @@ -4,7 +4,7 @@ Namespace: `core/viewport`. ## Selectors - + # **isViewportMatch** @@ -26,12 +26,11 @@ _Returns_ - `boolean`: Whether viewport matches query. - - + ## Actions - + # **setIsMatching** @@ -47,4 +46,5 @@ _Returns_ - `Object`: Action object. - + + diff --git a/docs/designers-developers/developers/data/data-core.md b/docs/designers-developers/developers/data/data-core.md index 79f3f41991c08f..54ab79f95f1e54 100644 --- a/docs/designers-developers/developers/data/data-core.md +++ b/docs/designers-developers/developers/data/data-core.md @@ -4,7 +4,7 @@ Namespace: `core`. ## Selectors - + # **canUser** @@ -441,12 +441,11 @@ _Returns_ - `boolean`: Whether the entity record is saving or not. - - + ## Actions - + # **addEntities** @@ -617,4 +616,5 @@ _Parameters_ Action triggered to undo the last edit to an entity record, if any. - + + diff --git a/docs/designers-developers/developers/tutorials/metabox/meta-block-3-add.md b/docs/designers-developers/developers/tutorials/metabox/meta-block-3-add.md index 4bf4c70ae646d5..1804a346f052c9 100644 --- a/docs/designers-developers/developers/tutorials/metabox/meta-block-3-add.md +++ b/docs/designers-developers/developers/tutorials/metabox/meta-block-3-add.md @@ -4,9 +4,7 @@ With the meta field registered in the previous step, next you will create a new For this block, you will use the TextControl component, which is similar to an HTML input text field. For additional components, check out the [components](/packages/components/src) and [editor](/packages/editor/src/components) packages repositories. -Attributes are the information displayed in blocks. As shown in the block tutorial, the source of attributes come from the text or HTML a user writes in the editor. For your meta block, the attribute will come from the post meta field. - -By specifying the source of the attributes as `meta`, the block editor automatically handles the loading and storing of the data; no REST API or data functions are needed. +The hook `useEntityProp` can be used by the blocks to get or change meta values. Add this code to your JavaScript file (this tutorial will call the file `myguten.js`): @@ -17,26 +15,42 @@ Add this code to your JavaScript file (this tutorial will call the file `myguten var el = wp.element.createElement; var registerBlockType = wp.blocks.registerBlockType; var TextControl = wp.components.TextControl; + var useSelect = wp.data.useSelect; + var useEntityProp = wp.coreData.useEntityProp; registerBlockType( 'myguten/meta-block', { title: 'Meta Block', icon: 'smiley', category: 'common', - attributes: { - blockValue: { - type: 'string', - source: 'meta', - meta: 'myguten_meta_block_field', - }, - }, - edit: function( props ) { var className = props.className; - var setAttributes = props.setAttributes; - function updateBlockValue( blockValue ) { - setAttributes( { blockValue } ); + var postType = useSelect( + function( select ) { + return select( 'core/editor' ).getCurrentPostType(); + }, + [] + ); + var entityProp = useEntityProp( + 'postType', + postType, + 'meta' + ); + var meta = entityProp[ 0 ]; + var setMeta = entityProp[ 1 ]; + + var metaFieldValue = meta['myguten_meta_block_field']; + function updateMetaValue( newValue ) { + setMeta( + Object.assign( + {}, + meta, + { + 'myguten_meta_block_field': newValue, + } + ) + ); } return el( @@ -44,8 +58,8 @@ Add this code to your JavaScript file (this tutorial will call the file `myguten { className: className }, el( TextControl, { label: 'Meta Block Field', - value: props.attributes.blockValue, - onChange: updateBlockValue, + value: metaFieldValue, + onChange: updateMetaValue, } ) ); }, @@ -62,38 +76,42 @@ Add this code to your JavaScript file (this tutorial will call the file `myguten ```js import { registerBlockType } from '@wordpress/blocks'; import { TextControl } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useEntityProp } from '@wordpress/core-data'; registerBlockType( 'myguten/meta-block', { title: 'Meta Block', icon: 'smiley', category: 'common', - attributes: { - blockValue: { - type: 'string', - source: 'meta', - meta: 'myguten_meta_block_field', - }, - }, - edit( { className, setAttributes, attributes } ) { - function updateBlockValue( blockValue ) { - setAttributes( { blockValue } ); + const postType = useSelect( + ( select ) => select( 'core/editor' ).getCurrentPostType(), + [] + ); + const [ meta, setMeta ] = useEntityProp( + 'postType', + postType, + 'meta' + ); + const metaFieldValue = meta['myguten_meta_block_field']; + function updateMetaValue( newValue ) { + setMeta( { ...meta, 'myguten_meta_block_field': newValue } ); } return (
); }, // No information saved to the block - // Data is saved to post meta via attributes + // Data is saved to post meta via the hook save() { return null; }, @@ -101,14 +119,14 @@ registerBlockType( 'myguten/meta-block', { ``` {% end %} -**Important:** Before you test, you need to enqueue your JavaScript file and its dependencies. Note the WordPress packages used above are `wp.element`, `wp.blocks`, and `wp.components`. Each of these need to be included in the array of dependencies. Update the `myguten-meta-block.php` file adding the enqueue function: +**Important:** Before you test, you need to enqueue your JavaScript file and its dependencies. Note the WordPress packages used above are `wp.element`, `wp.blocks`, `wp.components`, `wp.data`, and `wp.coreData`. Each of these need to be included in the array of dependencies. Update the `myguten-meta-block.php` file adding the enqueue function: ```php function myguten_enqueue() { wp_enqueue_script( 'myguten-script', plugins_url( 'myguten.js', __FILE__ ), - array( 'wp-blocks', 'wp-element', 'wp-components' ) + array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-data', 'wp-core-data' ) ); } add_action( 'enqueue_block_editor_assets', 'myguten_enqueue' ); @@ -119,4 +137,3 @@ You can now edit a draft post and add a Meta Block to the post. You will see you ![Meta Block](https://raw.githubusercontent.com/WordPress/gutenberg/master/docs/designers-developers/developers/tutorials/metabox/meta-block.png) You can now use the post meta data in a template, or another block. See next section for [using post meta data](/docs/designers-developers/developers/tutorials/metabox/meta-block-4-use-data.md). You could also confirm the data is saved by checking the database table `wp_postmeta` and confirm the new post id contains the new field data. - diff --git a/docs/manifest.json b/docs/manifest.json index b97d08f0d46cd7..537f6ea671988d 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -893,6 +893,12 @@ "markdown_source": "../packages/components/src/notice/README.md", "parent": "components" }, + { + "title": "NumberControl", + "slug": "number-control", + "markdown_source": "../packages/components/src/number-control/README.md", + "parent": "components" + }, { "title": "Panel", "slug": "panel", @@ -923,6 +929,12 @@ "markdown_source": "../packages/components/src/radio-control/README.md", "parent": "components" }, + { + "title": "RadioGroup", + "slug": "radio-group", + "markdown_source": "../packages/components/src/radio-group/README.md", + "parent": "components" + }, { "title": "RangeControl", "slug": "range-control", @@ -1031,6 +1043,12 @@ "markdown_source": "../packages/components/src/tree-select/README.md", "parent": "components" }, + { + "title": "UnitControl", + "slug": "unit-control", + "markdown_source": "../packages/components/src/unit-control/README.md", + "parent": "components" + }, { "title": "VisuallyHidden", "slug": "visually-hidden", @@ -1289,6 +1307,12 @@ "markdown_source": "../packages/e2e-tests/README.md", "parent": "packages" }, + { + "title": "@wordpress/edit-navigation", + "slug": "packages-edit-navigation", + "markdown_source": "../packages/edit-navigation/README.md", + "parent": "packages" + }, { "title": "@wordpress/edit-post", "slug": "packages-edit-post", @@ -1367,6 +1391,12 @@ "markdown_source": "../packages/icons/README.md", "parent": "packages" }, + { + "title": "@wordpress/interface", + "slug": "packages-interface", + "markdown_source": "../packages/interface/README.md", + "parent": "packages" + }, { "title": "@wordpress/is-shallow-equal", "slug": "packages-is-shallow-equal", diff --git a/docs/rfc/block-registration.md b/docs/rfc/block-registration.md index c1844e1646a42f..9ae9d5ad4b1de5 100644 --- a/docs/rfc/block-registration.md +++ b/docs/rfc/block-registration.md @@ -32,7 +32,7 @@ Initial support for server-defined block attributes was merged as part of [#2529 A demonstration for how block registration could be made filterable in PHP was explored in [#5802](https://github.com/WordPress/gutenberg/pull/5802). The purpose here was to explore how plugins could have better control over the registration. -Another exploration in [#5652](https://github.com/WordPress/gutenberg/pull/5652) considered using JSON as a file format to share block type definitions between JavaScript and PHP. +Another exploration in [#5652](https://github.com/WordPress/gutenberg/pull/5652) considered using JSON as a file format to share block type definitions between JavaScript and PHP. ### Conclusions @@ -77,8 +77,8 @@ To register a new block type, start by creating a `block.json` file. This file: "selector": ".message" } }, - "styleVariations": [ - { "name": "default", "label": "Default", "isDefault": true }, + "styleVariations": [ + { "name": "default", "label": "Default", "isDefault": true }, { "name": "other", "label": "Other" } ], "editorScript": "build/editor.js", @@ -222,7 +222,7 @@ The [gettext](https://www.gnu.org/software/gettext/) text domain of the plugin/b * Property: `attributes` ```json -{ +{ "attributes": { "cover": { "type": "string", @@ -252,9 +252,9 @@ See the [the attributes documentation](/docs/designers-developers/developers/blo * Alias: `styleVariations` ```json -{ - "styleVariations": [ - { "name": "default", "label": "Default", "isDefault": true }, +{ + "styleVariations": [ + { "name": "default", "label": "Default", "isDefault": true }, { "name": "other", "label": "Other" } ] } @@ -326,7 +326,7 @@ The following properties are going to be supported for backward compatibility re - `supports` - see the [block supports](/docs/designers-developers/developers/block-api/block-registration.md#supports-optional) documentation page for more details. - `merge` - undocumented as of today. Its role is to handle merging multiple blocks into one. - `getEditWrapperProps` - undocumented as well. Its role is to inject additional props to the block edit's component wrapper. - + **Example**: ```js wp.blocks.registerBlockType( 'my-block/name', { @@ -340,7 +340,7 @@ wp.blocks.registerBlockType( 'my-block/name', { html: false } } ); -``` +``` In the case of [dynamic blocks](/docs/designers-developers/developers/tutorials/block-tutorial/creating-dynamic-blocks.md) supported by WordPress, it should be still possible to register `render_callback` property using [`register_block_type`](https://developer.wordpress.org/reference/functions/register_block_type/) function on the server. @@ -365,31 +365,35 @@ That's why, the `WPDefinedAsset` type has to offer a way to mirror also the shap It's possible to provide an object which takes the following shape: - `handle` (`string`) - the name of the script. If omitted, it will be auto-generated. -- `dependencies` (`string[]`) - an array of registered script handles this script depends on. Default value: `[]`. +- `dependencies` (`string[]`) - an array of registered script handles this script depends on. Default value: `[]`. - `version` (`string`|`false`|`null`) - string specifying the script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If the version is set to `false`, a version number is automatically added equal to current installed WordPress version. If set to `null`, no version is added. Default value: `false`. -The definition is stored inside separate JSON file which ends with `.asset.json` and is located next to the JS/CSS file listed in `block.json`. WordPress will automatically detect this file through pattern matching. This option is the preferred one as it is expected it will become an option to auto-generate those asset files with `@wordpress/scripts` package. +The definition is stored inside separate PHP file which ends with `.asset.php` and is located next to the JS/CSS file listed in `block.json`. WordPress will automatically detect this file through pattern matching. This option is the preferred one as it is expected it will become an option to auto-generate those asset files with `@wordpress/scripts` package. **Example:** ``` build/ -├─ editor.js -└─ editor.asset.json +├─ index.js +└─ index.asset.php ``` In `block.json`: ```json -{ "editorScript": "build/editor.js" } +{ "editorScript": "build/index.js" } ``` -In `build/editor.asset.json`: -```json -{ - "handle": "my-plugin-notice-editor", - "dependencies": [ "wp-blocks","wp-element", "wp-i18n" ], - "version": "3.0.0" -} +In `build/index.asset.php`: +```php + array( + 'wp-blocks', + 'wp-element', + 'wp-i18n', + ), + 'version' => '3be55b05081a63d8f9d0ecb466c42cfd', +); ``` ## Internationalization @@ -432,6 +436,28 @@ $metadata = array( Implementation should follow the existing [get_plugin_data](https://codex.wordpress.org/Function_Reference/get_plugin_data) function which parses the plugin contents to retrieve the plugin’s metadata, and it applies translations dynamically. +## Server-side registration + +There is also a new API method proposed `register_block_type_from_metadata` that aims to simplify the block type registration on the server from metadata stored in the `block.json` file. This function is going to handle also all necessary work to make internationalization work seamlessly for metadata defined. + +This function takes two params: +- `$path` (`string`) – path to the folder where the `block.json` file is located. +- `$args` (`array`) – an optional array of block type arguments. Default value: `[]`. Any arguments may be defined. However, the one described below is supported by default: + - `$render_callback` (`callable`) – callback used to render blocks of this block type. + +It returns the registered block type (`WP_Block_Type`) on success or `false` on failure. + +**Example:** + +```php +register_block_type_from_metadata( + __DIR__ . '/shortcode', + array( + 'render_callback' => 'render_block_core_shortcode', + ) +); +``` + ## Backward Compatibility The existing registration mechanism (both server side and frontend) will continue to work, it will serve as low-level implementation detail for the `block.json` based registration. diff --git a/docs/tool/are-data-files-unstaged.js b/docs/tool/are-data-files-unstaged.js deleted file mode 100644 index 38f659ec9bb0c7..00000000000000 --- a/docs/tool/are-data-files-unstaged.js +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env node - -/** - * Node dependencies. - */ -const chalk = require( 'chalk' ); -const execSync = require( 'child_process' ).execSync; - -/** - * Local dependencies. - */ -const getPackages = require( './packages' ); - -const getUnstagedFiles = () => - execSync( 'git diff --name-only', { encoding: 'utf8' } ) - .split( '\n' ) - .filter( ( element ) => '' !== element ); -const readmeFiles = getPackages().map( - ( [ packageName ] ) => - `docs/designers-developers/developers/data/data-${ packageName.replace( - '/', - '-' - ) }.md` -); -const unstagedReadmes = getUnstagedFiles().filter( ( element ) => - readmeFiles.includes( element ) -); - -if ( unstagedReadmes.length > 0 ) { - process.exitCode = 1; - process.stdout.write( - chalk.red( - '\n', - 'Some API docs may be out of date:', - unstagedReadmes.toString(), - 'Either stage them or continue with --no-verify.', - '\n' - ) - ); -} diff --git a/docs/tool/index.js b/docs/tool/index.js index f0b1297f987dfb..d7e03d00974b3b 100644 --- a/docs/tool/index.js +++ b/docs/tool/index.js @@ -2,8 +2,6 @@ * Node dependencies */ const fs = require( 'fs' ); -const { join } = require( 'path' ); -const { execFileSync } = require( 'child_process' ); const path = require( 'path' ); /** @@ -14,9 +12,6 @@ const { getRootManifest } = require( './manifest' ); const tocFileInput = path.resolve( __dirname, '../toc.json' ); const manifestOutput = path.resolve( __dirname, '../manifest.json' ); -// Update data files from code -execFileSync( 'node', [ join( __dirname, 'update-data.js' ) ] ); - // Process TOC file and generate manifest handbook fs.writeFileSync( manifestOutput, diff --git a/docs/tool/packages.js b/docs/tool/packages.js deleted file mode 100644 index 558a3e62c43c23..00000000000000 --- a/docs/tool/packages.js +++ /dev/null @@ -1,39 +0,0 @@ -const packages = [ - [ - 'core', - { - 'Autogenerated actions': 'packages/core-data/src/actions.js', - 'Autogenerated selectors': 'packages/core-data/src/selectors.js', - }, - ], - 'core/annotations', - 'core/blocks', - 'core/block-editor', - 'core/editor', - 'core/edit-post', - 'core/keyboard-shortcuts', - 'core/notices', - 'core/nux', - 'core/viewport', -]; - -module.exports = function() { - return packages.map( ( entry ) => { - if ( ! Array.isArray( entry ) ) { - entry = [ - entry, - { - 'Autogenerated actions': `packages/${ entry.replace( - 'core/', - '' - ) }/src/store/actions.js`, - 'Autogenerated selectors': `packages/${ entry.replace( - 'core/', - '' - ) }/src/store/selectors.js`, - }, - ]; - } - return entry; - } ); -}; diff --git a/docs/tool/update-data.js b/docs/tool/update-data.js deleted file mode 100644 index 89f0fc614f1c50..00000000000000 --- a/docs/tool/update-data.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Node dependencies. - */ -const { join } = require( 'path' ); -const spawnSync = require( 'child_process' ).spawnSync; - -/** - * Local dependencies. - */ -const getPackages = require( './packages' ); - -getPackages().forEach( ( entry ) => { - const [ packageName, targetFiles ] = entry; - - Object.entries( targetFiles ).forEach( ( [ token, target ] ) => { - // Note that this needs to be a sync process for each output file that is updated: - // until docgen provides a way to update many tokens at once, we need to make sure - // the output file is updated before starting the second pass for the next token. - const { status, stderr } = spawnSync( - join( - __dirname, - '..', - '..', - 'node_modules', - '.bin', - 'docgen' - ).replace( / /g, '\\ ' ), - [ - target, - `--output docs/designers-developers/developers/data/data-${ packageName.replace( - '/', - '-' - ) }.md`, - '--to-token', - `--use-token "${ token }"`, - '--ignore "/unstable|experimental/i"', - ], - { shell: true } - ); - - if ( status !== 0 ) { - process.stderr.write( `${ packageName } ${ stderr.toString() }\n` ); - process.exit( 1 ); - } - } ); -} ); diff --git a/gutenberg.php b/gutenberg.php index 6865712b353bbc..4dc2ea3e862c23 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the new block editor in core. - * Version: 7.8.1 + * Version: 7.9.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * @@ -54,14 +54,24 @@ function gutenberg_menu() { 'the_gutenberg_widgets' ); } - if ( array_key_exists( 'gutenberg-full-site-editing', get_option( 'gutenberg-experiments' ) ) ) { + if ( array_key_exists( 'gutenberg-navigation', get_option( 'gutenberg-experiments' ) ) ) { add_submenu_page( 'gutenberg', + __( 'Navigation (beta)', 'gutenberg' ), + __( 'Navigation (beta)', 'gutenberg' ), + 'edit_theme_options', + 'gutenberg-navigation', + 'gutenberg_navigation_page' + ); + } + if ( array_key_exists( 'gutenberg-full-site-editing', get_option( 'gutenberg-experiments' ) ) ) { + add_menu_page( __( 'Site Editor (beta)', 'gutenberg' ), __( 'Site Editor (beta)', 'gutenberg' ), 'edit_theme_options', 'gutenberg-edit-site', - 'gutenberg_edit_site_page' + 'gutenberg_edit_site_page', + 'dashicons-layout' ); } } diff --git a/lib/class-wp-rest-menu-items-controller.php b/lib/class-wp-rest-menu-items-controller.php index 18079b23ed711e..f645b7d1b46d9f 100644 --- a/lib/class-wp-rest-menu-items-controller.php +++ b/lib/class-wp-rest-menu-items-controller.php @@ -404,7 +404,7 @@ protected function prepare_item_for_database( $request ) { } elseif ( 'post_type' === $prepared_nav_item['menu-item-type'] ) { $original = get_post( absint( $prepared_nav_item['menu-item-object-id'] ) ); if ( empty( $original ) ) { - return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.', 'gutenberg' ), array( 'status' => 400 ) ); + return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.', 'gutenberg' ), array( 'status' => 400 ) ); } $prepared_nav_item['menu-item-object'] = get_post_type( $original ); } @@ -422,10 +422,10 @@ protected function prepare_item_for_database( $request ) { // Check if menu item is type custom, then title and url are required. if ( 'custom' === $prepared_nav_item['menu-item-type'] ) { if ( '' === $prepared_nav_item['menu-item-title'] ) { - return new WP_Error( 'rest_title_required', __( 'Title require if menu item of type custom.', 'gutenberg' ), array( 'status' => 400 ) ); + return new WP_Error( 'rest_title_required', __( 'Title required if menu item of type custom.', 'gutenberg' ), array( 'status' => 400 ) ); } if ( empty( $prepared_nav_item['menu-item-url'] ) ) { - return new WP_Error( 'rest_url_required', __( 'URL require if menu item of type custom.', 'gutenberg' ), array( 'status' => 400 ) ); + return new WP_Error( 'rest_url_required', __( 'URL required if menu item of type custom.', 'gutenberg' ), array( 'status' => 400 ) ); } } @@ -840,7 +840,7 @@ public function get_item_schema() { ); $schema['properties']['menu_order'] = array( - 'description' => __( 'The DB ID of the nav_menu_item that is this item\'s menu parent, if any . 0 otherwise . ', 'gutenberg' ), + 'description' => __( 'The DB ID of the nav_menu_item that is this item\'s menu parent, if any, otherwise 0.', 'gutenberg' ), 'context' => array( 'view', 'edit', 'embed' ), 'type' => 'integer', 'minimum' => 0, diff --git a/lib/client-assets.php b/lib/client-assets.php index 1f3016019b6dc7..609627dc1e3ed0 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -396,6 +396,15 @@ function gutenberg_register_packages_styles( &$styles ) { ); $styles->add_data( 'wp-list-reusable-block', 'rtl', 'replace' ); + gutenberg_override_style( + $styles, + 'wp-edit-navigation', + gutenberg_url( 'build/edit-navigation/style.css' ), + array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ), + filemtime( gutenberg_dir_path() . 'build/edit-navigation/style.css' ) + ); + $styles->add_data( 'wp-edit-navigation', 'rtl', 'replace' ); + gutenberg_override_style( $styles, 'wp-edit-site', @@ -647,6 +656,32 @@ function gutenberg_extend_settings_block_patterns( $settings ) { } add_filter( 'block_editor_settings', 'gutenberg_extend_settings_block_patterns', 0 ); +/** + * Extends block editor settings to determine whether to use custom line height controls. + * + * @param array $settings Default editor settings. + * + * @return array Filtered editor settings. + */ +function gutenberg_extend_settings_custom_line_height( $settings ) { + $settings['__experimentalDisableCustomLineHeight'] = get_theme_support( 'disable-custom-line-height' ); + return $settings; +} +add_filter( 'block_editor_settings', 'gutenberg_extend_settings_custom_line_height' ); + +/** + * Extends block editor settings to determine whether to use custom unit controls. + * Currently experimental. + * + * @param array $settings Default editor settings. + * + * @return array Filtered editor settings. + */ +function gutenberg_extend_settings_custom_units( $settings ) { + $settings['__experimentalDisableCustomUnits'] = get_theme_support( 'experimental-custom-units' ); + return $settings; +} +add_filter( 'block_editor_settings', 'gutenberg_extend_settings_custom_units' ); /* * Register default patterns if not registered in Core already. @@ -656,4 +691,7 @@ function gutenberg_extend_settings_block_patterns( $settings ) { register_pattern( 'core/two-buttons', gutenberg_load_block_pattern( 'two-buttons' ) ); register_pattern( 'core/cover-abc', gutenberg_load_block_pattern( 'cover-abc' ) ); register_pattern( 'core/two-images', gutenberg_load_block_pattern( 'two-images' ) ); + register_pattern( 'core/hero-two-columns', gutenberg_load_block_pattern( 'hero-two-columns' ) ); + register_pattern( 'core/numbered-features', gutenberg_load_block_pattern( 'numbered-features' ) ); + register_pattern( 'core/its-time', gutenberg_load_block_pattern( 'its-time' ) ); } diff --git a/lib/compat.php b/lib/compat.php index 6e68f2134b2cff..f05a9b102feb34 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -8,6 +8,42 @@ * @package gutenberg */ +if ( ! function_exists( 'register_block_type_from_metadata' ) ) { + /** + * Registers a block type from metadata stored in the `block.json` file. + * + * @since 7.9.0 + * + * @param string $path Path to the folder where the `block.json` file is located. + * @param array $args { + * Optional. Array of block type arguments. Any arguments may be defined, however the + * ones described below are supported by default. Default empty array. + * + * @type callable $render_callback Callback used to render blocks of this block type. + * } + * @return WP_Block_Type|false The registered block type on success, or false on failure. + */ + function register_block_type_from_metadata( $path, $args = array() ) { + $file = trailingslashit( $path ) . 'block.json'; + if ( ! file_exists( $file ) ) { + return false; + } + + $metadata = json_decode( file_get_contents( $file ), true ); + if ( ! is_array( $metadata ) ) { + return false; + } + + return register_block_type( + $metadata['name'], + array_merge( + $metadata, + $args + ) + ); + } +} + /** * Extends block editor settings to include a list of image dimensions per size. * diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index ef24509f5447e6..c9cad42f3360cd 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -28,12 +28,56 @@ class="edit-site" * @return bool True for Site Editor pages, false otherwise. */ function gutenberg_is_edit_site_page( $page ) { - $allowed_pages = array( - 'gutenberg_page_gutenberg-edit-site', - 'toplevel_page_gutenberg-edit-site', + return 'toplevel_page_gutenberg-edit-site' === $page; +} + +/** + * Load editor styles (this is copied form edit-form-blocks.php). + * Ideally the code is extracted into a reusable function. + * + * @return array Editor Styles Setting. + */ +function gutenberg_get_editor_styles() { + global $editor_styles; + + // + // Ideally the code is extracted into a reusable function. + $styles = array( + array( + 'css' => file_get_contents( + ABSPATH . WPINC . '/css/dist/editor/editor-styles.css' + ), + ), + ); + + /* translators: Use this to specify the CSS font family for the default font. */ + $locale_font_family = esc_html_x( 'Noto Serif', 'CSS Font Family for Editor Font', 'gutenberg' ); + $styles[] = array( + 'css' => "body { font-family: '$locale_font_family' }", ); - return in_array( $page, $allowed_pages, true ); + if ( $editor_styles && current_theme_supports( 'editor-styles' ) ) { + foreach ( $editor_styles as $style ) { + if ( preg_match( '~^(https?:)?//~', $style ) ) { + $response = wp_remote_get( $style ); + if ( ! is_wp_error( $response ) ) { + $styles[] = array( + 'css' => wp_remote_retrieve_body( $response ), + ); + } + } else { + $file = get_theme_file_path( $style ); + if ( is_file( $file ) ) { + $styles[] = array( + 'css' => file_get_contents( $file ), + 'baseURL' => get_theme_file_uri( $style ), + ); + } + } + } + } + + return $styles; } /** @@ -152,12 +196,34 @@ function gutenberg_edit_site_init( $hook ) { $settings['templateType'] = 'wp_template'; $settings['templateIds'] = array_values( $template_ids ); $settings['templatePartIds'] = array_values( $template_part_ids ); + $settings['styles'] = gutenberg_get_editor_styles(); // This is so other parts of the code can hook their own settings. // Example: Global Styles. global $post; $settings = apply_filters( 'block_editor_settings', $settings, $post ); + // Preload block editor paths. + // most of these are copied from edit-forms-blocks.php. + $preload_paths = array( + '/', + '/wp/v2/types?context=edit', + '/wp/v2/taxonomies?per_page=-1&context=edit', + '/wp/v2/themes?status=active', + sprintf( '/wp/v2/templates/%s?context=edit', $_wp_current_template_id ), + array( '/wp/v2/media', 'OPTIONS' ), + ); + $preload_data = array_reduce( + $preload_paths, + 'rest_preload_api_request', + array() + ); + wp_add_inline_script( + 'wp-api-fetch', + sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', wp_json_encode( $preload_data ) ), + 'after' + ); + // Initialize editor. wp_add_inline_script( 'wp-edit-site', diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 2d8ac36a2c2569..07a7f2a200a7b3 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -51,6 +51,17 @@ function gutenberg_initialize_experiments_settings() { 'id' => 'gutenberg-widget-experiments', ) ); + add_settings_field( + 'gutenberg-navigation', + __( 'Navigation', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable Navigation screen', 'gutenberg' ), + 'id' => 'gutenberg-navigation', + ) + ); add_settings_field( 'gutenberg-block-directory', __( 'Block Directory', 'gutenberg' ), diff --git a/lib/load.php b/lib/load.php index 617c2b8c7b7a10..7207dbbed184c6 100644 --- a/lib/load.php +++ b/lib/load.php @@ -74,6 +74,7 @@ function gutenberg_is_experiment_enabled( $name ) { require dirname( __FILE__ ) . '/demo.php'; require dirname( __FILE__ ) . '/widgets.php'; require dirname( __FILE__ ) . '/widgets-page.php'; +require dirname( __FILE__ ) . '/navigation-page.php'; require dirname( __FILE__ ) . '/experiments-page.php'; require dirname( __FILE__ ) . '/customizer.php'; require dirname( __FILE__ ) . '/edit-site-page.php'; diff --git a/lib/navigation-page.php b/lib/navigation-page.php new file mode 100644 index 00000000000000..74227fcfbd1cd9 --- /dev/null +++ b/lib/navigation-page.php @@ -0,0 +1,101 @@ + + + __( 'Thumbnail', 'gutenberg' ), + 'medium' => __( 'Medium', 'gutenberg' ), + 'large' => __( 'Large', 'gutenberg' ), + 'full' => __( 'Full Size', 'gutenberg' ), + ) + ); + + $available_image_sizes = array(); + foreach ( $image_size_names as $image_size_slug => $image_size_name ) { + $available_image_sizes[] = array( + 'slug' => $image_size_slug, + 'name' => $image_size_name, + ); + } + + $settings = array( + 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), + 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ), + 'imageSizes' => $available_image_sizes, + 'isRTL' => is_rtl(), + 'maxUploadFileSize' => $max_upload_size, + ); + + list( $color_palette, ) = (array) get_theme_support( 'editor-color-palette' ); + list( $font_sizes, ) = (array) get_theme_support( 'editor-font-sizes' ); + + if ( false !== $color_palette ) { + $settings['colors'] = $color_palette; + } + + if ( false !== $font_sizes ) { + $settings['fontSizes'] = $font_sizes; + } + + wp_add_inline_script( + 'wp-edit-navigation', + sprintf( + 'wp.domReady( function() { + wp.editNavigation.initialize( "navigation-editor", %s ); + } );', + wp_json_encode( gutenberg_experiments_editor_settings( $settings ) ) + ) + ); + + // Preload server-registered block schemas. + wp_add_inline_script( + 'wp-blocks', + 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' + ); + + wp_enqueue_script( 'wp-edit-navigation' ); + wp_enqueue_style( 'wp-edit-navigation' ); + wp_enqueue_style( 'wp-block-library' ); + wp_enqueue_script( 'wp-format-library' ); + wp_enqueue_style( 'wp-format-library' ); +} +add_action( 'admin_enqueue_scripts', 'gutenberg_navigation_init' ); diff --git a/lib/patterns/hero-two-columns.json b/lib/patterns/hero-two-columns.json new file mode 100644 index 00000000000000..eb1805c3dff0e3 --- /dev/null +++ b/lib/patterns/hero-two-columns.json @@ -0,0 +1,5 @@ +{ + "__file": "wp_block", + "title": "Hero Two Columns", + "content": "\n
\n

Enjoy a wide variety of

\n\n\n\n

Custom Designs

\n\n\n\n
\n
\n

Extend it with over 54,000 plugins to help your website meet your needs. Add an online store, galleries, mailing lists, forums, analytics, and much more. Hundreds of thousands of developers and site owners trust it worldwide.

\n
\n\n\n\n
\n

Hundreds of thousands of developers and site owners trust it worldwide. Extend it with over 54,000 plugins to help your website meet your needs. Add an online store, galleries, mailing lists, forums, analytics, and much more.

\n
\n
\n
\n" + } diff --git a/lib/patterns/its-time.json b/lib/patterns/its-time.json new file mode 100644 index 00000000000000..0e048a908ba568 --- /dev/null +++ b/lib/patterns/its-time.json @@ -0,0 +1,5 @@ +{ + "__file": "wp_block", + "title": "It's time", + "content": "\n
\n
\n
\n

NEW

\n\n\n\n

John Lenwood \"Jackie\" McLean was an American jazz alto saxophonist, composer, bandleader, and educator, and is one of the few musicians to be elected to the DownBeat Hall of Fame in the year of their death.

\n
\n\n\n\n
\n

space

\n\n\n\n

Derek Ansell's full-length biography of McLean, Sugar Free Saxophone (London: Northway Books, 2012), details the story of his career and provides a full analysis of his music on record.

\n
\n
\n\n\n\n
\n
\n\n\n\n
\n

it's time

\n
\n
\n
\n" + } diff --git a/lib/patterns/numbered-features.json b/lib/patterns/numbered-features.json new file mode 100644 index 00000000000000..010a0f52e09ed4 --- /dev/null +++ b/lib/patterns/numbered-features.json @@ -0,0 +1,5 @@ +{ + "__file": "wp_block", + "title": "Numbered Features", + "content": "\n
\n
\n
\n
\n

1

\n
\n\n\n\n
\n

Custom Designs

\n\n\n\n

Extend it with over 54,000 plugins to help your website meet your needs.

\n\n\n\n
\n
\n
\n
\n\n\n\n
\n
\n
\n

2

\n
\n\n\n\n
\n

High Performance

\n\n\n\n

Add an online store, galleries, mailing lists, forums, analytics, and much more.

\n\n\n\n
\n
\n
\n
\n\n\n\n
\n
\n
\n

3

\n
\n\n\n\n
\n

Easy and Accessible

\n\n\n\n

Hundreds of thousands of developers and site owners trust it worldwide.

\n
\n
\n
\n
\n" + } diff --git a/lib/template-loader.php b/lib/template-loader.php index 2a103da5019657..183480ce821561 100644 --- a/lib/template-loader.php +++ b/lib/template-loader.php @@ -155,11 +155,11 @@ function gutenberg_find_template( $template_file ) { 'post_name__in' => $slugs, 'orderby' => 'post_name__in', 'posts_per_page' => 1, + 'no_found_rows' => true, ) ); - $template_posts = $template_query->get_posts(); - $current_template_post = array_shift( $template_posts ); + $current_template_post = $template_query->have_posts() ? $template_query->next_post() : null; // Build map of template slugs to their priority in the current hierarchy. $slug_priorities = array_flip( $slugs ); diff --git a/package-lock.json b/package-lock.json index 2b52e365c2e3a6..82d0ecdc121cc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "7.8.1", + "version": "7.9.0-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -29,56 +29,16 @@ } }, "@babel/compat-data": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.1.tgz", - "integrity": "sha512-Z+6ZOXvyOWYxJ50BwxzdhRnRsGST8Y3jaZgxYig575lTjVSs3KtJnmESwZegg6e2Dn0td1eDhoWlp1wI4BTCPw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.0.tgz", + "integrity": "sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==", "dev": true, "requires": { - "browserslist": "^4.8.2", + "browserslist": "^4.9.1", "invariant": "^2.2.4", "semver": "^5.5.0" }, "dependencies": { - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" - } - }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", - "dev": true - }, - "node-releases": { - "version": "1.1.47", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.47.tgz", - "integrity": "sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -88,22 +48,23 @@ } }, "@babel/core": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", - "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helpers": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", + "json5": "^2.1.2", "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", @@ -129,14 +90,20 @@ } }, "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.5" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -152,12 +119,12 @@ } }, "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", + "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==", "dev": true, "requires": { - "@babel/types": "^7.8.3", + "@babel/types": "^7.9.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -183,77 +150,52 @@ } }, "@babel/helper-builder-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", - "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz", + "integrity": "sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw==", "dev": true, "requires": { - "@babel/types": "^7.8.3", - "esutils": "^2.0.0" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/types": "^7.9.0" } }, - "@babel/helper-call-delegate": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", - "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", + "@babel/helper-builder-react-jsx-experimental": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.0.tgz", + "integrity": "sha512-3xJEiyuYU4Q/Ar9BsHisgdxZsRlsShMe90URZ0e6przL26CCs8NJbDoxH94kKT17PcxlMhsCAwZd90evCo26VQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-module-imports": "^7.8.3", + "@babel/types": "^7.9.0" } }, "@babel/helper-compilation-targets": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.3.tgz", - "integrity": "sha512-JLylPCsFjhLN+6uBSSh3iYdxKdeO9MNmoY96PE/99d8kyBFaXLORtAVhqN6iHa+wtPeqxKLghDOZry0+Aiw9Tw==", + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz", + "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==", "dev": true, "requires": { - "@babel/compat-data": "^7.8.1", - "browserslist": "^4.8.2", + "@babel/compat-data": "^7.8.6", + "browserslist": "^4.9.1", "invariant": "^2.2.4", - "levenary": "^1.1.0", + "levenary": "^1.1.1", "semver": "^5.5.0" }, "dependencies": { - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" - } - }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, - "node-releases": { - "version": "1.1.47", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.47.tgz", - "integrity": "sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==", + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", "dev": true, "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "leven": "^3.1.0" } }, "semver": { @@ -265,52 +207,28 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", - "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz", + "integrity": "sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.8.3", "@babel/helper-member-expression-to-functions": "^7.8.3", "@babel/helper-optimise-call-expression": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", "@babel/helper-split-export-declaration": "^7.8.3" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", - "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", + "version": "7.8.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", + "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==", "dev": true, "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-regex": "^7.8.3", - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "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" - } - }, - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.1.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - } + "regexpu-core": "^4.7.0" } }, "@babel/helper-define-map": { @@ -381,16 +299,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", - "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", + "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", "@babel/helper-simple-access": "^7.8.3", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3", + "@babel/template": "^7.8.6", + "@babel/types": "^7.9.0", "lodash": "^4.17.13" } }, @@ -432,15 +351,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", - "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", + "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.8.3", "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/traverse": "^7.8.6", + "@babel/types": "^7.8.6" } }, "@babel/helper-simple-access": { @@ -462,6 +381,11 @@ "@babel/types": "^7.8.3" } }, + "@babel/helper-validator-identifier": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", + "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==" + }, "@babel/helper-wrap-function": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", @@ -475,30 +399,42 @@ } }, "@babel/helpers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", - "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", + "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", "dev": true, "requires": { "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", "requires": { + "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", "dev": true }, "@babel/plugin-external-helpers": { @@ -571,10 +507,20 @@ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, - "@babel/plugin-proposal-object-rest-spread": { + "@babel/plugin-proposal-numeric-separator": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz", + "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz", + "integrity": "sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", @@ -592,9 +538,9 @@ } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", - "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", + "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", @@ -602,12 +548,12 @@ } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", - "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", + "version": "7.8.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz", + "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-create-regexp-features-plugin": "^7.8.8", "@babel/helper-plugin-utils": "^7.8.3" } }, @@ -620,6 +566,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, "@babel/plugin-syntax-class-properties": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz", @@ -674,6 +629,15 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz", + "integrity": "sha512-Zpg2Sgc++37kuFl6ppq2Q7Awc6E6AIW671x5PY8E/f7MCIyPPGK/EoeZXvvY3P42exZ3Q4/t3YOzP/HiN79jDg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", @@ -683,6 +647,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz", + "integrity": "sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", @@ -768,9 +741,9 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", - "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz", + "integrity": "sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.8.3", @@ -778,7 +751,7 @@ "@babel/helper-function-name": "^7.8.3", "@babel/helper-optimise-call-expression": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", "@babel/helper-split-export-declaration": "^7.8.3", "globals": "^11.1.0" }, @@ -801,9 +774,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", - "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", + "version": "7.8.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz", + "integrity": "sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3" @@ -839,9 +812,9 @@ } }, "@babel/plugin-transform-flow-strip-types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz", - "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz", + "integrity": "sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", @@ -849,9 +822,9 @@ } }, "@babel/plugin-transform-for-of": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz", - "integrity": "sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz", + "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3" @@ -886,47 +859,47 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", - "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz", + "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", - "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", + "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-simple-access": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", - "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz", + "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.8.3", - "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", - "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz", + "integrity": "sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3" } }, @@ -968,12 +941,11 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz", - "integrity": "sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==", + "version": "7.9.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz", + "integrity": "sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.8.3", "@babel/helper-get-function-arity": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" } @@ -988,41 +960,12 @@ } }, "@babel/plugin-transform-react-constant-elements": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.8.3.tgz", - "integrity": "sha512-glrzN2U+egwRfkNFtL34xIBYTxbbUF2qJTP8HD3qETBBqzAWSeNB821X0GjU06+dNpq/UyCIjI72FmGE5NNkQQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.9.0.tgz", + "integrity": "sha512-wXMXsToAUOxJuBBEHajqKLFWcCkOSLshTI2ChCFFj1zDd7od4IOxiwLCOObNUvOpkxLpjIuaIdBMmNt6ocCPAw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3" - }, - "dependencies": { - "@babel/helper-annotate-as-pure": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", - "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", - "dev": true - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-react-display-name": { @@ -1035,47 +978,42 @@ } }, "@babel/plugin-transform-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", - "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz", + "integrity": "sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==", "dev": true, "requires": { - "@babel/helper-builder-react-jsx": "^7.8.3", + "@babel/helper-builder-react-jsx": "^7.9.0", + "@babel/helper-builder-react-jsx-experimental": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz", + "integrity": "sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx-experimental": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-jsx": "^7.8.3" } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz", - "integrity": "sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz", + "integrity": "sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-syntax-jsx": "^7.8.3" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", - "dev": true - }, - "@babel/plugin-syntax-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", - "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - } } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz", - "integrity": "sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz", + "integrity": "sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", @@ -1083,23 +1021,12 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", - "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", + "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==", "dev": true, "requires": { - "regenerator-transform": "^0.14.0" - }, - "dependencies": { - "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - } + "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { @@ -1112,9 +1039,9 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz", - "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz", + "integrity": "sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.8.3", @@ -1170,18 +1097,18 @@ } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz", - "integrity": "sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", + "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz", - "integrity": "sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz", + "integrity": "sha512-yeWeUkKx2auDbSxRe8MusAG+n4m9BFY/v+lPjmQDgOFX5qnySkUY5oXzkp6FwPdsYqnKay6lorXYdC0n3bZO7w==", "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.8.3", @@ -1200,27 +1127,29 @@ } }, "@babel/preset-env": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.3.tgz", - "integrity": "sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.0.tgz", + "integrity": "sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.8.0", - "@babel/helper-compilation-targets": "^7.8.3", + "@babel/compat-data": "^7.9.0", + "@babel/helper-compilation-targets": "^7.8.7", "@babel/helper-module-imports": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-proposal-async-generator-functions": "^7.8.3", "@babel/plugin-proposal-dynamic-import": "^7.8.3", "@babel/plugin-proposal-json-strings": "^7.8.3", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.8.3", + "@babel/plugin-proposal-numeric-separator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.0", "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", - "@babel/plugin-proposal-optional-chaining": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", "@babel/plugin-syntax-async-generators": "^7.8.0", "@babel/plugin-syntax-dynamic-import": "^7.8.0", "@babel/plugin-syntax-json-strings": "^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.8.0", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", "@babel/plugin-syntax-optional-chaining": "^7.8.0", @@ -1229,97 +1158,55 @@ "@babel/plugin-transform-async-to-generator": "^7.8.3", "@babel/plugin-transform-block-scoped-functions": "^7.8.3", "@babel/plugin-transform-block-scoping": "^7.8.3", - "@babel/plugin-transform-classes": "^7.8.3", + "@babel/plugin-transform-classes": "^7.9.0", "@babel/plugin-transform-computed-properties": "^7.8.3", "@babel/plugin-transform-destructuring": "^7.8.3", "@babel/plugin-transform-dotall-regex": "^7.8.3", "@babel/plugin-transform-duplicate-keys": "^7.8.3", "@babel/plugin-transform-exponentiation-operator": "^7.8.3", - "@babel/plugin-transform-for-of": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.9.0", "@babel/plugin-transform-function-name": "^7.8.3", "@babel/plugin-transform-literals": "^7.8.3", "@babel/plugin-transform-member-expression-literals": "^7.8.3", - "@babel/plugin-transform-modules-amd": "^7.8.3", - "@babel/plugin-transform-modules-commonjs": "^7.8.3", - "@babel/plugin-transform-modules-systemjs": "^7.8.3", - "@babel/plugin-transform-modules-umd": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.9.0", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", + "@babel/plugin-transform-modules-systemjs": "^7.9.0", + "@babel/plugin-transform-modules-umd": "^7.9.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", "@babel/plugin-transform-new-target": "^7.8.3", "@babel/plugin-transform-object-super": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.7", "@babel/plugin-transform-property-literals": "^7.8.3", - "@babel/plugin-transform-regenerator": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.7", "@babel/plugin-transform-reserved-words": "^7.8.3", "@babel/plugin-transform-shorthand-properties": "^7.8.3", "@babel/plugin-transform-spread": "^7.8.3", "@babel/plugin-transform-sticky-regex": "^7.8.3", "@babel/plugin-transform-template-literals": "^7.8.3", - "@babel/plugin-transform-typeof-symbol": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", "@babel/plugin-transform-unicode-regex": "^7.8.3", - "@babel/types": "^7.8.3", - "browserslist": "^4.8.2", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.9.0", + "browserslist": "^4.9.1", "core-js-compat": "^3.6.2", "invariant": "^2.2.2", - "levenary": "^1.1.0", + "levenary": "^1.1.1", "semver": "^5.5.0" }, "dependencies": { - "browserslist": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.5.tgz", - "integrity": "sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001022", - "electron-to-chromium": "^1.3.338", - "node-releases": "^1.1.46" - } - }, - "caniuse-lite": { - "version": "1.0.30001022", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", - "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", - "dev": true - }, - "core-js-compat": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", - "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", - "dev": true, - "requires": { - "browserslist": "^4.8.3", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "electron-to-chromium": { - "version": "1.3.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz", - "integrity": "sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww==", + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, - "node-releases": { - "version": "1.1.47", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.47.tgz", - "integrity": "sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==", + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", "dev": true, "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "leven": "^3.1.0" } }, "semver": { @@ -1331,489 +1218,224 @@ } }, "@babel/preset-flow": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.8.3.tgz", - "integrity": "sha512-iCXFk+T4demnq+dNLLvlGOgvYF6sPZ/hS1EmswugOqh1Ysp2vuiqJzpgsnp5rW8+6dLJT/0CXDzye28ZH6BAfQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.9.0.tgz", + "integrity": "sha512-88uSmlshIrlmPkNkEcx3UpSZ6b8n0UGBq0/0ZMZCF/uxAW0XIAUuDHBhIOAh0pvweafH4RxOwi/H3rWhtqOYPA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-transform-flow-strip-types": "^7.8.3" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", - "dev": true - }, - "@babel/plugin-syntax-flow": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", - "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-flow-strip-types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz", - "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-flow": "^7.8.3" - } - } + "@babel/plugin-transform-flow-strip-types": "^7.9.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", + "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" } }, "@babel/preset-react": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.8.3.tgz", - "integrity": "sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.9.4.tgz", + "integrity": "sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-transform-react-display-name": "^7.8.3", - "@babel/plugin-transform-react-jsx": "^7.8.3", - "@babel/plugin-transform-react-jsx-self": "^7.8.3", - "@babel/plugin-transform-react-jsx-source": "^7.8.3" - }, - "dependencies": { - "@babel/helper-builder-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", - "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3", - "esutils": "^2.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", - "dev": true - }, - "@babel/plugin-syntax-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", - "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-react-display-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz", - "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", - "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==", - "dev": true, - "requires": { - "@babel/helper-builder-react-jsx": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.8.3" - } - }, - "@babel/plugin-transform-react-jsx-source": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz", - "integrity": "sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.8.3" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/plugin-transform-react-jsx": "^7.9.4", + "@babel/plugin-transform-react-jsx-development": "^7.9.0", + "@babel/plugin-transform-react-jsx-self": "^7.9.0", + "@babel/plugin-transform-react-jsx-source": "^7.9.0" } }, "@babel/preset-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz", - "integrity": "sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz", + "integrity": "sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-transform-typescript": "^7.8.3" + "@babel/plugin-transform-typescript": "^7.9.0" + } + }, + "@babel/register": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.9.0.tgz", + "integrity": "sha512-Tv8Zyi2J2VRR8g7pC5gTeIN8Ihultbmk0ocyNz8H2nEZbmhp1N6q0A1UGsQbDvGP/sNinQKUHf3SqXwqjtFv4Q==", + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "lodash": "^4.17.13", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" }, "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", - "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { - "@babel/types": "^7.8.3", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" } }, - "@babel/helper-create-class-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", - "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3" + "locate-path": "^3.0.0" } }, - "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "pify": "^4.0.1", + "semver": "^5.6.0" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "p-try": "^2.0.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "p-limit": "^2.0.0" } }, - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "@babel/helper-replace-supers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", - "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "find-up": "^3.0.0" } }, - "@babel/parser": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", - "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, - "@babel/plugin-syntax-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", - "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, - "@babel/plugin-transform-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz", - "integrity": "sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==", + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-typescript": "^7.8.3" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } - }, - "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "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 - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true } } }, - "@babel/register": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.8.3.tgz", - "integrity": "sha512-t7UqebaWwo9nXWClIPLPloa5pN33A2leVs8Hf0e9g9YwUP8/H9NeR7DJU+4CXo23QtjChQv5a3DjEtT83ih1rg==", - "dev": true, + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", "requires": { - "find-cache-dir": "^2.0.0", - "lodash": "^4.17.13", - "make-dir": "^2.1.0", - "pirates": "^4.0.0", - "source-map-support": "^0.5.16" + "regenerator-runtime": "^0.13.4" }, "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" } } }, - "@babel/runtime": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.3.tgz", - "integrity": "sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==", - "requires": { - "regenerator-runtime": "^0.13.2" - } - }, "@babel/runtime-corejs3": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.8.3.tgz", - "integrity": "sha512-lrIU4aVbmlM/wQPzhEvzvNJskKyYptuXb0fGC0lTQTupTOYtR2Vqbu6/jf8vTr4M8Wt1nIzxVrSvPI5qESa/xA==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz", + "integrity": "sha512-HHxmgxbIzOfFlZ+tdeRKtaxWOMUoCG5Mu3wKeUmOxjYrwb3AAHgnmtCUbPPK11/raIWLIBK250t8E2BPO0p7jA==", "dev": true, "requires": { "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.2" + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + } } }, "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", + "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6" } }, "@babel/traverse": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", - "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", + "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.3", + "@babel/generator": "^7.9.0", "@babel/helper-function-name": "^7.8.3", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -1843,11 +1465,11 @@ } }, "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", + "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", "requires": { - "esutils": "^2.0.2", + "@babel/helper-validator-identifier": "^7.9.0", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } @@ -1858,6 +1480,12 @@ "integrity": "sha512-4Th98KlMHr5+JkxfcoDT//6vY8vM+iSPrLNpHhRyLx2CFYi8e2RfqPLdpbnpo0Q5lQC5hNB79yes07zb02fvCw==", "dev": true }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "@cnakazawa/watch": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", @@ -2538,17 +2166,109 @@ "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", "dev": true }, + "@istanbuljs/load-nyc-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", + "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, "@jest/console": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", - "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", "dev": true, "requires": { - "@jest/source-map": "^24.3.0", + "@jest/source-map": "^24.9.0", "chalk": "^2.0.1", "slash": "^2.0.0" }, "dependencies": { + "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" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -2557,488 +2277,373 @@ } } }, - "@jest/core": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", - "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "@jest/environment": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.3.0.tgz", + "integrity": "sha512-vgooqwJTHLLak4fE+TaCGeYP7Tz1Y3CKOsNxR1sE0V3nx3KRUHn3NUnt+wbcfd5yQWKZQKAfW6wqbuwQLrXo3g==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/reporters": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-changed-files": "^24.9.0", - "jest-config": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-resolve-dependencies": "^24.9.0", - "jest-runner": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "jest-watcher": "^24.9.0", - "micromatch": "^3.1.10", - "p-each-series": "^1.0.0", - "realpath-native": "^1.1.0", - "rimraf": "^2.5.4", - "slash": "^2.0.0", - "strip-ansi": "^5.0.0" + "@jest/fake-timers": "^25.3.0", + "@jest/types": "^25.3.0", + "jest-mock": "^25.3.0" }, "dependencies": { "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.3.0.tgz", + "integrity": "sha512-NHAj7WbsyR3qBJPpBwSwqaq2WluIvUQsyzpJTN7XDVk7VnlC/y1BAnaYZL3vbPIP8Nhm0Ae5DJe0KExr/SdMJQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/types": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-mock": "^25.3.0", + "jest-util": "^25.3.0", + "lolex": "^5.0.0" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - } + "fill-range": "^7.0.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@types/yargs": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.5.tgz", - "integrity": "sha512-CF/+sxTO7FOwbIRL4wMv0ZYLCRfMid2HQpzDRyViH7kSpfoAFiMdGqKIxb1PxWfjtQXQhnQuD33lvRHNwr809Q==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "color-name": "~1.1.4" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "jest-message-util": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" - }, - "dependencies": { - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - } + "@babel/code-frame": "^7.0.0", + "@jest/types": "^25.3.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^1.0.1" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true + "jest-mock": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.3.0.tgz", + "integrity": "sha512-yRn6GbuqB4j3aYu+Z1ezwRiZfp0o9om5uOcBovVtkcRLeBCNP5mT0ysdenUsxAHnQUgGwPOE1wwhtQYe6NKirQ==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0" + } }, - "jest-config": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", - "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "jest-util": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^24.9.0", - "@jest/types": "^24.9.0", - "babel-jest": "^24.9.0", - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^24.9.0", - "jest-environment-node": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "micromatch": "^3.1.10", - "pretty-format": "^24.9.0", - "realpath-native": "^1.1.0" + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", + "is-ci": "^2.0.0", + "make-dir": "^3.0.0" } }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" + "has-flag": "^4.0.0" } }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "is-number": "^7.0.0" } - }, - "jest-message-util": { + } + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + }, + "dependencies": { + "@jest/types": { "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" } }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "@types/yargs-parser": "*" } - }, - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + } + } + }, + "@jest/reporters": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.3.0.tgz", + "integrity": "sha512-1u0ZBygs0C9DhdYgLCrRfZfNKQa+9+J7Uo+Z9z0RWLHzgsxhoG32lrmMOtUw48yR6bLNELdvzormwUqSk4H4Vg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^25.3.0", + "@jest/test-result": "^25.3.0", + "@jest/transform": "^25.3.0", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "jest-haste-map": "^25.3.0", + "jest-resolve": "^25.3.0", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "node-notifier": "^6.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^3.1.0", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^4.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, - "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", - "dev": true + "@jest/source-map": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.3", + "source-map": "^0.6.0" + } }, - "jest-snapshot": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", - "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "@jest/test-result": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "expect": "^24.9.0", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^24.9.0", - "semver": "^6.2.0" + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" } }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "@jest/transform": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.3.0.tgz", + "integrity": "sha512-W01p8kTDvvEX6kd0tJc7Y5VdYyFaKwNWy1HQz6Jqlhu48z/8Gxp+yFCDVj+H8Rc7ezl3Mg0hDaGuFVkmHOqirg==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - } - } - }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" + "@babel/core": "^7.1.0", + "@jest/types": "^25.3.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^3.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.3", + "jest-haste-map": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-util": "^25.3.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "realpath-native": "^2.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" } }, - "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" } }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@jest/environment": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", - "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", - "dev": true, - "requires": { - "@jest/fake-timers": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "fill-range": "^7.0.1" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "color-name": "~1.1.4" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "to-regex-range": "^5.0.1" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", "dev": true, - "requires": { - "@types/yargs-parser": "*" - } + "optional": true }, "graceful-fs": { "version": "4.2.3", @@ -3046,288 +2651,183 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true - } - } - }, - "@jest/fake-timers": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.7.1.tgz", - "integrity": "sha512-4vSQJDKfR2jScOe12L9282uiwuwQv9Lk7mgrCSZHA9evB9efB/qx8i0KJxsAKtp8fgJYBJdYY7ZU6u3F4/pyjA==", - "dev": true, - "requires": { - "@jest/types": "^24.7.0", - "jest-message-util": "^24.7.1", - "jest-mock": "^24.7.0" - } - }, - "@jest/reporters": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", - "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "istanbul-lib-coverage": "^2.0.2", - "istanbul-lib-instrument": "^3.0.1", - "istanbul-lib-report": "^2.0.4", - "istanbul-lib-source-maps": "^3.0.1", - "istanbul-reports": "^2.2.6", - "jest-haste-map": "^24.9.0", - "jest-resolve": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.6.0", - "node-notifier": "^5.4.2", - "slash": "^2.0.0", - "source-map": "^0.6.0", - "string-length": "^2.0.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + }, + "is-wsl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } + "optional": true }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "jest-haste-map": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.3.0.tgz", + "integrity": "sha512-LjXaRa+F8wwtSxo9G+hHD/Cp63PPQzvaBL9XCVoJD2rrcJO0Zr2+YYzAFWWYJ5GlPUkoaJFJtOuk0sL6MJY80A==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "@jest/types": "^25.3.0", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.3", + "jest-serializer": "^25.2.6", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "jest-regex-util": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", + "dev": true + }, + "jest-resolve": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@jest/types": "^25.3.0", + "browser-resolve": "^1.11.3", + "chalk": "^3.0.0", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "jest-serializer": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", + "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", + "dev": true + }, + "jest-util": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", + "is-ci": "^2.0.0", + "make-dir": "^3.0.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "jest-worker": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.2.6.tgz", + "integrity": "sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, - "istanbul-reports": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", - "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "handlebars": "^4.1.2" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, - "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "node-notifier": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz", + "integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==", "dev": true, + "optional": true, "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" + "growly": "^1.3.0", + "is-wsl": "^2.1.1", + "semver": "^6.3.0", + "shellwords": "^0.1.1", + "which": "^1.3.1" }, "dependencies": { - "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "optional": true, "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "isexe": "^2.0.0" } } } }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - }, - "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - } + "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 }, - "merge-stream": { + "realpath-native": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", "dev": true }, - "node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" + "path-parse": "^1.0.6" } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "optional": true }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -3337,30 +2837,77 @@ "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } }, "write-file-atomic": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", - "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, "requires": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } } } }, "@jest/source-map": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", - "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", "dev": true, "requires": { "callsites": "^3.0.0", @@ -3369,9 +2916,9 @@ }, "dependencies": { "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "source-map": { @@ -3383,177 +2930,219 @@ } }, "@jest/test-result": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.7.1.tgz", - "integrity": "sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/types": "^24.7.0", + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", "@types/istanbul-lib-coverage": "^2.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + } } }, "@jest/test-sequencer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", - "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.3.0.tgz", + "integrity": "sha512-Xvns3xbji7JCvVcDGvqJ/pf4IpmohPODumoPEZJ0/VgC5gI4XaNVIBET2Dq5Czu6Gk3xFcmhtthh/MBOTljdNg==", "dev": true, "requires": { - "@jest/test-result": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-runner": "^24.9.0", - "jest-runtime": "^24.9.0" + "@jest/test-result": "^25.3.0", + "jest-haste-map": "^25.3.0", + "jest-runner": "^25.3.0", + "jest-runtime": "^25.3.0" }, "dependencies": { "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", + "graceful-fs": "^4.2.3", "source-map": "^0.6.0" } }, "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } }, - "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" + "color-name": "~1.1.4" } }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "jest-haste-map": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.3.0.tgz", + "integrity": "sha512-LjXaRa+F8wwtSxo9G+hHD/Cp63PPQzvaBL9XCVoJD2rrcJO0Zr2+YYzAFWWYJ5GlPUkoaJFJtOuk0sL6MJY80A==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "@jest/types": "^25.3.0", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.3", + "jest-serializer": "^25.2.6", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" } }, "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", + "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", "dev": true }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.2.6.tgz", + "integrity": "sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==", "dev": true, "requires": { "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "supports-color": "^7.0.0" } }, "merge-stream": { @@ -3562,10 +3151,26 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -3575,12 +3180,30 @@ "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } } } @@ -3609,50 +3232,6 @@ "write-file-atomic": "2.4.1" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, "@jest/types": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", @@ -3665,111 +3244,29 @@ } }, "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" - } - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - }, - "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", - "dev": true - }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - } - }, - "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "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": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "slash": { @@ -3784,15 +3281,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, "write-file-atomic": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", @@ -3807,13 +3295,67 @@ } }, "@jest/types": { - "version": "24.7.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.7.0.tgz", - "integrity": "sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.3.0.tgz", + "integrity": "sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", - "@types/yargs": "^12.0.9" + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@lerna/add": { @@ -3934,6 +3476,17 @@ "strong-log-transformer": "^2.0.0" }, "dependencies": { + "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" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -4216,6 +3769,19 @@ "chalk": "^2.3.1", "figgy-pudding": "^3.5.1", "npmlog": "^4.1.2" + }, + "dependencies": { + "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" + } + } } }, "@lerna/collect-updates": { @@ -4982,6 +4548,19 @@ "@lerna/query-graph": "3.18.0", "chalk": "^2.3.1", "columnify": "^1.5.4" + }, + "dependencies": { + "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" + } + } } }, "@lerna/log-packed": { @@ -5532,6 +5111,19 @@ "string-width": "^2.1.0", "strip-ansi": "^5.1.0", "through": "^2.3.6" + }, + "dependencies": { + "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" + } + } } }, "strip-ansi": { @@ -5673,6 +5265,31 @@ "npmlog": "^4.1.2", "path-exists": "^3.0.0", "rimraf": "^2.6.2" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "@lerna/run": { @@ -5848,6 +5465,17 @@ "write-json-file": "^3.2.0" }, "dependencies": { + "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" + } + }, "graceful-fs": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", @@ -6083,6 +5711,19 @@ "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "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" + } + } } }, "@babel/parser": { @@ -6571,6 +6212,11 @@ } } }, + "@popperjs/core": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.1.1.tgz", + "integrity": "sha512-sLqWxCzC5/QHLhziXSCAksBxHfOnQlhPRVgPK0egEw+ktWvG75T2k+aYWVjVh9+WKeT3tlG3ZNbZQvZLmfuOIw==" + }, "@reach/router": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.2.1.tgz", @@ -6608,6 +6254,17 @@ "xmldoc": "^1.1.2" }, "dependencies": { + "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" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -6679,6 +6336,19 @@ "chalk": "^2.4.2", "js-yaml": "^3.13.1", "xcode": "^2.0.0" + }, + "dependencies": { + "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" + } + } } }, "@react-native-community/cli-tools": { @@ -6693,6 +6363,17 @@ "node-fetch": "^2.5.0" }, "dependencies": { + "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" + } + }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -6716,6 +6397,21 @@ "any-observable": "^0.3.0" } }, + "@sindresorhus/is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.0.tgz", + "integrity": "sha512-lXKXfypKo644k4Da4yXkPCrwcvn6SlUW2X2zFbuflKHNjf0w9htru01bo26uMhleMXsDmnZ12eJLdrAZa9MANg==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.1.tgz", + "integrity": "sha512-Debi3Baff1Qu1Unc3mjJ96MgpbwTn43S1+9yJ0llWygPwDNu2aaWBD6yc9y/Z8XDRNhx7U+u2UDg2OGQXkclUQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, "@storybook/addon-a11y": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-5.3.2.tgz", @@ -6912,6 +6608,15 @@ "ts-dedent": "^1.1.0" }, "dependencies": { + "@types/jest": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", + "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", + "dev": true, + "requires": { + "jest-diff": "^24.3.0" + } + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7043,9 +6748,9 @@ "dev": true }, "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -9287,6 +8992,19 @@ "stable": "^0.1.8", "unquote": "~1.1.1", "util.promisify": "~1.0.0" + }, + "dependencies": { + "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" + } + } } } } @@ -9831,6 +9549,19 @@ "stable": "^0.1.8", "unquote": "~1.1.1", "util.promisify": "~1.0.0" + }, + "dependencies": { + "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" + } + } } } } @@ -9885,32 +9616,158 @@ } } }, + "@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, "@tannin/compile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.0.3.tgz", - "integrity": "sha512-OkPHvaM/hIHdSco3+ZO1hzkOtfEddn5a0veWft2aDLvKnbdj9VusiLKNdEE9by3hCZIIcb9aWF+iBorhfrQOfw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz", + "integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==", "requires": { - "@tannin/evaluate": "^1.1.1", - "@tannin/postfix": "^1.0.2" + "@tannin/evaluate": "^1.2.0", + "@tannin/postfix": "^1.1.0" } }, "@tannin/evaluate": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.1.1.tgz", - "integrity": "sha512-ALuSZHjrLHGnw0WxsHDHde74FJ2WW0Ck4rg3QBxFBCmxd6Wsac+e0HXfJ++Qion15LIOCmFhyVpWzawMgeBA8Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz", + "integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==" }, "@tannin/plural-forms": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.0.3.tgz", - "integrity": "sha512-IUr9+FiCnzCiB9aRio3FVNR8TNL9SmX2zkV6tmfWWwSclX4uTCykoGsDhTGKK+sZnMrdPCTmb/OxbtGNdVyV4g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz", + "integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==", "requires": { - "@tannin/compile": "^1.0.3" + "@tannin/compile": "^1.1.0" } }, "@tannin/postfix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.0.2.tgz", - "integrity": "sha512-Nggtk7/ljfNPpAX8CjxxLkMKuO6u2gH1ozmTvGclWF2pNcxTf6YGghYNYNWZRKrimXGhQ8yZqvAHep7h80K04g==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", + "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==" + }, + "@testing-library/dom": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.2.1.tgz", + "integrity": "sha512-xIGoHlQ2ZiEL1dJIFKNmLDypzYF+4OJTTASRctl/aoIDaS5y/pRVHRigoqvPUV11mdJoR71IIgi/6UviMgyz4g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "@types/testing-library__dom": "^7.0.0", + "aria-query": "^4.0.2", + "dom-accessibility-api": "^0.4.2", + "pretty-format": "^25.1.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.0.2.tgz", + "integrity": "sha512-S1G1V790fTaigUSM/Gd0NngzEfiMy9uTUfMyHhKhVyy4cH5O/eTuR01ydhGL0z4Za1PXFTRGH3qL8VhUQuEO5w==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.4", + "@babel/runtime-corejs3": "^7.7.4" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + } + } + }, + "@testing-library/react": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-10.0.2.tgz", + "integrity": "sha512-YT6Mw0oJz7R6vlEkmo1FlUD+K15FeXApOB5Ffm9zooFVnrwkt00w18dUJFMOh1yRp9wTdVRonbor7o4PIpFCmA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2", + "@testing-library/dom": "^7.1.0", + "@types/testing-library__react": "^10.0.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + } + } }, "@types/babel-types": { "version": "7.0.7", @@ -9919,9 +9776,9 @@ "dev": true }, "@types/babel__core": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", - "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.7.tgz", + "integrity": "sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -9968,6 +9825,24 @@ "@types/babel-types": "*" } }, + "@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/classnames": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.10.tgz", + "integrity": "sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==", + "dev": true + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -9997,6 +9872,12 @@ "integrity": "sha512-+o2igcuZA3xtOoFH56s+MCZVidwlJNcJID57DSCyawS2i910yG9vkwehCjJNZ6ImhCR5S9DbvIJKyYHcMyOfMw==", "dev": true }, + "@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==", + "dev": true + }, "@types/is-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.0.tgz", @@ -10029,12 +9910,125 @@ } }, "@types/jest": { - "version": "24.0.25", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.25.tgz", - "integrity": "sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g==", + "version": "25.2.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.2.1.tgz", + "integrity": "sha512-msra1bCaAeEdkSyA0CZ6gW1ukMIvZ5YoJkdXw/qhQdsuuDlFTcEUrUw8CLCPt2rVRUfXlClVvK2gvPs9IokZaA==", "dev": true, "requires": { - "jest-diff": "^24.3.0" + "jest-diff": "^25.2.1", + "pretty-format": "^25.2.1" + }, + "dependencies": { + "@jest/types": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.2.6.tgz", + "integrity": "sha512-myJTTV37bxK7+3NgKc4Y/DlQ5q92/NOwZsZ+Uch7OXdElxOg61QYc72fPYNAjlvbnJ2YvbXLamIsa9tj48BmyQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.2.6.tgz", + "integrity": "sha512-KuadXImtRghTFga+/adnNrv9s61HudRMR7gVSbP35UKZdn4IK2/0N0PpGZIqtmllK9aUyye54I3nu28OYSnqOg==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.2.6" + } + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "pretty-format": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.2.6.tgz", + "integrity": "sha512-DEiWxLBaCHneffrIT4B+TpMvkV9RNvvJrd3lY9ew1CEQobDzEXmYT1mg0hJhljZty7kCc10z13ohOFAE8jrUDg==", + "dev": true, + "requires": { + "@jest/types": "^25.2.6", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@types/jest-specific-snapshot": { @@ -10047,9 +10041,24 @@ } }, "@types/json-schema": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", - "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, + "@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", "dev": true }, "@types/minimatch": { @@ -10075,6 +10084,12 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, + "@types/prettier": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.0.tgz", + "integrity": "sha512-gDE8JJEygpay7IjA/u3JiIURvwZW08f0cZSZLAzFoX/ZmeqvS0Sqv+97aKuHpNsalAMMhwPe+iAS6fQbfmbt7A==", + "dev": true + }, "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", @@ -10087,6 +10102,12 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, + "@types/qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-lhbQXx9HKZAPgBkISrBcmAcMpZsmpe/Cd/hY7LGZS5OfkySUBItnPZHgQPssWYUET8elF+yCFBbP1Q0RZPTdaw==", + "dev": true + }, "@types/reach__router": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.2.6.tgz", @@ -10116,6 +10137,15 @@ "@types/react": "*" } }, + "@types/react-dom": { + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.5.tgz", + "integrity": "sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/react-syntax-highlighter": { "version": "11.0.2", "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.2.tgz", @@ -10140,12 +10170,149 @@ "integrity": "sha512-BnnRkgWYijCIndUn+LgoqKHX/hNpJC5G03B9y7mZya/C2gUQTSn75fEj3ZP1/Rl2E6EYeXh2/7/8UNEZ4X7HuQ==", "dev": true }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-hkgzYF+qnIl8uTO8rmUSVSfQ8BIfMXC4yJAF4n8BE758YsKBZvFC4NumnAegj7KmylP0liEZNpb9RRGFMbFejA==", + "dev": true + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, + "@types/testing-library__dom": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@types/testing-library__dom/-/testing-library__dom-7.0.1.tgz", + "integrity": "sha512-WokGRksRJb3Dla6h02/0/NNHTkjsj4S8aJZiwMj/5/UL8VZ1iCe3H8SHzfpmBeH8Vp4SPRT8iC2o9kYULFhDIw==", + "dev": true, + "requires": { + "pretty-format": "^25.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + } + } + }, + "@types/testing-library__react": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/testing-library__react/-/testing-library__react-10.0.1.tgz", + "integrity": "sha512-RbDwmActAckbujLZeVO/daSfdL1pnjVqas25UueOkAY5r7vriavWf0Zqg7ghXMHa8ycD/kLkv8QOj31LmSYwww==", + "dev": true, + "requires": { + "@types/react-dom": "*", + "@types/testing-library__dom": "*", + "pretty-format": "^25.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + } + } + }, "@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", @@ -10180,10 +10347,13 @@ "dev": true }, "@types/yargs": { - "version": "12.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.13.tgz", - "integrity": "sha512-CXlavd8Q7ZQkB7sMpx9QKC/B7gUsjtftxMHNr7qGJaDiZZ+Qmhwe4Zt3aS9aXF7cn6BYQuFlKU1UlrebyKsh9g==", - "dev": true + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", + "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } }, "@types/yargs-parser": { "version": "13.1.0", @@ -10192,30 +10362,92 @@ "dev": true }, "@typescript-eslint/experimental-utils": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", - "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.26.0.tgz", + "integrity": "sha512-RELVoH5EYd+JlGprEyojUv9HeKcZqF7nZUGSblyAw1FwOGNnmQIU8kxJ69fttQvEwCsX5D6ECJT8GTozxrDKVQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-scope": "^4.0.0" + "@typescript-eslint/typescript-estree": "2.26.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } } }, "@typescript-eslint/typescript-estree": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", - "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.26.0.tgz", + "integrity": "sha512-3x4SyZCLB4zsKsjuhxDLeVJN6W29VwBnYpCsZ7vIdPel9ZqLfIZJgJXO47MNUkurGpQuIBALdPQKtsSnWpE1Yg==", "dev": true, "requires": { - "lodash.unescape": "4.0.1", - "semver": "5.5.0" + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" }, "dependencies": { + "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" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -10399,27 +10631,28 @@ "@wordpress/a11y": { "version": "file:packages/a11y", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/dom-ready": "file:packages/dom-ready" } }, "@wordpress/annotations": { "version": "file:packages/annotations", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/data": "file:packages/data", "@wordpress/hooks": "file:packages/hooks", "@wordpress/i18n": "file:packages/i18n", "@wordpress/rich-text": "file:packages/rich-text", "lodash": "^4.17.15", "rememo": "^3.0.0", - "uuid": "^3.3.2" + "uuid": "^7.0.2" } }, "@wordpress/api-fetch": { "version": "file:packages/api-fetch", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", + "@wordpress/element": "file:packages/element", "@wordpress/i18n": "file:packages/i18n", "@wordpress/url": "file:packages/url" } @@ -10427,7 +10660,7 @@ "@wordpress/autop": { "version": "file:packages/autop", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/babel-plugin-import-jsx-pragma": { @@ -10438,7 +10671,7 @@ "version": "file:packages/babel-plugin-makepot", "dev": true, "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "gettext-parser": "^1.3.1", "lodash": "^4.17.15" } @@ -10447,18 +10680,16 @@ "version": "file:packages/babel-preset-default", "dev": true, "requires": { - "@babel/core": "^7.8.3", - "@babel/plugin-proposal-async-generator-functions": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-react-jsx": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.8.3", - "@babel/preset-env": "^7.8.3", - "@babel/runtime": "^7.8.3", + "@babel/core": "^7.9.0", + "@babel/plugin-transform-react-jsx": "^7.9.4", + "@babel/plugin-transform-runtime": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@babel/runtime": "^7.9.2", "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", "@wordpress/browserslist-config": "file:packages/browserslist-config", "@wordpress/element": "file:packages/element", "@wordpress/warning": "file:packages/warning", - "core-js": "^3.1.4" + "core-js": "^3.6.4" } }, "@wordpress/base-styles": { @@ -10468,7 +10699,7 @@ "@wordpress/blob": { "version": "file:packages/blob", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/block-directory": { @@ -10490,7 +10721,7 @@ "@wordpress/block-editor": { "version": "file:packages/block-editor", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:packages/a11y", "@wordpress/blob": "file:packages/blob", "@wordpress/blocks": "file:packages/blocks", @@ -10507,6 +10738,7 @@ "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", "@wordpress/keycodes": "file:packages/keycodes", + "@wordpress/priority-queue": "file:packages/priority-queue", "@wordpress/rich-text": "file:packages/rich-text", "@wordpress/token-list": "file:packages/token-list", "@wordpress/url": "file:packages/url", @@ -10518,7 +10750,7 @@ "dom-scroll-into-view": "^1.2.1", "inherits": "^2.0.3", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "react-autosize-textarea": "^3.0.2", "react-spring": "^8.0.19", "redux-multi": "^0.1.12", @@ -10531,7 +10763,7 @@ "@wordpress/block-library": { "version": "file:packages/block-library", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:packages/a11y", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/autop": "file:packages/autop", @@ -10560,7 +10792,7 @@ "classnames": "^2.2.5", "fast-average-color": "4.3.0", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "moment": "^2.22.1", "tinycolor2": "^1.4.1" } @@ -10568,7 +10800,7 @@ "@wordpress/block-serialization-default-parser": { "version": "file:packages/block-serialization-default-parser", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/block-serialization-spec-parser": { @@ -10581,7 +10813,7 @@ "@wordpress/blocks": { "version": "file:packages/blocks", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/autop": "file:packages/autop", "@wordpress/blob": "file:packages/blob", "@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser", @@ -10601,7 +10833,7 @@ "showdown": "^1.8.6", "simple-html-tokenizer": "^0.5.7", "tinycolor2": "^1.4.1", - "uuid": "^3.3.2" + "uuid": "^7.0.2" } }, "@wordpress/browserslist-config": { @@ -10611,7 +10843,7 @@ "@wordpress/components": { "version": "file:packages/components", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@emotion/core": "^10.0.22", "@emotion/css": "^10.0.22", "@emotion/native": "^10.0.22", @@ -10635,21 +10867,21 @@ "downshift": "^4.0.5", "gradient-parser": "^0.1.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "moment": "^2.22.1", "re-resizable": "^6.0.0", "react-dates": "^17.1.1", "react-spring": "^8.0.20", - "reakit": "^1.0.0-beta.12", + "reakit": "^1.0.0-rc.0", "rememo": "^3.0.0", "tinycolor2": "^1.4.1", - "uuid": "^3.3.2" + "uuid": "^7.0.2" } }, "@wordpress/compose": { "version": "file:packages/compose", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/element": "file:packages/element", "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", "lodash": "^4.17.15", @@ -10660,7 +10892,7 @@ "@wordpress/core-data": { "version": "file:packages/core-data", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/blocks": "file:packages/blocks", "@wordpress/data": "file:packages/data", @@ -10678,11 +10910,11 @@ "version": "file:packages/create-block", "dev": true, "requires": { - "chalk": "^2.4.2", + "chalk": "^4.0.0", "check-node-version": "^3.1.1", "commander": "^4.1.0", "execa": "^4.0.0", - "inquirer": "^7.0.3", + "inquirer": "^7.1.0", "lodash": "^4.17.15", "make-dir": "^3.0.0", "mustache": "^4.0.0", @@ -10699,7 +10931,7 @@ "@wordpress/data": { "version": "file:packages/data", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:packages/compose", "@wordpress/deprecated": "file:packages/deprecated", "@wordpress/element": "file:packages/element", @@ -10709,7 +10941,7 @@ "equivalent-key-map": "^0.2.2", "is-promise": "^2.1.0", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "redux": "^4.0.0", "turbo-combine-reducers": "^1.0.2", "use-memo-one": "^1.1.1" @@ -10725,7 +10957,7 @@ "@wordpress/date": { "version": "file:packages/date", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "moment": "^2.22.1", "moment-timezone": "^0.5.16" } @@ -10742,7 +10974,7 @@ "@wordpress/deprecated": { "version": "file:packages/deprecated", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/hooks": "file:packages/hooks" } }, @@ -10763,21 +10995,21 @@ "@wordpress/dom": { "version": "file:packages/dom", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15" } }, "@wordpress/dom-ready": { "version": "file:packages/dom-ready", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/e2e-test-utils": { "version": "file:packages/e2e-test-utils", "dev": true, "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/keycodes": "file:packages/keycodes", "@wordpress/url": "file:packages/url", "lodash": "^4.17.15", @@ -10793,15 +11025,38 @@ "@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe", "@wordpress/scripts": "file:packages/scripts", "@wordpress/url": "file:packages/url", - "expect-puppeteer": "^4.3.0", + "chalk": "^4.0.0", + "expect-puppeteer": "^4.4.0", "lodash": "^4.17.15", - "uuid": "^3.3.2" + "uuid": "^7.0.2" + } + }, + "@wordpress/edit-navigation": { + "version": "file:packages/edit-navigation", + "requires": { + "@babel/runtime": "^7.9.2", + "@wordpress/block-editor": "file:packages/block-editor", + "@wordpress/block-library": "file:packages/block-library", + "@wordpress/blocks": "file:packages/blocks", + "@wordpress/components": "file:packages/components", + "@wordpress/compose": "file:packages/compose", + "@wordpress/data": "file:packages/data", + "@wordpress/data-controls": "file:packages/data-controls", + "@wordpress/dom-ready": "file:packages/dom-ready", + "@wordpress/element": "file:packages/element", + "@wordpress/hooks": "file:packages/hooks", + "@wordpress/i18n": "file:packages/i18n", + "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", + "@wordpress/media-utils": "file:packages/media-utils", + "@wordpress/notices": "file:packages/notices", + "lodash": "^4.17.15", + "rememo": "^3.0.0" } }, "@wordpress/edit-post": { "version": "file:packages/edit-post", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:packages/a11y", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/block-editor": "file:packages/block-editor", @@ -10811,11 +11066,13 @@ "@wordpress/compose": "file:packages/compose", "@wordpress/core-data": "file:packages/core-data", "@wordpress/data": "file:packages/data", + "@wordpress/data-controls": "file:packages/data-controls", "@wordpress/editor": "file:packages/editor", "@wordpress/element": "file:packages/element", "@wordpress/hooks": "file:packages/hooks", "@wordpress/i18n": "file:packages/i18n", "@wordpress/icons": "file:packages/icons", + "@wordpress/interface": "file:packages/interface", "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", "@wordpress/keycodes": "file:packages/keycodes", "@wordpress/media-utils": "file:packages/media-utils", @@ -10826,7 +11083,7 @@ "@wordpress/viewport": "file:packages/viewport", "classnames": "^2.2.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "refx": "^3.0.0", "rememo": "^3.0.0" } @@ -10834,7 +11091,7 @@ "@wordpress/edit-site": { "version": "file:packages/edit-site", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/block-editor": "file:packages/block-editor", "@wordpress/block-library": "file:packages/block-library", "@wordpress/blocks": "file:packages/blocks", @@ -10847,8 +11104,10 @@ "@wordpress/hooks": "file:packages/hooks", "@wordpress/i18n": "file:packages/i18n", "@wordpress/icons": "file:packages/icons", + "@wordpress/interface": "file:packages/interface", "@wordpress/media-utils": "file:packages/media-utils", "@wordpress/notices": "file:packages/notices", + "@wordpress/plugins": "file:packages/plugins", "@wordpress/primitives": "file:packages/primitives", "@wordpress/url": "file:packages/url", "file-saver": "^2.0.2", @@ -10859,7 +11118,7 @@ "@wordpress/edit-widgets": { "version": "file:packages/edit-widgets", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/block-editor": "file:packages/block-editor", "@wordpress/block-library": "file:packages/block-library", "@wordpress/blocks": "file:packages/blocks", @@ -10870,6 +11129,7 @@ "@wordpress/element": "file:packages/element", "@wordpress/hooks": "file:packages/hooks", "@wordpress/i18n": "file:packages/i18n", + "@wordpress/interface": "file:packages/interface", "@wordpress/media-utils": "file:packages/media-utils", "@wordpress/notices": "file:packages/notices", "lodash": "^4.17.15", @@ -10879,7 +11139,7 @@ "@wordpress/editor": { "version": "file:packages/editor", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/autop": "file:packages/autop", "@wordpress/blob": "file:packages/blob", @@ -10910,7 +11170,7 @@ "@wordpress/wordcount": "file:packages/wordcount", "classnames": "^2.2.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "react-autosize-textarea": "^3.0.2", "redux-optimist": "^1.0.0", "refx": "^3.0.0", @@ -10920,7 +11180,7 @@ "@wordpress/element": { "version": "file:packages/element", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/escape-html": "file:packages/escape-html", "lodash": "^4.17.15", "react": "^16.9.0", @@ -10931,268 +11191,38 @@ "version": "file:packages/env", "dev": true, "requires": { - "chalk": "^2.4.2", + "chalk": "^4.0.0", "copy-dir": "^1.2.0", "docker-compose": "^0.22.2", "extract-zip": "^1.6.7", - "inquirer": "^7.0.4", + "got": "^10.7.0", + "inquirer": "^7.1.0", "js-yaml": "^3.13.1", "nodegit": "^0.26.2", "ora": "^4.0.2", - "request": "^2.88.2", - "request-progress": "^3.0.0", "rimraf": "^3.0.2", "terminal-link": "^2.0.0", "yargs": "^14.0.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "inquirer": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", - "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", - "dev": true, - "requires": { - "mime-db": "1.43.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } } }, "@wordpress/escape-html": { "version": "file:packages/escape-html", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/eslint-plugin": { "version": "file:packages/eslint-plugin", "dev": true, "requires": { - "babel-eslint": "^10.0.3", - "eslint-config-prettier": "^6.10.0", - "eslint-plugin-jest": "^22.15.1", - "eslint-plugin-jsdoc": "^15.8.0", + "babel-eslint": "^10.1.0", + "eslint-config-prettier": "^6.10.1", + "eslint-plugin-jest": "^23.8.2", + "eslint-plugin-jsdoc": "^22.1.0", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-prettier": "^3.1.2", - "eslint-plugin-react": "^7.14.3", - "eslint-plugin-react-hooks": "^1.6.1", + "eslint-plugin-react": "^7.19.0", + "eslint-plugin-react-hooks": "^3.0.0", "globals": "^12.0.0", "prettier": "npm:wp-prettier@1.19.1", "requireindex": "^1.2.0" @@ -11201,7 +11231,7 @@ "@wordpress/format-library": { "version": "file:packages/format-library", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/block-editor": "file:packages/block-editor", "@wordpress/components": "file:packages/components", "@wordpress/data": "file:packages/data", @@ -11219,46 +11249,60 @@ "@wordpress/hooks": { "version": "file:packages/hooks", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/html-entities": { "version": "file:packages/html-entities", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/i18n": { "version": "file:packages/i18n", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "gettext-parser": "^1.3.1", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "sprintf-js": "^1.1.1", - "tannin": "^1.1.0" + "tannin": "^1.2.0" } }, "@wordpress/icons": { "version": "file:packages/icons", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/element": "file:packages/element", "@wordpress/primitives": "file:packages/primitives" } }, + "@wordpress/interface": { + "version": "file:packages/interface", + "requires": { + "@babel/runtime": "^7.9.2", + "@wordpress/components": "file:packages/components", + "@wordpress/data": "file:packages/data", + "@wordpress/element": "file:packages/element", + "@wordpress/i18n": "file:packages/i18n", + "@wordpress/icons": "file:packages/icons", + "@wordpress/plugins": "file:packages/plugins", + "classnames": "^2.2.5", + "lodash": "^4.17.15" + } + }, "@wordpress/is-shallow-equal": { "version": "file:packages/is-shallow-equal", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" } }, "@wordpress/jest-console": { "version": "file:packages/jest-console", "dev": true, "requires": { - "@babel/runtime": "^7.8.3", - "jest-matcher-utils": "^24.7.0", + "@babel/runtime": "^7.9.2", + "jest-matcher-utils": "^25.3.0", "lodash": "^4.17.15" } }, @@ -11266,26 +11310,26 @@ "version": "file:packages/jest-preset-default", "dev": true, "requires": { - "@jest/reporters": "^24.8.0", + "@jest/reporters": "^25.3.0", "@wordpress/jest-console": "file:packages/jest-console", - "babel-jest": "^24.9.0", - "enzyme": "^3.9.0", - "enzyme-adapter-react-16": "^1.10.0", - "enzyme-to-json": "^3.3.5" + "babel-jest": "^25.3.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-to-json": "^3.4.4" } }, "@wordpress/jest-puppeteer-axe": { "version": "file:packages/jest-puppeteer-axe", "dev": true, "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "axe-puppeteer": "^1.0.0" } }, "@wordpress/keyboard-shortcuts": { "version": "file:packages/keyboard-shortcuts", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:packages/compose", "@wordpress/data": "file:packages/data", "@wordpress/element": "file:packages/element", @@ -11297,7 +11341,7 @@ "@wordpress/keycodes": { "version": "file:packages/keycodes", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/i18n": "file:packages/i18n", "lodash": "^4.17.15" } @@ -11313,7 +11357,7 @@ "@wordpress/list-reusable-blocks": { "version": "file:packages/list-reusable-blocks", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/components": "file:packages/components", "@wordpress/compose": "file:packages/compose", @@ -11325,7 +11369,7 @@ "@wordpress/media-utils": { "version": "file:packages/media-utils", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/blob": "file:packages/blob", "@wordpress/element": "file:packages/element", @@ -11336,7 +11380,7 @@ "@wordpress/notices": { "version": "file:packages/notices", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:packages/a11y", "@wordpress/data": "file:packages/data", "lodash": "^4.17.15" @@ -11349,7 +11393,7 @@ "@wordpress/nux": { "version": "file:packages/nux", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/components": "file:packages/components", "@wordpress/compose": "file:packages/compose", "@wordpress/data": "file:packages/data", @@ -11364,7 +11408,7 @@ "@wordpress/plugins": { "version": "file:packages/plugins", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:packages/compose", "@wordpress/element": "file:packages/element", "@wordpress/hooks": "file:packages/hooks", @@ -11388,7 +11432,7 @@ "@wordpress/primitives": { "version": "file:packages/primitives", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/element": "file:packages/element", "classnames": "^2.2.5" } @@ -11396,13 +11440,22 @@ "@wordpress/priority-queue": { "version": "file:packages/priority-queue", "requires": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" + } + }, + "@wordpress/project-management-automation": { + "version": "file:packages/project-management-automation", + "dev": true, + "requires": { + "@actions/core": "^1.0.0", + "@actions/github": "^1.0.0", + "@babel/runtime": "^7.9.2" } }, "@wordpress/redux-routine": { "version": "file:packages/redux-routine", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "is-promise": "^2.1.0", "lodash": "^4.17.15", "rungen": "^0.3.2" @@ -11411,7 +11464,7 @@ "@wordpress/rich-text": { "version": "file:packages/rich-text", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:packages/compose", "@wordpress/data": "file:packages/data", "@wordpress/deprecated": "file:packages/deprecated", @@ -11421,7 +11474,7 @@ "@wordpress/keycodes": "file:packages/keycodes", "classnames": "^2.2.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "rememo": "^3.0.0" } }, @@ -11436,18 +11489,19 @@ "@wordpress/jest-preset-default": "file:packages/jest-preset-default", "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", "@wordpress/prettier-config": "file:packages/prettier-config", - "babel-jest": "^24.9.0", - "babel-loader": "^8.0.6", - "chalk": "^2.4.2", + "babel-jest": "^25.3.0", + "babel-loader": "^8.1.0", + "chalk": "^4.0.0", "check-node-version": "^3.1.1", "command-exists": "^1.2.8", "cross-spawn": "^5.1.0", "decompress-zip": "^0.2.2", "dir-glob": "^3.0.1", - "eslint": "^6.1.0", - "eslint-plugin-markdown": "1.0.1", - "jest": "^24.9.0", - "jest-puppeteer": "^4.3.0", + "eslint": "^6.8.0", + "eslint-plugin-markdown": "^1.0.2", + "got": "^10.7.0", + "jest": "^25.3.0", + "jest-puppeteer": "^4.4.0", "js-yaml": "^3.13.1", "lodash": "^4.17.15", "markdownlint": "^0.18.0", @@ -11457,7 +11511,6 @@ "prettier": "npm:wp-prettier@1.19.1", "puppeteer": "^2.0.0", "read-pkg-up": "^1.0.1", - "request": "^2.88.0", "resolve-bin": "^0.4.0", "source-map-loader": "^0.2.4", "sprintf-js": "^1.1.1", @@ -11474,7 +11527,7 @@ "@wordpress/server-side-render": { "version": "file:packages/server-side-render", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:packages/api-fetch", "@wordpress/components": "file:packages/components", "@wordpress/data": "file:packages/data", @@ -11488,22 +11541,22 @@ "@wordpress/shortcode": { "version": "file:packages/shortcode", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15", - "memize": "^1.0.5" + "memize": "^1.1.0" } }, "@wordpress/token-list": { "version": "file:packages/token-list", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15" } }, "@wordpress/url": { "version": "file:packages/url", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15", "qs": "^6.5.2", "react-native-url-polyfill": "^1.1.2" @@ -11512,7 +11565,7 @@ "@wordpress/viewport": { "version": "file:packages/viewport", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:packages/compose", "@wordpress/data": "file:packages/data", "lodash": "^4.17.15" @@ -11524,7 +11577,7 @@ "@wordpress/wordcount": { "version": "file:packages/wordcount", "requires": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15" } }, @@ -11561,12 +11614,6 @@ "through": ">=2.2.7 <3" } }, - "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "dev": true - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -11604,15 +11651,6 @@ "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", "dev": true }, - "acorn-globals": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", - "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", - "dev": true, - "requires": { - "acorn": "^5.0.0" - } - }, "acorn-jsx": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", @@ -12693,6 +12731,28 @@ "postcss-value-parser": "^4.0.0" }, "dependencies": { + "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" + }, + "dependencies": { + "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" + } + } + } + }, "postcss": { "version": "7.0.26", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz", @@ -12834,15 +12894,15 @@ "dev": true }, "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", "eslint-visitor-keys": "^1.0.0", "resolve": "^1.12.0" }, @@ -12854,9 +12914,9 @@ "dev": true }, "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12907,199 +12967,197 @@ "dev": true }, "babel-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", - "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.3.0.tgz", + "integrity": "sha512-qiXeX1Cmw4JZ5yQ4H57WpkO0MZ61Qj+YnsVUwAMnDV5ls+yHon11XjarDdgP7H8lTmiEi6biiZA8y3Tmvx6pCg==", "dev": true, "requires": { - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/babel__core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", - "babel-preset-jest": "^24.9.0", - "chalk": "^2.4.2", - "slash": "^2.0.0" + "@jest/transform": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^25.3.0", + "chalk": "^3.0.0", + "slash": "^3.0.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "@jest/transform": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.3.0.tgz", + "integrity": "sha512-W01p8kTDvvEX6kd0tJc7Y5VdYyFaKwNWy1HQz6Jqlhu48z/8Gxp+yFCDVj+H8Rc7ezl3Mg0hDaGuFVkmHOqirg==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@babel/core": "^7.1.0", + "@jest/types": "^25.3.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^3.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.3", + "jest-haste-map": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-util": "^25.3.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "realpath-native": "^2.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" } }, - "@jest/transform": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", - "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^24.9.0", - "babel-plugin-istanbul": "^5.1.0", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.15", - "jest-haste-map": "^24.9.0", - "jest-regex-util": "^24.9.0", - "jest-util": "^24.9.0", - "micromatch": "^3.1.10", - "pirates": "^4.0.1", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "2.4.1" + "fill-range": "^7.0.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@types/yargs": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.5.tgz", - "integrity": "sha512-CF/+sxTO7FOwbIRL4wMv0ZYLCRfMid2HQpzDRyViH7kSpfoAFiMdGqKIxb1PxWfjtQXQhnQuD33lvRHNwr809Q==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" } }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.3.0.tgz", + "integrity": "sha512-LjXaRa+F8wwtSxo9G+hHD/Cp63PPQzvaBL9XCVoJD2rrcJO0Zr2+YYzAFWWYJ5GlPUkoaJFJtOuk0sL6MJY80A==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", + "@jest/types": "^25.3.0", + "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.3", + "jest-serializer": "^25.2.6", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "micromatch": "^4.0.2", "sane": "^4.0.3", - "walker": "^1.0.7" - } - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" + "walker": "^1.0.7", + "which": "^2.0.2" } }, "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", "dev": true }, "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", + "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", "dev": true }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.2.6.tgz", + "integrity": "sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==", "dev": true, "requires": { "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "supports-color": "^7.0.0" } }, "merge-stream": { @@ -13108,10 +13166,32 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "slash": { + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "realpath-native": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -13121,39 +13201,89 @@ "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } }, "write-file-atomic": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", - "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } } } }, "babel-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", - "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", "dev": true, "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" }, "dependencies": { + "ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -13174,6 +13304,26 @@ "locate-path": "^3.0.0" } }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -13194,10 +13344,27 @@ "semver": "^5.6.0" } }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -13233,6 +13400,16 @@ "find-up": "^3.0.0" } }, + "schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ==", + "dev": true, + "requires": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -13248,19 +13425,19 @@ "dev": true }, "babel-plugin-apply-mdx-type-prop": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.5.5.tgz", - "integrity": "sha512-yaklz3xE5vFtZpPpYC9lDbTqlC6hq0CjgheiLw3i40lY8vG0DINh+HJ7rq1Gi1g0q/iihwetJ+YFGpUM4YXAGA==", + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.5.8.tgz", + "integrity": "sha512-xYp5F9mAnZdDRFSd1vF3XQ0GQUbIulCpnuht2jCmK30GAHL8szVL7TgzwhEGamQ6yJmP/gEyYNM9OR5D2n26eA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.8.0", - "@mdx-js/util": "^1.5.5" + "@babel/helper-plugin-utils": "7.8.3", + "@mdx-js/util": "^1.5.8" }, "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.0.tgz", - "integrity": "sha512-+hAlRGdf8fHQAyNnDBqTHQhwdLURLdrCROoWaEQYiQhk2sV9Rhs+GoFZZfMJExTq9HG8o2NX3uN2G90bFtmFdA==", + "@mdx-js/util": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.5.8.tgz", + "integrity": "sha512-a7Gjjw8bfBSertA/pTWBA/9WKEhgaSxvQE2NTSUzaknrzGFOhs4alZSHh3RHmSFdSWv5pUuzAgsWseMLhWEVkQ==", "dev": true } } @@ -13275,14 +13452,14 @@ } }, "babel-plugin-emotion": { - "version": "10.0.27", - "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.27.tgz", - "integrity": "sha512-SUNYcT4FqhOqvwv0z1oeYhqgheU8qrceLojuHyX17ngo7WtWqN5I9l3IGHzf21Xraj465CVzF4IvOlAF+3ed0A==", + "version": "10.0.33", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz", + "integrity": "sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ==", "requires": { "@babel/helper-module-imports": "^7.0.0", - "@emotion/hash": "0.7.4", + "@emotion/hash": "0.8.0", "@emotion/memoize": "0.7.4", - "@emotion/serialize": "^0.11.15", + "@emotion/serialize": "^0.11.16", "babel-plugin-macros": "^2.0.0", "babel-plugin-syntax-jsx": "^6.18.0", "convert-source-map": "^1.5.0", @@ -13292,9 +13469,9 @@ }, "dependencies": { "@emotion/hash": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.7.4.tgz", - "integrity": "sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A==" + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, "@emotion/memoize": { "version": "0.7.4", @@ -13302,11 +13479,11 @@ "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" }, "@emotion/serialize": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.15.tgz", - "integrity": "sha512-YE+qnrmGwyR+XB5j7Bi+0GT1JWsdcjM/d4POu+TXkcnrRs4RFCCsi3d/Ebf+wSStHqAlTT2+dfd+b9N9EO2KBg==", + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", + "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", "requires": { - "@emotion/hash": "0.7.4", + "@emotion/hash": "0.8.0", "@emotion/memoize": "0.7.4", "@emotion/unitless": "0.7.5", "@emotion/utils": "0.11.3", @@ -13326,20 +13503,12 @@ } }, "babel-plugin-extract-import-names": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.5.5.tgz", - "integrity": "sha512-F9paxnUtO3vddyOX+vbRa8KrkuovJIFB8KmB/dEICqTUm2331LcGbjCKzZApOri4Igbk9MnYybm2fDsuPJC3vA==", + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.5.8.tgz", + "integrity": "sha512-LcLfP8ZRBZMdMAXHLugyvvd5PY0gMmLMWFogWAUsG32X6TYW2Eavx+il2bw73KDbW+UdCC1bAJ3NuU25T1MI3g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "7.8.0" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.0.tgz", - "integrity": "sha512-+hAlRGdf8fHQAyNnDBqTHQhwdLURLdrCROoWaEQYiQhk2sV9Rhs+GoFZZfMJExTq9HG8o2NX3uN2G90bFtmFdA==", - "dev": true - } + "@babel/helper-plugin-utils": "7.8.3" } }, "babel-plugin-inline-json-import": { @@ -13352,14 +13521,15 @@ } }, "babel-plugin-istanbul": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.3.tgz", - "integrity": "sha512-IFyehbvRRwdBlI1lDp+FaMsWNnEndEk7065IB8NhzBX+ZKLPwPodgk4I5Gobw/8SNUUzso2Dv3hbqRh88eiSCQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", "dev": true, "requires": { + "@babel/helper-plugin-utils": "^7.0.0", "find-up": "^3.0.0", - "istanbul-lib-instrument": "^3.2.0", - "test-exclude": "^5.2.2" + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" }, "dependencies": { "find-up": { @@ -13371,27 +13541,53 @@ "locate-path": "^3.0.0" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-LXTBICkMARVgo579kWDm8SqfB6nvSDKNqIOBEjmJRnL04JvoMHCYGWaMddQnseJYtkEuEvO/sIcOxPLk9gERug==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true }, "istanbul-lib-instrument": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.2.0.tgz", - "integrity": "sha512-06IM3xShbNW4NgZv5AP4QH0oHqf1/ivFo8eFys0ZjPXHGldHJQWb3riYOKXqmOqfxXBfxu4B+g/iuhOPZH0RJg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", "dev": true, "requires": { - "@babel/generator": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "istanbul-lib-coverage": "^2.0.4", + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", "semver": "^6.0.0" } }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -13403,9 +13599,9 @@ } }, "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -13426,18 +13622,73 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } } } }, "babel-plugin-jest-hoist": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", - "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.2.6.tgz", + "integrity": "sha512-qE2xjMathybYxjiGFJg0mLFrz0qNp83aNZycWDY/SuHiZNq+vQfRQtuINqyXyue1ELd8Rd+1OhFSLjms8msMbw==", "dev": true, "requires": { "@types/babel__traverse": "^7.0.6" @@ -13487,9 +13738,9 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "resolve": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", - "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "requires": { "path-parse": "^1.0.6" } @@ -13591,9 +13842,9 @@ } }, "babel-plugin-named-asset-import": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.5.tgz", - "integrity": "sha512-sGhfINU+AuMw9oFAdIn/nD5sem3pn/WgxAfDZ//Q3CnF+5uaho7C7shh2rKLk6sKE/XkfmyibghocwKdVjLIKg==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz", + "integrity": "sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA==", "dev": true }, "babel-plugin-react-docgen": { @@ -13743,10 +13994,28 @@ "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", "dev": true }, + "babel-preset-current-node-syntax": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz", + "integrity": "sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, "babel-preset-fbjs": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.2.0.tgz", - "integrity": "sha512-5Jo+JeWiVz2wHUUyAlvb/sSYnXNig9r+HqGAOSfh5Fzxp7SnAaR/tEGRJ1ZX7C77kfk82658w6R5Z+uPATTD9g==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz", + "integrity": "sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw==", "dev": true, "requires": { "@babel/plugin-proposal-class-properties": "^7.0.0", @@ -13779,13 +14048,13 @@ } }, "babel-preset-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", - "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.3.0.tgz", + "integrity": "sha512-tjdvLKNMwDI9r+QWz9sZUQGTq1dpoxjUqFUpEasAc7MOtHg9XuLT2fx0udFG+k1nvMV0WvHHVAN7VmCZ+1Zxbw==", "dev": true, "requires": { - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "babel-plugin-jest-hoist": "^24.9.0" + "babel-plugin-jest-hoist": "^25.2.6", + "babel-preset-current-node-syntax": "^0.1.2" } }, "babel-preset-minify": { @@ -14166,9 +14435,9 @@ } }, "body-scroll-lock": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-2.6.4.tgz", - "integrity": "sha512-NP08WsovlmxEoZP9pdlqrE+AhNaivlTrz9a0FF37BQsnOrpN48eNqivKkE7SYpM9N+YIPjsdVzfLAUQDBm6OQw==" + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-2.7.1.tgz", + "integrity": "sha512-hS53SQ8RhM0e4DsQ3PKz6Gr2O7Kpdh59TWU98GHjaQznL7y4dFycEPk7pFQAikqBaUSCArkc5E3pe7CWIt2fZA==" }, "boolbase": { "version": "1.0.0", @@ -14286,6 +14555,12 @@ "has-flag": "^4.0.0" } }, + "term-size": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", + "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", + "dev": true + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -14618,6 +14893,31 @@ "y18n": "^4.0.0" }, "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -14643,6 +14943,64 @@ "unset-value": "^1.0.0" } }, + "cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", + "dev": true, + "requires": { + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" + } + }, + "cacheable-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", @@ -14802,13 +15160,55 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "character-entities": { @@ -14865,6 +15265,17 @@ "semver": "^5.0.3" }, "dependencies": { + "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" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -14879,20 +15290,6 @@ "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", "dev": true }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "dev": true, - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" - } - }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -15162,6 +15559,23 @@ "is-supported-regexp-flag": "^1.0.0" } }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -15177,6 +15591,19 @@ "@types/q": "^1.5.1", "chalk": "^2.4.1", "q": "^1.1.2" + }, + "dependencies": { + "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" + } + } } }, "code-point-at": { @@ -15190,6 +15617,12 @@ "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", "dev": true }, + "collect-v8-coverage": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.0.tgz", + "integrity": "sha512-VKIhJgvk8E1W28m5avZ2Gv2Ruv5YiF56ug2oclvaG9md69BuZImMG2sk9g7QNKLUbtYAKQjXjYxbYZVUlMMKmQ==", + "dev": true + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -15306,9 +15739,9 @@ "dev": true }, "comment-parser": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.6.1.tgz", - "integrity": "sha512-Putzd7Ilyvknmb1KxGf5el9uw0sPx9gEVnDrm8tlvXGN1i8Uaa2VBxB32hUhfzTlrEhhxNQ+pKq4ZNe8wNxjmw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.2.tgz", + "integrity": "sha512-4Rjb1FnxtOcv9qsfuaNuVsmmVn4ooVoBHzYfyKteiXwIU84PClyGA5jASoFMwPV93+FPh9spwueXauxFJZkGAg==", "dev": true }, "commondir": { @@ -16086,6 +16519,31 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "copy-descriptor": { @@ -16174,11 +16632,29 @@ } }, "core-js": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", - "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", "dev": true }, + "core-js-compat": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", + "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", + "dev": true, + "requires": { + "browserslist": "^4.8.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, "core-js-pure": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.2.1.tgz", @@ -16473,6 +16949,30 @@ "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" + }, + "dependencies": { + "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" + }, + "dependencies": { + "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" + } + } + } + } } }, "postcss-modules-extract-imports": { @@ -16714,11 +17214,22 @@ } } }, - "cssom": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", - "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==", - "dev": true + "cssstyle": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz", + "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } }, "csstype": { "version": "2.6.7", @@ -16774,17 +17285,6 @@ "assert-plus": "^1.0.0" } }, - "data-urls": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.0.tgz", - "integrity": "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA==", - "dev": true, - "requires": { - "abab": "^1.0.4", - "whatwg-mimetype": "^2.0.0", - "whatwg-url": "^6.4.0" - } - }, "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", @@ -16862,6 +17362,15 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress-response": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", + "dev": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, "decompress-zip": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.2.2.tgz", @@ -16969,6 +17478,12 @@ "clone": "^1.0.2" } }, + "defer-to-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", + "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==", + "dev": true + }, "define-properties": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", @@ -17280,9 +17795,9 @@ "dev": true }, "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, "detect-node": { @@ -17328,9 +17843,9 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "diff-sequences": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", - "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", "dev": true }, "diffie-hellman": { @@ -17393,6 +17908,12 @@ "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=", "dev": true }, + "dom-accessibility-api": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.4.3.tgz", + "integrity": "sha512-JZ8iPuEHDQzq6q0k7PKMGbrIdsgBB7TRrtVOUm4nSMCExlg5qQG4KXWTH2k90yggjM4tTumRGwTKJSldMzKyLA==", + "dev": true + }, "dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -17543,6 +18064,12 @@ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, "duplexify": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", @@ -17727,46 +18254,381 @@ "dev": true }, "enzyme": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.9.0.tgz", - "integrity": "sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", "dev": true, "requires": { - "array.prototype.flat": "^1.2.1", - "cheerio": "^1.0.0-rc.2", - "function.prototype.name": "^1.1.0", + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", "has": "^1.0.3", - "html-element-map": "^1.0.0", - "is-boolean-object": "^1.0.0", - "is-callable": "^1.1.4", - "is-number-object": "^1.0.3", - "is-regex": "^1.0.4", - "is-string": "^1.0.4", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", "is-subset": "^0.1.1", "lodash.escape": "^4.0.1", "lodash.isequal": "^4.5.0", - "object-inspect": "^1.6.0", - "object-is": "^1.0.1", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", "object.assign": "^4.1.0", - "object.entries": "^1.0.4", - "object.values": "^1.0.4", - "raf": "^3.4.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.1.2" + "string.prototype.trim": "^1.2.1" + }, + "dependencies": { + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "function.prototype.name": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.2.tgz", + "integrity": "sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "functions-have-names": "^1.2.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", + "dev": true + }, + "object.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + } } }, "enzyme-adapter-react-16": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.14.0.tgz", - "integrity": "sha512-7PcOF7pb4hJUvjY7oAuPGpq3BmlCig3kxXGi2kFx0YzJHppqX1K8IIV9skT1IirxXlu8W7bneKi+oQ10QRnhcA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz", + "integrity": "sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q==", "dev": true, "requires": { - "enzyme-adapter-utils": "^1.12.0", + "enzyme-adapter-utils": "^1.13.0", + "enzyme-shallow-equal": "^1.0.1", "has": "^1.0.3", "object.assign": "^4.1.0", - "object.values": "^1.1.0", + "object.values": "^1.1.1", "prop-types": "^15.7.2", - "react-is": "^16.8.6", + "react-is": "^16.12.0", "react-test-renderer": "^16.0.0-0", "semver": "^5.7.0" }, @@ -17780,54 +18642,148 @@ "object-keys": "^1.0.12" } }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } }, "react-is": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", - "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "version": "16.13.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", + "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==", "dev": true }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } } } }, "enzyme-adapter-utils": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.0.tgz", - "integrity": "sha512-wkZvE0VxcFx/8ZsBw0iAbk3gR1d9hK447ebnSYBf95+r32ezBq+XDSAvRErkc4LZosgH8J7et7H7/7CtUuQfBA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz", + "integrity": "sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ==", "dev": true, "requires": { - "airbnb-prop-types": "^2.13.2", - "function.prototype.name": "^1.1.0", + "airbnb-prop-types": "^2.15.0", + "function.prototype.name": "^1.1.2", "object.assign": "^4.1.0", - "object.fromentries": "^2.0.0", + "object.fromentries": "^2.0.2", "prop-types": "^15.7.2", - "semver": "^5.6.0" + "semver": "^5.7.1" }, "dependencies": { "airbnb-prop-types": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz", - "integrity": "sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz", + "integrity": "sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==", "dev": true, "requires": { - "array.prototype.find": "^2.0.4", - "function.prototype.name": "^1.1.0", + "array.prototype.find": "^2.1.0", + "function.prototype.name": "^1.1.1", "has": "^1.0.3", "is-regex": "^1.0.4", "object-is": "^1.0.1", @@ -17835,7 +18791,7 @@ "object.entries": "^1.1.0", "prop-types": "^15.7.2", "prop-types-exact": "^1.2.0", - "react-is": "^16.8.6" + "react-is": "^16.9.0" } }, "define-properties": { @@ -17847,39 +18803,183 @@ "object-keys": "^1.0.12" } }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "function.prototype.name": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.2.tgz", + "integrity": "sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "functions-have-names": "^1.2.0" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } }, "react-is": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", - "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "version": "16.13.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", + "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==", "dev": true }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + } + } + }, + "enzyme-shallow-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz", + "integrity": "sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object-is": "^1.0.2" + }, + "dependencies": { + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", "dev": true } } }, "enzyme-to-json": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz", - "integrity": "sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.4.4.tgz", + "integrity": "sha512-50LELP/SCPJJGic5rAARvU7pgE3m1YaNj7JLM+Qkhl5t7PAs6fiyc8xzc50RnkKPFQCv0EeFVjEWdIFRGPWMsA==", "dev": true, "requires": { - "lodash": "^4.17.4" + "lodash": "^4.17.15", + "react-is": "^16.12.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", + "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==", + "dev": true + } } }, "equivalent-key-map": { @@ -17903,12 +19003,13 @@ } }, "error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", "dev": true, "requires": { - "string-template": "~0.2.1" + "string-template": "~0.2.1", + "xtend": "~4.0.0" } }, "error-ex": { @@ -18152,32 +19253,10 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escodegen": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.10.0.tgz", - "integrity": "sha512-fjUOf8johsv23WuIKdNQU4P9t9jhQ4Qzx6pC2uW890OloK3Zs1ZAoCNpg/2larNF501jLl3UNy0kIRcF6VI22g==", - "dev": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, "eslint": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz", - "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -18187,19 +19266,19 @@ "debug": "^4.0.1", "doctrine": "^3.0.0", "eslint-scope": "^5.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^6.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^11.7.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.4.1", + "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -18208,7 +19287,7 @@ "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", + "optionator": "^0.8.3", "progress": "^2.0.0", "regexpp": "^2.0.1", "semver": "^6.1.2", @@ -18220,21 +19299,15 @@ }, "dependencies": { "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "dev": true }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, "ansi-regex": { @@ -18243,6 +19316,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "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" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -18292,29 +19376,36 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, "espree": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", - "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, "requires": { - "acorn": "^7.1.0", - "acorn-jsx": "^5.1.0", + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - } } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -18332,10 +19423,13 @@ } }, "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 + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "ignore": { "version": "4.0.6", @@ -18343,33 +19437,26 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -18387,6 +19474,17 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -18397,9 +19495,9 @@ } }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", "dev": true }, "table": { @@ -18412,27 +19510,20 @@ "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" - }, - "dependencies": { - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - } } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, "eslint-config-prettier": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz", - "integrity": "sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg==", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz", + "integrity": "sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ==", "dev": true, "requires": { "get-stdin": "^6.0.0" @@ -18447,13 +19538,13 @@ } }, "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", "dev": true, "requires": { "debug": "^2.6.9", - "resolve": "^1.5.0" + "resolve": "^1.13.1" }, "dependencies": { "debug": { @@ -18464,16 +19555,31 @@ "requires": { "ms": "2.0.0" } + }, + "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 + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", "dev": true, "requires": { - "debug": "^2.6.8", + "debug": "^2.6.9", "pkg-dir": "^2.0.0" }, "dependencies": { @@ -18507,22 +19613,23 @@ } }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.20.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz", + "integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==", "dev": true, "requires": { "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.0", + "eslint-module-utils": "^2.4.1", "has": "^1.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", - "resolve": "^1.11.0" + "resolve": "^1.12.0" }, "dependencies": { "debug": { @@ -18553,6 +19660,74 @@ "isarray": "^1.0.0" } }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -18565,14 +19740,20 @@ "strip-bom": "^3.0.0" } }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } @@ -18614,14 +19795,36 @@ } }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { "path-parse": "^1.0.6" } }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -18631,27 +19834,27 @@ } }, "eslint-plugin-jest": { - "version": "22.15.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-22.15.1.tgz", - "integrity": "sha512-CWq/RR/3tLaKFB+FZcCJwU9hH5q/bKeO3rFP8G07+q7hcDCFNqpvdphVbEbGE6o6qo1UbciEev4ejUWv7brUhw==", + "version": "23.8.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz", + "integrity": "sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "^1.13.0" + "@typescript-eslint/experimental-utils": "^2.5.0" } }, "eslint-plugin-jsdoc": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-15.8.0.tgz", - "integrity": "sha512-J6ozWkaAgBh1eLdQE+C2wcXhoEgDmGJOSB6zMF5ktEtMBnU62xT3wfHcUacuTnv6rt+ollC0uZThaEpGA+sTNg==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-22.1.0.tgz", + "integrity": "sha512-54NdbICM7KrxsGUqQsev9aIMqPXyvyBx2218Qcm0TQ16P9CtBI+YY4hayJR6adrxlq4Ej0JLpgfUXWaQVFqmQg==", "dev": true, "requires": { - "comment-parser": "^0.6.1", + "comment-parser": "^0.7.2", "debug": "^4.1.1", - "flat-map-polyfill": "^0.3.8", - "jsdoctypeparser": "5.0.1", + "jsdoctypeparser": "^6.1.0", "lodash": "^4.17.15", - "object.entries-ponyfill": "^1.0.1", - "regextras": "^0.6.1" + "regextras": "^0.7.0", + "semver": "^6.3.0", + "spdx-expression-parse": "^3.0.0" }, "dependencies": { "debug": { @@ -18668,6 +19871,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -18689,9 +19898,9 @@ } }, "eslint-plugin-markdown": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.1.tgz", - "integrity": "sha512-nAUURNHJGPooBMZMP23FmTbh3LTdgoSqeFBv9FA3fYrJ+vDUJxrp6nKiQF4iDNAmnWQnmnrDvV61BmIF4X9QAQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.2.tgz", + "integrity": "sha512-BfvXKsO0K+zvdarNc801jsE/NTLmig4oKhZ1U3aSUgTf2dB/US5+CrfGxMsCK2Ki1vS1R3HPok+uYpufFndhzw==", "dev": true, "requires": { "object-assign": "^4.0.1", @@ -18760,22 +19969,36 @@ } }, "eslint-plugin-react": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz", - "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz", + "integrity": "sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==", "dev": true, "requires": { - "array-includes": "^3.0.3", + "array-includes": "^3.1.1", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.1.0", - "object.entries": "^1.1.0", - "object.fromentries": "^2.0.0", - "object.values": "^1.1.0", + "jsx-ast-utils": "^2.2.3", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", "prop-types": "^15.7.2", - "resolve": "^1.10.1" + "resolve": "^1.15.1", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.2", + "xregexp": "^4.3.0" }, "dependencies": { + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -18785,26 +20008,128 @@ "object-keys": "^1.0.12" } }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "jsx-ast-utils": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", + "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "object.assign": "^4.1.0" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } @@ -18816,20 +20141,48 @@ "dev": true }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { "path-parse": "^1.0.6" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } } } }, "eslint-plugin-react-hooks": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.6.1.tgz", - "integrity": "sha512-wHhmGJyVuijnYIJXZJHDUF2WM+rJYTjulUTqF9k61d3BTk8etydz+M4dXUVH7M76ZRS85rqBTCx0Es/lLsrjnA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz", + "integrity": "sha512-EjxTHxjLKIBWFgDJdhKKzLh5q+vjTFrqNZX36uIxWS4OfyXe5DawqPj3U5qeJ1ngLwatjzQnmR0Lz0J0YH3kxw==", "dev": true }, "eslint-scope": { @@ -18843,12 +20196,20 @@ } }, "eslint-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", - "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.0.0" + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } } }, "eslint-visitor-keys": { @@ -18867,19 +20228,21 @@ "acorn-jsx": "^4.1.1" } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", + "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.0.0" + }, + "dependencies": { + "estraverse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", + "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", + "dev": true + } } }, "esrecurse": { @@ -18900,7 +20263,8 @@ "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "etag": { "version": "1.8.1", @@ -18969,9 +20333,9 @@ }, "dependencies": { "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", + "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -19148,39 +20512,6 @@ "jest-regex-util": "^24.9.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, "@jest/types": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", @@ -19193,9 +20524,9 @@ } }, "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -19207,36 +20538,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "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": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, "jest-matcher-utils": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", @@ -19249,28 +20561,6 @@ "pretty-format": "^24.9.0" } }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - }, "pretty-format": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", @@ -19282,25 +20572,13 @@ "ansi-styles": "^3.2.0", "react-is": "^16.8.4" } - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true } } }, "expect-puppeteer": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.3.0.tgz", - "integrity": "sha512-p8N/KSVPG9PAOJlftK5f1n3JrULJ6Qq1EQ8r/n9xzkX2NmXbK8PcnJnkSAEzEHrMycELKGnlJV7M5nkgm+wEWA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", + "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", "dev": true }, "express": { @@ -19885,12 +21163,24 @@ "klaw": "^1.0.0", "path-is-absolute": "^1.0.0", "rimraf": "^2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -20038,9 +21328,9 @@ } }, "find-process": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.2.tgz", - "integrity": "sha512-O83EVJr4dWvHJ7QpUzANNAMeQVKukRzRqRx4AIzdLYRrQorRdbqDwLPigkd9PYPhJRhmNPAoVjOm9bcwSmcZaw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.3.tgz", + "integrity": "sha512-+IA+AUsQCf3uucawyTwMWcY+2M3FXq3BRvw3S+j5Jvydjk31f/+NPWpYZOJs+JUs2GvxH4Yfr6Wham0ZtRLlPA==", "dev": true, "requires": { "chalk": "^2.0.1", @@ -20048,6 +21338,17 @@ "debug": "^2.6.8" }, "dependencies": { + "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" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -20195,12 +21496,6 @@ } } }, - "flat-map-polyfill": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/flat-map-polyfill/-/flat-map-polyfill-0.3.8.tgz", - "integrity": "sha512-ZfmD5MnU7GglUEhiky9C7yEPaNq1/wh36RDohe+Xr3nJVdccwHbdTkFIYvetcdsoAckUKT51fuf44g7Ni5Doyg==", - "dev": true - }, "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", @@ -20271,6 +21566,17 @@ "worker-rpc": "^0.1.0" }, "dependencies": { + "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" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -20402,6 +21708,21 @@ "dev": true, "optional": true }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", @@ -20430,6 +21751,18 @@ "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "nopt": { @@ -20491,6 +21824,7 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -20499,6 +21833,15 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -20523,6 +21866,12 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "functions-have-names": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.1.tgz", + "integrity": "sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==", + "dev": true + }, "fuse.js": { "version": "3.4.6", "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.4.6.tgz", @@ -21218,6 +22567,56 @@ "delegate": "^3.1.2" } }, + "got": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", + "dev": true, + "requires": { + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==", + "dev": true + } + } + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -21589,9 +22988,9 @@ "dev": true }, "html-element-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.0.0.tgz", - "integrity": "sha512-/SP6aOiM5Ai9zALvCxDubIeez0LvG3qP7R9GcRDnJEP/HBmv0A8A9K0o8+HFudcFt46+i921ANjzKsjPjb7Enw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.2.0.tgz", + "integrity": "sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw==", "dev": true, "requires": { "array-filter": "^1.0.0" @@ -21612,6 +23011,12 @@ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", "dev": true }, + "html-escaper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "dev": true + }, "html-minifier-terser": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.0.2.tgz", @@ -21804,6 +23209,17 @@ "slash": "^3.0.0" }, "dependencies": { + "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" + } + }, "cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", @@ -22046,6 +23462,30 @@ "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" + }, + "dependencies": { + "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" + }, + "dependencies": { + "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" + } + } + } + } } }, "source-map": { @@ -22292,33 +23732,33 @@ "dev": true }, "inquirer": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.3.tgz", - "integrity": "sha512-+OiOVeVydu4hnCGLCSX+wedovR/Yzskv9BFqUNNKq9uU2qg7LCcCo3R86S2E7WLo0y/x2pnEZfZe1CoYnORUAw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", + "chalk": "^3.0.0", "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.15", "mute-stream": "0.0.8", - "run-async": "^2.2.0", + "run-async": "^2.4.0", "rxjs": "^6.5.3", "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", + "strip-ansi": "^6.0.0", "through": "^2.3.6" }, "dependencies": { "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.11.0" } }, "ansi-regex": { @@ -22327,6 +23767,26 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -22336,6 +23796,21 @@ "restore-cursor": "^3.1.0" } }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -22343,14 +23818,20 @@ "dev": true }, "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -22388,10 +23869,19 @@ "signal-exit": "^3.0.2" } }, + "run-async": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", + "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -22406,40 +23896,30 @@ "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } + "has-flag": "^4.0.0" } }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", "dev": true } } @@ -22584,6 +24064,12 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -22665,9 +24151,9 @@ } }, "is-boolean-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz", - "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", "dev": true }, "is-buffer": { @@ -22829,9 +24315,9 @@ "dev": true }, "is-generator-fn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.0.0.tgz", - "integrity": "sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, "is-glob": { @@ -22882,9 +24368,9 @@ } }, "is-number-object": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz", - "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", "dev": true }, "is-obj": { @@ -23038,9 +24524,9 @@ "dev": true }, "is-whitespace-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", "dev": true }, "is-windows": { @@ -23050,9 +24536,9 @@ "dev": true }, "is-word-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", - "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", "dev": true }, "is-wsl": { @@ -23093,81 +24579,70 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true }, "istanbul-lib-instrument": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", - "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", + "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", "dev": true, "requires": { - "@babel/generator": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "istanbul-lib-coverage": "^2.0.3", - "semver": "^5.5.0" + "@babel/core": "^7.7.5", + "@babel/parser": "^7.7.5", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, "istanbul-lib-report": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz", - "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "supports-color": "^6.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "dependencies": { - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, "istanbul-lib-source-maps": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz", - "integrity": "sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", "dev": true, "requires": { "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "rimraf": "^2.6.2", + "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" }, "dependencies": { @@ -23180,27 +24655,12 @@ "ms": "^2.1.1" } }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -23226,271 +24686,716 @@ } }, "jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", - "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-25.3.0.tgz", + "integrity": "sha512-iKd5ShQSHzFT5IL/6h5RZJhApgqXSoPxhp5HEi94v6OAw9QkF8T7X+liEU2eEHJ1eMFYTHmeWLrpBWulsDpaUg==", "dev": true, "requires": { - "import-local": "^2.0.0", - "jest-cli": "^24.9.0" + "@jest/core": "^25.3.0", + "import-local": "^3.0.2", + "jest-cli": "^25.3.0" }, "dependencies": { "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "@jest/core": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.3.0.tgz", + "integrity": "sha512-+D5a/tFf6pA/Gqft2DLBp/yeSRgXhlJ+Wpst0X/ZkfTRP54qDR3C61VfHwaex+GzZBiTcE9vQeoZ2v5T10+Mqw==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/console": "^25.3.0", + "@jest/reporters": "^25.3.0", + "@jest/test-result": "^25.3.0", + "@jest/transform": "^25.3.0", + "@jest/types": "^25.3.0", + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.3", + "jest-changed-files": "^25.3.0", + "jest-config": "^25.3.0", + "jest-haste-map": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-resolve": "^25.3.0", + "jest-resolve-dependencies": "^25.3.0", + "jest-runner": "^25.3.0", + "jest-runtime": "^25.3.0", + "jest-snapshot": "^25.3.0", + "jest-util": "^25.3.0", + "jest-validate": "^25.3.0", + "jest-watcher": "^25.3.0", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "realpath-native": "^2.0.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", + "graceful-fs": "^4.2.3", "source-map": "^0.6.0" } }, "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "@jest/transform": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.3.0.tgz", + "integrity": "sha512-W01p8kTDvvEX6kd0tJc7Y5VdYyFaKwNWy1HQz6Jqlhu48z/8Gxp+yFCDVj+H8Rc7ezl3Mg0hDaGuFVkmHOqirg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "@babel/core": "^7.1.0", + "@jest/types": "^25.3.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^3.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.3", + "jest-haste-map": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-util": "^25.3.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "realpath-native": "^2.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "type-fest": "^0.11.0" } }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", + "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "expect": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-25.3.0.tgz", + "integrity": "sha512-buboTXML2h/L0Kh44Ys2Cx49mX20ISc5KDirkxIs3Q9AJv0kazweUAbukegr+nHDOvFRKmxdojjIHCjqAceYfg==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-regex-util": "^25.2.6" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "jest-changed-files": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-25.3.0.tgz", + "integrity": "sha512-eqd5hyLbUjIVvLlJ3vQ/MoPxsxfESVXG9gvU19XXjKzxr+dXmZIqCXiY0OiYaibwlHZBJl2Vebkc0ADEMzCXew==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "execa": "^3.2.0", + "throat": "^5.0.0" + } + }, "jest-cli": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", - "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-25.3.0.tgz", + "integrity": "sha512-XpNQPlW1tzpP7RGG8dxpkRegYDuLjzSiENu92+CYM87nEbmEPb3b4+yo8xcsHOnj0AG7DUt9b3uG8LuHI3MDzw==", "dev": true, "requires": { - "@jest/core": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", + "@jest/core": "^25.3.0", + "@jest/test-result": "^25.3.0", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "exit": "^0.1.2", - "import-local": "^2.0.0", + "import-local": "^3.0.2", "is-ci": "^2.0.0", - "jest-config": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", + "jest-config": "^25.3.0", + "jest-util": "^25.3.0", + "jest-validate": "^25.3.0", "prompts": "^2.0.1", - "realpath-native": "^1.1.0", - "yargs": "^13.3.0" + "realpath-native": "^2.0.0", + "yargs": "^15.3.1" + } + }, + "jest-diff": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.3.0.tgz", + "integrity": "sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" } }, "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", "dev": true }, + "jest-haste-map": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.3.0.tgz", + "integrity": "sha512-LjXaRa+F8wwtSxo9G+hHD/Cp63PPQzvaBL9XCVoJD2rrcJO0Zr2+YYzAFWWYJ5GlPUkoaJFJtOuk0sL6MJY80A==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.3", + "jest-serializer": "^25.2.6", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" + } + }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "jest-regex-util": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", + "dev": true + }, + "jest-resolve": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "browser-resolve": "^1.11.3", + "chalk": "^3.0.0", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "jest-serializer": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", + "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", + "dev": true + }, + "jest-snapshot": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.3.0.tgz", + "integrity": "sha512-GGpR6Oro2htJPKh5RX4PR1xwo5jCEjtvSPLW1IS7N85y+2bWKbiknHpJJRKSdGXghElb5hWaeQASJI4IiRayGg==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "@babel/types": "^7.0.0", + "@jest/types": "^25.3.0", + "@types/prettier": "^1.19.0", + "chalk": "^3.0.0", + "expect": "^25.3.0", + "jest-diff": "^25.3.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-resolve": "^25.3.0", + "make-dir": "^3.0.0", + "natural-compare": "^1.4.0", + "pretty-format": "^25.3.0", + "semver": "^6.3.0" } }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "jest-worker": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.2.6.tgz", + "integrity": "sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "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 + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "realpath-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { - "p-try": "^2.0.0" + "path-parse": "^1.0.6" } }, - "p-locate": { + "resolve-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "resolve-from": "^5.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "shebang-regex": "^3.0.0" } }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -23500,402 +25405,410 @@ "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "has-flag": "^4.0.0" } }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" } - } - } - }, - "jest-changed-files": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", - "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "execa": "^1.0.0", - "throat": "^4.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "is-number": "^7.0.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "isexe": "^2.0.0" } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", "dev": true, "requires": { - "pump": "^3.0.0" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" } }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "yargs-parser": { + "version": "18.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz", + "integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true } } }, "jest-config": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", - "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.3.0.tgz", + "integrity": "sha512-CmF1JnNWFmoCSPC4tnU52wnVBpuxHjilA40qH/03IHxIevkjUInSMwaDeE6ACfxMPTLidBGBCO3EbxvzPbo8wA==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^24.9.0", - "@jest/types": "^24.9.0", - "babel-jest": "^24.9.0", - "chalk": "^2.0.1", + "@jest/test-sequencer": "^25.3.0", + "@jest/types": "^25.3.0", + "babel-jest": "^25.3.0", + "chalk": "^3.0.0", + "deepmerge": "^4.2.2", "glob": "^7.1.1", - "jest-environment-jsdom": "^24.9.0", - "jest-environment-node": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "micromatch": "^3.1.10", - "pretty-format": "^24.9.0", - "realpath-native": "^1.1.0" + "jest-environment-jsdom": "^25.3.0", + "jest-environment-node": "^25.3.0", + "jest-get-type": "^25.2.6", + "jest-jasmine2": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-resolve": "^25.3.0", + "jest-util": "^25.3.0", + "jest-validate": "^25.3.0", + "micromatch": "^4.0.2", + "pretty-format": "^25.3.0", + "realpath-native": "^2.0.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "fill-range": "^7.0.1" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "color-name": "~1.1.4" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "to-regex-range": "^5.0.1" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", "dev": true }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } + "jest-regex-util": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", + "dev": true }, "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", + "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" } }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "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 }, "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" } }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "realpath-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "jest-dev-server": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-4.3.0.tgz", - "integrity": "sha512-bC9flKY2G1honQ/UI0gEhb0wFnDhpFr7xidC8Nk+evi7TgnNtfsGIzzF2dcIhF1G9BGF0n/M7CJrMAzwQhyTPA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-4.4.0.tgz", + "integrity": "sha512-STEHJ3iPSC8HbrQ3TME0ozGX2KT28lbT4XopPxUm2WimsX3fcB3YOptRh12YphQisMhfqNSNTZUmWyT3HEXS2A==", "dev": true, "requires": { - "chalk": "^2.4.2", + "chalk": "^3.0.0", "cwd": "^0.10.0", - "find-process": "^1.4.2", - "prompts": "^2.1.0", - "spawnd": "^4.0.0", - "tree-kill": "^1.2.1", + "find-process": "^1.4.3", + "prompts": "^2.3.0", + "spawnd": "^4.4.0", + "tree-kill": "^1.2.2", "wait-on": "^3.3.0" }, "dependencies": { - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } }, - "prompts": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", - "integrity": "sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.3" + "color-name": "~1.1.4" } }, - "sisteransi": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", - "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -23905,196 +25818,188 @@ } }, "jest-diff": { - "version": "24.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", - "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.3.0", - "jest-get-type": "^24.3.0", - "pretty-format": "^24.7.0" - } - }, - "jest-docblock": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", - "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", - "dev": true, - "requires": { - "detect-newline": "^2.1.0" - } - }, - "jest-each": { "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", - "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", "jest-get-type": "^24.9.0", - "jest-util": "^24.9.0", "pretty-format": "^24.9.0" }, "dependencies": { - "@jest/console": { + "@jest/types": { "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@types/yargs-parser": "*" } }, - "@jest/source-map": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "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" + } + }, + "pretty-format": { "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" } + } + } + }, + "jest-docblock": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-25.3.0.tgz", + "integrity": "sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-25.3.0.tgz", + "integrity": "sha512-aBfS4VOf/Qs95yUlX6d6WBv0szvOcTkTTyCIaLuQGj4bSHsT+Wd9dDngVHrCe5uytxpN8VM+NAloI6nbPjXfXw==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", + "jest-get-type": "^25.2.6", + "jest-util": "^25.3.0", + "pretty-format": "^25.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "color-name": "~1.1.4" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", "dev": true }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" } }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "jest-emotion": { - "version": "10.0.17", - "resolved": "https://registry.npmjs.org/jest-emotion/-/jest-emotion-10.0.17.tgz", - "integrity": "sha512-Z0SqaeXGr9dshhY5z9ctfPiw2qTw5BRbCsbBWziTtSdiLnqFprj2NuF38lMrpSMFKjNY+q+rioRI5gVyQZrrxA==", + "version": "10.0.32", + "resolved": "https://registry.npmjs.org/jest-emotion/-/jest-emotion-10.0.32.tgz", + "integrity": "sha512-hW3IwWc47qRuxnGsWFGY6uIMX8F4YBzq+Qci3LAYUCUqUBNP+1DU1L5Nudo9Ry0NHVFOqDnDeip1p2UR0kVMwA==", "dev": true, "requires": { "@babel/runtime": "^7.5.5", @@ -24103,466 +26008,614 @@ "css": "^2.2.1" }, "dependencies": { - "@babel/runtime": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.3.tgz", - "integrity": "sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.2" - } - }, "@types/jest": { "version": "23.3.14", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.14.tgz", "integrity": "sha512-Q5hTcfdudEL2yOmluA1zaSyPbzWPmJ3XfSWeP3RyoYvS9hnje1ZyagrZOuQ6+1nQC1Gw+7gap3pLNL3xL6UBug==", "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" + } } } }, "jest-environment-jsdom": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", - "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.3.0.tgz", + "integrity": "sha512-jdE4bQN+k2QEZ9sWOxsqDJvMzbdFSCN/4tw8X0TQaCqyzKz58PyEf41oIr4WO7ERdp7WaJGBSUKF7imR3UW1lg==", "dev": true, "requires": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0", - "jsdom": "^11.5.1" + "@jest/environment": "^25.3.0", + "@jest/fake-timers": "^25.3.0", + "@jest/types": "^25.3.0", + "jest-mock": "^25.3.0", + "jest-util": "^25.3.0", + "jsdom": "^15.2.1" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "@jest/fake-timers": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.3.0.tgz", + "integrity": "sha512-NHAj7WbsyR3qBJPpBwSwqaq2WluIvUQsyzpJTN7XDVk7VnlC/y1BAnaYZL3vbPIP8Nhm0Ae5DJe0KExr/SdMJQ==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@jest/types": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-mock": "^25.3.0", + "jest-util": "^25.3.0", + "lolex": "^5.0.0" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "fill-range": "^7.0.1" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "color-name": "~1.1.4" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "to-regex-range": "^5.0.1" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.3.0.tgz", + "integrity": "sha512-yRn6GbuqB4j3aYu+Z1ezwRiZfp0o9om5uOcBovVtkcRLeBCNP5mT0ysdenUsxAHnQUgGwPOE1wwhtQYe6NKirQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "@jest/types": "^25.3.0" } }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "jest-environment-node": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", - "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-25.3.0.tgz", + "integrity": "sha512-XO09S29Nx1NU7TiMPHMoDIkxoGBuKSTbE+sHp0gXbeLDXhIdhysUI25kOqFFSD9AuDgvPvxWCXrvNqiFsOH33g==", "dev": true, "requires": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0" + "@jest/environment": "^25.3.0", + "@jest/fake-timers": "^25.3.0", + "@jest/types": "^25.3.0", + "jest-mock": "^25.3.0", + "jest-util": "^25.3.0", + "semver": "^6.3.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "@jest/fake-timers": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.3.0.tgz", + "integrity": "sha512-NHAj7WbsyR3qBJPpBwSwqaq2WluIvUQsyzpJTN7XDVk7VnlC/y1BAnaYZL3vbPIP8Nhm0Ae5DJe0KExr/SdMJQ==", "dev": true, "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@jest/types": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-mock": "^25.3.0", + "jest-util": "^25.3.0", + "lolex": "^5.0.0" } }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "fill-range": "^7.0.1" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "color-name": "~1.1.4" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "to-regex-range": "^5.0.1" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.3.0.tgz", + "integrity": "sha512-yRn6GbuqB4j3aYu+Z1ezwRiZfp0o9om5uOcBovVtkcRLeBCNP5mT0ysdenUsxAHnQUgGwPOE1wwhtQYe6NKirQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "@jest/types": "^25.3.0" } }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "jest-environment-puppeteer": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-4.3.0.tgz", - "integrity": "sha512-ZighMsU39bnacn2ylyHb88CB+ldgCfXGD3lS78k4PEo8A8xyt6+2mxmSR62FH3Y7K+W2gPDu5+QM3/LZuq42fQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-4.4.0.tgz", + "integrity": "sha512-iV8S8+6qkdTM6OBR/M9gKywEk8GDSOe05hspCs5D8qKSwtmlUfdtHfB4cakdc68lC6YfK3AUsLirpfgodCHjzQ==", "dev": true, "requires": { - "chalk": "^2.4.2", + "chalk": "^3.0.0", "cwd": "^0.10.0", - "jest-dev-server": "^4.3.0", + "jest-dev-server": "^4.4.0", "merge-deep": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-get-type": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", - "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", "dev": true }, "jest-haste-map": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.7.1.tgz", - "integrity": "sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", "dev": true, "requires": { - "@jest/types": "^24.7.0", + "@jest/types": "^24.9.0", "anymatch": "^2.0.0", "fb-watchman": "^2.0.0", "fsevents": "^1.2.7", "graceful-fs": "^4.1.15", "invariant": "^2.2.4", - "jest-serializer": "^24.4.0", - "jest-util": "^24.7.1", - "jest-worker": "^24.6.0", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", "micromatch": "^3.1.10", "sane": "^4.0.3", "walker": "^1.0.7" }, "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true } } }, "jest-jasmine2": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", - "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.3.0.tgz", + "integrity": "sha512-NCYOGE6+HNzYFSui52SefgpsnIzvxjn6KAgqw66BdRp37xpMD/4kujDHLNW5bS5i53os5TcMn6jYrzQRO8VPrQ==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", + "@jest/environment": "^25.3.0", + "@jest/source-map": "^25.2.6", + "@jest/test-result": "^25.3.0", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "co": "^4.6.0", - "expect": "^24.9.0", + "expect": "^25.3.0", "is-generator-fn": "^2.0.0", - "jest-each": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "pretty-format": "^24.9.0", - "throat": "^4.0.0" + "jest-each": "^25.3.0", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-runtime": "^25.3.0", + "jest-snapshot": "^25.3.0", + "jest-util": "^25.3.0", + "pretty-format": "^25.3.0", + "throat": "^5.0.0" }, "dependencies": { "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", + "graceful-fs": "^4.2.3", "source-map": "^0.6.0" } }, "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "color-name": "~1.1.4" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", "dev": true }, "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-25.3.0.tgz", + "integrity": "sha512-buboTXML2h/L0Kh44Ys2Cx49mX20ISc5KDirkxIs3Q9AJv0kazweUAbukegr+nHDOvFRKmxdojjIHCjqAceYfg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" + "@jest/types": "^25.3.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-regex-util": "^25.2.6" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" } }, "graceful-fs": { @@ -24571,131 +26624,152 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.3.0.tgz", + "integrity": "sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w==", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" } }, "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", "dev": true }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", "dev": true }, "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", + "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" } }, "jest-snapshot": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", - "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.3.0.tgz", + "integrity": "sha512-GGpR6Oro2htJPKh5RX4PR1xwo5jCEjtvSPLW1IS7N85y+2bWKbiknHpJJRKSdGXghElb5hWaeQASJI4IiRayGg==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "expect": "^24.9.0", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "mkdirp": "^0.5.1", + "@jest/types": "^25.3.0", + "@types/prettier": "^1.19.0", + "chalk": "^3.0.0", + "expect": "^25.3.0", + "jest-diff": "^25.3.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-resolve": "^25.3.0", + "make-dir": "^3.0.0", "natural-compare": "^1.4.0", - "pretty-format": "^24.9.0", - "semver": "^6.2.0" + "pretty-format": "^25.3.0", + "semver": "^6.3.0" } }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, + "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 + }, "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "realpath-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" } }, "semver": { @@ -24705,9 +26779,9 @@ "dev": true }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -24715,29 +26789,44 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "jest-junit": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-6.4.0.tgz", - "integrity": "sha512-GXEZA5WBeUich94BARoEUccJumhCgCerg7mXDFLxWwI2P7wL3Z7sGWk+53x343YdBLjiMR9aD/gYMVKO+0pE4Q==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-10.0.0.tgz", + "integrity": "sha512-dbOVRyxHprdSpwSAR9/YshLwmnwf+RSl5hf0kCGlhAcEeZY9aRqo4oNmaT0tLC16Zy9D0zekDjWkjHGjXlglaQ==", "dev": true, "requires": { - "jest-validate": "^24.0.0", + "jest-validate": "^24.9.0", "mkdirp": "^0.5.1", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.2.0", + "uuid": "^3.3.3", "xml": "^1.0.1" - } - }, - "jest-leak-detector": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", - "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", - "dev": true, - "requires": { - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" }, "dependencies": { "@jest/types": { @@ -24752,9 +26841,9 @@ } }, "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -24766,10 +26855,41 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "jest-get-type": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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" + } + }, + "jest-validate": { "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, "pretty-format": { @@ -24783,30 +26903,212 @@ "ansi-styles": "^3.2.0", "react-is": "^16.8.4" } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "jest-leak-detector": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-25.3.0.tgz", + "integrity": "sha512-jk7k24dMIfk8LUSQQGN8PyOy9+J0NAfHZWiDmUDYVMctY8FLJQ1eQ8+PjMoN8PgwhLIggUqgYJnyRFvUz3jLRw==", + "dev": true, + "requires": { + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true } } }, "jest-matcher-utils": { - "version": "24.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", - "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.3.0.tgz", + "integrity": "sha512-ZBUJ2fchNIZt+fyzkuCFBb8SKaU//Rln45augfUtbHaGyVxCO++ANARdBK9oPGXU3hEDgyy7UHnOP/qNOJXFUg==", "dev": true, "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.7.0", - "jest-get-type": "^24.3.0", - "pretty-format": "^24.7.0" + "chalk": "^3.0.0", + "jest-diff": "^25.3.0", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.3.0.tgz", + "integrity": "sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" + } + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-message-util": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", - "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", "@types/stack-utils": "^1.0.1", "chalk": "^2.0.1", "micromatch": "^3.1.10", @@ -24814,6 +27116,37 @@ "stack-utils": "^1.0.1" }, "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "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" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -24823,12 +27156,34 @@ } }, "jest-mock": { - "version": "24.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.7.0.tgz", - "integrity": "sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", "dev": true, "requires": { - "@jest/types": "^24.7.0" + "@jest/types": "^24.9.0" + }, + "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + } } }, "jest-pnp-resolver": { @@ -24838,19 +27193,19 @@ "dev": true }, "jest-puppeteer": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-4.3.0.tgz", - "integrity": "sha512-WXhaWlbQl01xadZyNmdZntrtIr8uWUmgjPogDih7dOnr3G/xRr3A034SCqdjwV6fE0tqz7c5hwO8oBTyGZPRgA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-4.4.0.tgz", + "integrity": "sha512-ZaiCTlPZ07B9HW0erAWNX6cyzBqbXMM7d2ugai4epBDKpKvRDpItlRQC6XjERoJELKZsPziFGS0OhhUvTvQAXA==", "dev": true, "requires": { - "expect-puppeteer": "^4.3.0", - "jest-environment-puppeteer": "^4.3.0" + "expect-puppeteer": "^4.4.0", + "jest-environment-puppeteer": "^4.4.0" } }, "jest-regex-util": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", - "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", "dev": true }, "jest-resolve": { @@ -24878,210 +27233,251 @@ } }, "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { "@types/yargs-parser": "*" } + }, + "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" + } } } }, "jest-resolve-dependencies": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", - "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-25.3.0.tgz", + "integrity": "sha512-bDUlLYmHW+f7J7KgcY2lkq8EMRqKonRl0XoD4Wp5SJkgAxKJnsaIOlrrVNTfXYf+YOu3VCjm/Ac2hPF2nfsCIA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-snapshot": "^24.9.0" + "@jest/types": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-snapshot": "^25.3.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "fill-range": "^7.0.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "color-name": "~1.1.4" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", "dev": true }, "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-25.3.0.tgz", + "integrity": "sha512-buboTXML2h/L0Kh44Ys2Cx49mX20ISc5KDirkxIs3Q9AJv0kazweUAbukegr+nHDOvFRKmxdojjIHCjqAceYfg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" - }, - "dependencies": { - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - } + "@jest/types": "^25.3.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-regex-util": "^25.2.6" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "to-regex-range": "^5.0.1" } }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "jest-diff": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.3.0.tgz", + "integrity": "sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" } }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, + "jest-regex-util": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", + "dev": true + }, "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", + "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" } }, "jest-snapshot": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", - "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.3.0.tgz", + "integrity": "sha512-GGpR6Oro2htJPKh5RX4PR1xwo5jCEjtvSPLW1IS7N85y+2bWKbiknHpJJRKSdGXghElb5hWaeQASJI4IiRayGg==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "expect": "^24.9.0", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "mkdirp": "^0.5.1", + "@jest/types": "^25.3.0", + "@types/prettier": "^1.19.0", + "chalk": "^3.0.0", + "expect": "^25.3.0", + "jest-diff": "^25.3.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-resolve": "^25.3.0", + "make-dir": "^3.0.0", "natural-compare": "^1.4.0", - "pretty-format": "^24.9.0", - "semver": "^6.2.0" + "pretty-format": "^25.3.0", + "semver": "^6.3.0" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, + "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 + }, "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "realpath-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" } }, "semver": { @@ -25091,225 +27487,256 @@ "dev": true }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "jest-runner": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", - "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-25.3.0.tgz", + "integrity": "sha512-csDqSC9qGHYWDrzrElzEgFbteztFeZJmKhSgY5jlCIcN0+PhActzRNku0DA1Xa1HxGOb0/AfbP1EGJlP4fGPtA==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.4.2", + "@jest/console": "^25.3.0", + "@jest/environment": "^25.3.0", + "@jest/test-result": "^25.3.0", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-config": "^24.9.0", - "jest-docblock": "^24.3.0", - "jest-haste-map": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-leak-detector": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.6.0", + "graceful-fs": "^4.2.3", + "jest-config": "^25.3.0", + "jest-docblock": "^25.3.0", + "jest-haste-map": "^25.3.0", + "jest-jasmine2": "^25.3.0", + "jest-leak-detector": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-resolve": "^25.3.0", + "jest-runtime": "^25.3.0", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", "source-map-support": "^0.5.6", - "throat": "^4.0.0" + "throat": "^5.0.0" }, "dependencies": { - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "@jest/console": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", + "graceful-fs": "^4.2.3", "source-map": "^0.6.0" } }, "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - } + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" } }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.3.0.tgz", + "integrity": "sha512-LjXaRa+F8wwtSxo9G+hHD/Cp63PPQzvaBL9XCVoJD2rrcJO0Zr2+YYzAFWWYJ5GlPUkoaJFJtOuk0sL6MJY80A==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", + "@jest/types": "^25.3.0", + "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.3", + "jest-serializer": "^25.2.6", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "micromatch": "^4.0.2", "sane": "^4.0.3", - "walker": "^1.0.7" - }, - "dependencies": { - "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" - } - } + "walker": "^1.0.7", + "which": "^2.0.2" } }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", + "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" } }, "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", + "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", "dev": true }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - } + "make-dir": "^3.0.0" + } + }, + "jest-worker": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.2.6.tgz", + "integrity": "sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" } }, "merge-stream": { @@ -25318,10 +27745,47 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "slash": { + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "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 + }, + "realpath-native": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -25331,173 +27795,274 @@ "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } } } }, "jest-runtime": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", - "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.9.0", - "@jest/source-map": "^24.3.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "chalk": "^2.0.1", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-25.3.0.tgz", + "integrity": "sha512-gn5KYB1wxXRM3nfw8fVpthFu60vxQUCr+ShGq41+ZBFF3DRHZRKj3HDWVAVB4iTNBj2y04QeAo5cZ/boYaPg0w==", + "dev": true, + "requires": { + "@jest/console": "^25.3.0", + "@jest/environment": "^25.3.0", + "@jest/source-map": "^25.2.6", + "@jest/test-result": "^25.3.0", + "@jest/transform": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0", + "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.1.15", - "jest-config": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "strip-bom": "^3.0.0", - "yargs": "^13.3.0" + "graceful-fs": "^4.2.3", + "jest-config": "^25.3.0", + "jest-haste-map": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-mock": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-resolve": "^25.3.0", + "jest-snapshot": "^25.3.0", + "jest-util": "^25.3.0", + "jest-validate": "^25.3.0", + "realpath-native": "^2.0.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.3.1" }, "dependencies": { - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "@jest/console": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "@jest/source-map": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - } + "callsites": "^3.0.0", + "graceful-fs": "^4.2.3", + "source-map": "^0.6.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "@jest/test-result": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "collect-v8-coverage": "^1.0.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "@jest/transform": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.3.0.tgz", + "integrity": "sha512-W01p8kTDvvEX6kd0tJc7Y5VdYyFaKwNWy1HQz6Jqlhu48z/8Gxp+yFCDVj+H8Rc7ezl3Mg0hDaGuFVkmHOqirg==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "@babel/core": "^7.1.0", + "@jest/types": "^25.3.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^3.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.3", + "jest-haste-map": "^25.3.0", + "jest-regex-util": "^25.2.6", + "jest-util": "^25.3.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "realpath-native": "^2.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" } }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-25.3.0.tgz", + "integrity": "sha512-buboTXML2h/L0Kh44Ys2Cx49mX20ISc5KDirkxIs3Q9AJv0kazweUAbukegr+nHDOvFRKmxdojjIHCjqAceYfg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" - }, - "dependencies": { - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - } + "@jest/types": "^25.3.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-regex-util": "^25.2.6" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -25524,203 +28089,163 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.3.0.tgz", + "integrity": "sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w==", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.3.0" } }, "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", "dev": true }, "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.3.0.tgz", + "integrity": "sha512-LjXaRa+F8wwtSxo9G+hHD/Cp63PPQzvaBL9XCVoJD2rrcJO0Zr2+YYzAFWWYJ5GlPUkoaJFJtOuk0sL6MJY80A==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", + "@jest/types": "^25.3.0", + "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.3", + "jest-serializer": "^25.2.6", + "jest-util": "^25.3.0", + "jest-worker": "^25.2.6", + "micromatch": "^4.0.2", "sane": "^4.0.3", - "walker": "^1.0.7" - } - }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "walker": "^1.0.7", + "which": "^2.0.2" } }, "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.3.0.tgz", + "integrity": "sha512-5QNy9Id4WxJbRITEbA1T1kem9bk7y2fD0updZMSTNHtbEDnYOGLDPAuFBhFgVmOZpv0n6OMdVkK+WhyXEPCcOw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", + "chalk": "^3.0.0", + "micromatch": "^4.0.2", + "slash": "^3.0.0", "stack-utils": "^1.0.1" } }, "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.3.0.tgz", + "integrity": "sha512-yRn6GbuqB4j3aYu+Z1ezwRiZfp0o9om5uOcBovVtkcRLeBCNP5mT0ysdenUsxAHnQUgGwPOE1wwhtQYe6NKirQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "@jest/types": "^25.3.0" } }, + "jest-regex-util": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", + "integrity": "sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==", + "dev": true + }, "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.3.0.tgz", + "integrity": "sha512-IHoQAAybulsJ+ZgWis+ekYKDAoFkVH5Nx/znpb41zRtpxj4fr2WNV9iDqavdSm8GIpMlsfZxbC/fV9DhW0q9VQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", + "@jest/types": "^25.3.0", "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", + "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "realpath-native": "^2.0.0", + "resolve": "^1.15.1" } }, "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", + "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", "dev": true }, "jest-snapshot": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", - "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.3.0.tgz", + "integrity": "sha512-GGpR6Oro2htJPKh5RX4PR1xwo5jCEjtvSPLW1IS7N85y+2bWKbiknHpJJRKSdGXghElb5hWaeQASJI4IiRayGg==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "expect": "^24.9.0", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "mkdirp": "^0.5.1", + "@jest/types": "^25.3.0", + "@types/prettier": "^1.19.0", + "chalk": "^3.0.0", + "expect": "^25.3.0", + "jest-diff": "^25.3.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.3.0", + "jest-message-util": "^25.3.0", + "jest-resolve": "^25.3.0", + "make-dir": "^3.0.0", "natural-compare": "^1.4.0", - "pretty-format": "^24.9.0", - "semver": "^6.2.0" + "pretty-format": "^25.3.0", + "semver": "^6.3.0" } }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - } - } - }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" + "make-dir": "^3.0.0" } }, "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.2.6.tgz", + "integrity": "sha512-FJn9XDUSxcOR4cwDzRfL1z56rUofNTFs539FGASpd50RHdb6EVkhxQqktodW2mI49l+W3H+tFJDotCHUQF6dmA==", "dev": true, "requires": { "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "supports-color": "^7.0.0" } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "merge-stream": { @@ -25729,22 +28254,38 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^2.2.0" } }, "p-try": { @@ -25753,24 +28294,57 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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 + }, "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" } }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "realpath-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", + "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", + "dev": true + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -25778,9 +28352,9 @@ "dev": true }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -25790,49 +28364,90 @@ "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, "y18n": { @@ -25842,29 +28457,40 @@ "dev": true }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^3.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^18.1.1" + } + }, + "yargs-parser": { + "version": "18.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz", + "integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, "jest-serializer": { - "version": "24.4.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", - "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", "dev": true }, "jest-serializer-enzyme": { @@ -25914,39 +28540,6 @@ "semver": "^6.2.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, "@jest/types": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", @@ -25959,9 +28552,9 @@ } }, "@types/yargs": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.6.tgz", - "integrity": "sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA==", + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -25973,36 +28566,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "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": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, "jest-matcher-utils": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", @@ -26015,22 +28589,6 @@ "pretty-format": "^24.9.0" } }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, "pretty-format": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", @@ -26048,18 +28606,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true } } }, @@ -26073,16 +28619,16 @@ } }, "jest-util": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.7.1.tgz", - "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/fake-timers": "^24.7.1", - "@jest/source-map": "^24.3.0", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", "callsites": "^3.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.15", @@ -26092,6 +28638,37 @@ "source-map": "^0.6.0" }, "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "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" + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -26113,161 +28690,234 @@ } }, "jest-validate": { - "version": "24.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.7.0.tgz", - "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.3.0.tgz", + "integrity": "sha512-3WuXgIZ4HXUvW6gk9twFFkT9j6zUorKnF2oEY8VEsHb7x5LGvVlN3WUsbqazVKuyXwvikO2zFJ/YTySMsMje2w==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "camelcase": "^5.0.0", - "chalk": "^2.0.1", - "jest-get-type": "^24.3.0", - "leven": "^2.1.0", - "pretty-format": "^24.7.0" + "@jest/types": "^25.3.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "jest-get-type": "^25.2.6", + "leven": "^3.1.0", + "pretty-format": "^25.3.0" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "pretty-format": { + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz", + "integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==", + "dev": true, + "requires": { + "@jest/types": "^25.3.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "jest-watcher": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", - "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.3.0.tgz", + "integrity": "sha512-dtFkfidFCS9Ucv8azOg2hkiY3sgJEHeTLtGFHS+jfBEE7eRtrO6+2r1BokyDkaG2FOD7485r/SgpC1MFAENfeA==", "dev": true, "requires": { - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "jest-util": "^24.9.0", - "string-length": "^2.0.0" + "@jest/test-result": "^25.3.0", + "@jest/types": "^25.3.0", + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "string-length": "^3.1.0" }, "dependencies": { "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.3.0.tgz", + "integrity": "sha512-LvSDNqpmZIZyweFaEQ6wKY7CbexPitlsLHGJtcooNECo0An/w49rFhjCJzu6efeb6+a3ee946xss1Jcd9r03UQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "@jest/source-map": "^25.2.6", + "chalk": "^3.0.0", + "jest-util": "^25.3.0", + "slash": "^3.0.0" } }, "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", + "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", + "graceful-fs": "^4.2.3", "source-map": "^0.6.0" } }, "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.3.0.tgz", + "integrity": "sha512-mqrGuiiPXl1ap09Mydg4O782F3ouDQfsKqtQzIjitpwv3t1cHDwCto21jThw6WRRE+dKcWQvLG70GpyLJICfGw==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@jest/console": "^25.3.0", + "@jest/types": "^25.3.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "type-fest": "^0.11.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "@jest/types": "^24.9.0" + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.3.0.tgz", + "integrity": "sha512-dc625P/KS/CpWTJJJxKc4bA3A6c+PJGBAqS8JTJqx4HqPoKNqXg/Ec8biL2Z1TabwK7E7Ilf0/ukSEXM1VwzNA==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", + "@jest/types": "^25.3.0", + "chalk": "^3.0.0", "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "make-dir": "^3.0.0" } }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "source-map": { @@ -26275,19 +28925,40 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true } } }, "jest-worker": { - "version": "24.6.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", - "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "requires": { - "merge-stream": "^1.0.1", + "merge-stream": "^2.0.0", "supports-color": "^6.1.0" }, "dependencies": { + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -26424,80 +29095,213 @@ } }, "jsdoctypeparser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-5.0.1.tgz", - "integrity": "sha512-dYwcK6TKzvq+ZKtbp4sbQSW9JMo6s+4YFfUs5D/K7bZsn3s1NhEhZ+jmIPzby0HbkbECBe+hNPEa6a+E21o94w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-6.1.0.tgz", + "integrity": "sha512-UCQBZ3xCUBv/PLfwKAJhp6jmGOSLFNKzrotXGNgbKhWvz27wPsCsVeP7gIcHPElQw2agBmynAitXqhxR58XAmA==", "dev": true }, "jsdom": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz", + "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==", "dev": true, "requires": { "abab": "^2.0.0", - "acorn": "^5.5.3", - "acorn-globals": "^4.1.0", + "acorn": "^7.1.0", + "acorn-globals": "^4.3.2", "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": "^1.0.0", - "data-urls": "^1.0.0", + "cssom": "^0.4.1", + "cssstyle": "^2.0.0", + "data-urls": "^1.1.0", "domexception": "^1.0.1", - "escodegen": "^1.9.1", + "escodegen": "^1.11.1", "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.3.0", - "nwsapi": "^2.0.7", - "parse5": "4.0.0", + "nwsapi": "^2.2.0", + "parse5": "5.1.0", "pn": "^1.1.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", + "request": "^2.88.0", + "request-promise-native": "^1.0.7", + "saxes": "^3.1.9", "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.4", + "tough-cookie": "^3.0.1", "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.1", - "ws": "^5.2.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^7.0.0", "xml-name-validator": "^3.0.0" }, "dependencies": { "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", "dev": true }, - "cssstyle": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", - "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "acorn": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, "requires": { - "cssom": "0.3.x" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + } } }, - "nwsapi": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", - "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==", + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, + "escodegen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", + "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "dev": true }, - "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dev": true, + "requires": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "ws": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", + "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", + "dev": true } } }, @@ -26507,6 +29311,12 @@ "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", "dev": true }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -26633,6 +29443,15 @@ "set-immediate-shim": "~1.0.1" } }, + "keyv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.0.tgz", + "integrity": "sha512-U7ioE8AimvRVLfw4LffyOIRhL2xVgmE8T22L6i0BucSnBUyv4w+I7VN/zVZwRKHOI6ZRUcdMdWHQ8KSUvGpEog==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -26695,12 +29514,6 @@ "invert-kv": "^1.0.0" } }, - "left-pad": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", - "dev": true - }, "lerna": { "version": "3.18.2", "resolved": "https://registry.npmjs.org/lerna/-/lerna-3.18.2.tgz", @@ -26732,23 +29545,6 @@ "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", "dev": true }, - "levenary": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.0.tgz", - "integrity": "sha512-VHcwhO0UTpUW7rLPN2/OiWJdgA1e9BqEDALhrgCe/F+uUJnep6CoUsTzMeP8Rh0NGr9uKquXxqe7lwLZo509nQ==", - "dev": true, - "requires": { - "leven": "^3.1.0" - }, - "dependencies": { - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - } - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -26820,6 +29616,17 @@ "fill-range": "^7.0.1" } }, + "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" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -27161,6 +29968,19 @@ "cli-cursor": "^2.1.0", "date-fns": "^1.27.2", "figures": "^2.0.0" + }, + "dependencies": { + "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" + } + } } }, "livereload-js": { @@ -27352,12 +30172,6 @@ "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", "dev": true }, - "lodash.unescape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", - "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", - "dev": true - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -27371,6 +30185,19 @@ "dev": true, "requires": { "chalk": "^2.0.1" + }, + "dependencies": { + "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" + } + } } }, "log-update": { @@ -27590,6 +30417,15 @@ } } }, + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -27626,6 +30462,12 @@ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", "dev": true }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, "lowlight": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.11.0.tgz", @@ -28098,9 +30940,9 @@ } }, "memize": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/memize/-/memize-1.0.5.tgz", - "integrity": "sha512-Dm8Jhb5kiC4+ynYsVR4QDXKt+o2dfqGuY4hE2x+XlXZkdndlT80bJxfcMv5QGp/FCy6MhG7f5ElpmKPFKOSEpg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/memize/-/memize-1.1.0.tgz", + "integrity": "sha512-K4FcPETOMTwe7KL2LK0orMhpOmWD2wRGwWWpbZy0fyArwsyIKR8YJVz8+efBAh3BO4zPqlSICu4vsLTRRqtFAg==" }, "memoize-one": { "version": "5.1.1", @@ -28368,6 +31210,17 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "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" + } + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -28722,6 +31575,7 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -28730,6 +31584,15 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -28745,6 +31608,85 @@ "metro-cache": "0.56.3", "metro-core": "0.56.3", "pretty-format": "^24.7.0" + }, + "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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" + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + } + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + } } }, "metro-core": { @@ -29175,6 +32117,12 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true + }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", @@ -29521,6 +32469,31 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "ms": { @@ -29672,6 +32645,35 @@ "lower-case": "^1.1.1" } }, + "nock": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-12.0.3.tgz", + "integrity": "sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.13", + "propagate": "^2.0.0" + }, + "dependencies": { + "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" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -29721,6 +32723,31 @@ "which": "1" }, "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", @@ -29824,6 +32851,20 @@ "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", "dev": true }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", @@ -29844,6 +32885,15 @@ "osenv": "^0.1.4" } }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -30108,6 +33158,14 @@ "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "strip-ansi": { @@ -30225,6 +33283,33 @@ "semver": "~5.3.0", "tar": "^4.4.8", "which": "1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + } } }, "semver": { @@ -30392,6 +33477,33 @@ "semver": "~5.3.0", "tar": "^4.4.12", "which": "1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + } } }, "resolve-from": { @@ -30491,6 +33603,17 @@ "fill-range": "^7.0.1" } }, + "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" + } + }, "cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", @@ -30772,6 +33895,12 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -30878,12 +34007,6 @@ "has": "^1.0.1" } }, - "object.entries-ponyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.entries-ponyfill/-/object.entries-ponyfill-1.0.1.tgz", - "integrity": "sha1-Kavfd8v70mVm3RqiTp2I9lQz0lY=", - "dev": true - }, "object.fromentries": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", @@ -31050,6 +34173,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "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" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -31177,6 +34311,12 @@ "os-tmpdir": "^1.0.0" } }, + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==", + "dev": true + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -31184,12 +34324,18 @@ "dev": true }, "p-each-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", - "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", + "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==", + "dev": true + }, + "p-event": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.1.0.tgz", + "integrity": "sha512-4vAd06GCsgflX4wHN1JqrMzBh/8QZ4j+rzp0cd2scXRwuBEv+QR3wrVA5aLhWDLw4y2WgDKvzWF3CCLmVM1UgA==", "dev": true, "requires": { - "p-reduce": "^1.0.0" + "p-timeout": "^2.0.1" } }, "p-finally": { @@ -31258,6 +34404,15 @@ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", @@ -31724,6 +34879,28 @@ "supports-color": "^6.1.0" }, "dependencies": { + "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" + }, + "dependencies": { + "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" + } + } + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -31799,6 +34976,19 @@ "chalk": "^2.4.1", "source-map": "^0.6.1", "supports-color": "^5.4.0" + }, + "dependencies": { + "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" + } + } } }, "source-map": { @@ -32375,6 +35565,19 @@ "lodash": "^4.17.11", "log-symbols": "^2.2.0", "postcss": "^7.0.7" + }, + "dependencies": { + "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" + } + } } }, "postcss-resolve-nested-selector": { @@ -32513,6 +35716,26 @@ "react-is": "^16.8.4" }, "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -32827,13 +36050,13 @@ } }, "prompts": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", - "integrity": "sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.1.tgz", + "integrity": "sha512-qIP2lQyCwYbdzcqHIUi2HAxiWixhoM9OdLCWf8txXsapC/X9YdsCoeyRIXE/GP+Q0J37Q7+XN/MFqbUa7IzXNA==", "dev": true, "requires": { "kleur": "^3.0.3", - "sisteransi": "^1.0.3" + "sisteransi": "^1.0.4" } }, "promzard": { @@ -32865,6 +36088,12 @@ "reflect.ownkeys": "^0.2.0" } }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, "property-information": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.3.0.tgz", @@ -33168,6 +36397,20 @@ "ms": "^2.1.1" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "https-proxy-agent": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", @@ -33195,6 +36438,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", @@ -33540,6 +36792,17 @@ "node-releases": "^1.1.29" } }, + "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" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -33868,6 +37131,19 @@ "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "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" + } + } } }, "@babel/parser": { @@ -34208,6 +37484,17 @@ "ws": "^1.1.0" }, "dependencies": { + "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" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -34371,6 +37658,17 @@ "through": "^2.3.6" }, "dependencies": { + "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" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -34459,6 +37757,19 @@ "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" + }, + "dependencies": { + "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" + } + } } }, "p-limit": { @@ -34976,32 +38287,37 @@ } }, "reakit": { - "version": "1.0.0-beta.12", - "resolved": "https://registry.npmjs.org/reakit/-/reakit-1.0.0-beta.12.tgz", - "integrity": "sha512-jf/0RWmJypG9wFbbCSj9mFxb474TCFnAweKnrh3yLJiMjKDEAFXic0cNyhqxSuOUUyZeT67bUFbu25DXBNfRmQ==", + "version": "1.0.0-rc.0", + "resolved": "https://registry.npmjs.org/reakit/-/reakit-1.0.0-rc.0.tgz", + "integrity": "sha512-jG9RfLE9DX3XP6xiUmindu8dJmd4rLs+ohQ2xppF9LVYQ/7Qa9B4kz8mNYbe42u8muE3nMM78T2RfXz+c/ZMsQ==", "requires": { + "@popperjs/core": "^2.1.0", "body-scroll-lock": "^2.6.4", - "popper.js": "^1.16.0", - "reakit-system": "^0.7.0", - "reakit-utils": "^0.7.1" - }, - "dependencies": { - "popper.js": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.0.tgz", - "integrity": "sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==" - } + "reakit-system": "^0.10.0", + "reakit-utils": "^0.10.0", + "reakit-warning": "^0.1.0" } }, "reakit-system": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/reakit-system/-/reakit-system-0.7.0.tgz", - "integrity": "sha512-6MaQsoyIhU0b0RGfIfGSSGujCx0XVBtfJkRcn+TviiWwMXGS9liTCDBE1vn7fLnUYiR6kqll50Nmw//oIn97cg==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/reakit-system/-/reakit-system-0.10.0.tgz", + "integrity": "sha512-73ZI50NB2A6WAF3OsPJEEz73fax5cFiMoGMx3KxPT/AcS39rPqlBW6QkawtZC1HUebQXlsLxwZWicoFt8UubmQ==", + "requires": { + "reakit-utils": "^0.10.0" + } }, "reakit-utils": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/reakit-utils/-/reakit-utils-0.7.1.tgz", - "integrity": "sha512-xQJctof9V+wkC7OxSL7P14d5Se6l/apCfhY8liIfVihtakzXOkvKea4Ka/TbEfpoTKN7MRO4xNMxjfzuGFexHQ==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/reakit-utils/-/reakit-utils-0.10.0.tgz", + "integrity": "sha512-s1+nqLYrHo54U38iETdY86+VD+CZBTqF9rxMmphuft1Iz1i+L+OqOVJMq5sviBkTiEz8zRMhrNLcjBERFiPnkA==" + }, + "reakit-warning": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/reakit-warning/-/reakit-warning-0.1.0.tgz", + "integrity": "sha512-nfujYGWoZ1lh6eAFTVQc2aNjrAEf30PHffJw8Q8tiJJY4Knoy7eLA4jQGHTl3gOjhA9+Yd8KSmiLoOPlr6A0kA==", + "requires": { + "reakit-utils": "^0.10.0" + } }, "realpath-native": { "version": "1.1.0", @@ -35123,11 +38439,30 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, "regenerator-runtime": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" }, + "regenerator-transform": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz", + "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4", + "private": "^0.1.8" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -35259,22 +38594,36 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, "regextras": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.6.1.tgz", - "integrity": "sha512-EzIHww9xV2Kpqx+corS/I7OBmf2rZ0pKKJPsw5Dc+l6Zq1TslDmtRIP9maVn3UH+72MIXmn8zzDgP07ihQogUA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.7.0.tgz", + "integrity": "sha512-ds+fL+Vhl918gbAUb0k2gVKbTZLsg84Re3DI6p85Et0U0tYME3hyW4nMK8Px4dtDaBA2qNjvG5uWyW7eK5gfmw==", "dev": true }, "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", "dev": true }, "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -35441,6 +38790,19 @@ "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "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" + } + } } }, "@babel/parser": { @@ -35824,18 +39186,15 @@ "requires": { "mime-db": "1.40.0" } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true } } }, - "request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, "request-promise-core": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", @@ -35963,6 +39322,15 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -36019,12 +39387,28 @@ } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "ripemd160": { @@ -36066,6 +39450,17 @@ "strip-json-comments": "^2.0.0" }, "dependencies": { + "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" + } + }, "postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -36387,6 +39782,15 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "dev": true, + "requires": { + "xmlchars": "^2.1.1" + } + }, "scheduler": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", @@ -37173,9 +40577,9 @@ } }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -37209,21 +40613,21 @@ "dev": true }, "spawnd": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-4.0.0.tgz", - "integrity": "sha512-ql3qhJnhAkvXpaqKBWOqou1rUTSQhFRaZkyOT+MTFB4xY3X+brgw6LTWV2wHuE9A6YPhrNe1cbg7S+jAYnbC0Q==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-4.4.0.tgz", + "integrity": "sha512-jLPOfB6QOEgMOQY15Z6+lwZEhH3F5ncXxIaZ7WHPIapwNNLyjrs61okj3VJ3K6tmP5TZ6cO0VAu9rEY4MD4YQg==", "dev": true, "requires": { "exit": "^0.1.2", "signal-exit": "^3.0.2", - "tree-kill": "^1.2.1", - "wait-port": "^0.2.2" + "tree-kill": "^1.2.2", + "wait-port": "^0.2.7" }, "dependencies": { "tree-kill": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", - "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true } } @@ -37465,13 +40869,30 @@ "dev": true }, "string-length": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", - "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", "dev": true, "requires": { "astral-regex": "^1.0.0", - "strip-ansi": "^4.0.0" + "strip-ansi": "^5.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, "string-template": { @@ -37817,72 +41238,413 @@ "dev": true }, "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + } + } + }, + "string.prototype.trim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz", + "integrity": "sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + } + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + } + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz", + "integrity": "sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" } }, "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - } - } - }, - "string.prototype.trim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", - "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.0", - "function-bind": "^1.0.2" - } - }, - "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - }, - "dependencies": { - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - } - } - }, - "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - }, - "dependencies": { - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" } } } @@ -38117,6 +41879,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "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" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -38340,6 +42113,17 @@ "util.promisify": "~1.0.0" }, "dependencies": { + "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" + } + }, "css-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", @@ -38668,11 +42452,11 @@ } }, "tannin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.1.0.tgz", - "integrity": "sha512-LxhcXqpMHEOVeVKmuG5aCPPsTXFlO373vrWkqN7FSJBVLS6lFOAg8ZGzIyGhrOf7Ho3xB4jdGedY1gi/8J1FCA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", + "integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==", "requires": { - "@tannin/plural-forms": "^1.0.3" + "@tannin/plural-forms": "^1.1.0" } }, "tapable": { @@ -38822,15 +42606,15 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true } } }, - "term-size": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.1.1.tgz", - "integrity": "sha512-UqvQSch04R+69g4RDhrslmGvGL3ucDRX/U+snYW0Mab4uCAyKSndUksaoqlJ81QKSpRnIsuOYQCbC2ZWx2896A==", - "dev": true - }, "terminal-link": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.0.0.tgz", @@ -39151,30 +42935,20 @@ } }, "test-exclude": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.2.tgz", - "integrity": "sha512-N2pvaLpT8guUpb5Fe1GJlmvmzH3x+DAKmmyEQmFP792QcLYoGE1syxztSvPD1V8yPe6VrcCt6YGQVjSRjCASsA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -39184,101 +42958,6 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true } } }, @@ -39343,12 +43022,6 @@ "integrity": "sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==", "dev": true }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -39462,6 +43135,12 @@ } } }, + "to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==", + "dev": true + }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -39641,6 +43320,15 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -39677,6 +43365,12 @@ "prelude-ls": "~1.1.2" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", @@ -39721,10 +43415,19 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, "ua-parser-js": { @@ -39853,9 +43556,9 @@ } }, "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==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", "dev": true }, "unicode-property-aliases-ecmascript": { @@ -40261,9 +43964,9 @@ "dev": true }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", + "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==" }, "v8-compile-cache": { "version": "2.1.0", @@ -40271,6 +43974,34 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, + "v8-to-istanbul": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.2.tgz", + "integrity": "sha512-G9R+Hpw0ITAmPSr47lSlc5A1uekSYzXxTMlFxso2xoffwo4jQnzbv1p9yXIinO8UMZKfAFewaCHwWvnH4Jb4Ug==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", @@ -40483,6 +44214,17 @@ "browser-process-hrtime": "^0.1.2" } }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, "wait-on": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.3.0.tgz", @@ -40497,9 +44239,9 @@ }, "dependencies": { "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true }, "rx": { @@ -40511,9 +44253,9 @@ } }, "wait-port": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.6.tgz", - "integrity": "sha512-nXE5Yp0Zs1obhFVc0Da7WVJc3y0LxoCq3j4mtV0NdI5P/ZvRdKp5yhuojvMOcOxSwpQL1hGbOgMNQ+4wpRpwCA==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.7.tgz", + "integrity": "sha512-pJ6cSBIa0w1sDg4y/wXN4bmvhM9OneOvwdFHo647L2NShBi/oXG4lRaLic5cO1HaYGbUhEvratPfl/WMlIC+tg==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -40521,6 +44263,17 @@ "debug": "^4.1.1" }, "dependencies": { + "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" + } + }, "commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", @@ -40720,6 +44473,17 @@ "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "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" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -40759,6 +44523,28 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "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" + }, + "dependencies": { + "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" + } + } + } + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -41125,6 +44911,12 @@ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true } } }, @@ -41193,23 +44985,6 @@ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" }, - "whatwg-mimetype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz", - "integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew==", - "dev": true - }, - "whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, "whatwg-url-without-unicode": { "version": "8.0.0-1", "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-1.tgz", @@ -41401,6 +45176,12 @@ } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -41577,6 +45358,14 @@ "requires": { "simple-plist": "^1.0.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "xml": { @@ -41597,6 +45386,12 @@ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "xmldoc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.1.2.tgz", @@ -41618,6 +45413,15 @@ "integrity": "sha1-jdi/Rfw/f1Xw4FS4ePQ6YmFNr98=", "dev": true }, + "xregexp": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", + "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", + "dev": true, + "requires": { + "@babel/runtime-corejs3": "^7.8.3" + } + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index 74457f26e6648a..b2a95e5213b517 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "7.8.1", + "version": "7.9.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", @@ -38,6 +38,7 @@ "@wordpress/deprecated": "file:packages/deprecated", "@wordpress/dom": "file:packages/dom", "@wordpress/dom-ready": "file:packages/dom-ready", + "@wordpress/edit-navigation": "file:packages/edit-navigation", "@wordpress/edit-post": "file:packages/edit-post", "@wordpress/edit-site": "file:packages/edit-site", "@wordpress/edit-widgets": "file:packages/edit-widgets", @@ -49,6 +50,7 @@ "@wordpress/html-entities": "file:packages/html-entities", "@wordpress/i18n": "file:packages/i18n", "@wordpress/icons": "file:packages/icons", + "@wordpress/interface": "file:packages/interface", "@wordpress/is-shallow-equal": "file:packages/is-shallow-equal", "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts", "@wordpress/keycodes": "file:packages/keycodes", @@ -72,10 +74,11 @@ "devDependencies": { "@actions/core": "1.0.0", "@actions/github": "1.0.0", - "@babel/core": "7.8.3", + "@babel/core": "7.9.0", "@babel/plugin-syntax-jsx": "7.8.3", - "@babel/runtime-corejs3": "7.8.3", - "@babel/traverse": "7.8.3", + "@babel/runtime-corejs3": "7.9.2", + "@babel/traverse": "7.9.0", + "@jest/types": "25.3.0", "@octokit/rest": "16.26.0", "@octokit/webhooks": "7.1.0", "@storybook/addon-a11y": "5.3.2", @@ -85,8 +88,14 @@ "@storybook/addon-storysource": "5.3.2", "@storybook/addon-viewport": "5.3.2", "@storybook/react": "5.3.2", - "@types/jest": "24.0.25", + "@testing-library/react": "10.0.2", + "@types/classnames": "2.2.10", + "@types/lodash": "4.14.149", + "@types/prettier": "1.19.0", + "@types/qs": "6.9.1", + "@types/react-dom": "16.9.5", "@types/requestidlecallback": "0.3.1", + "@types/sprintf-js": "1.1.2", "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", "@wordpress/babel-preset-default": "file:packages/babel-preset-default", @@ -107,16 +116,17 @@ "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", "@wordpress/postcss-themes": "file:packages/postcss-themes", "@wordpress/prettier-config": "file:packages/prettier-config", + "@wordpress/project-management-automation": "file:packages/project-management-automation", "@wordpress/scripts": "file:packages/scripts", - "babel-loader": "8.0.6", - "babel-plugin-emotion": "10.0.27", + "babel-loader": "8.1.0", + "babel-plugin-emotion": "10.0.33", "babel-plugin-inline-json-import": "0.3.2", "babel-plugin-react-native-classname-to-style": "1.2.2", "babel-plugin-react-native-platform-specific-extensions": "1.1.1", "babel-plugin-require-context-hook": "1.0.0", "benchmark": "2.1.4", "browserslist": "4.9.1", - "chalk": "2.4.2", + "chalk": "4.0.0", "commander": "4.1.0", "concurrently": "3.5.0", "copy-webpack-plugin": "4.5.2", @@ -124,19 +134,20 @@ "css-loader": "3.2.0", "cssnano": "4.1.10", "deep-freeze": "0.0.1", - "enzyme": "3.9.0", + "enzyme": "3.11.0", "eslint-plugin-eslint-comments": "3.1.2", - "eslint-plugin-import": "2.18.2", + "eslint-plugin-import": "2.20.2", + "execa": "4.0.0", "fast-glob": "2.2.7", "fbjs": "0.8.17", "glob": "7.1.2", "husky": "3.0.5", - "inquirer": "7.0.3", + "inquirer": "7.1.0", "is-equal-shallow": "0.1.3", - "jest-emotion": "10.0.17", - "jest-junit": "6.4.0", + "jest-emotion": "10.0.32", + "jest-junit": "10.0.0", "jest-serializer-enzyme": "1.0.0", - "jsdom": "11.12.0", + "jsdom": "15.2.1", "lerna": "3.18.2", "lint-staged": "9.2.5", "lodash": "4.17.15", @@ -144,6 +155,7 @@ "metro-react-native-babel-preset": "0.55.0", "metro-react-native-babel-transformer": "0.55.0", "mkdirp": "0.5.1", + "nock": "12.0.3", "node-sass": "4.12.0", "node-watch": "0.6.0", "postcss": "7.0.13", @@ -154,7 +166,7 @@ "react-dom": "16.9.0", "react-native": "0.61.5", "react-test-renderer": "16.9.0", - "rimraf": "2.6.2", + "rimraf": "3.0.2", "rtlcss": "2.4.0", "sass-loader": "6.0.7", "semver": "6.0.0", @@ -166,16 +178,18 @@ "sprintf-js": "1.1.1", "style-loader": "1.0.0", "stylelint-config-wordpress": "13.1.0", - "typescript": "3.5.3", - "uuid": "3.3.2", + "typescript": "3.8.3", + "uuid": "7.0.2", "webpack": "4.42.0", "worker-farm": "1.7.0" }, "scripts": { "prebuild": "npm run check-engines", - "clean:packages": "rimraf ./packages/*/build ./packages/*/build-module ./packages/*/build-style ./packages/*/node_modules", + "clean:packages": "rimraf \"./packages/*/@(build|build-module|build-style)\"", + "clean:package-types": "tsc --build --clean", "prebuild:packages": "npm run clean:packages && lerna run build", - "build:packages": "node ./bin/packages/build.js", + "build:packages": "npm run build:package-types && node ./bin/packages/build.js", + "build:package-types": "node ./bin/packages/validate-typescript-version.js && tsc --build", "build": "npm run build:packages && wp-scripts build", "check-engines": "wp-scripts check-engines", "check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2\" \"wp-scripts check-licenses --dev\"", @@ -184,28 +198,27 @@ "predev": "npm run check-engines", "dev": "npm run build:packages && concurrently \"wp-scripts start\" \"npm run dev:packages\"", "dev:packages": "node ./bin/packages/watch.js", - "docs:build": "node ./docs/tool/index.js && node ./bin/api-docs/update-readmes.js", + "docs:build": "node ./docs/tool/index.js && node ./bin/api-docs/update-api-docs.js", "fixtures:clean": "rimraf \"packages/e2e-tests/fixtures/blocks/*.+(json|serialized.html)\"", "fixtures:server-registered": "packages/env/bin/wp-env run wordpress ./wp-content/plugins/gutenberg/bin/get-server-blocks.php > test/integration/full-content/server-registered.json", "fixtures:generate": "npm run fixtures:server-registered && cross-env GENERATE_MISSING_FIXTURES=y npm run test-unit", "fixtures:regenerate": "npm run fixtures:clean && npm run fixtures:generate", "format-js": "wp-scripts format-js", - "lint": "concurrently \"npm run lint-js\" \"npm run lint-pkg-json\" \"npm run lint-css\" \"npm run lint-types\"", + "lint": "concurrently \"npm run lint-js\" \"npm run lint-pkg-json\" \"npm run lint-css\"", "lint-js": "wp-scripts lint-js", "lint-js:fix": "npm run lint-js -- --fix", "lint-php": "npm run wp-env run composer run-script lint", "lint-pkg-json": "wp-scripts lint-pkg-json . 'packages/*/package.json'", "lint-css": "wp-scripts lint-style '**/*.scss'", "lint-css:fix": "npm run lint-css -- --fix", - "lint-types": "tsc", "lint:md-js": "wp-scripts lint-md-js", "lint:md-docs": "wp-scripts lint-md-docs", "package-plugin": "./bin/build-plugin-zip.sh", "pot-to-php": "./bin/pot-to-php.js", "publish:check": "lerna updated", - "publish:dev": "npm run build:packages && lerna publish --dist-tag next", - "publish:legacy": "npm run build:packages && lerna publish --dist-tag legacy", - "publish:prod": "npm run build:packages && lerna publish", + "publish:dev": "npm run clean:package-types && npm run build:packages && lerna publish --dist-tag next", + "publish:legacy": "npm run clean:package-types && npm run build:packages && lerna publish --dist-tag legacy", + "publish:prod": "npm run clean:package-types && npm run build:packages && lerna publish", "test": "npm run lint && npm run test-unit", "test-e2e": "wp-scripts test-e2e --config packages/e2e-tests/jest.config.js", "test-e2e:watch": "npm run test-e2e -- --watch", @@ -236,6 +249,9 @@ } }, "lint-staged": { + "package-lock.json": [ + "node ./bin/check-latest-npm.js" + ], "packages/*/package.json": [ "wp-scripts lint-pkg-json" ], @@ -246,13 +262,13 @@ "wp-scripts format-js", "wp-scripts lint-js" ], - "{docs/{toc.json,tool/*.js},packages/{*/README.md,*/src/{actions,selectors}.js,components/src/*/**/README.md}}": [ - "node ./docs/tool/index.js", - "node ./docs/tool/are-data-files-unstaged.js" + "{docs/{toc.json,tool/*.js},packages/{*/README.md,components/src/*/**/README.md}}": [ + "node ./docs/tool/index.js" ], "packages/**/*.js": [ - "node ./bin/api-docs/update-readmes.js", - "node ./bin/api-docs/are-readmes-unstaged.js" + "node ./bin/api-docs/update-api-docs.js", + "node ./bin/api-docs/are-api-docs-unstaged.js", + "node ./bin/packages/lint-staged-typecheck.js" ] }, "wp-env": { diff --git a/packages/README.md b/packages/README.md index 30cccbed973c42..44162e64f69b23 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,46 +7,44 @@ This repository uses [lerna] to manage WordPress modules and publish them as pac When creating a new package, you need to provide at least the following: 1. `package.json` based on the template: - ```json - { - "name": "@wordpress/package-name", - "version": "1.0.0-beta.0", - "description": "Package description.", - "author": "The WordPress Contributors", - "license": "GPL-2.0-or-later", - "keywords": [ - "wordpress" - ], - "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/package-name/README.md", - "repository": { - "type": "git", - "url": "https://github.com/WordPress/gutenberg.git" - }, - "bugs": { - "url": "https://github.com/WordPress/gutenberg/issues" - }, - "main": "build/index.js", - "module": "build-module/index.js", - "react-native": "src/index", - "dependencies": { - "@babel/runtime": "^7.8.3" - }, - "publishConfig": { - "access": "public" - } - } - ``` - This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. + ```json + { + "name": "@wordpress/package-name", + "version": "1.0.0-beta.0", + "description": "Package description.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ "wordpress" ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/package-name/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "react-native": "src/index", + "dependencies": { + "@babel/runtime": "^7.9.2" + }, + "publishConfig": { + "access": "public" + } + } + ``` + This assumes that your code is located in the `src` folder and will be transpiled with `Babel`. 2. `.npmrc` file which disables creating `package-lock.json` file for the package: - ``` - package-lock=false - ``` + ``` + package-lock=false + ``` 3. `README.md` file containing at least: - - Package name - - Package description - - Installation details - - Usage example - - `Code is Poetry` logo (`

Code is Poetry.

`) + - Package name + - Package description + - Installation details + - Usage example + - `Code is Poetry` logo (`

Code is Poetry.

`) ## Managing Dependencies @@ -57,7 +55,7 @@ There are two types of dependencies that you might want to add to one of the exi Production dependencies are stored in the `dependencies` section of the package’s `package.json` file. #### Adding New Dependencies - + The simplest way to add a production dependency to one of the packages is to run a very convenient [lerna add](https://github.com/lerna/lerna/tree/master/commands/add#readme) command from the root of the project. _Example:_ @@ -79,9 +77,9 @@ _Example:_ @@ -43,7 +43,6 @@ "check-node-version": "^3.1.1", "cross-spawn": "^5.1.0", - "eslint": "^5.16.0", -- "jest": "^24.7.1", - "jest-puppeteer": "^4.0.0", + "eslint": "^6.8.0", +- "jest": "^25.3.0", + "jest-puppeteer": "^4.4.0", "minimist": "^1.2.0", "npm-package-json-lint": "^3.6.0", ``` @@ -93,7 +91,7 @@ Next, you need to run `npm install` in the root of the project to ensure that `p This is the most confusing part of working with [lerna] which causes a lot of hassles for contributors. The most successful strategy so far is to do the following: 1. First, remove the existing dependency as described in the previous section. 2. Next, add the same dependency back as described in the first section of this chapter. This time it wil get the latest version applied unless you enforce a different version explicitly. - + ### Development Dependencies In contrast to production dependencies, development dependencies shouldn't be stored in individual WordPress packages. Instead they should be installed in the project's `package.json` file using the usual `npm install` command. In effect, all development tools are configured to work with every package at the same time to ensure they share the same characteristics and integrate correctly with each other. @@ -119,16 +117,16 @@ _Example:_ ### Bug Fix -- Fixed an off-by-one error with the `sum` function. +- Fixed an off-by-one error with the `sum` function. ``` There are a number of common release subsections you can follow. Each is intended to align to a specific meaning in the context of the [Semantic Versioning (`semver`) specification](https://semver.org/) the project adheres to. It is important that you describe your changes accurately, since this is used in the packages release process to help determine the version of the next release. -- "Breaking Change" - A backwards-incompatible change which requires specific attention of the impacted developers to reconcile (requires a major version bump). -- "New Feature" - The addition of a new backwards-compatible function or feature to the existing public API (requires a minor verison bump). -- "Enhancement" - Backwards-compatible improvements to existing functionality (requires a minor version bump). -- "Bug Fix" - Resolutions to existing buggy behavior (requires a patch version bump). -- "Internal" - Changes which do not have an impact on the public interface or behavior of the module (requires a patch version bump). +- "Breaking Change" - A backwards-incompatible change which requires specific attention of the impacted developers to reconcile (requires a major version bump). +- "New Feature" - The addition of a new backwards-compatible function or feature to the existing public API (requires a minor verison bump). +- "Enhancement" - Backwards-compatible improvements to existing functionality (requires a minor version bump). +- "Bug Fix" - Resolutions to existing buggy behavior (requires a patch version bump). +- "Internal" - Changes which do not have an impact on the public interface or behavior of the module (requires a patch version bump). While other section naming can be used when appropriate, it's important that are expressed clearly to avoid confusion for both the packages releaser and third-party consumers. @@ -190,5 +188,61 @@ npm run publish:legacy This is usually necessary when adding bug fixes or security patches to the earlier versions of WordPress. +## TypeScript + +The [TypeScript](http://www.typescriptlang.org/) language is a typed superset of JavaScript that compiles to plain JavaScript. +Gutenberg does not use the TypeScript language, however TypeScript has powerful tooling that can be applied to JavaScript projects. + +Gutenberg uses TypeScript for several reasons, including: + +- Powerful editor integrations improve developer experience. +- Type system can detect some issues and lead to more robust software. +- Type declarations can be produced to allow other projects to benefit from these advantages as well. + +### Using TypeScript + +Gutenberg uses TypeScript by running the TypeScript compiler (`tsc`) on select packages. +These packages benefit from type checking and produced type declarations in the published packages. + +To opt-in to TypeScript tooling, packages should include a `tsconfig.json` file in the package root and add an entry to the root `tsconfig.json` references. +The changes will indicate that the package has opted-in and will be included in the TypeScript build process. + +A `tsconfig.json` file should look like the following (comments are not necessary): + +```jsonc +{ + // Extends a base configuration common to most packages + "extends": "../../tsconfig.base.json", + + // Options for the TypeScript compiler + // We'll usually set our `rootDir` and `declarationDir` as follows, which is specific + // to each project. + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + + // Which source files should be included + "include": [ "src/**/*" ], + + // Other WordPress package dependencies that have opted-in to TypeScript should be listed + // here. In this case, our package depends on `@wordpress/dom-ready`. + "references": [ { "path": "../dom-ready" } ] +} +``` + +Type declarations will be produced in the `build-types` which should be included in the published package. +For consumers to use the published type declarations, we'll set the `types` field in `package.json`: + +```json +{ + "main": "build/index.js", + "main-module": "build-module/index.js", + "types": "build-types" +} +``` + +Ensure that the `build-types` directory will be included in the published package, for example if a `files` field is declared. + [lerna]: https://lerna.js.org/ [npm]: https://www.npmjs.com/ diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 6d3354f059cc82..b1c90b9bd0c75d 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 2.0.0 (2018-09-05) ### Breaking Change diff --git a/packages/a11y/README.md b/packages/a11y/README.md index a45253197e7e6b..46cf83291fd301 100644 --- a/packages/a11y/README.md +++ b/packages/a11y/README.md @@ -23,7 +23,7 @@ Create the live regions. # **speak** Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions. -This module is inspired by the `speak` function in wp-a11y.js +This module is inspired by the `speak` function in `wp-a11y.js`. _Usage_ @@ -39,15 +39,15 @@ speak( 'The message you want to send to the ARIA live region', 'assertive' ); _Parameters_ -- _message_ `string`: The message to be announced by Assistive Technologies. -- _ariaLive_ `string`: Optional. The politeness level for aria-live. Possible values: polite or assertive. Default polite. +- _message_ `string`: The message to be announced by assistive technologies. +- _ariaLive_ `[string]`: The politeness level for aria-live; default: 'polite'. ### Background -For context I'll quote [this article on WordPress.org](https://make.wordpress.org/accessibility/2015/04/15/let-wordpress-speak-new-in-wordpress-4-2/) by [@joedolson](https://github.com/joedolson): +For context I’ll quote [this article on WordPress.org](https://make.wordpress.org/accessibility/2015/04/15/let-wordpress-speak-new-in-wordpress-4-2/) by [@joedolson](https://github.com/joedolson): > #### Why. > @@ -71,4 +71,4 @@ For context I'll quote [this article on WordPress.org](https://make.wordpress.or See -

Code is Poetry.

+

Code is Poetry.

diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 481818d58d818c..70cf5f6766ea4c 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -21,8 +21,9 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/dom-ready": "file:../dom-ready" }, "publishConfig": { diff --git a/packages/a11y/src/addContainer.js b/packages/a11y/src/add-container.js similarity index 72% rename from packages/a11y/src/addContainer.js rename to packages/a11y/src/add-container.js index edd733a6626a60..122adeaf8a15da 100644 --- a/packages/a11y/src/addContainer.js +++ b/packages/a11y/src/add-container.js @@ -1,15 +1,13 @@ /** * Build the live regions markup. * - * @param {string} ariaLive Optional. Value for the 'aria-live' attribute, default 'polite'. + * @param {string} [ariaLive] Value for the 'aria-live' attribute; default: 'polite'. * * @return {HTMLDivElement} The ARIA live region HTML element. */ -const addContainer = function( ariaLive ) { - ariaLive = ariaLive || 'polite'; - +export default function addContainer( ariaLive = 'polite' ) { const container = document.createElement( 'div' ); - container.id = 'a11y-speak-' + ariaLive; + container.id = `a11y-speak-${ ariaLive }`; container.className = 'a11y-speak-region'; container.setAttribute( @@ -30,12 +28,10 @@ const addContainer = function( ariaLive ) { container.setAttribute( 'aria-relevant', 'additions text' ); container.setAttribute( 'aria-atomic', 'true' ); - const body = document.querySelector( 'body' ); + const { body } = document; if ( body ) { body.appendChild( container ); } return container; -}; - -export default addContainer; +} diff --git a/packages/a11y/src/clear.js b/packages/a11y/src/clear.js index 94bab6ff853084..d4429a5394db2e 100644 --- a/packages/a11y/src/clear.js +++ b/packages/a11y/src/clear.js @@ -1,11 +1,10 @@ /** * Clear the a11y-speak-region elements. */ -const clear = function() { - const regions = document.querySelectorAll( '.a11y-speak-region' ); +export default function clear() { + const regions = document.getElementsByClassName( 'a11y-speak-region' ); + for ( let i = 0; i < regions.length; i++ ) { regions[ i ].textContent = ''; } -}; - -export default clear; +} diff --git a/packages/a11y/src/filterMessage.js b/packages/a11y/src/filter-message.js similarity index 89% rename from packages/a11y/src/filterMessage.js rename to packages/a11y/src/filter-message.js index 27a48e85fec98b..54fab7dec1aaa4 100644 --- a/packages/a11y/src/filterMessage.js +++ b/packages/a11y/src/filter-message.js @@ -7,7 +7,7 @@ let previousMessage = ''; * * @return {string} The filtered message. */ -const filterMessage = function( message ) { +export default function filterMessage( message ) { /* * Strip HTML tags (if any) from the message string. Ideally, messages should * be simple strings, carefully crafted for specific use with A11ySpeak. @@ -24,6 +24,4 @@ const filterMessage = function( message ) { previousMessage = message; return message; -}; - -export default filterMessage; +} diff --git a/packages/a11y/src/index.js b/packages/a11y/src/index.js index 97d10c65920202..cdd493091c2394 100644 --- a/packages/a11y/src/index.js +++ b/packages/a11y/src/index.js @@ -6,26 +6,26 @@ import domReady from '@wordpress/dom-ready'; /** * Internal dependencies */ -import addContainer from './addContainer'; +import addContainer from './add-container'; import clear from './clear'; -import filterMessage from './filterMessage'; +import filterMessage from './filter-message'; /** * Create the live regions. */ -export const setup = function() { - const containerPolite = document.getElementById( 'a11y-speak-polite' ); +export function setup() { const containerAssertive = document.getElementById( 'a11y-speak-assertive' ); + const containerPolite = document.getElementById( 'a11y-speak-polite' ); - if ( containerPolite === null ) { - addContainer( 'polite' ); - } if ( containerAssertive === null ) { addContainer( 'assertive' ); } -}; + if ( containerPolite === null ) { + addContainer( 'polite' ); + } +} /** * Run setup on domReady. @@ -34,11 +34,10 @@ domReady( setup ); /** * Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions. - * This module is inspired by the `speak` function in wp-a11y.js + * This module is inspired by the `speak` function in `wp-a11y.js`. * - * @param {string} message The message to be announced by Assistive Technologies. - * @param {string} ariaLive Optional. The politeness level for aria-live. Possible values: - * polite or assertive. Default polite. + * @param {string} message The message to be announced by assistive technologies. + * @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'. * * @example * ```js @@ -51,20 +50,20 @@ domReady( setup ); * speak( 'The message you want to send to the ARIA live region', 'assertive' ); * ``` */ -export const speak = function( message, ariaLive ) { +export function speak( message, ariaLive ) { // Clear previous messages to allow repeated strings being read out. clear(); message = filterMessage( message ); - const containerPolite = document.getElementById( 'a11y-speak-polite' ); const containerAssertive = document.getElementById( 'a11y-speak-assertive' ); + const containerPolite = document.getElementById( 'a11y-speak-polite' ); - if ( containerAssertive && 'assertive' === ariaLive ) { + if ( containerAssertive && ariaLive === 'assertive' ) { containerAssertive.textContent = message; } else if ( containerPolite ) { containerPolite.textContent = message; } -}; +} diff --git a/packages/a11y/src/index.native.js b/packages/a11y/src/index.native.js index 4e5e9841118b17..41a6591d34516f 100644 --- a/packages/a11y/src/index.native.js +++ b/packages/a11y/src/index.native.js @@ -1,19 +1,18 @@ /** * Internal dependencies */ -import filterMessage from './filterMessage'; +import filterMessage from './filter-message'; /** * Update the ARIA live notification area text node. * * @param {string} message The message to be announced by Assistive Technologies. - * @param {string} ariaLive Optional. The politeness level for aria-live. Possible values: - * polite or assertive. Default polite. + * @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'. */ -export const speak = function( message, ariaLive ) { +export function speak( message, ariaLive ) { message = filterMessage( message ); //TODO: Use native module to speak message - if ( 'assertive' === ariaLive ) { + if ( ariaLive === 'assertive' ) { } else { } -}; +} diff --git a/packages/a11y/src/test/addContainer.test.js b/packages/a11y/src/test/add-container.test.js similarity index 91% rename from packages/a11y/src/test/addContainer.test.js rename to packages/a11y/src/test/add-container.test.js index 6ebf062237c9c0..c7e351dd38ef28 100644 --- a/packages/a11y/src/test/addContainer.test.js +++ b/packages/a11y/src/test/add-container.test.js @@ -1,14 +1,14 @@ /** * Internal dependencies */ -import addContainer from '../addContainer'; +import addContainer from '../add-container'; describe( 'addContainer', () => { describe( 'with polite param', () => { it( 'should create an aria-live element with aria-live attr set to polite', () => { const container = addContainer( 'polite' ); - expect( container ).not.toBe( null ); + expect( container ).not.toBeNull(); expect( container.className ).toBe( 'a11y-speak-region' ); expect( container.id ).toBe( 'a11y-speak-polite' ); expect( container.getAttribute( 'style' ) ).not.toBeNull(); @@ -24,7 +24,7 @@ describe( 'addContainer', () => { it( 'should create an aria-live element with aria-live attr set to assertive', () => { const container = addContainer( 'assertive' ); - expect( container ).not.toBe( null ); + expect( container ).not.toBeNull(); expect( container.className ).toBe( 'a11y-speak-region' ); expect( container.id ).toBe( 'a11y-speak-assertive' ); expect( container.getAttribute( 'style' ) ).not.toBeNull(); @@ -40,7 +40,7 @@ describe( 'addContainer', () => { it( 'should default to creating an aria-live element with aria-live attr set to polite', () => { const container = addContainer( 'polite' ); - expect( container ).not.toBe( null ); + expect( container ).not.toBeNull(); expect( container.className ).toBe( 'a11y-speak-region' ); expect( container.id ).toBe( 'a11y-speak-polite' ); expect( container.getAttribute( 'style' ) ).not.toBeNull(); diff --git a/packages/a11y/src/test/clear.test.js b/packages/a11y/src/test/clear.test.js index 02438dda1a4ecb..e45a45560c666f 100644 --- a/packages/a11y/src/test/clear.test.js +++ b/packages/a11y/src/test/clear.test.js @@ -8,12 +8,12 @@ describe( 'clear', () => { const container1 = document.createElement( 'div' ); container1.className = 'a11y-speak-region'; container1.textContent = 'not empty'; - document.querySelector( 'body' ).appendChild( container1 ); + document.body.appendChild( container1 ); const container2 = document.createElement( 'div' ); container2.className = 'a11y-speak-region'; container2.textContent = 'not empty'; - document.querySelector( 'body' ).appendChild( container2 ); + document.body.appendChild( container2 ); clear(); expect( container1.textContent ).toBe( '' ); diff --git a/packages/a11y/src/test/filterMessage.test.js b/packages/a11y/src/test/filter-message.test.js similarity index 88% rename from packages/a11y/src/test/filterMessage.test.js rename to packages/a11y/src/test/filter-message.test.js index 95302abb8d1ce2..9b0613ae72e3d5 100644 --- a/packages/a11y/src/test/filterMessage.test.js +++ b/packages/a11y/src/test/filter-message.test.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import filterMessage from '../filterMessage'; +import filterMessage from '../filter-message'; describe( 'filterMessage', () => { describe( 'when a clean message is passed in', () => { @@ -15,7 +15,7 @@ describe( 'filterMessage', () => { it( 'should add a space to the message to make sure it is announced again', () => { filterMessage( 'repeated message.' ); const actual = filterMessage( 'repeated message.' ); - expect( actual ).toBe( 'repeated message.' + '\u00A0' ); + expect( actual ).toBe( 'repeated message.\u00A0' ); } ); } ); diff --git a/packages/a11y/src/test/index.test.js b/packages/a11y/src/test/index.test.js index 9888f9adb3a145..b17806c895353c 100644 --- a/packages/a11y/src/test/index.test.js +++ b/packages/a11y/src/test/index.test.js @@ -8,7 +8,7 @@ import domReady from '@wordpress/dom-ready'; */ import { setup, speak } from '../'; import clear from '../clear'; -import filterMessage from '../filterMessage'; +import filterMessage from '../filter-message'; jest.mock( '../clear', () => { return jest.fn(); @@ -18,7 +18,7 @@ jest.mock( '@wordpress/dom-ready', () => { callback(); } ); } ); -jest.mock( '../filterMessage', () => { +jest.mock( '../filter-message', () => { return jest.fn( ( message ) => { return message; } ); @@ -82,9 +82,9 @@ describe( 'speak', () => { it( 'should set the textcontent of the polite aria-live region', () => { speak( 'message', 'assertive' ); expect( containerPolite.textContent ).toBe( 'message' ); - expect( document.getElementById( 'a11y-speak-assertive' ) ).toBe( - null - ); + expect( + document.getElementById( 'a11y-speak-assertive' ) + ).toBeNull(); } ); } ); @@ -103,12 +103,10 @@ describe( 'speak', () => { } ); it( 'should set the textcontent of the polite aria-live region', () => { - expect( document.getElementById( 'a11y-speak-polite' ) ).toBe( - null - ); - expect( document.getElementById( 'a11y-speak-assertive' ) ).toBe( - null - ); + expect( document.getElementById( 'a11y-speak-polite' ) ).toBeNull(); + expect( + document.getElementById( 'a11y-speak-assertive' ) + ).toBeNull(); } ); } ); diff --git a/packages/a11y/tsconfig.json b/packages/a11y/tsconfig.json new file mode 100644 index 00000000000000..1a0a90bc8cb582 --- /dev/null +++ b/packages/a11y/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "references": [ { "path": "../dom-ready" } ], + "include": [ "src/**/*" ] +} diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 4c731b31390571..a536f7f889d00c 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -21,14 +21,14 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/data": "file:../data", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", "@wordpress/rich-text": "file:../rich-text", "lodash": "^4.17.15", "rememo": "^3.0.0", - "uuid": "^3.3.2" + "uuid": "^7.0.2" }, "publishConfig": { "access": "public" diff --git a/packages/annotations/src/store/actions.js b/packages/annotations/src/store/actions.js index f5d5b8cf208e55..00c9fa589732af 100644 --- a/packages/annotations/src/store/actions.js +++ b/packages/annotations/src/store/actions.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import uuid from 'uuid/v4'; +import { v4 as uuid } from 'uuid'; /** * Adds an annotation to a block. diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index fcc39efcb347bb..574aef5182ddaa 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -22,7 +22,8 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", + "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "@wordpress/url": "file:../url" }, diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index 9e7edc985709ed..64fc3ef09e0c33 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { useEffect, useState } from '@wordpress/element'; /** * Internal dependencies @@ -156,6 +157,42 @@ function apiFetch( options ) { } ); } +/** + * Function that fetches data using apiFetch, and updates the status. + * + * @param {string} path Query path. + */ +function useApiFetch( path ) { + // Indicate the fetching status + const [ isLoading, setIsLoading ] = useState( true ); + const [ data, setData ] = useState( null ); + const [ error, setError ] = useState( null ); + + useEffect( () => { + setIsLoading( true ); + setData( null ); + setError( null ); + + apiFetch( { path } ) + .then( ( fetchedData ) => { + setData( fetchedData ); + // We've stopped fetching + setIsLoading( false ); + } ) + .catch( ( err ) => { + setError( err ); + // We've stopped fetching + setIsLoading( false ); + } ); + }, [ path ] ); + + return { + isLoading, + data, + error, + }; +} + apiFetch.use = registerMiddleware; apiFetch.setFetchHandler = setFetchHandler; @@ -165,4 +202,6 @@ apiFetch.createRootURLMiddleware = createRootURLMiddleware; apiFetch.fetchAllMiddleware = fetchAllMiddleware; apiFetch.mediaUploadMiddleware = mediaUploadMiddleware; +apiFetch.useApiFetch = useApiFetch; + export default apiFetch; diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 0f40e07f861653..918e47c7352990 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#20669](https://github.com/WordPress/gutenberg/pull/20669)) + ## 2.3.0 (2019-05-21) ### Bug Fix diff --git a/packages/autop/package.json b/packages/autop/package.json index 9a4f5d7fbaaacb..1e7da05e1bae57 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -20,9 +20,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/autop/src/index.js b/packages/autop/src/index.js index 3a0fc7fa73600e..b2c605620852f3 100644 --- a/packages/autop/src/index.js +++ b/packages/autop/src/index.js @@ -1,7 +1,7 @@ /** * The regular expression for an HTML element. * - * @type {string} + * @type {RegExp} */ const htmlSplitRegex = ( () => { /* eslint-disable no-multi-spaces */ @@ -52,7 +52,7 @@ const htmlSplitRegex = ( () => { * Separate HTML elements and comments from the text. * * @param {string} input The text which has to be formatted. - * @return {Array} The formatted text. + * @return {string[]} The formatted text. */ function htmlSplit( input ) { const parts = []; @@ -60,9 +60,15 @@ function htmlSplit( input ) { let match; while ( ( match = workingInput.match( htmlSplitRegex ) ) ) { - parts.push( workingInput.slice( 0, match.index ) ); + // The `match` result, when invoked on a RegExp with the `g` flag (`/foo/g`) will not include `index`. + // If the `g` flag is omitted, `index` is included. + // `htmlSplitRegex` does not have the `g` flag so we can assert it will have an index number. + // Assert `match.index` is a number. + const index = /** @type {number} */ ( match.index ); + + parts.push( workingInput.slice( 0, index ) ); parts.push( match[ 0 ] ); - workingInput = workingInput.slice( match.index + match[ 0 ].length ); + workingInput = workingInput.slice( index + match[ 0 ].length ); } if ( workingInput.length ) { @@ -75,9 +81,9 @@ function htmlSplit( input ) { /** * Replace characters or phrases within HTML elements only. * - * @param {string} haystack The text which has to be formatted. - * @param {Object} replacePairs In the form {from: 'to', ...}. - * @return {string} The formatted text. + * @param {string} haystack The text which has to be formatted. + * @param {Record} replacePairs In the form {from: 'to', …}. + * @return {string} The formatted text. */ function replaceInHtmlTags( haystack, replacePairs ) { // Find all elements. @@ -337,6 +343,7 @@ export function removep( html ) { 'blockquote|ul|ol|li|dl|dt|dd|table|thead|tbody|tfoot|tr|th|td|h[1-6]|fieldset|figure'; const blocklist1 = blocklist + '|div|p'; const blocklist2 = blocklist + '|pre'; + /** @type {string[]} */ const preserve = []; let preserveLinebreaks = false; let preserveBr = false; @@ -399,7 +406,7 @@ export function removep( html ) { html = html.replace( /\n[\s\u00a0]+\n/g, '\n\n' ); // Replace
tags with line breaks. - html = html.replace( /(\s*)
\s*/gi, function( match, space ) { + html = html.replace( /(\s*)
\s*/gi, function( _, space ) { if ( space && space.indexOf( '\n' ) !== -1 ) { return '\n\n'; } @@ -470,7 +477,7 @@ export function removep( html ) { // Restore preserved tags. if ( preserve.length ) { html = html.replace( //g, function() { - return preserve.shift(); + return /** @type {string} */ ( preserve.shift() ); } ); } diff --git a/packages/autop/tsconfig.json b/packages/autop/tsconfig.json new file mode 100644 index 00000000000000..1a0a90bc8cb582 --- /dev/null +++ b/packages/autop/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "references": [ { "path": "../dom-ready" } ], + "include": [ "src/**/*" ] +} diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 2219269afd4b65..1e38d79c3d792d 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -29,7 +29,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "gettext-parser": "^1.3.1", "lodash": "^4.17.15" }, diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 16bd181f83a302..809a4c64bba645 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -1,10 +1,14 @@ ## Master +### New Features + +- The bundled `@babel/core` dependency has been updated from requiring `^7.8.3` to requiring `^7.9.0`. All other Babel plugins were updated to the latest version (see [Highlights](https://babeljs.io/blog/2020/03/16/7.9.0)). + ## 4.10.0 (2020-02-04) ### New Feature -- The bundled `@babel/core` dependency has been updated from requiring `^7.4.4` to requiring `^7.8.3`. All other Babel plugins were updated to the latest version. `@babel/preset-env` has now ESMAScript 2020 support enabled by default (see [Highlights](https://babeljs.io/blog/2020/01/11/7.8.0#highlights)). +- The bundled `@babel/core` dependency has been updated from requiring `^7.4.4` to requiring `^7.8.3`. All other Babel plugins were updated to the latest version. `@babel/preset-env` has now ESMAScript 2020 support enabled by default (see [Highlights](https://babeljs.io/blog/2020/01/11/7.8.0#highlights)). ## 4.5.0 (2019-08-29) diff --git a/packages/babel-preset-default/index.js b/packages/babel-preset-default/index.js index 15454ecb36fd65..e331b212cd0ba8 100644 --- a/packages/babel-preset-default/index.js +++ b/packages/babel-preset-default/index.js @@ -58,7 +58,6 @@ module.exports = function( api ) { return { presets: [ getPresetEnv() ], plugins: [ - require.resolve( '@babel/plugin-proposal-object-rest-spread' ), require.resolve( '@wordpress/warning/babel-plugin' ), [ require.resolve( '@wordpress/babel-plugin-import-jsx-pragma' ), @@ -76,9 +75,6 @@ module.exports = function( api ) { pragmaFrag: 'Fragment', }, ], - require.resolve( - '@babel/plugin-proposal-async-generator-functions' - ), maybeGetPluginTransformRuntime(), ].filter( Boolean ), }; diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 904cdd8fb2f82b..ec2f3124dcf5eb 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -27,18 +27,16 @@ ], "main": "index.js", "dependencies": { - "@babel/core": "^7.8.3", - "@babel/plugin-proposal-async-generator-functions": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-react-jsx": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.8.3", - "@babel/preset-env": "^7.8.3", - "@babel/runtime": "^7.8.3", + "@babel/core": "^7.9.0", + "@babel/plugin-transform-react-jsx": "^7.9.4", + "@babel/plugin-transform-runtime": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@babel/runtime": "^7.9.2", "@wordpress/babel-plugin-import-jsx-pragma": "file:../babel-plugin-import-jsx-pragma", "@wordpress/browserslist-config": "file:../browserslist-config", "@wordpress/element": "file:../element", "@wordpress/warning": "file:../warning", - "core-js": "^3.1.4" + "core-js": "^3.6.4" }, "publishConfig": { "access": "public" diff --git a/packages/babel-preset-default/test/__snapshots__/index.js.snap b/packages/babel-preset-default/test/__snapshots__/index.js.snap index 58bfb14629a285..9f7b9d7e009d99 100644 --- a/packages/babel-preset-default/test/__snapshots__/index.js.snap +++ b/packages/babel-preset-default/test/__snapshots__/index.js.snap @@ -11,9 +11,7 @@ describe('Babel preset default', function () { } function _foo() { - _foo = _wrapAsyncGenerator( - /*#__PURE__*/ - _regeneratorRuntime.mark(function _callee() { + _foo = _wrapAsyncGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { @@ -35,11 +33,7 @@ describe('Babel preset default', function () { return _foo.apply(this, arguments); } - test('support for async generator functions', - /*#__PURE__*/ - _asyncToGenerator( - /*#__PURE__*/ - _regeneratorRuntime.mark(function _callee2() { + test('support for async generator functions', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() { var generator; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { @@ -52,13 +46,12 @@ describe('Babel preset default', function () { case 4: _context2.t1 = _context2.sent; - _context2.t2 = { + (0, _context2.t0)(_context2.t1).toEqual({ done: false, value: 2 - }; - (0, _context2.t0)(_context2.t1).toEqual(_context2.t2); + }); - case 7: + case 6: case \\"end\\": return _context2.stop(); } diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index b97325fd9116ff..2e1b4d957e0132 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -114,124 +114,32 @@ } /** - * Button states and focus styles + * Focus styles. */ -// Buttons with rounded corners. -@mixin button-style__disabled { - opacity: 0.6; - cursor: default; -} - -@mixin button-style__active() { - outline: none; - background-color: $white; - color: $dark-gray-900; - box-shadow: inset 0 0 0 1px $light-gray-700, inset 0 0 0 2px $white; -} - -@mixin button-style__focus-active() { - box-shadow: 0 0 0 1px color($theme-color); - - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 1px solid transparent; -} - -// Switch. -@mixin switch-style__focus-active() { - box-shadow: 0 0 0 2px $white, 0 0 0 3px $dark-gray-300; +@mixin block-toolbar-button-style__focus() { + box-shadow: inset 0 0 0 $border-width-focus $theme-color, inset 0 0 0 4px $white; // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 2px solid transparent; - outline-offset: 2px; } - -/** - * Block Toolbar/Formatting Buttons - */ - -@mixin block-toolbar-button-style__focus() { - box-shadow: inset 0 0 0 2px color($theme-color), inset 0 0 0 4px $white; // Inner halo makes this work on top of a toggled button. - outline: 2px solid transparent; // Shown to Windows 10 High Contrast Mode. -} - - // Tabs, Inputs, Square buttons. @mixin input-style__neutral() { box-shadow: 0 0 0 transparent; transition: box-shadow 0.1s linear; - border-radius: $radius-round-rectangle; - border: $border-width solid $dark-gray-200; + border-radius: $radius-block-ui; + border: $border-width solid $medium-gray-text; @include reduce-motion("transition"); } -@mixin input-style__focus() { - color: $dark-gray-900; - border-color: $blue-medium-focus; - box-shadow: 0 0 0 1px $blue-medium-focus; - - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; -} - -// Square buttons. -@mixin square-style__neutral() { - outline-offset: -1px; -} - -@mixin square-style__focus() { - color: $dark-gray-900; - outline-offset: -1px; - outline: 1px dotted $dark-gray-500; -} - -// Menu items. -@mixin menu-style__neutral() { - border: none; - box-shadow: none; -} - -@mixin menu-style__hover() { - color: $dark-gray-900; - border: none; - box-shadow: none; - background: $light-gray-200; -} - -@mixin menu-style__focus() { - color: $dark-gray-900; - border: none; - box-shadow: none; - outline-offset: -2px; - outline: 1px dotted $dark-gray-500; -} -// Blocks in the Library. -@mixin block-style__disabled { - opacity: 0.6; - cursor: default; -} - -@mixin block-style__hover { - border-color: $theme-color; - color: $theme-color !important; -} - -@mixin block-style__focus() { - box-shadow: inset 0 0 0 1px $white, 0 0 0 2px $theme-color; - - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; -} - -@mixin block-style__is-active() { - color: $white; - background: $dark-gray-primary; +@mixin input-style__focus() { + border-color: color($theme-color); + box-shadow: 0 0 0 ($border-width-focus - $border-width) $theme-color; // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 2px solid transparent; - outline-offset: -2px; } @@ -416,7 +324,7 @@ } &:checked:focus { - box-shadow: 0 0 0 2px $medium-gray-text; + box-shadow: 0 0 0 $border-width-focus $medium-gray-text; } } @@ -459,7 +367,7 @@ } &:focus { - box-shadow: 0 0 0 2px $dark-gray-500; + box-shadow: 0 0 0 $border-width-focus $dark-gray-500; } } } diff --git a/packages/base-styles/_variables.scss b/packages/base-styles/_variables.scss index 106652e07e095d..1d33712cc44e65 100644 --- a/packages/base-styles/_variables.scss +++ b/packages/base-styles/_variables.scss @@ -16,6 +16,8 @@ $editor-line-height: 1.8; $big-font-size: 18px; $mobile-text-min-font-size: 16px; // Any font size below 16px will cause Mobile Safari to "zoom in" $border-width: 1px; +$border-width-focus: 1.5px; +$border-width-tab: 4px; /** * Grid System. @@ -75,7 +77,7 @@ $block-toolbar-height: $grid-unit-60; $mobile-block-toolbar-height: 44px; $block-padding: 14px; // Space between block footprint and focus boundaries. These are drawn outside the block footprint, and do not affect the size. $block-spacing: 4px; // Vertical space between blocks. -$block-side-ui-width: 28px; // Width of the movers/drag handle UI. +$block-side-ui-width: $button-size; // Width of the movers/drag handle UI. $block-side-ui-clearance: 2px; // Space between movers/drag handle UI, and block. $block-container-side-padding: $block-side-ui-width + $block-padding + 2 * $block-side-ui-clearance; // Total space left and right of the block footprint. $block-bg-padding--v: $block-padding + $block-spacing + $block-side-ui-clearance; // padding for Blocks with a background color (eg: paragraph or group) @@ -83,18 +85,13 @@ $block-bg-padding--h: $block-side-ui-width + $block-side-ui-clearance; // paddin $dimmed-opacity: 1; $block-edge-to-content: 16px; +$solid-border-space: 12px; +$dashed-border-space: 6px; $block-selected-margin: 3px; $block-selected-border-width: 1px; $block-selected-padding: 0; $block-selected-child-margin: 5px; -$block-selected-child-border-width: 1px; -$block-selected-child-padding: 0; $block-selected-to-content: $block-edge-to-content - $block-selected-margin - $block-selected-border-width; -$block-selected-child-to-content: $block-selected-to-content - $block-selected-child-margin - $block-selected-child-border-width; -$block-custom-appender-to-content: $block-selected-margin - $block-selected-border-width; -$block-media-container-to-content: $block-selected-child-margin + $block-selected-border-width; -$block-selected-vertical-margin-descendant: 2 * $block-selected-to-content; -$block-selected-vertical-margin-child: $block-edge-to-content; /** diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 6b6e7e1a5dbfed..b0b09d483dab9f 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -24,7 +24,7 @@ $z-layers: ( ".block-library-gallery-item__inline-menu": 20, ".block-editor-url-input__suggestions": 30, ".edit-post-layout__footer": 30, - ".block-editor-editor-skeleton__header": 30, + ".interface-interface-skeleton__header": 30, ".edit-site-header": 62, ".edit-widgets-header": 30, ".block-library-button__inline-link .block-editor-url-input__suggestions": 6, // URL suggestions for button block above sibling inserter @@ -62,7 +62,7 @@ $z-layers: ( // Show sidebar above wp-admin navigation bar for mobile viewports: // #wpadminbar { z-index: 99999 } - ".block-editor-editor-skeleton__sidebar": 100000, + ".interface-interface-skeleton__sidebar": 100000, ".edit-post-layout__toogle-sidebar-panel": 100000, ".edit-site-sidebar": 100000, ".edit-widgets-sidebar": 100000, @@ -73,7 +73,7 @@ $z-layers: ( // Show sidebar in greater than small viewports above editor related elements // but bellow #adminmenuback { z-index: 100 } - ".block-editor-editor-skeleton__sidebar {greater than small}": 90, + ".interface-interface-skeleton__sidebar {greater than small}": 90, ".edit-site-sidebar {greater than small}": 90, ".edit-widgets-sidebar {greater than small}": 90, @@ -108,7 +108,7 @@ $z-layers: ( ".components-autocomplete__results": 1000000, ".skip-to-selected-block": 100000, - ".block-editor-editor-skeleton__publish": 100000, + ".interface-interface-skeleton__actions": 100000, // Show NUX tips above popovers, wp-admin menus, submenus, and sidebar: ".nux-dot-tip": 1000001, diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 1288967c3cfdb6..03731fb72850fa 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 2.1.0 (2018-10-19) ### New Features diff --git a/packages/blob/package.json b/packages/blob/package.json index 86a19462a1e219..b364053b9474fe 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -20,9 +20,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/blob/src/index.js b/packages/blob/src/index.js index 61e90ef2b4c294..ef8ba7e2f7e394 100644 --- a/packages/blob/src/index.js +++ b/packages/blob/src/index.js @@ -4,7 +4,7 @@ const { createObjectURL, revokeObjectURL } = window.URL; /** - * @type {{[key: string]: File|undefined}} + * @type {Record} */ const cache = {}; diff --git a/packages/blob/tsconfig.json b/packages/blob/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/blob/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/block-directory/src/components/block-ratings/index.js b/packages/block-directory/src/components/block-ratings/index.js index c55cace300028c..c04f6c0fd7c5cd 100644 --- a/packages/block-directory/src/components/block-ratings/index.js +++ b/packages/block-directory/src/components/block-ratings/index.js @@ -13,13 +13,11 @@ export const BlockRatings = ( { rating, ratingCount } ) => ( ({ ratingCount }) diff --git a/packages/block-directory/src/components/block-ratings/stars.js b/packages/block-directory/src/components/block-ratings/stars.js index 843fca4385ce2a..a2d13b0aacb51b 100644 --- a/packages/block-directory/src/components/block-ratings/stars.js +++ b/packages/block-directory/src/components/block-ratings/stars.js @@ -17,7 +17,13 @@ function Stars( { rating } ) { const emptyStarCount = 5 - ( fullStarCount + halfStarCount ); return ( -
+
{ times( fullStarCount, ( i ) => ( - { sprintf( __( 'Authored by %s' ), author ) } + { sprintf( + /* translators: %s: author name. */ + __( 'Authored by %s' ), + author + ) } { sprintf( + /* translators: 1: number of blocks. 2: average rating. */ _n( - 'This author has %d block, with an average rating of %d.', - 'This author has %d blocks, with an average rating of %d.', + 'This author has %1$d block, with an average rating of %2$d.', + 'This author has %1$d blocks, with an average rating of %2$d.', authorBlockCount ), authorBlockCount, diff --git a/packages/block-directory/src/components/downloadable-block-header/index.js b/packages/block-directory/src/components/downloadable-block-header/index.js index 78ab2962e60ce8..dc835ed3295399 100644 --- a/packages/block-directory/src/components/downloadable-block-header/index.js +++ b/packages/block-directory/src/components/downloadable-block-header/index.js @@ -20,10 +20,13 @@ function DownloadableBlockHeader( { return (
{ icon.match( /\.(jpeg|jpg|gif|png)(?:\?.*)?$/ ) !== null ? ( - // translators: %s: Name of the plugin e.g: "Akismet". { ) : ( diff --git a/packages/block-directory/src/components/downloadable-block-info/index.js b/packages/block-directory/src/components/downloadable-block-info/index.js index b6865a5c9197e9..4c65e639554a9d 100644 --- a/packages/block-directory/src/components/downloadable-block-info/index.js +++ b/packages/block-directory/src/components/downloadable-block-info/index.js @@ -19,6 +19,7 @@ function DownloadableBlockInfo( {
{ sprintf( + /* translators: %s: number of active installations. */ _n( '%d active installation', '%d active installations', diff --git a/packages/block-directory/src/components/downloadable-blocks-panel/index.js b/packages/block-directory/src/components/downloadable-blocks-panel/index.js index 29d7cbb29ecac0..08d346d6774a58 100644 --- a/packages/block-directory/src/components/downloadable-blocks-panel/index.js +++ b/packages/block-directory/src/components/downloadable-blocks-panel/index.js @@ -55,6 +55,7 @@ function DownloadableBlocksPanel( { } const resultsFoundMessage = sprintf( + /* translators: %s: number of available blocks. */ _n( 'No blocks found in your library. We did find %d block available for download.', 'No blocks found in your library. We did find %d blocks available for download.', diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index e9ea7ce70d1cc0..820137bd973fa8 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -143,8 +143,9 @@ _Related_ _Parameters_ -- _blocks_ `(Array|Object)`: A block instance (object) or an array of blocks to be previewed. -- _viewportWidth_ `number`: Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview. Default: 700. +- _preview_ `Object`: options for how the preview should be shown +- _preview.blocks_ `(Array|Object)`: A block instance (object) or an array of blocks to be previewed. +- _preview.viewportWidth_ `number`: Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview. Default: 700. _Returns_ @@ -289,7 +290,7 @@ _Parameters_ _Returns_ -- `?string`: If fontSizeAttribute is set and an equal slug is found in fontSizes it returns the font size object for that slug. Otherwise, an object with just the size value based on customFontSize is returned. +- `?Object`: If fontSizeAttribute is set and an equal slug is found in fontSizes it returns the font size object for that slug. Otherwise, an object with just the size value based on customFontSize is returned. # **getFontSizeClass** @@ -303,6 +304,45 @@ _Returns_ - `string`: String with the class corresponding to the fontSize passed. The class is generated by appending 'has-' followed by fontSizeSlug in kebabCase and ending with '-font-size'. +# **getFontSizeObjectByValue** + +Returns the corresponding font size object for a given value. + +_Parameters_ + +- _fontSizes_ `Array`: Array of font size objects. +- _value_ `number`: Font size value. + +_Returns_ + +- `Object`: Font size object. + +# **getGradientSlugByValue** + +Retrieves the gradient slug per slug. + +_Parameters_ + +- _gradients_ `Array`: Gradient Palette +- _value_ `string`: Gradient value + +_Returns_ + +- `string`: Gradient slug. + +# **getGradientValueBySlug** + +Retrieves the gradient value per slug. + +_Parameters_ + +- _gradients_ `Array`: Gradient Palette +- _slug_ `string`: Gradient slug + +_Returns_ + +- `string`: Gradient value. + # **InnerBlocks** _Related_ diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 8a372addaa7fb7..e798509f52ae5b 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -22,7 +22,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:../a11y", "@wordpress/blob": "file:../blob", "@wordpress/blocks": "file:../blocks", @@ -39,6 +39,7 @@ "@wordpress/is-shallow-equal": "file:../is-shallow-equal", "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", + "@wordpress/priority-queue": "file:../priority-queue", "@wordpress/rich-text": "file:../rich-text", "@wordpress/token-list": "file:../token-list", "@wordpress/url": "file:../url", @@ -50,7 +51,7 @@ "dom-scroll-into-view": "^1.2.1", "inherits": "^2.0.3", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "react-autosize-textarea": "^3.0.2", "react-spring": "^8.0.19", "redux-multi": "^0.1.12", diff --git a/packages/block-editor/src/components/alignment-toolbar/index.js b/packages/block-editor/src/components/alignment-toolbar/index.js index 4e44ea01387b4e..2536e2e7e79b96 100644 --- a/packages/block-editor/src/components/alignment-toolbar/index.js +++ b/packages/block-editor/src/components/alignment-toolbar/index.js @@ -30,6 +30,7 @@ const DEFAULT_ALIGNMENT_CONTROLS = [ const POPOVER_PROPS = { position: 'bottom right', + isAlternate: true, }; export function AlignmentToolbar( props ) { diff --git a/packages/block-editor/src/components/alignment-toolbar/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/alignment-toolbar/test/__snapshots__/index.js.snap index fad7ec9756a73a..4c5300651aef32 100644 --- a/packages/block-editor/src/components/alignment-toolbar/test/__snapshots__/index.js.snap +++ b/packages/block-editor/src/components/alignment-toolbar/test/__snapshots__/index.js.snap @@ -50,6 +50,7 @@ exports[`AlignmentToolbar should allow custom alignment controls to be specified label="Change text alignment" popoverProps={ Object { + "isAlternate": true, "position": "bottom right", } } @@ -121,6 +122,7 @@ exports[`AlignmentToolbar should match snapshot 1`] = ` label="Change text alignment" popoverProps={ Object { + "isAlternate": true, "position": "bottom right", } } diff --git a/packages/block-editor/src/components/block-breadcrumb/style.scss b/packages/block-editor/src/components/block-breadcrumb/style.scss index db915e4d68f7bc..6dc47828019ad9 100644 --- a/packages/block-editor/src/components/block-breadcrumb/style.scss +++ b/packages/block-editor/src/components/block-breadcrumb/style.scss @@ -17,6 +17,7 @@ height: $button-size-small; line-height: $button-size-small; padding: 0; + position: relative; &:hover:not(:disabled) { text-decoration: underline; @@ -24,10 +25,20 @@ } &:focus { - @include square-style__focus(); - outline-offset: -2px; box-shadow: none; } + + &:focus::before { + content: ""; + display: block; + position: absolute; + border-radius: $radius-block-ui; + top: $border-width; + right: $border-width; + bottom: $border-width; + left: $border-width; + box-shadow: inset 0 0 0 $border-width-focus $theme-color; + } } .block-editor-block-breadcrumb__current { diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index e1b4d017e03d67..0a0eab0784ab19 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -32,7 +32,6 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true, } ) => { const slot = useSlot( InspectorAdvancedControls.slotName ); - const hasFills = Boolean( slot.fills && slot.fills.length ); if ( count > 1 ) { return ; @@ -60,6 +59,8 @@ const BlockInspector = ( { return null; } + const hasFills = Boolean( slot.fills && slot.fills.length ); + return (
diff --git a/packages/block-editor/src/components/block-list/block-elements.js b/packages/block-editor/src/components/block-list/block-elements.js new file mode 100644 index 00000000000000..1d71649a1cc479 --- /dev/null +++ b/packages/block-editor/src/components/block-list/block-elements.js @@ -0,0 +1,23 @@ +const ELEMENTS = [ + 'p', + 'div', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'ol', + 'ul', + 'li', + 'figure', + 'nav', + 'pre', + 'header', + 'section', + 'aside', + 'footer', + 'main', +]; + +export default ELEMENTS; diff --git a/packages/block-editor/src/components/block-list/block-wrapper.js b/packages/block-editor/src/components/block-list/block-wrapper.js index c728b2a8a01364..52f353428e23f0 100644 --- a/packages/block-editor/src/components/block-list/block-wrapper.js +++ b/packages/block-editor/src/components/block-list/block-wrapper.js @@ -27,6 +27,7 @@ import { isInsideRootBlock } from '../../utils/dom'; import useMovingAnimation from './moving-animation'; import { Context, BlockNodes } from './root-container'; import { BlockContext } from './block'; +import ELEMENTS from './block-elements'; const BlockComponent = forwardRef( ( { children, tagName = 'div', __unstableIsHtml, ...props }, wrapper ) => { @@ -101,7 +102,10 @@ const BlockComponent = forwardRef( // should only consider tabbables within editable display, since it // may be the wrapper itself or a side control which triggered the // focus event, don't unnecessary transition to an inner tabbable. - if ( wrapper.current.contains( document.activeElement ) ) { + if ( + document.activeElement && + isInsideRootBlock( wrapper.current, document.activeElement ) + ) { return; } @@ -109,9 +113,11 @@ const BlockComponent = forwardRef( const textInputs = focus.tabbable .find( wrapper.current ) .filter( isTextField ) - // Exclude inner blocks - .filter( ( node ) => - isInsideRootBlock( wrapper.current, node ) + // Exclude inner blocks and block appenders + .filter( + ( node ) => + isInsideRootBlock( wrapper.current, node ) && + ! node.closest( '.block-list-appender' ) ); // If reversed (e.g. merge via backspace), use the last in the set of @@ -199,7 +205,11 @@ const BlockComponent = forwardRef( { ...props } id={ blockElementId } ref={ wrapper } - className={ classnames( className, props.className ) } + className={ classnames( + className, + props.className, + wrapperProps && wrapperProps.className + ) } data-block={ clientId } data-type={ name } data-title={ blockTitle } @@ -209,6 +219,7 @@ const BlockComponent = forwardRef( onMouseLeave={ isSelected ? onMouseLeave : undefined } tabIndex="0" style={ { + ...( wrapperProps ? wrapperProps.style : {} ), ...( props.style || {} ), ...animationStyle, } } @@ -219,23 +230,7 @@ const BlockComponent = forwardRef( } ); -const elements = [ - 'p', - 'div', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'ol', - 'ul', - 'li', - 'figure', - 'nav', -]; - -const ExtendedBlockComponent = elements.reduce( ( acc, element ) => { +const ExtendedBlockComponent = ELEMENTS.reduce( ( acc, element ) => { acc[ element ] = forwardRef( ( props, ref ) => { return ; } ); diff --git a/packages/block-editor/src/components/block-list/block-wrapper.native.js b/packages/block-editor/src/components/block-list/block-wrapper.native.js index 69cbf52723125a..c97dae59059f54 100644 --- a/packages/block-editor/src/components/block-list/block-wrapper.native.js +++ b/packages/block-editor/src/components/block-list/block-wrapper.native.js @@ -1,20 +1,9 @@ -const elements = [ - 'p', - 'div', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'ol', - 'ul', - 'li', - 'figure', - 'nav', -]; +/** + * Internal dependencies + */ +import ELEMENTS from './block-elements'; -const ExtendedBlockComponent = elements.reduce( ( acc, element ) => { +const ExtendedBlockComponent = ELEMENTS.reduce( ( acc, element ) => { acc[ element ] = element; return acc; }, String ); diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 2ae2354576a6fe..448f4b74514565 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -62,7 +62,6 @@ function BlockListBlock( { enableAnimation, isNavigationMode, isMultiSelecting, - hasSelectedUI = true, } ) { // In addition to withSelect, we should favor using useSelect in this // component going forward to avoid leaking new props to the public API @@ -88,7 +87,7 @@ function BlockListBlock( { isDraggingBlocks && ( isSelected || isPartOfMultiSelection ); // Determine whether the block has props to apply to the wrapper. - if ( ! lightBlockWrapper && blockType.getEditWrapperProps ) { + if ( blockType.getEditWrapperProps ) { wrapperProps = { ...wrapperProps, ...blockType.getEditWrapperProps( attributes ), @@ -110,7 +109,6 @@ function BlockListBlock( { customClassName, 'wp-block block-editor-block-list__block', { - 'has-selected-ui': hasSelectedUI, 'has-warning': ! isValid || !! hasError || isUnregisteredBlock, 'is-selected': isSelected, 'is-highlighted': isHighlighted, diff --git a/packages/block-editor/src/components/block-list/block.native.js b/packages/block-editor/src/components/block-list/block.native.js index 2501094b59339c..918c414ba833ce 100644 --- a/packages/block-editor/src/components/block-list/block.native.js +++ b/packages/block-editor/src/components/block-list/block.native.js @@ -12,7 +12,6 @@ import { withDispatch, withSelect } from '@wordpress/data'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { getBlockType, - getUnregisteredTypeHandlerName, __experimentalGetAccessibleBlockLabel as getAccessibleBlockLabel, } from '@wordpress/blocks'; import { __ } from '@wordpress/i18n'; @@ -67,6 +66,7 @@ class BlockListBlock extends Component { this.props.onCaretVerticalPositionChange } clientId={ this.props.clientId } + contentStyle={ this.props.contentStyle } /> ); } @@ -79,104 +79,6 @@ class BlockListBlock extends Component { ); } - applySelectedBlockStyle() { - const { hasChildren, getStylesFromColorScheme } = this.props; - - const fullSolidBorderStyle = { - // define style for full border - ...styles.fullSolidBordered, - ...getStylesFromColorScheme( - styles.solidBorderColor, - styles.solidBorderColorDark - ), - }; - - if ( hasChildren ) { - // if block has children apply style for selected parent - return { ...styles.selectedParent, ...fullSolidBorderStyle }; - } - - /* selected block is one of below: - 1. does not have children - 2. is not on root list level - 3. is an emty group block on root or nested level */ - return { ...styles.selectedLeaf, ...fullSolidBorderStyle }; - } - - applyUnSelectedBlockStyle() { - const { - hasChildren, - isParentSelected, - isAncestorSelected, - hasParent, - getStylesFromColorScheme, - isLastBlock, - } = this.props; - - // if block does not have parent apply neutral or full - // margins depending if block has children or not - if ( ! hasParent ) { - return hasChildren ? styles.neutral : styles.full; - } - - if ( isParentSelected ) { - // parent of a block is selected - const dashedBorderStyle = { - // define style for dashed border - ...styles.dashedBordered, - ...getStylesFromColorScheme( - styles.dashedBorderColor, - styles.dashedBorderColorDark - ), - }; - - // return apply childOfSelected or childOfSelectedLeaf - // margins depending if block has children or not - return { - ...( hasChildren - ? styles.childOfSelected - : styles.childOfSelectedLeaf ), - ...dashedBorderStyle, - ...( ! isLastBlock && styles.marginVerticalChild ), - }; - } - - if ( isAncestorSelected ) { - // ancestor of a block is selected - return { - ...styles.descendantOfSelectedLeaf, - ...( hasChildren && { - ...styles.marginHorizontalNone, - ...styles.marginVerticalNone, - } ), - ...( ! isLastBlock && styles.marginVerticalDescendant ), - }; - } - - // if none of above condition are met return apply neutral or full - // margins depending if block has children or not - return hasChildren ? styles.neutral : styles.full; - } - - applyBlockStyle() { - const { isSelected, isDimmed } = this.props; - - return [ - isSelected - ? this.applySelectedBlockStyle() - : this.applyUnSelectedBlockStyle(), - isDimmed && styles.dimmed, - ]; - } - - applyToolbarStyle() { - const { hasChildren, isUnregisteredBlock } = this.props; - - if ( ! hasChildren || isUnregisteredBlock ) { - return styles.neutralToolbar; - } - } - render() { const { attributes, @@ -188,10 +90,18 @@ class BlockListBlock extends Component { order, title, parentId, + isDimmed, isTouchable, + onDeleteBlock, + horizontalDirection, hasParent, + isParentSelected, onSelect, showFloatingToolbar, + getStylesFromColorScheme, + marginVertical, + marginHorizontal, + isInnerBlockSelected, } = this.props; const accessibilityLabel = getAccessibleBlockLabel( @@ -200,13 +110,18 @@ class BlockListBlock extends Component { order + 1 ); + const accessible = ! ( isSelected || isInnerBlockSelected ); + return ( - + { showFloatingToolbar && ( { hasParent && ( @@ -225,8 +140,33 @@ class BlockListBlock extends Component { + { isSelected && ( + + ) } + { isParentSelected && ( + + ) } { isValid ? ( this.getBlockForType() ) : ( @@ -235,9 +175,13 @@ class BlockListBlock extends Component { icon={ icon } /> ) } - + { isSelected && ( - + ) } @@ -259,16 +203,15 @@ export default compose( [ getBlockRootClientId, getLowestCommonAncestorWithSelectedBlock, getBlockParents, - getBlockCount, + hasSelectedInnerBlock, } = select( 'core/block-editor' ); const order = getBlockIndex( clientId, rootClientId ); const isSelected = isBlockSelected( clientId ); - const isLastBlock = order === getBlockCount( rootClientId ) - 1; + const isInnerBlockSelected = hasSelectedInnerBlock( clientId ); const block = __unstableGetBlockWithoutInnerBlocks( clientId ); const { name, attributes, isValid } = block || {}; - const isUnregisteredBlock = name === getUnregisteredTypeHandlerName(); const blockType = getBlockType( name || 'core/missing' ); const title = blockType.title; const icon = blockType.icon; @@ -292,8 +235,6 @@ export default compose( [ ? parents[ commonAncestorIndex ] : parents[ parents.length - 1 ]; - const hasChildren = - ! isUnregisteredBlock && !! getBlockCount( clientId ); const hasParent = !! parentId; const isParentSelected = selectedBlockClientId && selectedBlockClientId === parentId; @@ -329,18 +270,16 @@ export default compose( [ title, attributes, blockType, - isLastBlock, isSelected, + isInnerBlockSelected, isValid, parentId, isParentSelected, firstToSelectId, - hasChildren, hasParent, isAncestorSelected, isTouchable, isDimmed, - isUnregisteredBlock, showFloatingToolbar, }; } ), diff --git a/packages/block-editor/src/components/block-list/block.native.scss b/packages/block-editor/src/components/block-list/block.native.scss index 85bae3528b130a..0d1c60fe4f1f19 100644 --- a/packages/block-editor/src/components/block-list/block.native.scss +++ b/packages/block-editor/src/components/block-list/block.native.scss @@ -2,18 +2,6 @@ flex: 1 1 auto; } -.fullSolidBordered { - border-width: $block-selected-border-width; - border-radius: 4px; - border-style: solid; -} - -.dashedBordered { - border-width: $block-selected-child-border-width; - border-radius: 2px; - border-style: dashed; -} - .solidBorderColor { border-color: $blue-wordpress; } @@ -34,31 +22,6 @@ opacity: $dimmed-opacity; } -.horizontalSpaceNone { - padding-left: 0; - padding-right: 0; - margin-left: 0; - margin-right: 0; -} - -.marginHorizontalNone { - margin-left: 0; - margin-right: 0; -} - -.marginVerticalDescendant { - margin-bottom: $block-selected-vertical-margin-descendant; -} - -.marginVerticalChild { - margin-bottom: $block-selected-vertical-margin-child; -} - -.marginVerticalNone { - margin-top: 0; - margin-bottom: 0; -} - .blockTitle { background-color: $gray; padding-left: 8px; @@ -66,44 +29,6 @@ padding-bottom: 4px; } -.neutral { - margin: 0; - border: 0; - padding: 0; -} - -.full { - margin: $block-edge-to-content; - border: 0; - padding: 0; -} - -.selectedLeaf { - margin: $block-selected-margin; - padding-left: $block-selected-to-content; - padding-right: $block-selected-to-content; - padding-top: $block-selected-to-content; -} - -.selectedParent { - margin: $block-selected-margin; - padding: 0; -} - -.childOfSelected { - margin: $block-selected-child-margin; - padding: 0; -} - -.childOfSelectedLeaf { - margin: $block-selected-child-margin; - padding: $block-selected-child-to-content; -} - -.descendantOfSelectedLeaf { - margin: $block-selected-child-to-content; -} - .aztec_container { flex: 1; } @@ -137,3 +62,25 @@ margin-left: -$block-edge-to-content; margin-right: -$block-edge-to-content; } + +.solidBorder { + position: absolute; + top: -$solid-border-space; + bottom: 0; + left: -$solid-border-space; + right: -$solid-border-space; + border-width: $block-selected-border-width; + border-radius: 4px; + border-style: solid; +} + +.dashedBorder { + position: absolute; + top: -$dashed-border-space; + bottom: -$dashed-border-space; + left: -$dashed-border-space; + right: -$dashed-border-space; + border-width: $block-selected-border-width; + border-radius: 2px; + border-style: dashed; +} diff --git a/packages/block-editor/src/components/block-list/breadcrumb.js b/packages/block-editor/src/components/block-list/breadcrumb.js index a47db75152663e..2151725040c461 100644 --- a/packages/block-editor/src/components/block-list/breadcrumb.js +++ b/packages/block-editor/src/components/block-list/breadcrumb.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { Toolbar, Button } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { useEffect, useRef } from '@wordpress/element'; import { BACKSPACE, DELETE } from '@wordpress/keycodes'; @@ -75,16 +75,14 @@ function BlockBreadcrumb( { return (
- - - +
); } diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 8905a17b58f22a..aeb21f503e78d4 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -29,7 +29,6 @@ function BlockList( rootClientId, isDraggable, renderAppender, - __experimentalUIParts = {}, __experimentalTagName = 'div', __experimentalAppenderTagName, __experimentalPassedProps = {}, @@ -73,9 +72,6 @@ function BlockList( element: ref, rootClientId, } ); - const __experimentalContainerProps = rootClientId - ? {} - : { hasPopover: __experimentalUIParts.hasPopover }; return ( { blockClientIds.map( ( clientId, index ) => { const isBlockInSelection = hasMultiSelection @@ -108,9 +103,6 @@ function BlockList( // otherwise there might be a small delay to trigger the animation. index={ index } enableAnimation={ enableAnimation } - hasSelectedUI={ - __experimentalUIParts.hasSelectedUI - } className={ clientId === targetClientId ? 'is-drop-target' diff --git a/packages/block-editor/src/components/block-list/index.native.js b/packages/block-editor/src/components/block-list/index.native.js index b43b6f82c94e0a..830f92559b5cea 100644 --- a/packages/block-editor/src/components/block-list/index.native.js +++ b/packages/block-editor/src/components/block-list/index.native.js @@ -72,13 +72,15 @@ export class BlockList extends Component { const { shouldShowInsertionPointBefore } = this.props; const willShowInsertionPoint = shouldShowInsertionPointBefore(); // call without the client_id argument since this is the appender return ( - - - + + + + + ); } @@ -96,8 +98,12 @@ export class BlockList extends Component { withFooter = true, isReadOnly, isRootList, + horizontal, + scrollEnabled, shouldShowInsertionPointBefore, shouldShowInsertionPointAfter, + marginVertical = styles.defaultBlock.marginTop, + marginHorizontal = styles.defaultBlock.marginLeft, } = this.props; const { blockToolbar, blockBorder, headerToolbar } = styles; @@ -105,9 +111,16 @@ export class BlockList extends Component { const forceRefresh = shouldShowInsertionPointBefore || shouldShowInsertionPointAfter; + const containerStyle = { + flex: isRootList ? 1 : 0, + // We set negative margin in the parent to remove the edge spacing between parent block and child block in ineer blocks + marginVertical: isRootList ? 0 : -marginVertical, + marginHorizontal: isRootList ? 0 : -marginHorizontal, + }; + return ( { this.shouldShowInnerBlockAppender() && ( - + - + + { shouldShowInsertionPointBefore( clientId ) && ( ) } @@ -170,10 +212,16 @@ export class BlockList extends Component { key={ clientId } showTitle={ false } clientId={ clientId } + marginVertical={ marginVertical } + marginHorizontal={ marginHorizontal } rootClientId={ this.props.rootClientId } onCaretVerticalPositionChange={ this.onCaretVerticalPositionChange } + horizontalDirection={ horizontalDirection } + contentStyle={ contentStyle } + onAddBlock={ onAddBlock } + onDeleteBlock={ onDeleteBlock } /> { ! this.shouldShowInnerBlockAppender() && shouldShowInsertionPointAfter( clientId ) && ( @@ -202,7 +250,7 @@ export class BlockList extends Component { } export default compose( [ - withSelect( ( select, { rootClientId } ) => { + withSelect( ( select, { rootClientId, __experimentalMoverDirection } ) => { const { getBlockCount, getBlockOrder, @@ -212,12 +260,16 @@ export default compose( [ getSettings, } = select( 'core/block-editor' ); + const horizontalDirection = + __experimentalMoverDirection === 'horizontal'; + const selectedBlockClientId = getSelectedBlockClientId(); const blockClientIds = getBlockOrder( rootClientId ); const insertionPoint = getBlockInsertionPoint(); const blockInsertionPointIsVisible = isBlockInsertionPointVisible(); const shouldShowInsertionPointBefore = ( clientId ) => { return ( + ! horizontalDirection && blockInsertionPointIsVisible && insertionPoint.rootClientId === rootClientId && // if list is empty, show the insertion point (via the default appender) @@ -228,6 +280,7 @@ export default compose( [ }; const shouldShowInsertionPointAfter = ( clientId ) => { return ( + ! horizontalDirection && blockInsertionPointIsVisible && insertionPoint.rootClientId === rootClientId && // if the insertion point is at the end of the list @@ -248,6 +301,7 @@ export default compose( [ selectedBlockClientId, isReadOnly, isRootList: rootClientId === undefined, + horizontalDirection, }; } ), withDispatch( ( dispatch ) => { diff --git a/packages/block-editor/src/components/block-list/insertion-point.js b/packages/block-editor/src/components/block-list/insertion-point.js index 842b1e40b73cbe..3d23ad7da4431b 100644 --- a/packages/block-editor/src/components/block-list/insertion-point.js +++ b/packages/block-editor/src/components/block-list/insertion-point.js @@ -180,7 +180,10 @@ export default function InsertionPoint( { } ) } > - +
diff --git a/packages/block-editor/src/components/block-list/moving-animation.js b/packages/block-editor/src/components/block-list/moving-animation.js index 6af4ba78ea6348..c4fa6a46fc2d14 100644 --- a/packages/block-editor/src/components/block-list/moving-animation.js +++ b/packages/block-editor/src/components/block-list/moving-animation.js @@ -10,7 +10,7 @@ import { useState, useLayoutEffect, useReducer, - useMemo, + useRef, } from '@wordpress/element'; import { useReducedMotion } from '@wordpress/compose'; import { getScrollContainer } from '@wordpress/dom'; @@ -69,12 +69,7 @@ function useMovingAnimation( } ); const previous = ref.current ? getAbsolutePosition( ref.current ) : null; - const scrollContainer = useMemo( () => { - if ( ! adjustScrolling ) { - return false; - } - return getScrollContainer( ref.current ); - }, [ adjustScrolling ] ); + const scrollContainer = useRef(); useLayoutEffect( () => { if ( triggeredAnimation ) { @@ -82,14 +77,17 @@ function useMovingAnimation( } }, [ triggeredAnimation ] ); useLayoutEffect( () => { + scrollContainer.current = getScrollContainer( ref.current ); if ( prefersReducedMotion ) { - if ( adjustScrolling && scrollContainer ) { + if ( adjustScrolling && scrollContainer.current && previous ) { // if the animation is disabled and the scroll needs to be adjusted, // just move directly to the final scroll position ref.current.style.transform = 'none'; const destination = getAbsolutePosition( ref.current ); - scrollContainer.scrollTop = - scrollContainer.scrollTop - previous.top + destination.top; + scrollContainer.current.scrollTop = + scrollContainer.current.scrollTop - + previous.top + + destination.top; } return; @@ -100,8 +98,10 @@ function useMovingAnimation( x: previous ? previous.left - destination.left : 0, y: previous ? previous.top - destination.top : 0, scrollTop: - previous && scrollContainer - ? scrollContainer.scrollTop - previous.top + destination.top + previous && scrollContainer.current + ? scrollContainer.current.scrollTop - + previous.top + + destination.top : 0, }; ref.current.style.transform = @@ -127,11 +127,12 @@ function useMovingAnimation( onFrame: ( props ) => { if ( adjustScrolling && - scrollContainer && + scrollContainer.current && ! prefersReducedMotion && props.y ) { - scrollContainer.scrollTop = transform.scrollTop + props.y; + scrollContainer.current.scrollTop = + transform.scrollTop + props.y; } }, } ); diff --git a/packages/block-editor/src/components/block-list/root-container.js b/packages/block-editor/src/components/block-list/root-container.js index 1ca09351851667..89569ab0a90444 100644 --- a/packages/block-editor/src/components/block-list/root-container.js +++ b/packages/block-editor/src/components/block-list/root-container.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -46,7 +51,7 @@ function onDragStart( event ) { } } -function RootContainer( { children, className, hasPopover = true }, ref ) { +function RootContainer( { children, className }, ref ) { const { selectedBlockClientId, hasMultiSelection, @@ -82,10 +87,10 @@ function RootContainer( { children, className, hasPopover = true }, ref ) { containerRef={ ref } > - { hasPopover ? : null } +
diff --git a/packages/block-editor/src/components/block-list/style.native.scss b/packages/block-editor/src/components/block-list/style.native.scss index 30b6ecc1dc5458..78994455ca0f30 100644 --- a/packages/block-editor/src/components/block-list/style.native.scss +++ b/packages/block-editor/src/components/block-list/style.native.scss @@ -4,6 +4,16 @@ background-color: #fff; } +.horizontalContentContainer { + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: stretch; + max-width: $content-width; + overflow: visible; + width: 100%; +} + .switch { flex-direction: row; justify-content: flex-start; @@ -47,9 +57,16 @@ height: 80px; } -.paddingToContent { - padding-left: $block-custom-appender-to-content; - padding-right: $block-custom-appender-to-content; +.defaultBlock { + margin: $block-edge-to-content; +} + +.defaultAppender { + margin: $block-edge-to-content; +} + +.innerAppender { + margin: $block-edge-to-content / 2; } .blockBorder { @@ -63,3 +80,7 @@ .blockToolbar { height: $mobile-block-toolbar-height; } + +.overflowVisible { + overflow: visible; +} diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index 1157c381e643bb..c6a7caeee341b2 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -21,33 +21,6 @@ margin: 0; } -/** - * General Post Content Layout - */ - -// Add side padding for the main block container, currently post_content. -// The purpose of this padding is to ensure that on small viewports, there is -// room for the block border that sits 14px ($block-padding) offset from the -// block footprint, as well as the side-UI. -.block-editor-block-list__layout { - padding-left: $block-padding; - padding-right: $block-padding; - position: relative; - - // Beyond the mobile breakpoint, compensate for side UI. - @include break-small() { - padding-left: $block-padding + $block-side-ui-width + $block-padding + $border-width * 2; - padding-right: $block-padding + $block-side-ui-width + $block-padding + $border-width * 2; - } - - // Don't propogate that padding to nested blocks. - .block-editor-block-list__layout { - padding-left: 0; - padding-right: 0; - } -} - - /** * Notices & Block Selected/Hover Styles. */ @@ -96,18 +69,18 @@ z-index: 1; pointer-events: none; content: ""; - top: 0; - bottom: 0; - left: 0; - right: 0; + top: $border-width; + bottom: $border-width; + left: $border-width; + right: $border-width; // 2px outside. - box-shadow: 0 0 0 2px $blue-medium-focus; - border-radius: $radius-block-ui; + box-shadow: 0 0 0 $border-width-focus $blue-medium-focus; + border-radius: $radius-block-ui - $border-width; // Border is outset, so so subtract the width to achieve correct radius. // Show a light color for dark themes. .is-dark-theme & { - box-shadow: 0 0 0 2px $blue-medium-focus-dark; + box-shadow: 0 0 0 $border-width-focus $blue-medium-focus-dark; } } } @@ -145,6 +118,7 @@ */ .block-editor-block-list__layout { + position: relative; // The primary indicator of selection in text is the native selection marker. // When selecting multiple blocks, we provide an additional selection indicator. @@ -158,17 +132,17 @@ z-index: 1; pointer-events: none; content: ""; - top: 0; - bottom: 0; - left: 0; - right: 0; + top: $border-width; + bottom: $border-width; + left: $border-width; + right: $border-width; } .is-block-content, // Floats. &::after { // Everything else. // 2px outside. - box-shadow: 0 0 0 2px $blue-medium-focus; - border-radius: $radius-block-ui; + box-shadow: 0 0 0 $border-width-focus $blue-medium-focus; + border-radius: $radius-block-ui - $border-width; // Border is outset, so so subtract the width to achieve correct radius. transition: box-shadow 0.2s ease-out; @include reduce-motion("transition"); @@ -177,7 +151,7 @@ // Show a lighter color for dark themes. .is-dark-theme & { - box-shadow: 0 0 0 2px $blue-medium-focus-dark; + box-shadow: 0 0 0 $border-width-focus $blue-medium-focus-dark; } } @@ -215,7 +189,7 @@ bottom: 0; left: 0; border-radius: $radius-block-ui; - box-shadow: 0 0 0 2px transparent; + box-shadow: 0 0 0 $border-width-focus transparent; transition: box-shadow 0.1s ease-in; @include reduce-motion("transition"); } @@ -316,18 +290,6 @@ clear: both; } - // Full-wide. - &[data-align="full"], - &.alignfull { - margin-left: -$block-padding; - margin-right: -$block-padding; - - @include break-small() { - margin-left: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; - margin-right: -$block-padding - $block-padding - $block-side-ui-width - $border-width - $border-width; - } - } - // Clear floats. &[data-clear="true"] { float: none; @@ -353,7 +315,7 @@ cursor: grab; } -// Insertion point (includes inbetween inserter and insertion indicator) +// Insertion point (includes inbetween/sibling inserter and insertion indicator) .block-editor-block-list__insertion-point { position: relative; z-index: z-index(".block-editor-block-list__insertion-point"); @@ -363,7 +325,7 @@ .block-editor-block-list__insertion-point-indicator { position: absolute; top: calc(50% - #{ $border-width }); - height: 2px; + height: $border-width-focus; left: 0; right: 0; background: theme(primary); @@ -428,27 +390,18 @@ animation: block-editor-inserter__toggle__fade-in-animation-delayed 1.2s ease; animation-fill-mode: forwards; @include reduce-motion("animation"); - - &:hover { - animation: block-editor-inserter__toggle__fade-in-animation 0.1s ease; - animation-fill-mode: forwards; - @include reduce-motion("animation"); - } } } @keyframes block-editor-inserter__toggle__fade-in-animation-delayed { 0% { opacity: 0; - transform: scale(0); } 80% { opacity: 0; - transform: scale(0); } 100% { opacity: 1; - transform: scale(1); } } @@ -524,21 +477,6 @@ padding-left: $block-toolbar-height; // Provide space for the mover control on full-wide items. } -.edit-post-header-toolbar__block-toolbar, -.block-editor-block-contextual-toolbar { - // Adapt the height of the toolbar items. - .components-toolbar { - height: $block-toolbar-height; - background: none; - } - - // Adapt the height of all toolbar buttons. - .components-button { - height: $block-toolbar-height; - } -} - - /** * Block Toolbar when contextual. */ @@ -563,30 +501,28 @@ display: block; z-index: z-index(".block-editor-block-list__breadcrumb"); - .components-toolbar { - display: flex; - border: none; - background: none; + // The button here has a special style to appear as a toolbar. + .components-button { + font-size: $default-font-size; + height: $block-toolbar-height - $border-width - $border-width; + padding: $grid-unit-15 $grid-unit-20; - // The button here has a special style to appear as a toolbar. - .components-button { - font-size: $default-font-size; - height: $block-toolbar-height; - padding: $grid-unit-15 $grid-unit-20; - - // Block UI appearance. - border: $border-width solid $dark-gray-primary; - border-radius: $radius-block-ui; - background-color: $white; - - // When button is focused, it receives a box-shadow instead of the border. - &:focus { - border: none; - box-shadow: inset 0 0 0 1px color($theme-color), 0 0 0 1px color($theme-color); - } - } + // Position this to align with the block toolbar. + position: relative; + top: -$border-width; + + // Block UI appearance. + box-shadow: 0 0 0 $border-width $dark-gray-primary; + border-radius: $radius-block-ui - $border-width; // Border is outset, so so subtract the width to achieve correct radius. + background-color: $white; - // @todo, it should have the block type icon here. + // Indent to align with block toolbar. + margin-left: $block-toolbar-height + $border-width; + + // When button is focused, it receives a box-shadow instead of the border. + &:focus { + box-shadow: 0 0 0 $border-width-focus $theme-color; + } } } @@ -648,11 +584,8 @@ // Position the block toolbar. .block-editor-block-list__breadcrumb, .block-editor-block-contextual-toolbar { - margin-bottom: $grid-unit-20; - - // @todo It should position the block transform dialog as the left margin of a block. It currently - // positions instead, the mover control. - margin-left: - $block-toolbar-height - $border-width; + margin-bottom: $grid-unit-15; + margin-left: - $block-toolbar-height; } .block-editor-block-contextual-toolbar[data-align="full"], @@ -669,3 +602,35 @@ .is-dragging-components-draggable .components-tooltip { display: none; } + + +// Add side padding for the canvas, currently edit-post-visual-editor. +// The purpose of this padding is to ensure that on small viewports, there is +// room for the block border that sits 14px ($block-padding) offset from the +// block footprint. +.block-editor-block-list__layout.is-root-container { + padding-left: $block-padding; + padding-right: $block-padding; + + @include break-small() { + padding-left: $block-side-ui-width; + padding-right: $block-side-ui-width; + } +} + +.block-editor-block-list__layout.is-root-container { + // Full-wide. (to account for the padddings added above) + // The first two rules account for the alignment wrapper div for the image block. + > div:not(.block-editor-block-list__block) > .block-editor-block-list__block[data-align="full"], + > div:not(.block-editor-block-list__block) > .block-editor-block-list__block.alignfull, + > .block-editor-block-list__block[data-align="full"], + > .block-editor-block-list__block.alignfull { + margin-left: -$block-padding; + margin-right: -$block-padding; + + @include break-small() { + margin-left: -$block-side-ui-width; + margin-right: -$block-side-ui-width; + } + } +} diff --git a/packages/block-editor/src/components/block-list/use-multi-selection.js b/packages/block-editor/src/components/block-list/use-multi-selection.js index 1e77f8711a51de..2d40464f2c0c56 100644 --- a/packages/block-editor/src/components/block-list/use-multi-selection.js +++ b/packages/block-editor/src/components/block-list/use-multi-selection.js @@ -105,8 +105,9 @@ export default function useMultiSelection( ref ) { ); if ( - ! blockNode.contains( startContainer ) || - ! blockNode.contains( endContainer ) + !! blockNode && + ( ! blockNode.contains( startContainer ) || + ! blockNode.contains( endContainer ) ) ) { selection.removeAllRanges(); } diff --git a/packages/block-editor/src/components/block-mobile-toolbar/index.native.js b/packages/block-editor/src/components/block-mobile-toolbar/index.native.js index 43a34c0466b54d..b4a56abc4df1b0 100644 --- a/packages/block-editor/src/components/block-mobile-toolbar/index.native.js +++ b/packages/block-editor/src/components/block-mobile-toolbar/index.native.js @@ -19,9 +19,17 @@ import styles from './style.scss'; import BlockMover from '../block-mover'; import { BlockSettingsButton } from '../block-settings'; -const BlockMobileToolbar = ( { clientId, onDelete, order } ) => ( +const BlockMobileToolbar = ( { + clientId, + onDelete, + order, + horizontalDirection, +} ) => ( - + @@ -48,13 +56,15 @@ export default compose( order: getBlockIndex( clientId ), }; } ), - withDispatch( ( dispatch, { clientId, rootClientId } ) => { + withDispatch( ( dispatch, { clientId, rootClientId, onDelete } ) => { const { removeBlock } = dispatch( 'core/block-editor' ); return { - onDelete: () => { - Keyboard.dismiss(); - removeBlock( clientId, rootClientId ); - }, + onDelete: + onDelete || + ( () => { + Keyboard.dismiss(); + removeBlock( clientId, rootClientId ); + } ), }; } ) )( BlockMobileToolbar ); diff --git a/packages/block-editor/src/components/block-mover/index.native.js b/packages/block-editor/src/components/block-mover/index.native.js index b572e21ee79dd8..5ca80153bee052 100644 --- a/packages/block-editor/src/components/block-mover/index.native.js +++ b/packages/block-editor/src/components/block-mover/index.native.js @@ -1,6 +1,7 @@ /** * External dependencies */ +import { I18nManager } from 'react-native'; import { first, last, partial, castArray } from 'lodash'; /** @@ -10,58 +11,123 @@ import { ToolbarButton } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { withSelect, withDispatch } from '@wordpress/data'; import { withInstanceId, compose } from '@wordpress/compose'; -import { arrowUp, arrowDown } from '@wordpress/icons'; +import { arrowUp, arrowDown, arrowLeft, arrowRight } from '@wordpress/icons'; + +const horizontalMover = { + backwardButtonIcon: arrowLeft, + forwardButtonIcon: arrowRight, + backwardButtonHint: __( 'Double tap to move the block to the left' ), + forwardButtonHint: __( 'Double tap to move the block to the right' ), + firstBlockTitle: __( 'Move block left' ), + lastBlockTitle: __( 'Move block right' ), + /* translators: accessibility text. %1: current block position (number). %2: next block position (number) */ + backwardButtonTitle: __( + 'Move block left from position %1$s to position %2$s' + ), + /* translators: accessibility text. %1: current block position (number). %2: next block position (number) */ + forwardButtonTitle: __( + 'Move block right from position %1$s to position %2$s' + ), +}; + +const verticalMover = { + backwardButtonIcon: arrowUp, + forwardButtonIcon: arrowDown, + backwardButtonHint: __( 'Double tap to move the block up' ), + forwardButtonHint: __( 'Double tap to move the block down' ), + firstBlockTitle: __( 'Move block up' ), + lastBlockTitle: __( 'Move block down' ), + /* translators: accessibility text. %1: current block position (number). %2: next block position (number) */ + backwardButtonTitle: __( 'Move block up from row %1$s to row %2$s' ), + /* translators: accessibility text. %1: current block position (number). %2: next block position (number) */ + forwardButtonTitle: __( 'Move block down from row %1$s to row %2$s' ), +}; const BlockMover = ( { isFirst, isLast, + isRTL, isLocked, onMoveDown, onMoveUp, firstIndex, rootClientId, + horizontalDirection, } ) => { + const { + backwardButtonIcon, + forwardButtonIcon, + backwardButtonHint, + forwardButtonHint, + firstBlockTitle, + lastBlockTitle, + } = horizontalDirection ? horizontalMover : verticalMover; + if ( isLocked || ( isFirst && isLast && ! rootClientId ) ) { return null; } + const switchButtonPropIfRTL = ( + isBackwardButton, + forwardButtonProp, + backwardButtonProp + ) => { + if ( isRTL && horizontalDirection ) { + // for RTL and horizontal direction switch prop between forward and backward button + if ( isBackwardButton ) { + return forwardButtonProp; // set forwardButtonProp for backward button + } + return backwardButtonProp; // set backwardButtonProp for forward button + } + + return isBackwardButton ? backwardButtonProp : forwardButtonProp; + }; + + const getMoverButtonTitle = ( isBackwardButton ) => { + const fromIndex = firstIndex + 1; // current position based on index + // for backwardButton decrease index (move left/up) for forwardButton increase index (move right/down) + const direction = isBackwardButton ? -1 : 1; + const toIndex = fromIndex + direction; // position after move + + const { backwardButtonTitle, forwardButtonTitle } = horizontalDirection + ? horizontalMover + : verticalMover; + + const buttonTitle = switchButtonPropIfRTL( + isBackwardButton, + forwardButtonTitle, + backwardButtonTitle + ); + + return sprintf( buttonTitle, fromIndex, toIndex ); + }; + + const getArrowIcon = ( isBackwardButton ) => + switchButtonPropIfRTL( + isBackwardButton, + forwardButtonIcon, + backwardButtonIcon + ); + return ( <> @@ -90,6 +156,7 @@ export default compose( firstIndex, isFirst: firstIndex === 0, isLast: lastIndex === blockOrder.length - 1, + isRTL: I18nManager.isRTL, isLocked: getTemplateLock( rootClientId ) === 'all', rootClientId, }; diff --git a/packages/block-editor/src/components/block-mover/mover-description.js b/packages/block-editor/src/components/block-mover/mover-description.js index 88e67e5ff4a715..fbdc10cb256138 100644 --- a/packages/block-editor/src/components/block-mover/mover-description.js +++ b/packages/block-editor/src/components/block-mover/mover-description.js @@ -58,8 +58,8 @@ export function getBlockMoverDescription( } if ( isFirst && isLast ) { - // translators: %s: Type of block (i.e. Text, Image etc) return sprintf( + // translators: %s: Type of block (i.e. Text, Image etc) __( 'Block %s is the only block, and cannot be moved' ), type ); diff --git a/packages/block-editor/src/components/block-mover/style.scss b/packages/block-editor/src/components/block-mover/style.scss index 83dcf5c459fe60..e60bbcaacdb902 100644 --- a/packages/block-editor/src/components/block-mover/style.scss +++ b/packages/block-editor/src/components/block-mover/style.scss @@ -21,6 +21,10 @@ flex-direction: row; } + .block-editor-block-mover__control { + height: $block-toolbar-height/2; + } + // Position the icons correctly. .components-toolbar .block-editor-block-mover__control-up { svg { diff --git a/packages/block-editor/src/components/block-navigation/style.scss b/packages/block-editor/src/components/block-navigation/style.scss index 6a6f47e7250561..abc9ad802ed08e 100644 --- a/packages/block-editor/src/components/block-navigation/style.scss +++ b/packages/block-editor/src/components/block-navigation/style.scss @@ -81,10 +81,12 @@ $tree-item-height: 36px; margin-right: 6px; } - &.is-selected, - &.is-selected:focus { + &.is-selected svg, + &.is-selected:focus svg { color: $white; background: $dark-gray-primary; + box-shadow: 0 0 0 $border-width $dark-gray-primary; + border-radius: $border-width; } } diff --git a/packages/block-editor/src/components/block-patterns/index.js b/packages/block-editor/src/components/block-patterns/index.js index 5ffd7f0727a164..729065ff06d04f 100644 --- a/packages/block-editor/src/components/block-patterns/index.js +++ b/packages/block-editor/src/components/block-patterns/index.js @@ -16,6 +16,7 @@ import { __, sprintf } from '@wordpress/i18n'; * Internal dependencies */ import BlockPreview from '../block-preview'; +import useAsyncList from './use-async-list'; function BlockPattern( { pattern, onClick } ) { const { title, content } = pattern; @@ -34,14 +35,26 @@ function BlockPattern( { pattern, onClick } ) { tabIndex={ 0 } >
- +
{ title }
); } +function BlockPatternPlaceholder( { pattern } ) { + const { title } = pattern; + + return ( +
+
+
{ title }
+
+ ); +} + function BlockPatterns( { patterns } ) { + const currentShownPatterns = useAsyncList( patterns ); const getBlockInsertionPoint = useSelect( ( select ) => { return select( 'core/block-editor' ).getBlockInsertionPoint; } ); @@ -69,13 +82,20 @@ function BlockPatterns( { patterns } ) { return (
- { patterns.map( ( pattern, index ) => ( - - ) ) } + { patterns.map( ( pattern, index ) => + currentShownPatterns[ index ] === pattern ? ( + + ) : ( + + ) + ) }
); } diff --git a/packages/block-editor/src/components/block-patterns/style.scss b/packages/block-editor/src/components/block-patterns/style.scss index f40f46b04001cb..3d668004212c98 100644 --- a/packages/block-editor/src/components/block-patterns/style.scss +++ b/packages/block-editor/src/components/block-patterns/style.scss @@ -1,11 +1,21 @@ .block-editor-patterns { - padding: 16px; + background: $light-gray-200; + padding: $grid-unit-20; +} + +.block-editor-patterns__item { + background: $white; + border-radius: $radius-block-ui; + + &.is-placeholder .block-editor-patterns__item-preview { + min-height: 100px; + } } .block-editor-patterns__item { - border-radius: 2px; + border-radius: $radius-block-ui; cursor: pointer; - margin-bottom: 16px; + margin-bottom: $grid-unit-20; border: 1px solid $light-gray-500; transition: all 0.05s ease-in-out; position: relative; @@ -16,15 +26,15 @@ } &:focus { - @include block-style__focus(); - } -} + box-shadow: inset 0 0 0 1px $white, 0 0 0 $border-width-focus $theme-color; -.block-editor-patterns__item-preview { - padding: $grid-unit-20; + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + } } .block-editor-patterns__item-title { text-align: center; padding: 10px 0; + padding: $grid-unit-20; } diff --git a/packages/block-editor/src/components/block-patterns/use-async-list.js b/packages/block-editor/src/components/block-patterns/use-async-list.js new file mode 100644 index 00000000000000..ab546f08b2c896 --- /dev/null +++ b/packages/block-editor/src/components/block-patterns/use-async-list.js @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { useEffect, useReducer } from '@wordpress/element'; +import { createQueue } from '@wordpress/priority-queue'; + +function listReducer( state, action ) { + if ( action.type === 'reset' && state.length !== 0 ) { + return []; + } + + if ( action.type === 'append' ) { + return [ ...state, action.item ]; + } + + return state; +} + +function useAsyncList( list ) { + const [ current, dispatch ] = useReducer( listReducer, [] ); + + useEffect( () => { + dispatch( { type: 'reset' } ); + const asyncQueue = createQueue(); + const append = ( index = 0 ) => () => { + if ( list.length <= index ) { + return; + } + dispatch( { type: 'append', item: list[ index ] } ); + asyncQueue.add( {}, append( index + 1 ) ); + }; + asyncQueue.add( {}, append( 0 ) ); + + return () => asyncQueue.reset(); + }, [ list ] ); + + return current; +} + +export default useAsyncList; diff --git a/packages/block-editor/src/components/block-preview/auto.js b/packages/block-editor/src/components/block-preview/auto.js index 81d26ada36d111..d819680b24053e 100644 --- a/packages/block-editor/src/components/block-preview/auto.js +++ b/packages/block-editor/src/components/block-preview/auto.js @@ -2,14 +2,17 @@ * WordPress dependencies */ import { Disabled } from '@wordpress/components'; -import { useResizeObserver } from '@wordpress/compose'; +import { useResizeObserver, pure } from '@wordpress/compose'; /** * Internal dependencies */ import BlockList from '../block-list'; -function AutoBlockPreview( { viewportWidth } ) { +// This is used to avoid rendering the block list if the sizes change. +const MemoizedBlockList = pure( BlockList ); + +function AutoBlockPreview( { viewportWidth, __experimentalPadding } ) { const [ containerResizeListener, { width: containerWidth }, @@ -19,24 +22,31 @@ function AutoBlockPreview( { viewportWidth } ) { { height: contentHeight }, ] = useResizeObserver(); + const scale = + ( containerWidth - 2 * __experimentalPadding ) / viewportWidth; + return (
{ containerResizeListener } { containtResizeListener } - +
); diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 522bd6014282bc..d49fad67dac347 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -1,19 +1,18 @@ /** * External dependencies */ -import { castArray, noop } from 'lodash'; +import { castArray } from 'lodash'; /** * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { useLayoutEffect, useReducer, useMemo } from '@wordpress/element'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ import BlockEditorProvider from '../provider'; -import ScaledBlockPreview from './scaled'; import AutoHeightBlockPreview from './auto'; /** @@ -21,52 +20,30 @@ import AutoHeightBlockPreview from './auto'; * * @see https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/block-preview/README.md * - * @param {Array|Object} blocks A block instance (object) or an array of blocks to be previewed. - * @param {number} viewportWidth Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview. Default: 700. + * @param {Object} preview options for how the preview should be shown + * @param {Array|Object} preview.blocks A block instance (object) or an array of blocks to be previewed. + * @param {number} preview.viewportWidth Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview. Default: 700. + * * @return {WPComponent} The component to be rendered. */ export function BlockPreview( { blocks, + __experimentalPadding = 0, viewportWidth = 700, - padding, - autoHeight = false, - __experimentalOnReady = noop, - __experimentalScalingDelay = 100, } ) { const settings = useSelect( ( select ) => select( 'core/block-editor' ).getSettings() ); const renderedBlocks = useMemo( () => castArray( blocks ), [ blocks ] ); - const [ recompute, triggerRecompute ] = useReducer( - ( state ) => state + 1, - 0 - ); - useLayoutEffect( triggerRecompute, [ blocks ] ); if ( ! blocks || blocks.length === 0 ) { return null; } return ( - { /* - * The key prop is used to force recomputing the preview - * by remounting the component, ScaledBlockPreview is not meant to - * be rerendered. - */ } - { autoHeight ? ( - - ) : ( - - ) } + ); } diff --git a/packages/block-editor/src/components/block-preview/scaled.js b/packages/block-editor/src/components/block-preview/scaled.js deleted file mode 100644 index 69496241fdb5ac..00000000000000 --- a/packages/block-editor/src/components/block-preview/scaled.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - -/** - * WordPress dependencies - */ -import { Disabled } from '@wordpress/components'; -import { useLayoutEffect, useState, useRef } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import BlockList from '../block-list'; -import { getBlockPreviewContainerDOMNode } from '../../utils/dom'; - -const getInlineStyles = ( scale, x, y, isReady, width ) => ( { - transform: `scale(${ scale })`, - visibility: isReady ? 'visible' : 'hidden', - left: x, - top: y, - width, -} ); - -function ScaledBlockPreview( { - blocks, - viewportWidth, - padding = 0, - onReady, - scalingDelay, -} ) { - const previewRef = useRef( null ); - - const [ isReady, setIsReady ] = useState( false ); - const [ previewScale, setPreviewScale ] = useState( 1 ); - const [ { x, y }, setPosition ] = useState( { x: 0, y: 0 } ); - - // Dynamically calculate the scale factor - useLayoutEffect( () => { - // Timer - required to account for async render of `BlockEditorProvider` - const timerId = setTimeout( () => { - const containerElement = previewRef.current; - if ( ! containerElement ) { - return; - } - - // Auxiliary vars used for onReady() callback. - let scale, - offsetX = 0, - offsetY = 0; - - // If we're previewing a single block, scale the preview to fit it. - if ( blocks.length === 1 ) { - const block = blocks[ 0 ]; - const previewElement = getBlockPreviewContainerDOMNode( - block.clientId - ); - if ( ! previewElement ) { - return; - } - - let containerElementRect = containerElement.getBoundingClientRect(); - containerElementRect = { - width: containerElementRect.width - padding * 2, - height: containerElementRect.height - padding * 2, - left: containerElementRect.left, - top: containerElementRect.top, - }; - const scaledElementRect = previewElement.getBoundingClientRect(); - - scale = - containerElementRect.width / scaledElementRect.width || 1; - offsetX = - -( scaledElementRect.left - containerElementRect.left ) * - scale + - padding; - offsetY = - containerElementRect.height > - scaledElementRect.height * scale - ? ( containerElementRect.height - - scaledElementRect.height * scale ) / - 2 + - padding - : 0; - - setPreviewScale( scale ); - setPosition( { x: offsetX, y: offsetY } ); - - // Hack: we need to reset the scaled elements margins - previewElement.style.marginTop = '0'; - } else { - const containerElementRect = containerElement.getBoundingClientRect(); - scale = containerElementRect.width / viewportWidth; - setPreviewScale( scale ); - } - - setIsReady( true ); - onReady( { - scale, - position: { x: offsetX, y: offsetY }, - previewContainerRef: previewRef, - - inlineStyles: getInlineStyles( - scale, - offsetX, - offsetY, - true, - viewportWidth - ), - } ); - }, scalingDelay ); - - // Cleanup - return () => { - if ( timerId ) { - window.clearTimeout( timerId ); - } - }; - }, [] ); - - if ( ! blocks || blocks.length === 0 ) { - return null; - } - - const previewStyles = getInlineStyles( - previewScale, - x, - y, - isReady, - viewportWidth - ); - - return ( -
- - - -
- ); -} - -export default ScaledBlockPreview; diff --git a/packages/block-editor/src/components/block-preview/style.scss b/packages/block-editor/src/components/block-preview/style.scss index 1628c178dbd059..c6ef74f6c28b60 100644 --- a/packages/block-editor/src/components/block-preview/style.scss +++ b/packages/block-editor/src/components/block-preview/style.scss @@ -9,9 +9,6 @@ width: 100%; overflow: hidden; - &.is-ready { - overflow: visible; - } } .block-editor-block-preview__content { @@ -35,13 +32,6 @@ overflow: visible; min-height: auto; - .block-editor-block-preview__container &.is-centered { - .block-editor-block-list__layout, - .block-editor-block-list__block { - padding: 0; - } - } - .block-editor-block-list__insertion-point, .block-editor-block-drop-zone, .reusable-block-indicator, diff --git a/packages/block-editor/src/components/block-settings-menu/index.js b/packages/block-editor/src/components/block-settings-menu/index.js index 278c3b79b0be32..e4c2c64682a32f 100644 --- a/packages/block-editor/src/components/block-settings-menu/index.js +++ b/packages/block-editor/src/components/block-settings-menu/index.js @@ -29,7 +29,7 @@ import BlockSettingsMenuControls from '../block-settings-menu-controls'; const POPOVER_PROPS = { className: 'block-editor-block-settings-menu__popover', position: 'bottom right', - noArrow: true, + isAlternate: true, }; export function BlockSettingsMenu( { clientIds } ) { diff --git a/packages/block-editor/src/components/block-styles/style.scss b/packages/block-editor/src/components/block-styles/style.scss index b84725cf707f35..0be7aab8113c90 100644 --- a/packages/block-editor/src/components/block-styles/style.scss +++ b/packages/block-editor/src/components/block-styles/style.scss @@ -12,18 +12,18 @@ overflow: hidden; border-radius: $radius-round-rectangle; padding: $grid-unit-05 * 1.5; - padding-top: calc(50% * 0.75 - #{ $grid-unit-05 } * 1.5); + display: flex; + flex-direction: column; &:focus { - @include block-style__focus(); - } + box-shadow: 0 0 0 $border-width-focus $theme-color; - &:hover { - @include block-style__hover; + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + } - .block-editor-block-styles__item-preview { - border-color: $theme-color; - } + &:hover .block-editor-block-styles__item-preview { + border-color: $theme-color; } &.is-active { @@ -46,14 +46,9 @@ display: flex; overflow: hidden; background: $white; - padding-top: 75%; - margin-top: -75%; - - .block-editor-block-preview__container { - padding-top: 0; - margin: 0; - margin-top: -75%; - } + align-items: center; + flex-grow: 1; + min-height: 80px; } .block-editor-block-styles__item-label { diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index e74cfc9ad94b76..eb2f7653af4f28 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -29,6 +29,11 @@ import BlockStyles from '../block-styles'; import BlockPreview from '../block-preview'; import BlockTypesList from '../block-types-list'; +const POPOVER_PROPS = { + position: 'bottom right', + isAlternate: true, +}; + export class BlockSwitcher extends Component { constructor() { super( ...arguments ); @@ -99,7 +104,7 @@ export class BlockSwitcher extends Component { return ( { @@ -114,6 +119,7 @@ export class BlockSwitcher extends Component { 1 === blocks.length ? __( 'Change block type or style' ) : sprintf( + /* translators: %s: number of blocks. */ _n( 'Change type of %d block', 'Change type of %d blocks', diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index 207acd240f0a45..17878a4db2963c 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -6,19 +6,6 @@ .block-editor-block-switcher__no-switcher-icon, .block-editor-block-switcher__toggle { position: relative; - - &::after { - display: block; - content: ""; - position: absolute; - bottom: 1px; - right: 0; - border-color: transparent; - border-style: solid; - border-width: 4px; - border-right-color: currentColor; - border-bottom-color: currentColor; - } } @@ -82,7 +69,6 @@ max-width: calc(340px * 2); display: flex; background: $white; - box-shadow: $shadow-popover; padding: 0; .components-menu-group { diff --git a/packages/block-editor/src/components/block-switcher/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/block-switcher/test/__snapshots__/index.js.snap index ab8ff515675b62..a7a9d6dd1bbed0 100644 --- a/packages/block-editor/src/components/block-switcher/test/__snapshots__/index.js.snap +++ b/packages/block-editor/src/components/block-switcher/test/__snapshots__/index.js.snap @@ -29,7 +29,12 @@ exports[`BlockSwitcher should render enabled block switcher with multi block whe @@ -39,7 +44,12 @@ exports[`BlockSwitcher should render switcher with blocks 1`] = ` diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 04a13cc498e27e..d2dc21fff63c20 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -26,7 +26,6 @@ export default function BlockToolbar( { hideDragHandle } ) { isValid, mode, moverDirection, - hasMovers = true, } = useSelect( ( select ) => { const { getBlockMode, @@ -40,7 +39,7 @@ export default function BlockToolbar( { hideDragHandle } ) { const selectedBlockClientId = selectedBlockClientIds[ 0 ]; const blockRootClientId = getBlockRootClientId( selectedBlockClientId ); - const { __experimentalMoverDirection, __experimentalUIParts = {} } = + const { __experimentalMoverDirection } = getBlockListSettings( blockRootClientId ) || {}; return { @@ -57,7 +56,6 @@ export default function BlockToolbar( { hideDragHandle } ) { ? getBlockMode( selectedBlockClientIds[ 0 ] ) : null, moverDirection: __experimentalMoverDirection, - hasMovers: __experimentalUIParts.hasMovers, }; }, [] ); @@ -74,8 +72,7 @@ export default function BlockToolbar( { hideDragHandle } ) { const displayHeaderToolbar = useViewportMatch( 'medium', '<' ) || hasFixedToolbar; - const shouldShowMovers = - displayHeaderToolbar || ( showMovers && hasMovers ); + const shouldShowMovers = displayHeaderToolbar || showMovers; if ( blockClientIds.length === 0 ) { return null; diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index d03ae73ec64351..6cc37f4d9309d4 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -44,130 +44,11 @@ .block-editor-block-toolbar, .block-editor-format-toolbar { - // Toolbar buttons. - .components-button { - position: relative; - - // Give all buttons extra padding to fit text. - padding-left: $grid-unit-20; - padding-right: $grid-unit-20; - - // Don't show the focus inherited by the Button component. - &:focus:enabled { - box-shadow: none; - outline: none; - } - - // Focus and toggle pseudo elements. - &::before { - content: ""; - position: absolute; - display: block; - border-radius: $radius-block-ui; - height: 32px; - min-width: 32px; - - // Position the focus rectangle. - left: $grid-unit-10; - right: $grid-unit-10; - } - - svg { - position: relative; - - // Center the icon inside. - margin-left: auto; - margin-right: auto; - } - - // Toggled style. - &.is-pressed { - color: $white; - - &::before { - background: $dark-gray-primary; - } - } - - // Focus style. - &:focus::before { - @include block-toolbar-button-style__focus(); - } - - // Ensure the icon buttons remain square. - &.has-icon { - // Reduce the default padding when a button only has an icon. - padding-left: $grid-unit-10; - padding-right: $grid-unit-10; - - min-width: $block-toolbar-height; - justify-content: center; - } - - // @todo: We should extract the tabs styles to the tabs component itself - &.components-tab-button { - font-weight: 500; - - span { - display: inline-block; - padding-left: 0; - padding-right: 0; - position: relative; - } - } - } - - // Size multiple sequential buttons to be optically balanced. - // Icons are 36px, as set by a 24px icon and 12px padding. - .components-toolbar div > .components-button.has-icon { - min-width: $block-toolbar-height - $grid-unit-15; - padding-left: $grid-unit-15 / 2; // 6px. - padding-right: $grid-unit-15 / 2; - - svg { - min-width: $button-size-small; // This is the optimal icon size, and we size the whole button after this. - } - - &::before { - left: 2px; - right: 2px; - } - } - - // First button in a group. - .components-toolbar div:first-child .components-button { - min-width: $block-toolbar-height - $grid-unit-15 / 2; - padding-left: $grid-unit-15 - $border-width; - padding-right: $grid-unit-15 / 2; - - &::before { - left: $grid-unit-10; - right: 2px; - } - } - - // Last button in a group. - .components-toolbar div:last-child .components-button { - min-width: $block-toolbar-height - $grid-unit-15 / 2; - padding-left: $grid-unit-15 / 2; - padding-right: $grid-unit-15 - $border-width; - - &::before { - left: 2px; - right: $grid-unit-10; - } - } - - // Single buttons should remain 48px. - .components-toolbar div:first-child:last-child > .components-button { - min-width: $block-toolbar-height; - padding-left: $grid-unit-15; - padding-right: $grid-unit-15; - - &::before { - left: $grid-unit-10; - right: $grid-unit-10; - } + // Override Toolbar buttons size. + .components-toolbar-group, + .components-toolbar { + display: flex; + flex-wrap: nowrap; } } @@ -202,10 +83,19 @@ top: -1px; transform: translateX(-48px); user-select: none; - z-index: -1; // This makes it slide out from underneath the toolbar. } } + // Explicitly color the background of the switcher to "cover" the mover control as it animates out. + .block-editor-block-toolbar__block-switcher-wrapper { + background: $white; + border-left: $border-width solid; + border-radius: 0 0 $radius-block-ui $radius-block-ui; + position: relative; + z-index: 1; + margin-left: -$border-width; + } + .block-editor-block-toolbar__mover-trigger-wrapper:not(:empty) { @include break-medium() { background-color: $white; diff --git a/packages/block-editor/src/components/button-block-appender/index.js b/packages/block-editor/src/components/button-block-appender/index.js index 91de376e909117..385666e257e2e0 100644 --- a/packages/block-editor/src/components/button-block-appender/index.js +++ b/packages/block-editor/src/components/button-block-appender/index.js @@ -8,7 +8,7 @@ import classnames from 'classnames'; */ import { Button, Tooltip, VisuallyHidden } from '@wordpress/components'; import { _x, sprintf } from '@wordpress/i18n'; -import { Icon, plus } from '@wordpress/icons'; +import { Icon, create } from '@wordpress/icons'; /** * Internal dependencies @@ -22,6 +22,7 @@ function ButtonBlockAppender( { } ) { return ( { let label; if ( hasSingleBlockType ) { - // translators: %s: the name of the block when there is only one label = sprintf( + // translators: %s: the name of the block when there is only one _x( 'Add %s', 'directly add the only allowed block' ), blockTitle ); @@ -63,7 +64,7 @@ function ButtonBlockAppender( { label={ label } > { label } - + ); diff --git a/packages/block-editor/src/components/button-block-appender/index.native.js b/packages/block-editor/src/components/button-block-appender/index.native.js index 692c013a69f729..4a3be1a5b5ac06 100644 --- a/packages/block-editor/src/components/button-block-appender/index.native.js +++ b/packages/block-editor/src/components/button-block-appender/index.native.js @@ -20,6 +20,7 @@ function ButtonBlockAppender( { rootClientId, getStylesFromColorScheme, showSeparator, + onAddBlock, } ) { const appenderStyle = { ...styles.appender, @@ -39,7 +40,7 @@ function ButtonBlockAppender( { rootClientId={ rootClientId } renderToggle={ ( { onToggle, disabled, isOpen } ) => (
); }, - migrate: colorsMigration, }, { attributes: { @@ -253,7 +397,7 @@ const deprecated = [
); }, - migrate: colorsMigration, + migrate: oldColorsMigration, }, { attributes: { @@ -287,7 +431,7 @@ const deprecated = [
); }, - migrate: colorsMigration, + migrate: oldColorsMigration, }, ]; diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index a7e33c4c3430d2..38b5b43f96d684 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -8,54 +8,26 @@ import classnames from 'classnames'; */ import { __ } from '@wordpress/i18n'; import { useCallback, useState } from '@wordpress/element'; -import { compose } from '@wordpress/compose'; import { KeyboardShortcuts, PanelBody, RangeControl, TextControl, ToggleControl, - withFallbackStyles, ToolbarButton, ToolbarGroup, Popover, } from '@wordpress/components'; import { BlockControls, - __experimentalUseGradient, - ContrastChecker, InspectorControls, - __experimentalPanelColorGradientSettings as PanelColorGradientSettings, RichText, - withColors, + __experimentalBlock as Block, __experimentalLinkControl as LinkControl, } from '@wordpress/block-editor'; import { rawShortcut, displayShortcut } from '@wordpress/keycodes'; import { link } from '@wordpress/icons'; -const { getComputedStyle } = window; - -const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => { - const { textColor, backgroundColor } = ownProps; - const backgroundColorValue = backgroundColor && backgroundColor.color; - const textColorValue = textColor && textColor.color; - //avoid the use of querySelector if textColor color is known and verify if node is available. - const textNode = - ! textColorValue && node - ? node.querySelector( '[contenteditable="true"]' ) - : null; - return { - fallbackBackgroundColor: - backgroundColorValue || ! node - ? undefined - : getComputedStyle( node ).backgroundColor, - fallbackTextColor: - textColorValue || ! textNode - ? undefined - : getComputedStyle( textNode ).color, - }; -} ); - const NEW_TAB_REL = 'noreferrer noopener'; const MIN_BORDER_RADIUS_VALUE = 0; const MAX_BORDER_RADIUS_VALUE = 50; @@ -141,18 +113,7 @@ function URLPicker( { ); } -function ButtonEdit( { - attributes, - backgroundColor, - textColor, - setBackgroundColor, - setTextColor, - fallbackBackgroundColor, - fallbackTextColor, - setAttributes, - className, - isSelected, -} ) { +function ButtonEdit( { attributes, setAttributes, className, isSelected } ) { const { borderRadius, linkTarget, @@ -186,33 +147,19 @@ function ButtonEdit( { }, [ rel, setAttributes ] ); - const { - gradientClass, - gradientValue, - setGradient, - } = __experimentalUseGradient(); return ( -
+ <> setAttributes( { text: value } ) } withoutInteractiveFormatting - className={ classnames( 'wp-block-button__link', { - 'has-background': backgroundColor.color || gradientValue, - [ backgroundColor.class ]: - ! gradientValue && backgroundColor.class, - 'has-text-color': textColor.color, - [ textColor.class ]: textColor.class, - [ gradientClass ]: gradientClass, + className={ classnames( className, 'wp-block-button__link', { 'no-border-radius': borderRadius === 0, } ) } style={ { - ...( ! backgroundColor.color && gradientValue - ? { background: gradientValue } - : { backgroundColor: backgroundColor.color } ), - color: textColor.color, borderRadius: borderRadius ? borderRadius + 'px' : undefined, @@ -226,35 +173,6 @@ function ButtonEdit( { onToggleOpenInNewTab={ onToggleOpenInNewTab } /> - - - -
+ ); } -export default compose( [ - withColors( 'backgroundColor', { textColor: 'color' } ), - applyFallbackStyles, -] )( ButtonEdit ); +export default ButtonEdit; diff --git a/packages/block-library/src/button/edit.native.js b/packages/block-library/src/button/edit.native.js index be1215a9cdbca0..c0bd9b51fa3be3 100644 --- a/packages/block-library/src/button/edit.native.js +++ b/packages/block-library/src/button/edit.native.js @@ -24,7 +24,7 @@ import { BottomSheet, } from '@wordpress/components'; import { Component } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; +import { withSelect, withDispatch } from '@wordpress/data'; import { isURL, prependHTTP } from '@wordpress/url'; import { link, external } from '@wordpress/icons'; @@ -52,8 +52,10 @@ class ButtonEdit extends Component { this.onChangeURL = this.onChangeURL.bind( this ); this.onClearSettings = this.onClearSettings.bind( this ); this.onLayout = this.onLayout.bind( this ); + this.dismissSheet = this.dismissSheet.bind( this ); this.getURLFromClipboard = this.getURLFromClipboard.bind( this ); - this.onToggleLinkSettings = this.onToggleLinkSettings.bind( this ); + this.onShowLinkSettings = this.onShowLinkSettings.bind( this ); + this.onHideLinkSettings = this.onHideLinkSettings.bind( this ); this.onToggleButtonFocus = this.onToggleButtonFocus.bind( this ); this.setRef = this.setRef.bind( this ); @@ -200,9 +202,12 @@ class ButtonEdit extends Component { } ); } - onToggleLinkSettings() { - const { isLinkSheetVisible } = this.state; - this.setState( { isLinkSheetVisible: ! isLinkSheetVisible } ); + onShowLinkSettings() { + this.setState( { isLinkSheetVisible: true } ); + } + + onHideLinkSettings() { + this.setState( { isLinkSheetVisible: false } ); } onToggleButtonFocus( value ) { @@ -228,6 +233,13 @@ class ButtonEdit extends Component { this.setState( { maxWidth: width - buttonSpacing } ); } + dismissSheet() { + this.setState( { + isLinkSheetVisible: false, + } ); + this.props.closeSettingsBottomSheet(); + } + getLinkSettings( url, rel, linkTarget, isCompatibleWithSettings ) { return ( <> @@ -237,6 +249,7 @@ class ButtonEdit extends Component { value={ url || '' } valuePlaceholder={ __( 'Add URL' ) } onChange={ this.onChangeURL } + onSubmit={ this.dismissSheet } autoCapitalize="none" autoCorrect={ false } // eslint-disable-next-line jsx-a11y/no-autofocus @@ -263,6 +276,7 @@ class ButtonEdit extends Component { value={ rel || '' } valuePlaceholder={ __( 'None' ) } onChange={ this.onChangeLinkRel } + onSubmit={ this.dismissSheet } autoCapitalize="none" autoCorrect={ false } separatorType={ @@ -378,9 +392,9 @@ class ButtonEdit extends Component { @@ -389,7 +403,7 @@ class ButtonEdit extends Component { { this.getLinkSettings( url, rel, linkTarget ) } @@ -447,4 +461,11 @@ export default compose( [ hasParents, }; } ), + withDispatch( ( dispatch ) => { + return { + closeSettingsBottomSheet() { + dispatch( 'core/edit-post' ).closeGeneralSidebar(); + }, + }; + } ), ] )( ButtonEdit ); diff --git a/packages/block-library/src/button/editor.scss b/packages/block-library/src/button/editor.scss index db005f644042ce..efed2d4910b1a1 100644 --- a/packages/block-library/src/button/editor.scss +++ b/packages/block-library/src/button/editor.scss @@ -13,10 +13,7 @@ .wp-block-button { position: relative; - - [contenteditable] { - cursor: text; - } + cursor: text; // Make placeholder text white unless custom colors or outline versions are chosen. &:not(.has-text-color):not(.is-style-outline) [data-rich-text-placeholder]::after { @@ -24,7 +21,7 @@ } // Add outline to button on focus to indicate focus-state - .block-editor-rich-text__editable:focus { + &:focus { box-shadow: 0 0 0 1px $white, 0 0 0 3px $blue-medium-500; // Windows' High Contrast mode will show this outline, but not the box-shadow. @@ -33,7 +30,7 @@ } // Increase placeholder opacity to meet contrast ratios. - [data-rich-text-placeholder]::after { + &[data-rich-text-placeholder]::after { opacity: 0.8; } } diff --git a/packages/block-library/src/button/index.js b/packages/block-library/src/button/index.js index f71e2187de083f..fab563649938fb 100644 --- a/packages/block-library/src/button/index.js +++ b/packages/block-library/src/button/index.js @@ -34,6 +34,8 @@ export const settings = { align: true, alignWide: false, reusable: false, + lightBlockWrapper: true, + __experimentalColor: { gradients: true }, }, parent: [ 'core/buttons' ], styles: [ diff --git a/packages/block-library/src/button/save.js b/packages/block-library/src/button/save.js index 542222f49e98c2..6a7aeb8088c1a7 100644 --- a/packages/block-library/src/button/save.js +++ b/packages/block-library/src/button/save.js @@ -6,54 +6,16 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { - RichText, - getColorClassName, - __experimentalGetGradientClass, -} from '@wordpress/block-editor'; +import { RichText } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { - backgroundColor, - borderRadius, - customBackgroundColor, - customTextColor, - customGradient, - linkTarget, - gradient, - rel, - text, - textColor, - title, - url, - } = attributes; - - const textClass = getColorClassName( 'color', textColor ); - const backgroundClass = - ! customGradient && - getColorClassName( 'background-color', backgroundColor ); - const gradientClass = __experimentalGetGradientClass( gradient ); + const { borderRadius, linkTarget, rel, text, title, url } = attributes; const buttonClasses = classnames( 'wp-block-button__link', { - 'has-text-color': textColor || customTextColor, - [ textClass ]: textClass, - 'has-background': - backgroundColor || - customBackgroundColor || - customGradient || - gradient, - [ backgroundClass ]: backgroundClass, 'no-border-radius': borderRadius === 0, - [ gradientClass ]: gradientClass, } ); const buttonStyle = { - background: customGradient ? customGradient : undefined, - backgroundColor: - backgroundClass || customGradient || gradient - ? undefined - : customBackgroundColor, - color: textClass ? undefined : customTextColor, borderRadius: borderRadius ? borderRadius + 'px' : undefined, }; @@ -62,17 +24,15 @@ export default function save( { attributes } ) { // A title will no longer be assigned for new or updated button block links. return ( -
- -
+ ); } diff --git a/packages/block-library/src/button/style.scss b/packages/block-library/src/button/style.scss index 7bbe8900b8dc29..69c651422c517f 100644 --- a/packages/block-library/src/button/style.scss +++ b/packages/block-library/src/button/style.scss @@ -2,23 +2,10 @@ $blocks-button__height: 56px; .wp-block-button { color: $white; - - &.aligncenter { - text-align: center; - } - - &.alignright { - /*rtl:ignore*/ - text-align: right; - } -} - -.wp-block-button__link { background-color: $dark-gray-700; border: none; border-radius: $blocks-button__height / 2; box-shadow: none; - color: inherit; cursor: pointer; display: inline-block; font-size: $big-font-size; @@ -32,26 +19,29 @@ $blocks-button__height: 56px; &:focus, &:active, &:visited { - color: inherit; + color: $white; } -} -.wp-gs .wp-block-button__link:not(.has-background) { - background-color: var(--wp--color--primary); + &.aligncenter { + text-align: center; + } + + &.alignright { + /*rtl:ignore*/ + text-align: right; + } } -.is-style-squared .wp-block-button__link { +.wp-block-button.is-style-squared { border-radius: 0; } -.no-border-radius.wp-block-button__link { + +.wp-block-button.no-border-radius { border-radius: 0 !important; } -.is-style-outline { +.wp-block-button.is-style-outline { color: $dark-gray-700; - - .wp-block-button__link { - background-color: transparent; - border: 2px solid; - } + background-color: transparent; + border: 2px solid; } diff --git a/packages/block-library/src/buttons/edit.js b/packages/block-library/src/buttons/edit.js index 15590ca49e713b..d9b76ed8f1bcb6 100644 --- a/packages/block-library/src/buttons/edit.js +++ b/packages/block-library/src/buttons/edit.js @@ -13,9 +13,6 @@ import { name as buttonBlockName } from '../button/'; const ALLOWED_BLOCKS = [ buttonBlockName ]; const BUTTONS_TEMPLATE = [ [ 'core/button' ] ]; -const UI_PARTS = { - hasSelectedUI: false, -}; // Inside buttons block alignment options are not supported. const alignmentHooksSetting = { @@ -29,7 +26,6 @@ function ButtonsEdit( { className } ) { diff --git a/packages/block-library/src/buttons/style.scss b/packages/block-library/src/buttons/style.scss index f82a5191316863..3d4843d5ca3e9b 100644 --- a/packages/block-library/src/buttons/style.scss +++ b/packages/block-library/src/buttons/style.scss @@ -1,7 +1,15 @@ -.wp-block-buttons .wp-block-button { +// Increased specificity to override blocks default margin. +.wp-block-buttons .wp-block-button.wp-block-button { display: inline-block; - margin: $grid-unit-05; + margin-right: $grid-unit-10; + margin-bottom: $grid-unit-10; } + +.wp-block-buttons.alignright .wp-block-button { + margin-right: none; + margin-left: $grid-unit-10; +} + .wp-block-buttons.aligncenter { text-align: center; } diff --git a/packages/block-library/src/code/edit.js b/packages/block-library/src/code/edit.js index 5aa4b337bd3f12..03ebb86b4ec71a 100644 --- a/packages/block-library/src/code/edit.js +++ b/packages/block-library/src/code/edit.js @@ -6,17 +6,22 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { PlainText } from '@wordpress/block-editor'; +import { + PlainText, + __experimentalBlock as Block, +} from '@wordpress/block-editor'; -export default function CodeEdit( { attributes, setAttributes, className } ) { +export default function CodeEdit( { attributes, setAttributes } ) { return ( -
+ setAttributes( { content } ) } placeholder={ __( 'Write code…' ) } aria-label={ __( 'Code' ) } /> - </div> + </Block.pre> ); } diff --git a/packages/block-library/src/code/editor.scss b/packages/block-library/src/code/editor.scss index 5a4d5ee76e1acc..bc47a4f35ee9da 100644 --- a/packages/block-library/src/code/editor.scss +++ b/packages/block-library/src/code/editor.scss @@ -1,14 +1,4 @@ -.wp-block-code .block-editor-plain-text { - font-family: $editor-html-font; - color: $dark-gray-800; - - /* Fonts smaller than 16px causes mobile safari to zoom. */ - font-size: $mobile-text-min-font-size; - @include break-small { - font-size: $default-font-size; - } - - &:focus { - box-shadow: none; - } +.wp-block-code > code { + // PlainText cannot be an inline element yet. + display: block; } diff --git a/packages/block-library/src/code/index.js b/packages/block-library/src/code/index.js index 65506cfcdfc5d7..ce07ea4e3e98ad 100644 --- a/packages/block-library/src/code/index.js +++ b/packages/block-library/src/code/index.js @@ -24,14 +24,17 @@ export const settings = { icon, example: { attributes: { + /* eslint-disable @wordpress/i18n-no-collapsible-whitespace */ // translators: Preserve \n markers for line breaks content: __( '// A "block" is the abstract term used\n// to describe units of markup that\n// when composed together, form the\n// content or layout of a page.\nregisterBlockType( name, settings );' ), + /* eslint-enable @wordpress/i18n-no-collapsible-whitespace */ }, }, supports: { html: false, + lightBlockWrapper: true, }, transforms, edit, diff --git a/packages/block-library/src/column/edit.native.js b/packages/block-library/src/column/edit.native.js new file mode 100644 index 00000000000000..d10d2374d0fb77 --- /dev/null +++ b/packages/block-library/src/column/edit.native.js @@ -0,0 +1,119 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; + +/** + * WordPress dependencies + */ +import { withSelect } from '@wordpress/data'; +import { compose, withPreferredColorScheme } from '@wordpress/compose'; +import { + InnerBlocks, + BlockControls, + BlockVerticalAlignmentToolbar, +} from '@wordpress/block-editor'; +/** + * Internal dependencies + */ +import styles from './editor.scss'; + +function ColumnEdit( { + attributes, + setAttributes, + hasChildren, + isSelected, + getStylesFromColorScheme, + isParentSelected, + contentStyle, +} ) { + const { verticalAlignment } = attributes; + + const updateAlignment = ( alignment ) => { + setAttributes( { verticalAlignment: alignment } ); + }; + + if ( ! isSelected && ! hasChildren ) { + return ( + <View + style={ [ + ! isParentSelected && + getStylesFromColorScheme( + styles.columnPlaceholder, + styles.columnPlaceholderDark + ), + contentStyle, + styles.columnPlaceholderNotSelected, + ] } + ></View> + ); + } + + return ( + <> + <BlockControls> + <BlockVerticalAlignmentToolbar + onChange={ updateAlignment } + value={ verticalAlignment } + /> + </BlockControls> + <View + style={ [ + contentStyle, + isSelected && hasChildren && styles.innerBlocksBottomSpace, + ] } + > + <InnerBlocks + scrollEnabled={ false } + renderAppender={ + isSelected && InnerBlocks.ButtonBlockAppender + } + /> + </View> + </> + ); +} + +function ColumnEditWrapper( props ) { + const { verticalAlignment } = props.attributes; + + const getVerticalAlignmentRemap = ( alignment ) => { + if ( ! alignment ) return styles.flexBase; + return { + ...styles.flexBase, + ...styles[ `is-vertically-aligned-${ alignment }` ], + }; + }; + + return ( + <View style={ getVerticalAlignmentRemap( verticalAlignment ) }> + <ColumnEdit { ...props } /> + </View> + ); +} + +export default compose( [ + withSelect( ( select, { clientId } ) => { + const { + getBlockCount, + getBlockRootClientId, + getSelectedBlockClientId, + } = select( 'core/block-editor' ); + + const selectedBlockClientId = getSelectedBlockClientId(); + const isSelected = selectedBlockClientId === clientId; + + const parentId = getBlockRootClientId( clientId ); + const hasChildren = !! getBlockCount( clientId ); + + const isParentSelected = + selectedBlockClientId && selectedBlockClientId === parentId; + + return { + hasChildren, + isParentSelected, + isSelected, + }; + } ), + withPreferredColorScheme, +] )( ColumnEditWrapper ); diff --git a/packages/block-library/src/column/editor.native.scss b/packages/block-library/src/column/editor.native.scss new file mode 100644 index 00000000000000..ec9579c63234b1 --- /dev/null +++ b/packages/block-library/src/column/editor.native.scss @@ -0,0 +1,36 @@ +.columnPlaceholderNotSelected { + padding-top: $block-selected-to-content; +} + +.columnPlaceholder { + flex: 1; + padding: $block-selected-to-content; + background-color: $white; + border: $border-width dashed $gray; + border-radius: 4px; +} + +.columnPlaceholderDark { + background-color: $black; + border: $border-width dashed $gray-70; +} + +.innerBlocksBottomSpace { + margin-bottom: $block-selected-to-content; +} + +.is-vertically-aligned-top { + justify-content: flex-start; +} + +.is-vertically-aligned-center { + justify-content: center; +} + +.is-vertically-aligned-bottom { + justify-content: flex-end; +} + +.flexBase { + flex: 1; +} diff --git a/packages/block-library/src/column/index.native.js b/packages/block-library/src/column/index.native.js new file mode 100644 index 00000000000000..d03c4756174bcc --- /dev/null +++ b/packages/block-library/src/column/index.native.js @@ -0,0 +1,17 @@ +/** + * Internal dependencies + */ +import * as webSettings from './index.js'; +import metadata from './block.json'; + +const { name } = metadata; + +export { metadata, name }; + +export const settings = { + ...webSettings.settings, + supports: { + ...webSettings.settings.supports, + inserter: true, + }, +}; diff --git a/packages/block-library/src/columns/block.json b/packages/block-library/src/columns/block.json index 8dc01cfafab4dd..3c22ca71fba621 100644 --- a/packages/block-library/src/columns/block.json +++ b/packages/block-library/src/columns/block.json @@ -4,18 +4,6 @@ "attributes": { "verticalAlignment": { "type": "string" - }, - "backgroundColor": { - "type": "string" - }, - "customBackgroundColor": { - "type": "string" - }, - "customTextColor" : { - "type": "string" - }, - "textColor": { - "type": "string" } } } diff --git a/packages/block-library/src/columns/deprecated.js b/packages/block-library/src/columns/deprecated.js index 3d08e3d74c2183..34b3076904a63f 100644 --- a/packages/block-library/src/columns/deprecated.js +++ b/packages/block-library/src/columns/deprecated.js @@ -8,7 +8,7 @@ import classnames from 'classnames'; * WordPress dependencies */ import { createBlock } from '@wordpress/blocks'; -import { InnerBlocks } from '@wordpress/block-editor'; +import { InnerBlocks, getColorClassName } from '@wordpress/block-editor'; /** * Given an HTML string for a deprecated columns inner block, returns the @@ -38,7 +38,84 @@ function getDeprecatedLayoutColumn( originalContent ) { } } +const migrateCustomColors = ( attributes ) => { + if ( ! attributes.customTextColor && ! attributes.customBackgroundColor ) { + return attributes; + } + const style = { color: {} }; + if ( attributes.customTextColor ) { + style.color.text = attributes.customTextColor; + } + if ( attributes.customBackgroundColor ) { + style.color.background = attributes.customBackgroundColor; + } + return { + ...omit( attributes, [ 'customTextColor', 'customBackgroundColor' ] ), + style, + }; +}; + export default [ + { + attributes: { + verticalAlignment: { + type: 'string', + }, + backgroundColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + customTextColor: { + type: 'string', + }, + textColor: { + type: 'string', + }, + }, + migrate: migrateCustomColors, + save( { attributes } ) { + const { + verticalAlignment, + backgroundColor, + customBackgroundColor, + textColor, + customTextColor, + } = attributes; + + const backgroundClass = getColorClassName( + 'background-color', + backgroundColor + ); + + const textClass = getColorClassName( 'color', textColor ); + + const className = classnames( { + 'has-background': backgroundColor || customBackgroundColor, + 'has-text-color': textColor || customTextColor, + [ backgroundClass ]: backgroundClass, + [ textClass ]: textClass, + [ `are-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, + } ); + + const style = { + backgroundColor: backgroundClass + ? undefined + : customBackgroundColor, + color: textClass ? undefined : customTextColor, + }; + + return ( + <div + className={ className ? className : undefined } + style={ style } + > + <InnerBlocks.Content /> + </div> + ); + }, + }, { attributes: { columns: { diff --git a/packages/block-library/src/columns/edit.js b/packages/block-library/src/columns/edit.js index 05aaed154a4e4d..372e535a931a8f 100644 --- a/packages/block-library/src/columns/edit.js +++ b/packages/block-library/src/columns/edit.js @@ -9,7 +9,6 @@ import { dropRight, get, map, times } from 'lodash'; */ import { __ } from '@wordpress/i18n'; import { PanelBody, RangeControl } from '@wordpress/components'; -import { useRef } from '@wordpress/element'; import { InspectorControls, @@ -17,7 +16,6 @@ import { BlockControls, BlockVerticalAlignmentToolbar, __experimentalBlockVariationPicker, - __experimentalUseColors, __experimentalBlock as Block, } from '@wordpress/block-editor'; import { withDispatch, useDispatch, useSelect } from '@wordpress/data'; @@ -61,22 +59,6 @@ function ColumnsEditContainer( { [ clientId ] ); - const ref = useRef(); - const { - BackgroundColor, - InspectorControlsColorPanel, - TextColor, - } = __experimentalUseColors( - [ - { name: 'textColor', property: 'color' }, - { name: 'backgroundColor', className: 'has-background' }, - ], - { - contrastCheckers: [ { backgroundColor: true, textColor: true } ], - colorDetector: { targetRef: ref }, - } - ); - const classes = classnames( { [ `are-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, } ); @@ -100,32 +82,14 @@ function ColumnsEditContainer( { /> </PanelBody> </InspectorControls> - { InspectorControlsColorPanel } - <BackgroundColor> - { ( backgroundProps ) => ( - <TextColor> - { ( textColorProps ) => ( - <InnerBlocks - allowedBlocks={ ALLOWED_BLOCKS } - __experimentalMoverDirection="horizontal" - ref={ ref } - __experimentalTagName={ Block.div } - __experimentalPassedProps={ { - className: classnames( - classes, - backgroundProps.className, - textColorProps.className - ), - style: { - ...backgroundProps.style, - ...textColorProps.style, - }, - } } - /> - ) } - </TextColor> - ) } - </BackgroundColor> + <InnerBlocks + allowedBlocks={ ALLOWED_BLOCKS } + __experimentalMoverDirection="horizontal" + __experimentalTagName={ Block.div } + __experimentalPassedProps={ { + className: classes, + } } + /> </> ); } diff --git a/packages/block-library/src/columns/edit.native.js b/packages/block-library/src/columns/edit.native.js new file mode 100644 index 00000000000000..e1cc669a414c11 --- /dev/null +++ b/packages/block-library/src/columns/edit.native.js @@ -0,0 +1,280 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; +import { dropRight, times } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { PanelBody, StepperControl } from '@wordpress/components'; +import { + InspectorControls, + InnerBlocks, + BlockControls, + BlockVerticalAlignmentToolbar, +} from '@wordpress/block-editor'; +import { withDispatch, useSelect } from '@wordpress/data'; +import { useEffect, useState } from '@wordpress/element'; +import { useResizeObserver } from '@wordpress/compose'; +import { createBlock } from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import styles from './editor.scss'; + +/** + * Allowed blocks constant is passed to InnerBlocks precisely as specified here. + * The contents of the array should never change. + * The array should contain the name of each block that is allowed. + * In columns block, the only block we allow is 'core/column'. + * + * @constant + * @type {string[]} + */ +const ALLOWED_BLOCKS = [ 'core/column' ]; + +/** + * Number of columns to assume for template in case the user opts to skip + * template option selection. + * + * @type {number} + */ +const DEFAULT_COLUMNS = 2; +const MIN_COLUMNS_NUMBER = 1; + +const BREAKPOINTS = { + mobile: 480, + large: 768, +}; + +function ColumnsEditContainer( { + attributes, + updateAlignment, + updateColumns, + columnCount, + isSelected, + onAddNextColumn, + onDeleteBlock, +} ) { + const [ resizeListener, sizes ] = useResizeObserver(); + const [ columnsInRow, setColumnsInRow ] = useState( MIN_COLUMNS_NUMBER ); + + const containerMaxWidth = styles.columnsContainer.maxWidth; + + const { verticalAlignment } = attributes; + const { width } = sizes || {}; + + useEffect( () => { + const newColumnCount = ! columnCount ? DEFAULT_COLUMNS : columnCount; + updateColumns( columnCount, newColumnCount ); + setColumnsInRow( getColumnsInRow( width, newColumnCount ) ); + }, [ columnCount ] ); + + useEffect( () => { + setColumnsInRow( getColumnsInRow( width, columnCount ) ); + }, [ width ] ); + + const getColumnWidth = ( containerWidth = containerMaxWidth ) => { + const minWidth = Math.min( containerWidth, containerMaxWidth ); + const columnBaseWidth = minWidth / columnsInRow; + + let columnWidth = columnBaseWidth; + if ( columnsInRow > 1 ) { + const margins = columnsInRow * 2 * styles.columnMargin.marginLeft; + columnWidth = ( minWidth - margins ) / columnsInRow; + } + + return columnWidth; + }; + + const getColumnsInRow = ( containerWidth, columnsNumber ) => { + if ( containerWidth < BREAKPOINTS.mobile ) { + // show only 1 Column in row for mobile breakpoint container width + return 1; + } else if ( containerWidth < BREAKPOINTS.large ) { + // show 2 Column in row for large breakpoint container width + return Math.min( Math.max( 1, columnCount ), 2 ); + } + // show all Column in one row + return Math.max( 1, columnsNumber ); + }; + + const renderAppender = () => { + if ( isSelected ) { + return ( + <InnerBlocks.ButtonBlockAppender + onAddBlock={ onAddNextColumn } + /> + ); + } + return null; + }; + + return ( + <> + <InspectorControls> + <PanelBody title={ __( 'Columns Settings' ) }> + <StepperControl + label={ __( 'Number of columns' ) } + icon="columns" + value={ columnCount } + onChange={ ( value ) => + updateColumns( columnCount, value ) + } + min={ MIN_COLUMNS_NUMBER } + max={ columnCount + 1 } + separatorType={ 'none' } + /> + </PanelBody> + </InspectorControls> + <BlockControls> + <BlockVerticalAlignmentToolbar + onChange={ updateAlignment } + value={ verticalAlignment } + /> + </BlockControls> + <View style={ isSelected && styles.innerBlocksSelected }> + { resizeListener } + <InnerBlocks + renderAppender={ renderAppender } + __experimentalMoverDirection={ + columnsInRow > 1 ? 'horizontal' : undefined + } + horizontal={ true } + scrollEnabled={ false } + allowedBlocks={ ALLOWED_BLOCKS } + contentResizeMode="stretch" + onAddBlock={ onAddNextColumn } + onDeleteBlock={ + columnCount === 1 ? onDeleteBlock : undefined + } + contentStyle={ { width: getColumnWidth( width ) } } + /> + </View> + </> + ); +} + +const ColumnsEditContainerWrapper = withDispatch( + ( dispatch, ownProps, registry ) => ( { + /** + * Update all child Column blocks with a new vertical alignment setting + * based on whatever alignment is passed in. This allows change to parent + * to overide anything set on a individual column basis. + * + * @param {string} verticalAlignment the vertical alignment setting + */ + updateAlignment( verticalAlignment ) { + const { clientId, setAttributes } = ownProps; + const { updateBlockAttributes } = dispatch( 'core/block-editor' ); + const { getBlockOrder } = registry.select( 'core/block-editor' ); + + // Update own alignment. + setAttributes( { verticalAlignment } ); + + // Update all child Column Blocks to match + const innerBlockClientIds = getBlockOrder( clientId ); + innerBlockClientIds.forEach( ( innerBlockClientId ) => { + updateBlockAttributes( innerBlockClientId, { + verticalAlignment, + } ); + } ); + }, + updateBlockSettings( settings ) { + const { clientId } = ownProps; + const { updateBlockListSettings } = dispatch( 'core/block-editor' ); + updateBlockListSettings( clientId, settings ); + }, + /** + * Updates the column columnCount, including necessary revisions to child Column + * blocks to grant required or redistribute available space. + * + * @param {number} previousColumns Previous column columnCount. + * @param {number} newColumns New column columnCount. + */ + updateColumns( previousColumns, newColumns ) { + const { clientId } = ownProps; + const { replaceInnerBlocks } = dispatch( 'core/block-editor' ); + const { getBlocks, getBlockAttributes } = registry.select( + 'core/block-editor' + ); + + let innerBlocks = getBlocks( clientId ); + + // Redistribute available width for existing inner blocks. + const isAddingColumn = newColumns > previousColumns; + + if ( isAddingColumn ) { + // Get verticalAlignment from Columns block to set the same to new Column + const { verticalAlignment } = getBlockAttributes( clientId ); + + innerBlocks = [ + ...innerBlocks, + ...times( newColumns - previousColumns, () => { + return createBlock( 'core/column', { + verticalAlignment, + } ); + } ), + ]; + } else { + // The removed column will be the last of the inner blocks. + innerBlocks = dropRight( + innerBlocks, + previousColumns - newColumns + ); + } + + replaceInnerBlocks( clientId, innerBlocks, false ); + }, + onAddNextColumn: () => { + const { clientId } = ownProps; + const { replaceInnerBlocks, selectBlock } = dispatch( + 'core/block-editor' + ); + const { getBlocks, getBlockAttributes } = registry.select( + 'core/block-editor' + ); + + // Get verticalAlignment from Columns block to set the same to new Column + const { verticalAlignment } = getBlockAttributes( clientId ); + + const innerBlocks = getBlocks( clientId ); + + const insertedBlock = createBlock( 'core/column', { + verticalAlignment, + } ); + + innerBlocks.push( insertedBlock ); + + replaceInnerBlocks( clientId, innerBlocks, true ); + selectBlock( insertedBlock.clientId ); + }, + onDeleteBlock: () => { + const { clientId } = ownProps; + const { removeBlock } = dispatch( 'core/block-editor' ); + removeBlock( clientId ); + }, + } ) +)( ColumnsEditContainer ); + +const ColumnsEdit = ( props ) => { + const { clientId } = props; + const { columnCount } = useSelect( + ( select ) => { + const { getBlockCount } = select( 'core/block-editor' ); + + return { + columnCount: getBlockCount( clientId ), + }; + }, + [ clientId ] + ); + + return ( + <ColumnsEditContainerWrapper columnCount={ columnCount } { ...props } /> + ); +}; + +export default ColumnsEdit; diff --git a/packages/block-library/src/columns/editor.native.scss b/packages/block-library/src/columns/editor.native.scss new file mode 100644 index 00000000000000..991655a13f3278 --- /dev/null +++ b/packages/block-library/src/columns/editor.native.scss @@ -0,0 +1,11 @@ +.columnsContainer { + max-width: $content-width; +} + +.innerBlocksSelected { + margin-bottom: $block-edge-to-content; +} + +.columnMargin { + margin: $block-edge-to-content / 2; +} diff --git a/packages/block-library/src/columns/index.js b/packages/block-library/src/columns/index.js index 8d94dcd82ea4ec..dec1d8672e6974 100644 --- a/packages/block-library/src/columns/index.js +++ b/packages/block-library/src/columns/index.js @@ -27,6 +27,7 @@ export const settings = { align: [ 'wide', 'full' ], html: false, lightBlockWrapper: true, + __experimentalColor: { gradients: true }, }, variations, example: { diff --git a/packages/block-library/src/columns/save.js b/packages/block-library/src/columns/save.js index 3d2249389910d2..0d9a5305cbeaeb 100644 --- a/packages/block-library/src/columns/save.js +++ b/packages/block-library/src/columns/save.js @@ -6,39 +6,17 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { InnerBlocks, getColorClassName } from '@wordpress/block-editor'; +import { InnerBlocks } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { - verticalAlignment, - backgroundColor, - customBackgroundColor, - textColor, - customTextColor, - } = attributes; - - const backgroundClass = getColorClassName( - 'background-color', - backgroundColor - ); - - const textClass = getColorClassName( 'color', textColor ); + const { verticalAlignment } = attributes; const className = classnames( { - 'has-background': backgroundColor || customBackgroundColor, - 'has-text-color': textColor || customTextColor, - [ backgroundClass ]: backgroundClass, - [ textClass ]: textClass, [ `are-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, } ); - const style = { - backgroundColor: backgroundClass ? undefined : customBackgroundColor, - color: textClass ? undefined : customTextColor, - }; - return ( - <div className={ className ? className : undefined } style={ style }> + <div className={ className ? className : undefined }> <InnerBlocks.Content /> </div> ); diff --git a/packages/block-library/src/cover/block.json b/packages/block-library/src/cover/block.json index cb6a0a1c330e64..c2b3098b16c23e 100644 --- a/packages/block-library/src/cover/block.json +++ b/packages/block-library/src/cover/block.json @@ -32,6 +32,9 @@ "minHeight": { "type": "number" }, + "minHeightUnit": { + "type": "string" + }, "gradient": { "type": "string" }, diff --git a/packages/block-library/src/cover/edit.js b/packages/block-library/src/cover/edit.js index b9354dc6fc7363..5fe5db7a206757 100644 --- a/packages/block-library/src/cover/edit.js +++ b/packages/block-library/src/cover/edit.js @@ -20,7 +20,7 @@ import { ToggleControl, withNotices, } from '@wordpress/components'; -import { compose, withInstanceId } from '@wordpress/compose'; +import { compose, withInstanceId, useInstanceId } from '@wordpress/compose'; import { BlockControls, BlockIcon, @@ -32,6 +32,7 @@ import { ColorPalette, __experimentalUseGradient, __experimentalPanelColorGradientSettings as PanelColorGradientSettings, + __experimentalUnitControl as UnitControl, } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { withDispatch } from '@wordpress/data'; @@ -45,6 +46,7 @@ import { IMAGE_BACKGROUND_TYPE, VIDEO_BACKGROUND_TYPE, COVER_MIN_HEIGHT, + CSS_UNITS, backgroundImageStyles, dimRatioToClass, } from './shared'; @@ -71,47 +73,57 @@ function retrieveFastAverageColor() { return retrieveFastAverageColor.fastAverageColor; } -const CoverHeightInput = withInstanceId( function( { - value = '', - instanceId, +function CoverHeightInput( { onChange, + onUnitChange, + unit = 'px', + value = '', } ) { const [ temporaryInput, setTemporaryInput ] = useState( null ); + const instanceId = useInstanceId( UnitControl ); const inputId = `block-cover-height-input-${ instanceId }`; + const isPx = unit === 'px'; + + const handleOnChange = ( unprocessedValue ) => { + const inputValue = + unprocessedValue !== '' + ? parseInt( unprocessedValue, 10 ) + : undefined; + + if ( isNaN( inputValue ) && inputValue !== undefined ) { + setTemporaryInput( unprocessedValue ); + return; + } + setTemporaryInput( null ); + onChange( inputValue ); + }; + + const handleOnBlur = () => { + if ( temporaryInput !== null ) { + setTemporaryInput( null ); + } + }; + + const inputValue = temporaryInput !== null ? temporaryInput : value; + const min = isPx ? COVER_MIN_HEIGHT : 0; + return ( - <BaseControl label={ __( 'Minimum height in pixels' ) } id={ inputId }> - <input - type="number" + <BaseControl label={ __( 'Minimum height of cover' ) } id={ inputId }> + <UnitControl id={ inputId } - onChange={ ( event ) => { - const unprocessedValue = event.target.value; - const inputValue = - unprocessedValue !== '' - ? parseInt( event.target.value, 10 ) - : undefined; - if ( - ( isNaN( inputValue ) || - inputValue < COVER_MIN_HEIGHT ) && - inputValue !== undefined - ) { - setTemporaryInput( event.target.value ); - return; - } - setTemporaryInput( null ); - onChange( inputValue ); - } } - onBlur={ () => { - if ( temporaryInput !== null ) { - setTemporaryInput( null ); - } - } } - value={ temporaryInput !== null ? temporaryInput : value } - min={ COVER_MIN_HEIGHT } + min={ min } + onBlur={ handleOnBlur } + onChange={ handleOnChange } + onUnitChange={ onUnitChange } step="1" + style={ { maxWidth: 80 } } + unit={ unit } + units={ CSS_UNITS } + value={ inputValue } /> </BaseControl> ); -} ); +} const RESIZABLE_BOX_ENABLE_OPTION = { top: false, @@ -227,6 +239,7 @@ function CoverEdit( { focalPoint, hasParallax, minHeight, + minHeightUnit, url, } = attributes; const { @@ -252,15 +265,18 @@ function CoverEdit( { ); const [ temporaryMinHeight, setTemporaryMinHeight ] = useState( null ); - const { removeAllNotices, createErrorNotice } = noticeOperations; + const minHeightWithUnit = minHeightUnit + ? `${ minHeight }${ minHeightUnit }` + : minHeight; + const style = { ...( backgroundType === IMAGE_BACKGROUND_TYPE ? backgroundImageStyles( url ) : {} ), backgroundColor: overlayColor.color, - minHeight: temporaryMinHeight || minHeight, + minHeight: temporaryMinHeight || minHeightWithUnit || undefined, }; if ( gradientValue && ! url ) { @@ -339,9 +355,15 @@ function CoverEdit( { <PanelBody title={ __( 'Dimensions' ) }> <CoverHeightInput value={ temporaryMinHeight || minHeight } + unit={ minHeightUnit } onChange={ ( newMinHeight ) => setAttributes( { minHeight: newMinHeight } ) } + onUnitChange={ ( nextUnit ) => { + setAttributes( { + minHeightUnit: nextUnit, + } ); + } } /> </PanelBody> <PanelColorGradientSettings @@ -436,7 +458,10 @@ function CoverEdit( { 'is-selected': isSelected, } ) } - onResizeStart={ () => toggleSelection( false ) } + onResizeStart={ () => { + setAttributes( { minHeightUnit: 'px' } ); + toggleSelection( false ); + } } onResize={ setTemporaryMinHeight } onResizeStop={ ( newMinHeight ) => { toggleSelection( true ); diff --git a/packages/block-library/src/cover/edit.native.js b/packages/block-library/src/cover/edit.native.js index b3487dce2702c3..230a129123c083 100644 --- a/packages/block-library/src/cover/edit.native.js +++ b/packages/block-library/src/cover/edit.native.js @@ -2,7 +2,7 @@ * External dependencies */ import { View, TouchableWithoutFeedback } from 'react-native'; -import { default as Video } from 'react-native-video'; +import Video from 'react-native-video'; /** * WordPress dependencies @@ -25,6 +25,7 @@ import { MEDIA_TYPE_VIDEO, MediaPlaceholder, MediaUpload, + MediaUploadProgress, withColors, __experimentalUseGradient, } from '@wordpress/block-editor'; @@ -63,19 +64,27 @@ const COVER_DEFAULT_HEIGHT = 300; const Cover = ( { attributes, getStylesFromColorScheme, - hasChildren, isParentSelected, onFocus, overlayColor, setAttributes, } ) => { - const { backgroundType, dimRatio, focalPoint, minHeight, url } = attributes; + const { + backgroundType, + dimRatio, + focalPoint, + minHeight, + url, + id, + style, + } = attributes; const CONTAINER_HEIGHT = minHeight || COVER_DEFAULT_HEIGHT; const { gradientValue } = __experimentalUseGradient(); const hasBackground = !! ( url || + ( style && style.color && style.color.background ) || attributes.overlayColor || overlayColor.color || gradientValue @@ -112,12 +121,12 @@ const Cover = ( { const overlayStyles = [ styles.overlay, - { + url && { opacity: dimRatio / 100 }, + ! gradientValue && { backgroundColor: - overlayColor && overlayColor.color - ? overlayColor.color - : styles.overlay.color, - opacity: dimRatio / 100, + overlayColor?.color || + style?.color?.background || + styles.overlay.color, }, // While we don't support theme colors we add a default bg color ! overlayColor.color && ! url @@ -176,12 +185,10 @@ const Cover = ( { </InspectorControls> ); - const containerStyles = [ - hasChildren && ! isParentSelected && styles.regularMediaPadding, - hasChildren && isParentSelected && styles.innerPadding, - ]; - - const background = ( openMediaOptions, getMediaOptions ) => ( + const renderBackground = ( { + open: openMediaOptions, + getMediaOptions, + } ) => ( <TouchableWithoutFeedback accessible={ ! isParentSelected } onLongPress={ openMediaOptions } @@ -190,39 +197,49 @@ const Cover = ( { <View style={ styles.background }> { getMediaOptions() } { isParentSelected && toolbarControls( openMediaOptions ) } - - { /* When the gradient is set as a background the backgroundType is equal to IMAGE_BACKGROUND_TYPE */ } - { IMAGE_BACKGROUND_TYPE === backgroundType && - ( gradientValue ? ( - <LinearGradient - gradientValue={ gradientValue } - style={ styles.background } - /> - ) : ( - <ImageWithFocalPoint - focalPoint={ focalPoint } - url={ url } - /> - ) ) } - { VIDEO_BACKGROUND_TYPE === backgroundType && ( - <Video - muted - disableFocus - repeat - resizeMode={ 'cover' } - source={ { uri: url } } - style={ styles.background } - /> - ) } + <MediaUploadProgress + mediaId={ id } + onFinishMediaUploadWithSuccess={ ( { + mediaServerId, + mediaUrl, + } ) => { + setAttributes( { + id: mediaServerId, + url: mediaUrl, + backgroundType, + } ); + } } + renderContent={ () => ( + <> + { IMAGE_BACKGROUND_TYPE === backgroundType && ( + <ImageWithFocalPoint + focalPoint={ focalPoint } + url={ url } + /> + ) } + { VIDEO_BACKGROUND_TYPE === backgroundType && ( + <Video + muted + disableFocus + repeat + resizeMode={ 'cover' } + source={ { uri: url } } + style={ styles.background } + /> + ) } + </> + ) } + /> </View> </TouchableWithoutFeedback> ); if ( ! hasBackground ) { return ( - <View style={ containerStyles }> + <View> <MediaPlaceholder - __experimentalOnlyMediaLibrary + // eslint-disable-next-line no-undef + __experimentalOnlyMediaLibrary={ ! __DEV__ } icon={ placeholderIcon } labels={ { title: __( 'Cover' ), @@ -236,33 +253,32 @@ const Cover = ( { } return ( - <View style={ containerStyles }> + <View style={ styles.backgroundContainer }> { controls } - <View style={ styles.backgroundContainer }> - <View - pointerEvents="box-none" - style={ [ - styles.content, - { minHeight: CONTAINER_HEIGHT }, - ] } - > - <InnerBlocks template={ INNER_BLOCKS_TEMPLATE } /> - </View> - { /* We don't render overlay on top of gradient */ } - { ! gradientValue && ( - <View pointerEvents="none" style={ overlayStyles } /> - ) } + <View + pointerEvents="box-none" + style={ [ styles.content, { minHeight: CONTAINER_HEIGHT } ] } + > + <InnerBlocks template={ INNER_BLOCKS_TEMPLATE } /> + </View> - <MediaUpload - __experimentalOnlyMediaLibrary - allowedTypes={ ALLOWED_MEDIA_TYPES } - onSelect={ onSelectMedia } - render={ ( { open, getMediaOptions } ) => { - return background( open, getMediaOptions ); - } } - /> + <View pointerEvents="none" style={ overlayStyles }> + { gradientValue && ( + <LinearGradient + gradientValue={ gradientValue } + style={ styles.background } + /> + ) } </View> + + <MediaUpload + // eslint-disable-next-line no-undef + __experimentalOnlyMediaLibrary={ ! __DEV__ } + allowedTypes={ ALLOWED_MEDIA_TYPES } + onSelect={ onSelectMedia } + render={ renderBackground } + /> </View> ); }; @@ -270,15 +286,11 @@ const Cover = ( { export default compose( [ withColors( { overlayColor: 'background-color' } ), withSelect( ( select, { clientId } ) => { - const { getSelectedBlockClientId, getBlockCount } = select( - 'core/block-editor' - ); + const { getSelectedBlockClientId } = select( 'core/block-editor' ); const selectedBlockClientId = getSelectedBlockClientId(); - const hasChildren = getBlockCount( clientId ); return { - hasChildren, isParentSelected: selectedBlockClientId === clientId, }; } ), diff --git a/packages/block-library/src/cover/editor.scss b/packages/block-library/src/cover/editor.scss index cca0e8a751e099..31faa3872936d0 100644 --- a/packages/block-library/src/cover/editor.scss +++ b/packages/block-library/src/cover/editor.scss @@ -9,10 +9,6 @@ width: 100%; } - .block-editor-block-list__block { - color: $light-gray-100; - } - // The .wp-block-cover class is used just to increase selector specificity. .wp-block-cover__inner-container { // Avoid text align inherit from cover image align. diff --git a/packages/block-library/src/cover/save.js b/packages/block-library/src/cover/save.js index 8cb56dbe4752d5..4e45fa41347b58 100644 --- a/packages/block-library/src/cover/save.js +++ b/packages/block-library/src/cover/save.js @@ -33,13 +33,17 @@ export default function save( { attributes } ) { hasParallax, overlayColor, url, - minHeight, + minHeight: minHeightProp, + minHeightUnit, } = attributes; const overlayColorClass = getColorClassName( 'background-color', overlayColor ); const gradientClass = __experimentalGetGradientClass( gradient ); + const minHeight = minHeightUnit + ? `${ minHeightProp }${ minHeightUnit }` + : minHeightProp; const style = backgroundType === IMAGE_BACKGROUND_TYPE diff --git a/packages/block-library/src/cover/shared.js b/packages/block-library/src/cover/shared.js index bf1e794606aa3d..1fba24ccd1c68f 100644 --- a/packages/block-library/src/cover/shared.js +++ b/packages/block-library/src/cover/shared.js @@ -5,6 +5,14 @@ export function backgroundImageStyles( url ) { return url ? { backgroundImage: `url(${ url })` } : {}; } +export const CSS_UNITS = [ + { value: 'px', label: 'px', default: 430 }, + { value: 'em', label: 'em', default: 20 }, + { value: 'rem', label: 'rem', default: 20 }, + { value: 'vw', label: 'vw', default: 20 }, + { value: 'vh', label: 'vh', default: 50 }, +]; + export function dimRatioToClass( ratio ) { return ratio === 0 || ratio === 50 || ! ratio ? null diff --git a/packages/block-library/src/cover/style.native.scss b/packages/block-library/src/cover/style.native.scss index 2141f715a2b7e5..b1e7b5bad9257d 100644 --- a/packages/block-library/src/cover/style.native.scss +++ b/packages/block-library/src/cover/style.native.scss @@ -8,18 +8,6 @@ fill: $white; } -.innerPadding { - padding: $block-selected-to-content; -} - -.regularMediaPadding { - padding: $block-edge-to-content; -} - -.denseMediaPadding { - padding: $block-media-container-to-content; -} - .backgroundContainer { overflow: hidden; width: 100%; @@ -29,6 +17,7 @@ .content { justify-content: center; width: 100%; + padding: $block-edge-to-content; z-index: 3; } diff --git a/packages/block-library/src/cover/style.scss b/packages/block-library/src/cover/style.scss index 739742d1e62270..1742bf45f9de5a 100644 --- a/packages/block-library/src/cover/style.scss +++ b/packages/block-library/src/cover/style.scss @@ -1,7 +1,6 @@ .wp-block-cover-image, .wp-block-cover { position: relative; - background-color: $black; background-size: cover; background-position: center center; min-height: 430px; @@ -11,7 +10,6 @@ justify-content: center; align-items: center; overflow: hidden; - &.has-parallax { background-attachment: fixed; @@ -28,9 +26,13 @@ } } - &.has-background-dim::before { - content: ""; - background-color: inherit; + &.has-background-dim { + background-color: $black; + + &::before { + content: ""; + background-color: inherit; + } } &.has-background-dim:not(.has-background-gradient)::before, diff --git a/packages/block-library/src/embed/embed-preview.js b/packages/block-library/src/embed/embed-preview.js index 419ef17c7bb115..0e70f84729acc6 100644 --- a/packages/block-library/src/embed/embed-preview.js +++ b/packages/block-library/src/embed/embed-preview.js @@ -73,8 +73,8 @@ class EmbedPreview extends Component { .splice( parsedHost.length - 2, parsedHost.length - 1 ) .join( '.' ); const cannotPreview = includes( HOSTS_NO_PREVIEWS, parsedHostBaseUrl ); - // translators: %s: host providing embed content e.g: www.youtube.com const iframeTitle = sprintf( + // translators: %s: host providing embed content e.g: www.youtube.com __( 'Embedded content from %s' ), parsedHostBaseUrl ); @@ -125,8 +125,8 @@ class EmbedPreview extends Component { <a href={ url }>{ url }</a> </p> <p className="components-placeholder__error"> - { /* translators: %s: host providing embed content e.g: www.youtube.com */ - sprintf( + { sprintf( + /* translators: %s: host providing embed content e.g: www.youtube.com */ __( "Embedded content from %s can't be previewed in the editor." ), diff --git a/packages/block-library/src/embed/icons.js b/packages/block-library/src/embed/icons.js index 1ad0c76cf1c634..292a3d336aaaa2 100644 --- a/packages/block-library/src/embed/icons.js +++ b/packages/block-library/src/embed/icons.js @@ -98,7 +98,7 @@ export const embedTumblrIcon = { foreground: '#35465c', src: ( <SVG viewBox="0 0 24 24"> - <Path d="M19 3H5c-1.105 0-2 .895-2 2v14c0 1.105.895 2 2 2h14c1.105 0 2-.895 2-2V5c0-1.105-.895-2-2-2zm-5.57 14.265c-2.445.042-3.37-1.742-3.37-2.998V10.6H8.922V9.15c1.703-.615 2.113-2.15 2.21-3.026.006-.06.053-.084.08-.084h1.645V8.9h2.246v1.7H12.85v3.495c.008.476.182 1.13 1.08 1.107.3-.008.698-.094.907-.194l.54 1.6c-.205.297-1.12.642-1.946.657z" /> + <Path d="M19 3H5a2 2 0 00-2 2v14c0 1.1.9 2 2 2h14a2 2 0 002-2V5a2 2 0 00-2-2zm-5.69 14.66c-2.72 0-3.1-1.9-3.1-3.16v-3.56H8.49V8.99c1.7-.62 2.54-1.99 2.64-2.87 0-.06.06-.41.06-.58h1.9v3.1h2.17v2.3h-2.18v3.1c0 .47.13 1.3 1.2 1.26h1.1v2.36c-1.01.02-2.07 0-2.07 0z" /> </SVG> ), }; diff --git a/packages/block-library/src/gallery/columns-control/index.js b/packages/block-library/src/gallery/columns-control/index.js new file mode 100644 index 00000000000000..8eb15c87037bbc --- /dev/null +++ b/packages/block-library/src/gallery/columns-control/index.js @@ -0,0 +1,17 @@ +/** + * WordPress dependencies + */ +import { RangeControl } from '@wordpress/components'; + +const ColumnsControl = ( { label, value, onChange, min, max } ) => ( + <RangeControl + label={ label } + max={ max } + min={ min } + onChange={ onChange } + required + value={ value } + /> +); + +export default ColumnsControl; diff --git a/packages/block-library/src/gallery/columns-control/index.native.js b/packages/block-library/src/gallery/columns-control/index.native.js new file mode 100644 index 00000000000000..ab819c916a9988 --- /dev/null +++ b/packages/block-library/src/gallery/columns-control/index.native.js @@ -0,0 +1,17 @@ +/** + * WordPress dependencies + */ +import { StepperControl } from '@wordpress/components'; + +const ColumnsControl = ( { label, value, onChange, min, max } ) => ( + <StepperControl + label={ label } + max={ max } + min={ min } + onChange={ onChange } + separatorType="fullWidth" + value={ value } + /> +); + +export default ColumnsControl; diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index c3b556b683503d..ac031e6c34085f 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -20,9 +20,7 @@ import { import { compose } from '@wordpress/compose'; import { PanelBody, - RangeControl, SelectControl, - StepperControl, ToggleControl, withNotices, } from '@wordpress/components'; @@ -39,8 +37,8 @@ import { withViewportMatch } from '@wordpress/viewport'; import { sharedIcon } from './shared-icon'; import { defaultColumnsNumber, pickRelevantMediaFiles } from './shared'; import Gallery from './gallery'; +import ColumnsControl from './columns-control'; -const ColumnsControl = Platform.OS === 'web' ? RangeControl : StepperControl; const MAX_COLUMNS = 8; const linkOptions = [ { value: 'attachment', label: __( 'Attachment Page' ) }, @@ -395,7 +393,6 @@ class GalleryEdit extends Component { { images.length > 1 && ( <ColumnsControl label={ __( 'Columns' ) } - { ...MOBILE_CONTROL_PROPS } value={ columns } onChange={ this.setColumnsNumber } min={ 1 } diff --git a/packages/block-library/src/gallery/gallery.js b/packages/block-library/src/gallery/gallery.js index d0f0c03d9b3260..53c319d26c0594 100644 --- a/packages/block-library/src/gallery/gallery.js +++ b/packages/block-library/src/gallery/gallery.js @@ -51,8 +51,8 @@ export const Gallery = ( props ) => { > <ul className="blocks-gallery-grid"> { images.map( ( img, index ) => { - /* translators: %1$d is the order number of the image, %2$d is the total number of images. */ const ariaLabel = sprintf( + /* translators: 1: the order number of the image. 2: the total number of images. */ __( 'image %1$d of %2$d in gallery' ), index + 1, images.length diff --git a/packages/block-library/src/gallery/gallery.native.js b/packages/block-library/src/gallery/gallery.native.js index 0a72cd8bbe42b9..70cd50e08e5e77 100644 --- a/packages/block-library/src/gallery/gallery.native.js +++ b/packages/block-library/src/gallery/gallery.native.js @@ -88,8 +88,8 @@ export const Gallery = ( props ) => { } > { images.map( ( img, index ) => { - /* translators: %1$d is the order number of the image, %2$d is the total number of images. */ const ariaLabel = sprintf( + /* translators: 1: the order number of the image. 2: the total number of images. */ __( 'image %1$d of %2$d in gallery' ), index + 1, images.length diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json index 8883720bbc2aab..9359f8101603ba 100644 --- a/packages/block-library/src/group/block.json +++ b/packages/block-library/src/group/block.json @@ -2,17 +2,9 @@ "name": "core/group", "category": "layout", "attributes": { - "backgroundColor": { - "type": "string" - }, - "customBackgroundColor": { - "type": "string" - }, - "textColor": { - "type": "string" - }, - "customTextColor": { - "type": "string" + "tagName": { + "type": "string", + "default": "div" } } } diff --git a/packages/block-library/src/group/deprecated.js b/packages/block-library/src/group/deprecated.js index 31440c003f8669..3e6d394197ffd6 100644 --- a/packages/block-library/src/group/deprecated.js +++ b/packages/block-library/src/group/deprecated.js @@ -2,13 +2,94 @@ * External dependencies */ import classnames from 'classnames'; +import { omit } from 'lodash'; /** * WordPress dependencies */ import { InnerBlocks, getColorClassName } from '@wordpress/block-editor'; +const migrateAttributes = ( attributes ) => { + if ( ! attributes.tagName ) { + attributes = { + ...attributes, + tagName: 'div', + }; + } + + if ( ! attributes.customTextColor && ! attributes.customBackgroundColor ) { + return attributes; + } + const style = { color: {} }; + if ( attributes.customTextColor ) { + style.color.text = attributes.customTextColor; + } + if ( attributes.customBackgroundColor ) { + style.color.background = attributes.customBackgroundColor; + } + return { + ...omit( attributes, [ 'customTextColor', 'customBackgroundColor' ] ), + style, + }; +}; + const deprecated = [ + // Version of the block without global styles support + { + attributes: { + backgroundColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + textColor: { + type: 'string', + }, + customTextColor: { + type: 'string', + }, + }, + supports: { + align: [ 'wide', 'full' ], + anchor: true, + html: false, + }, + migrate: migrateAttributes, + save( { attributes } ) { + const { + backgroundColor, + customBackgroundColor, + textColor, + customTextColor, + } = attributes; + + const backgroundClass = getColorClassName( + 'background-color', + backgroundColor + ); + const textClass = getColorClassName( 'color', textColor ); + const className = classnames( backgroundClass, textClass, { + 'has-text-color': textColor || customTextColor, + 'has-background': backgroundColor || customBackgroundColor, + } ); + + const styles = { + backgroundColor: backgroundClass + ? undefined + : customBackgroundColor, + color: textClass ? undefined : customTextColor, + }; + + return ( + <div className={ className } style={ styles }> + <div className="wp-block-group__inner-container"> + <InnerBlocks.Content /> + </div> + </div> + ); + }, + }, // Version of the group block with a bug that made text color class not applied. { attributes: { @@ -25,6 +106,7 @@ const deprecated = [ type: 'string', }, }, + migrate: migrateAttributes, supports: { align: [ 'wide', 'full' ], anchor: true, @@ -79,6 +161,7 @@ const deprecated = [ anchor: true, html: false, }, + migrate: migrateAttributes, save( { attributes } ) { const { backgroundColor, customBackgroundColor } = attributes; diff --git a/packages/block-library/src/group/edit.js b/packages/block-library/src/group/edit.js index f7dab36292ffea..6a7989f8a8df96 100644 --- a/packages/block-library/src/group/edit.js +++ b/packages/block-library/src/group/edit.js @@ -1,64 +1,36 @@ /** * WordPress dependencies */ -import { withSelect } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; import { InnerBlocks, - __experimentalUseColors, __experimentalBlock as Block, } from '@wordpress/block-editor'; -import { useRef } from '@wordpress/element'; -function GroupEdit( { hasInnerBlocks, className } ) { - const ref = useRef(); - const { - TextColor, - BackgroundColor, - InspectorControlsColorPanel, - } = __experimentalUseColors( - [ - { name: 'textColor', property: 'color' }, - { name: 'backgroundColor', className: 'has-background' }, - ], - { - contrastCheckers: [ { backgroundColor: true, textColor: true } ], - colorDetector: { targetRef: ref }, - } +function GroupEdit( { attributes, className, clientId } ) { + const hasInnerBlocks = useSelect( + ( select ) => { + const { getBlock } = select( 'core/block-editor' ); + const block = getBlock( clientId ); + return !! ( block && block.innerBlocks.length ); + }, + [ clientId ] ); + const BlockWrapper = Block[ attributes.tagName ]; return ( - <> - { InspectorControlsColorPanel } - <BackgroundColor> - <TextColor> - <Block.div className={ className } ref={ ref }> - <div className="wp-block-group__inner-container"> - <InnerBlocks - renderAppender={ - hasInnerBlocks - ? undefined - : () => ( - <InnerBlocks.ButtonBlockAppender /> - ) - } - /> - </div> - </Block.div> - </TextColor> - </BackgroundColor> - </> + <BlockWrapper className={ className }> + <div className="wp-block-group__inner-container"> + <InnerBlocks + renderAppender={ + hasInnerBlocks + ? undefined + : () => <InnerBlocks.ButtonBlockAppender /> + } + /> + </div> + </BlockWrapper> ); } -export default compose( [ - withSelect( ( select, { clientId } ) => { - const { getBlock } = select( 'core/block-editor' ); - - const block = getBlock( clientId ); - - return { - hasInnerBlocks: !! ( block && block.innerBlocks.length ), - }; - } ), -] )( GroupEdit ); +export default GroupEdit; diff --git a/packages/block-library/src/group/edit.native.js b/packages/block-library/src/group/edit.native.js index a1b261f3340c6c..6545600f939040 100644 --- a/packages/block-library/src/group/edit.native.js +++ b/packages/block-library/src/group/edit.native.js @@ -33,9 +33,14 @@ function GroupEdit( { hasInnerBlocks, isSelected, getStylesFromColorScheme } ) { } return ( - <InnerBlocks - renderAppender={ isSelected && InnerBlocks.ButtonBlockAppender } - /> + <View style={ isSelected && hasInnerBlocks && styles.innerBlocks }> + <InnerBlocks + renderAppender={ isSelected && InnerBlocks.ButtonBlockAppender } + flatListProps={ { + scrollEnabled: false, + } } + /> + </View> ); } diff --git a/packages/block-library/src/group/editor.native.scss b/packages/block-library/src/group/editor.native.scss index 2f426176fe22a2..7f8a9ce1322462 100644 --- a/packages/block-library/src/group/editor.native.scss +++ b/packages/block-library/src/group/editor.native.scss @@ -22,3 +22,7 @@ margin-left: 0; margin-right: 0; } + +.innerBlocks { + margin-bottom: $block-edge-to-content; +} diff --git a/packages/block-library/src/group/index.js b/packages/block-library/src/group/index.js index c977195156b73d..d07cf54f7256d8 100644 --- a/packages/block-library/src/group/index.js +++ b/packages/block-library/src/group/index.js @@ -29,8 +29,12 @@ export const settings = { ], example: { attributes: { - customBackgroundColor: '#ffffff', - customTextColor: '#000000', + style: { + color: { + text: '#000000', + background: '#ffffff', + }, + }, }, innerBlocks: [ { @@ -88,6 +92,7 @@ export const settings = { anchor: true, html: false, lightBlockWrapper: true, + __experimentalColor: { gradients: true }, }, transforms: { from: [ diff --git a/packages/block-library/src/group/save.js b/packages/block-library/src/group/save.js index 6d248efbfc2579..f24c9f37cdf409 100644 --- a/packages/block-library/src/group/save.js +++ b/packages/block-library/src/group/save.js @@ -1,41 +1,16 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ -import { InnerBlocks, getColorClassName } from '@wordpress/block-editor'; +import { InnerBlocks } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { - backgroundColor, - customBackgroundColor, - textColor, - customTextColor, - } = attributes; - - const backgroundClass = getColorClassName( - 'background-color', - backgroundColor - ); - const textClass = getColorClassName( 'color', textColor ); - const className = classnames( backgroundClass, textClass, { - 'has-text-color': textColor || customTextColor, - 'has-background': backgroundColor || customBackgroundColor, - } ); - - const styles = { - backgroundColor: backgroundClass ? undefined : customBackgroundColor, - color: textClass ? undefined : customTextColor, - }; + const { tagName: Tag } = attributes; return ( - <div className={ className } style={ styles }> + <Tag> <div className="wp-block-group__inner-container"> <InnerBlocks.Content /> </div> - </div> + </Tag> ); } diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index 2c47b2c7096521..120bece3d39ae3 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -17,12 +17,6 @@ }, "placeholder": { "type": "string" - }, - "textColor": { - "type": "string" - }, - "customTextColor": { - "type": "string" } } } diff --git a/packages/block-library/src/heading/deprecated.js b/packages/block-library/src/heading/deprecated.js index fffa0f9b4e7976..7a43fc9d5b8689 100644 --- a/packages/block-library/src/heading/deprecated.js +++ b/packages/block-library/src/heading/deprecated.js @@ -2,6 +2,7 @@ * External dependencies */ import classnames from 'classnames'; +import { omit } from 'lodash'; /** * WordPress dependencies @@ -30,17 +31,77 @@ const blockAttributes = { placeholder: { type: 'string', }, - textColor: { - type: 'string', - }, - customTextColor: { - type: 'string', - }, +}; + +const migrateCustomColors = ( attributes ) => { + if ( ! attributes.customTextColor ) { + return attributes; + } + const style = { + color: { + text: attributes.customTextColor, + }, + }; + return { + ...omit( attributes, [ 'customTextColor' ] ), + style, + }; }; const deprecated = [ { - attributes: blockAttributes, + supports: blockSupports, + attributes: { + ...blockAttributes, + customTextColor: { + type: 'string', + }, + textColor: { + type: 'string', + }, + }, + migrate: migrateCustomColors, + save( { attributes } ) { + const { + align, + content, + customTextColor, + level, + textColor, + } = attributes; + const tagName = 'h' + level; + + const textClass = getColorClassName( 'color', textColor ); + + const className = classnames( { + [ textClass ]: textClass, + 'has-text-color': textColor || customTextColor, + [ `has-text-align-${ align }` ]: align, + } ); + + return ( + <RichText.Content + className={ className ? className : undefined } + tagName={ tagName } + style={ { + color: textClass ? undefined : customTextColor, + } } + value={ content } + /> + ); + }, + }, + { + attributes: { + ...blockAttributes, + customTextColor: { + type: 'string', + }, + textColor: { + type: 'string', + }, + }, + migrate: migrateCustomColors, save( { attributes } ) { const { align, @@ -73,7 +134,16 @@ const deprecated = [ }, { supports: blockSupports, - attributes: blockAttributes, + attributes: { + ...blockAttributes, + customTextColor: { + type: 'string', + }, + textColor: { + type: 'string', + }, + }, + migrate: migrateCustomColors, save( { attributes } ) { const { align, diff --git a/packages/block-library/src/heading/edit.js b/packages/block-library/src/heading/edit.js index 3e43660a300efe..28f9a6da5be576 100644 --- a/packages/block-library/src/heading/edit.js +++ b/packages/block-library/src/heading/edit.js @@ -12,93 +12,91 @@ import HeadingToolbar from './heading-toolbar'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { PanelBody } from '@wordpress/components'; +import { PanelBody, __experimentalText as Text } from '@wordpress/components'; import { createBlock } from '@wordpress/blocks'; import { AlignmentToolbar, BlockControls, InspectorControls, RichText, - __experimentalUseColors, __experimentalBlock as Block, } from '@wordpress/block-editor'; -import { useRef } from '@wordpress/element'; +import { Platform } from '@wordpress/element'; function HeadingEdit( { attributes, setAttributes, mergeBlocks, onReplace } ) { - const ref = useRef(); - const { TextColor, InspectorControlsColorPanel } = __experimentalUseColors( - [ { name: 'textColor', property: 'color' } ], - { - contrastCheckers: { backgroundColor: true, textColor: true }, - colorDetector: { targetRef: ref }, - }, - [] - ); - - const { align, content, level, placeholder } = attributes; + const { align, content, level, placeholder, style } = attributes; const tagName = 'h' + level; + const isAndroid = Platform.select( { + android: true, + native: false, + web: false, + } ); + + const styles = { + color: style && style.color && style.color.text, + }; return ( <> <BlockControls> <HeadingToolbar - minLevel={ 2 } - maxLevel={ 5 } + minLevel={ Platform.OS === 'web' ? 2 : 1 } + maxLevel={ Platform.OS === 'web' ? 5 : 7 } selectedLevel={ level } onChange={ ( newLevel ) => setAttributes( { level: newLevel } ) } /> - <AlignmentToolbar - value={ align } - onChange={ ( nextAlign ) => { - setAttributes( { align: nextAlign } ); - } } - /> - </BlockControls> - <InspectorControls> - <PanelBody title={ __( 'Heading settings' ) }> - <p>{ __( 'Level' ) }</p> - <HeadingToolbar - isCollapsed={ false } - minLevel={ 1 } - maxLevel={ 7 } - selectedLevel={ level } - onChange={ ( newLevel ) => - setAttributes( { level: newLevel } ) - } + { ! isAndroid && ( + <AlignmentToolbar + value={ align } + onChange={ ( nextAlign ) => { + setAttributes( { align: nextAlign } ); + } } /> - </PanelBody> - </InspectorControls> - { InspectorControlsColorPanel } - <TextColor> - <RichText - ref={ ref } - identifier="content" - tagName={ Block[ tagName ] } - value={ content } - onChange={ ( value ) => - setAttributes( { content: value } ) + ) } + </BlockControls> + { Platform.OS === 'web' && ( + <InspectorControls> + <PanelBody title={ __( 'Heading settings' ) }> + <Text variant="label">{ __( 'Level' ) }</Text> + <HeadingToolbar + isCollapsed={ false } + minLevel={ 1 } + maxLevel={ 7 } + selectedLevel={ level } + onChange={ ( newLevel ) => + setAttributes( { level: newLevel } ) + } + /> + </PanelBody> + </InspectorControls> + ) } + <RichText + identifier="content" + tagName={ Block[ tagName ] } + value={ content } + onChange={ ( value ) => setAttributes( { content: value } ) } + onMerge={ mergeBlocks } + onSplit={ ( value ) => { + if ( ! value ) { + return createBlock( 'core/paragraph' ); } - onMerge={ mergeBlocks } - onSplit={ ( value ) => { - if ( ! value ) { - return createBlock( 'core/paragraph' ); - } - return createBlock( 'core/heading', { - ...attributes, - content: value, - } ); - } } - onReplace={ onReplace } - onRemove={ () => onReplace( [] ) } - className={ classnames( { - [ `has-text-align-${ align }` ]: align, - } ) } - placeholder={ placeholder || __( 'Write heading…' ) } - /> - </TextColor> + return createBlock( 'core/heading', { + ...attributes, + content: value, + } ); + } } + onReplace={ onReplace } + onRemove={ () => onReplace( [] ) } + className={ classnames( { + [ `has-text-align-${ align }` ]: align, + } ) } + placeholder={ placeholder || __( 'Write heading…' ) } + textAlign={ align } + style={ styles } + /> </> ); } diff --git a/packages/block-library/src/heading/edit.native.js b/packages/block-library/src/heading/edit.native.js deleted file mode 100644 index 8d8d8b49aef99a..00000000000000 --- a/packages/block-library/src/heading/edit.native.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Internal dependencies - */ -import HeadingToolbar from './heading-toolbar'; - -/** - * External dependencies - */ -import { View } from 'react-native'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { - RichText, - BlockControls, - __experimentalUseColors, -} from '@wordpress/block-editor'; -import { createBlock } from '@wordpress/blocks'; - -const HeadingEdit = ( { - attributes, - mergeBlocks, - onFocus, - onReplace, - setAttributes, - style, -} ) => { - const { align, content, level, placeholder } = attributes; - - /* eslint-disable @wordpress/no-unused-vars-before-return */ - const { TextColor } = __experimentalUseColors( [ - { name: 'textColor', property: 'color' }, - ] ); - /* eslint-enable @wordpress/no-unused-vars-before-return */ - - return ( - <View onAccessibilityTap={ onFocus }> - <BlockControls> - <HeadingToolbar - minLevel={ 2 } - maxLevel={ 7 } - selectedLevel={ level } - onChange={ ( newLevel ) => - setAttributes( { level: newLevel } ) - } - isCollapsed={ false } - /> - </BlockControls> - <TextColor> - <RichText - identifier="content" - tagName={ 'h' + level } - value={ content } - style={ style } - onChange={ ( value ) => - setAttributes( { content: value } ) - } - onMerge={ mergeBlocks } - onSplit={ ( value ) => { - if ( ! value ) { - return createBlock( 'core/paragraph' ); - } - - return createBlock( 'core/heading', { - ...attributes, - content: value, - } ); - } } - onReplace={ onReplace } - onRemove={ () => onReplace( [] ) } - placeholder={ placeholder || __( 'Write heading…' ) } - textAlign={ align } - /> - </TextColor> - </View> - ); -}; - -export default HeadingEdit; diff --git a/packages/block-library/src/heading/heading-level-icon.js b/packages/block-library/src/heading/heading-level-icon.js index 29a60cd93d7217..eef2b3af3b5e7e 100644 --- a/packages/block-library/src/heading/heading-level-icon.js +++ b/packages/block-library/src/heading/heading-level-icon.js @@ -18,8 +18,8 @@ export default function HeadingLevelIcon( { level, isPressed = false } ) { return ( <SVG - width="20" - height="20" + width="24" + height="24" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" isPressed={ isPressed } diff --git a/packages/block-library/src/heading/index.js b/packages/block-library/src/heading/index.js index de82e618486222..2b9eac45e956d7 100644 --- a/packages/block-library/src/heading/index.js +++ b/packages/block-library/src/heading/index.js @@ -34,6 +34,9 @@ export const settings = { anchor: true, __unstablePasteTextInline: true, lightBlockWrapper: true, + __experimentalColor: true, + __experimentalLineHeight: true, + __experimentalFontSize: true, }, example: { attributes: { diff --git a/packages/block-library/src/heading/save.js b/packages/block-library/src/heading/save.js index 5b2adacec2a633..00ecf40e1c27ce 100644 --- a/packages/block-library/src/heading/save.js +++ b/packages/block-library/src/heading/save.js @@ -6,17 +6,13 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { getColorClassName, RichText } from '@wordpress/block-editor'; +import { RichText } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { align, content, customTextColor, level, textColor } = attributes; + const { align, content, level } = attributes; const tagName = 'h' + level; - const textClass = getColorClassName( 'color', textColor ); - const className = classnames( { - [ textClass ]: textClass, - 'has-text-color': textColor || customTextColor, [ `has-text-align-${ align }` ]: align, } ); @@ -24,9 +20,6 @@ export default function save( { attributes } ) { <RichText.Content className={ className ? className : undefined } tagName={ tagName } - style={ { - color: textClass ? undefined : customTextColor, - } } value={ content } /> ); diff --git a/packages/block-library/src/heading/style.scss b/packages/block-library/src/heading/style.scss new file mode 100644 index 00000000000000..31a6989c39c817 --- /dev/null +++ b/packages/block-library/src/heading/style.scss @@ -0,0 +1,10 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + &.has-background { + padding: $block-bg-padding--v $block-bg-padding--h; + } +} diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index a80dadeec55c46..30ddaefd89602e 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -541,6 +541,7 @@ export class ImageEdit extends Component { defaultedAlt = alt; } else if ( filename ) { defaultedAlt = sprintf( + /* translators: %s: file name */ __( 'This image has an empty alt attribute; its file name is %s' ), diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 14fb569a91f8b2..90c4b4707df689 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -15,7 +15,6 @@ import { requestImageFailedRetryDialog, requestImageUploadCancelDialog, requestImageFullscreenPreview, - showMediaEditorButton, } from 'react-native-gutenberg-bridge'; import { isEmpty, get, find, map } from 'lodash'; @@ -390,7 +389,6 @@ export class ImageEdit extends React.Component { <BlockAlignmentToolbar value={ align } onChange={ this.updateAlignment } - isCollapsed={ false } /> </BlockControls> ); @@ -607,8 +605,7 @@ export class ImageEdit extends React.Component { ! isUploadInProgress && ! isUploadFailed && finalWidth && - finalHeight && - showMediaEditorButton && ( + finalHeight && ( <MediaEdit allowedTypes={ [ MEDIA_TYPE_IMAGE, diff --git a/packages/block-library/src/index.native.js b/packages/block-library/src/index.native.js index aaa2305a9fdc83..4efee4a3deda82 100644 --- a/packages/block-library/src/index.native.js +++ b/packages/block-library/src/index.native.js @@ -148,13 +148,16 @@ export const registerCoreBlocks = () => { mediaText, preformatted, gallery, + columns, + column, group, button, spacer, shortcode, latestPosts, devOnly( verse ), - devOnly( cover ), + cover, + devOnly( pullquote ), ].forEach( registerBlock ); setDefaultBlockName( paragraph.name ); diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 746919eba3935c..8e58ddd7260554 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -363,20 +363,30 @@ class LatestPostsEdit extends Component { [ `align${ featuredImageAlign }` ]: !! featuredImageAlign, } ); - const postExcerpt = + const needsReadMore = excerptLength < excerpt.trim().split( ' ' ).length && - post.excerpt.raw === '' - ? excerpt - .trim() - .split( ' ', excerptLength ) - .join( ' ' ) + - ' ... <a href="' + - post.link + - '" target="_blank" rel="noopener noreferrer">' + - __( 'Read more' ) + - '</a>' - : excerpt; + post.excerpt.raw === ''; + + const postExcerpt = needsReadMore ? ( + <> + { excerpt + .trim() + .split( ' ', excerptLength ) + .join( ' ' ) } + { /* translators: excerpt truncation character, default … */ } + { __( ' … ' ) } + <a + href={ post.link } + target="_blank" + rel="noopener noreferrer" + > + { __( 'Read more' ) } + </a> + </> + ) : ( + excerpt + ); return ( <li key={ i }> @@ -422,9 +432,7 @@ class LatestPostsEdit extends Component { { displayPostContent && displayPostContentRadio === 'excerpt' && ( <div className="wp-block-latest-posts__post-excerpt"> - <RawHTML key="html"> - { postExcerpt } - </RawHTML> + { postExcerpt } </div> ) } { displayPostContent && @@ -475,8 +483,16 @@ export default withSelect( ( select, props ) => { .map( ( { name, slug } ) => ( { value: slug, label: name } ) ); return { - defaultImageWidth: imageDimensions[ featuredImageSizeSlug ].width, - defaultImageHeight: imageDimensions[ featuredImageSizeSlug ].height, + defaultImageWidth: get( + imageDimensions, + [ featuredImageSizeSlug, 'width' ], + 0 + ), + defaultImageHeight: get( + imageDimensions, + [ featuredImageSizeSlug, 'height' ], + 0 + ), imageSizeOptions, latestPosts: ! Array.isArray( posts ) ? posts diff --git a/packages/block-library/src/latest-posts/edit.native.js b/packages/block-library/src/latest-posts/edit.native.js index 5b37ad2a530a81..37af86b2036a3f 100644 --- a/packages/block-library/src/latest-posts/edit.native.js +++ b/packages/block-library/src/latest-posts/edit.native.js @@ -185,7 +185,10 @@ class LatestPostsEdit extends Component { } onOrderChange={ this.onSetOrder } onOrderByChange={ this.onSetOrderBy } - onCategoryChange={ this.onSetCategories } + onCategoryChange={ + // eslint-disable-next-line no-undef + __DEV__ ? this.onSetCategories : undefined + } onNumberOfItemsChange={ this.onSetPostsToShow } /> </PanelBody> diff --git a/packages/block-library/src/latest-posts/index.php b/packages/block-library/src/latest-posts/index.php index 2245ae53930af1..f9002ebde627da 100644 --- a/packages/block-library/src/latest-posts/index.php +++ b/packages/block-library/src/latest-posts/index.php @@ -33,7 +33,7 @@ function block_core_latest_posts_get_excerpt_length() { * @return string Returns the post content with latest posts added. */ function render_block_core_latest_posts( $attributes ) { - global $block_core_latest_posts_excerpt_length; + global $post, $block_core_latest_posts_excerpt_length; $args = array( 'posts_per_page' => $attributes['postsToShow'], @@ -55,6 +55,7 @@ function render_block_core_latest_posts( $attributes ) { $list_items_markup = ''; foreach ( $recent_posts as $post ) { + $list_items_markup .= '<li>'; if ( $attributes['displayFeaturedImage'] && has_post_thumbnail( $post ) ) { @@ -108,21 +109,9 @@ function render_block_core_latest_posts( $attributes ) { $trimmed_excerpt = get_the_excerpt( $post ); $list_items_markup .= sprintf( - '<div class="wp-block-latest-posts__post-excerpt">%1$s', + '<div class="wp-block-latest-posts__post-excerpt">%1$s</div>', $trimmed_excerpt ); - - if ( strpos( $trimmed_excerpt, ' &hellip; ' ) !== false ) { - $list_items_markup .= sprintf( - '<a href="%1$s">%2$s</a></div>', - esc_url( get_permalink( $post ) ), - __( 'Read more' ) - ); - } else { - $list_items_markup .= sprintf( - '</div>' - ); - } } if ( isset( $attributes['displayPostContent'] ) && $attributes['displayPostContent'] diff --git a/packages/block-library/src/media-text/block.json b/packages/block-library/src/media-text/block.json index eb16cddf7d6a64..44cca8579e99c9 100644 --- a/packages/block-library/src/media-text/block.json +++ b/packages/block-library/src/media-text/block.json @@ -6,12 +6,6 @@ "type": "string", "default": "wide" }, - "backgroundColor": { - "type": "string" - }, - "customBackgroundColor": { - "type": "string" - }, "mediaAlt": { "type": "string", "source": "attribute", diff --git a/packages/block-library/src/media-text/deprecated.js b/packages/block-library/src/media-text/deprecated.js index 83512f4ee163fb..cd06840df83df6 100644 --- a/packages/block-library/src/media-text/deprecated.js +++ b/packages/block-library/src/media-text/deprecated.js @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import { noop } from 'lodash'; +import { noop, isEmpty, omit } from 'lodash'; /** * WordPress dependencies @@ -16,6 +16,21 @@ import { imageFillStyles } from './media-container'; const DEFAULT_MEDIA_WIDTH = 50; +const migrateCustomColors = ( attributes ) => { + if ( ! attributes.customBackgroundColor ) { + return attributes; + } + const style = { + color: { + background: attributes.customBackgroundColor, + }, + }; + return { + ...omit( attributes, [ 'customBackgroundColor' ] ), + style, + }; +}; + const baseAttributes = { align: { type: 'string', @@ -24,9 +39,6 @@ const baseAttributes = { backgroundColor: { type: 'string', }, - customBackgroundColor: { - type: 'string', - }, mediaAlt: { type: 'string', source: 'attribute', @@ -41,12 +53,6 @@ const baseAttributes = { mediaId: { type: 'number', }, - mediaUrl: { - type: 'string', - source: 'attribute', - selector: 'figure video,figure img', - attribute: 'src', - }, mediaType: { type: 'string', }, @@ -64,6 +70,39 @@ export default [ { attributes: { ...baseAttributes, + customBackgroundColor: { + type: 'string', + }, + mediaLink: { + type: 'string', + }, + linkDestination: { + type: 'string', + }, + linkTarget: { + type: 'string', + source: 'attribute', + selector: 'figure a', + attribute: 'target', + }, + href: { + type: 'string', + source: 'attribute', + selector: 'figure a', + attribute: 'href', + }, + rel: { + type: 'string', + source: 'attribute', + selector: 'figure a', + attribute: 'rel', + }, + linkClass: { + type: 'string', + source: 'attribute', + selector: 'figure a', + attribute: 'class', + }, verticalAlignment: { type: 'string', }, @@ -74,6 +113,124 @@ export default [ type: 'object', }, }, + migrate: migrateCustomColors, + save( { attributes } ) { + const { + backgroundColor, + customBackgroundColor, + isStackedOnMobile, + mediaAlt, + mediaPosition, + mediaType, + mediaUrl, + mediaWidth, + mediaId, + verticalAlignment, + imageFill, + focalPoint, + linkClass, + href, + linkTarget, + rel, + } = attributes; + const newRel = isEmpty( rel ) ? undefined : rel; + + let image = ( + <img + src={ mediaUrl } + alt={ mediaAlt } + className={ + mediaId && mediaType === 'image' + ? `wp-image-${ mediaId }` + : null + } + /> + ); + + if ( href ) { + image = ( + <a + className={ linkClass } + href={ href } + target={ linkTarget } + rel={ newRel } + > + { image } + </a> + ); + } + + const mediaTypeRenders = { + image: () => image, + video: () => <video controls src={ mediaUrl } />, + }; + const backgroundClass = getColorClassName( + 'background-color', + backgroundColor + ); + const className = classnames( { + 'has-media-on-the-right': 'right' === mediaPosition, + 'has-background': backgroundClass || customBackgroundColor, + [ backgroundClass ]: backgroundClass, + 'is-stacked-on-mobile': isStackedOnMobile, + [ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, + 'is-image-fill': imageFill, + } ); + const backgroundStyles = imageFill + ? imageFillStyles( mediaUrl, focalPoint ) + : {}; + + let gridTemplateColumns; + if ( mediaWidth !== DEFAULT_MEDIA_WIDTH ) { + gridTemplateColumns = + 'right' === mediaPosition + ? `auto ${ mediaWidth }%` + : `${ mediaWidth }% auto`; + } + const style = { + backgroundColor: backgroundClass + ? undefined + : customBackgroundColor, + gridTemplateColumns, + }; + return ( + <div className={ className } style={ style }> + <figure + className="wp-block-media-text__media" + style={ backgroundStyles } + > + { ( mediaTypeRenders[ mediaType ] || noop )() } + </figure> + <div className="wp-block-media-text__content"> + <InnerBlocks.Content /> + </div> + </div> + ); + }, + }, + { + attributes: { + ...baseAttributes, + customBackgroundColor: { + type: 'string', + }, + mediaUrl: { + type: 'string', + source: 'attribute', + selector: 'figure video,figure img', + attribute: 'src', + }, + verticalAlignment: { + type: 'string', + }, + imageFill: { + type: 'boolean', + }, + focalPoint: { + type: 'object', + }, + }, + migrate: migrateCustomColors, save( { attributes } ) { const { backgroundColor, @@ -147,7 +304,18 @@ export default [ }, }, { - attributes: baseAttributes, + attributes: { + ...baseAttributes, + customBackgroundColor: { + type: 'string', + }, + mediaUrl: { + type: 'string', + source: 'attribute', + selector: 'figure video,figure img', + attribute: 'src', + }, + }, save( { attributes } ) { const { backgroundColor, diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js index 03a767862f1be4..86fd9c808596ce 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit.js @@ -15,8 +15,6 @@ import { BlockVerticalAlignmentToolbar, InnerBlocks, InspectorControls, - PanelColorSettings, - withColors, __experimentalImageURLInputUI as ImageURLInputUI, } from '@wordpress/block-editor'; import { Component } from '@wordpress/element'; @@ -183,10 +181,8 @@ class MediaTextEdit extends Component { const { attributes, className, - backgroundColor, isSelected, setAttributes, - setBackgroundColor, image, } = this.props; const { @@ -210,8 +206,6 @@ class MediaTextEdit extends Component { const classNames = classnames( className, { 'has-media-on-the-right': 'right' === mediaPosition, 'is-selected': isSelected, - 'has-background': backgroundColor.class || backgroundColor.color, - [ backgroundColor.class ]: backgroundColor.class, 'is-stacked-on-mobile': isStackedOnMobile, [ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, 'is-image-fill': imageFill, @@ -224,15 +218,7 @@ class MediaTextEdit extends Component { const style = { gridTemplateColumns, msGridColumns: gridTemplateColumns, - backgroundColor: backgroundColor.color, }; - const colorSettings = [ - { - value: backgroundColor.color, - onChange: setBackgroundColor, - label: __( 'Background color' ), - }, - ]; const toolbarControls = [ { icon: pullLeft, @@ -311,11 +297,6 @@ class MediaTextEdit extends Component { <> <InspectorControls> { mediaTextGeneralSettings } - <PanelColorSettings - title={ __( 'Color settings' ) } - initialOpen={ false } - colorSettings={ colorSettings } - /> </InspectorControls> <BlockControls> <ToolbarGroup controls={ toolbarControls } /> @@ -352,7 +333,6 @@ class MediaTextEdit extends Component { } export default compose( [ - withColors( 'backgroundColor' ), withSelect( ( select, props ) => { const { getMedia } = select( 'core' ); const { diff --git a/packages/block-library/src/media-text/edit.native.js b/packages/block-library/src/media-text/edit.native.js index 3a582686c7c7b6..d2c70814cd5f7b 100644 --- a/packages/block-library/src/media-text/edit.native.js +++ b/packages/block-library/src/media-text/edit.native.js @@ -184,14 +184,13 @@ class MediaTextEdit extends Component { backgroundColor, setAttributes, isSelected, - isParentSelected, - isAncestorSelected, } = this.props; const { isStackedOnMobile, mediaPosition, mediaWidth, verticalAlignment, + style, } = attributes; const { containerWidth } = this.state; @@ -202,11 +201,14 @@ class MediaTextEdit extends Component { : this.state.mediaWidth || mediaWidth; const widthString = `${ temporaryMediaWidth }%`; - const innerBlockContainerStyle = ! shouldStack && { - ...styles.paddingHorizontalNone, - ...( mediaPosition === 'right' && styles.innerPaddingMediaOnRight ), - ...( mediaPosition === 'left' && styles.innerPaddingMediaOnLeft ), - }; + const innerBlockContainerStyle = ! shouldStack + ? styles.innerBlock + : { + ...( mediaPosition === 'left' + ? styles.innerBlockStackMediaLeft + : styles.innerBlockStackMediaRight ), + }; + const containerStyles = { ...styles[ 'wp-block-media-text' ], ...styles[ @@ -215,20 +217,28 @@ class MediaTextEdit extends Component { ...( mediaPosition === 'right' ? styles[ 'has-media-on-the-right' ] : {} ), - ...( shouldStack ? styles[ 'is-stacked-on-mobile' ] : {} ), + ...( shouldStack && styles[ 'is-stacked-on-mobile' ] ), ...( shouldStack && mediaPosition === 'right' ? styles[ 'is-stacked-on-mobile.has-media-on-the-right' ] : {} ), - backgroundColor: backgroundColor.color, + ...( isSelected && styles[ 'is-selected' ] ), + backgroundColor: + ( style && style.color && style.color.background ) || + backgroundColor.color, }; + const innerBlockWidth = shouldStack ? 100 : 100 - temporaryMediaWidth; const innerBlockWidthString = `${ innerBlockWidth }%`; - const mediaContainerStyle = { - ...( isParentSelected || isAncestorSelected - ? styles.denseMediaPadding - : styles.regularMediaPadding ), - ...( isSelected && styles.innerPadding ), - }; + + const mediaContainerStyle = shouldStack + ? { + ...( mediaPosition === 'left' && styles.mediaStackLeft ), + ...( mediaPosition === 'right' && styles.mediaStackRight ), + } + : { + ...( mediaPosition === 'left' && styles.mediaLeft ), + ...( mediaPosition === 'right' && styles.mediaRight ), + }; const toolbarControls = [ { @@ -256,7 +266,6 @@ class MediaTextEdit extends Component { <BlockVerticalAlignmentToolbar onChange={ onVerticalAlignmentChange } value={ verticalAlignment } - isCollapsed={ false } /> </BlockControls> <View diff --git a/packages/block-library/src/media-text/index.js b/packages/block-library/src/media-text/index.js index 97996b6a8bb5e9..db22f30b70abf0 100644 --- a/packages/block-library/src/media-text/index.js +++ b/packages/block-library/src/media-text/index.js @@ -25,6 +25,7 @@ export const settings = { supports: { align: [ 'wide', 'full' ], html: false, + __experimentalColor: { gradients: true }, }, example: { attributes: { diff --git a/packages/block-library/src/media-text/save.js b/packages/block-library/src/media-text/save.js index 12a39e2d45f0a4..f7b676b94c18fb 100644 --- a/packages/block-library/src/media-text/save.js +++ b/packages/block-library/src/media-text/save.js @@ -7,7 +7,7 @@ import { noop, isEmpty } from 'lodash'; /** * WordPress dependencies */ -import { InnerBlocks, getColorClassName } from '@wordpress/block-editor'; +import { InnerBlocks } from '@wordpress/block-editor'; /** * Internal dependencies @@ -18,8 +18,6 @@ const DEFAULT_MEDIA_WIDTH = 50; export default function save( { attributes } ) { const { - backgroundColor, - customBackgroundColor, isStackedOnMobile, mediaAlt, mediaPosition, @@ -66,14 +64,8 @@ export default function save( { attributes } ) { image: () => image, video: () => <video controls src={ mediaUrl } />, }; - const backgroundClass = getColorClassName( - 'background-color', - backgroundColor - ); const className = classnames( { 'has-media-on-the-right': 'right' === mediaPosition, - 'has-background': backgroundClass || customBackgroundColor, - [ backgroundClass ]: backgroundClass, 'is-stacked-on-mobile': isStackedOnMobile, [ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment, 'is-image-fill': imageFill, @@ -90,7 +82,6 @@ export default function save( { attributes } ) { : `${ mediaWidth }% auto`; } const style = { - backgroundColor: backgroundClass ? undefined : customBackgroundColor, gridTemplateColumns, }; return ( diff --git a/packages/block-library/src/media-text/style.native.scss b/packages/block-library/src/media-text/style.native.scss index 75fb16c740df81..4e8cca364896da 100644 --- a/packages/block-library/src/media-text/style.native.scss +++ b/packages/block-library/src/media-text/style.native.scss @@ -1,3 +1,5 @@ +$media-to-text: 12px; + .wp-block-media-text { display: flex; align-items: flex-start; @@ -28,6 +30,10 @@ align-items: flex-end; } +.is-selected { + padding-bottom: 8; +} + .content { flex: 1; } @@ -104,27 +110,35 @@ color: $gray-dark; } -.innerPadding { - padding: $block-selected-to-content; +// Inner blocks STACK +.innerBlockStackMediaLeft { + margin-top: $media-to-text; +} + +.innerBlockStackMediaRight { + margin-bottom: $media-to-text; } -.innerPaddingMediaOnLeft { - padding-right: $block-selected-to-content; +// Inner blocks +.innerBlock { + padding-right: $media-to-text; + padding-left: $media-to-text; } -.innerPaddingMediaOnRight { - padding-left: $block-selected-to-content; +// Media STACK +.mediaStackLeft { + margin-bottom: $media-to-text; } -.paddingHorizontalNone { - padding-left: 0; - padding-right: 0; +.mediaStackRight { + margin-top: $media-to-text; } -.regularMediaPadding { - padding: $block-edge-to-content; +// Media +.mediaLeft { + padding-right: $media-to-text; } -.denseMediaPadding { - padding: $block-media-container-to-content; +.mediaRight { + padding-left: $media-to-text; } diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index 2a59f2cbffbecc..76549eac202696 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -65,8 +65,8 @@ /*!rtl:end:ignore*/ } -.wp-block-media-text > figure > img, -.wp-block-media-text > figure > video { +.wp-block-media-text__media img, +.wp-block-media-text__media video { max-width: unset; width: 100%; vertical-align: middle; diff --git a/packages/block-library/src/missing/edit.js b/packages/block-library/src/missing/edit.js index b9caa890a5b950..3f1d39f11edc01 100644 --- a/packages/block-library/src/missing/edit.js +++ b/packages/block-library/src/missing/edit.js @@ -17,6 +17,7 @@ function MissingBlockWarning( { attributes, convertToHTML } ) { let messageHTML; if ( hasContent && hasHTMLBlock ) { messageHTML = sprintf( + /* translators: %s: block name */ __( 'Your site doesn’t include support for the "%s" block. You can leave this block intact, convert its content to a Custom HTML block, or remove it entirely.' ), @@ -29,6 +30,7 @@ function MissingBlockWarning( { attributes, convertToHTML } ) { ); } else { messageHTML = sprintf( + /* translators: %s: block name */ __( 'Your site doesn’t include support for the "%s" block. You can leave this block intact or remove it entirely.' ), diff --git a/packages/block-library/src/missing/edit.native.js b/packages/block-library/src/missing/edit.native.js index f77e29ce9c94a3..f4072ca42000db 100644 --- a/packages/block-library/src/missing/edit.native.js +++ b/packages/block-library/src/missing/edit.native.js @@ -75,11 +75,12 @@ export class UnsupportedBlockEdit extends Component { styles.infoSheetIconDark ); - // translators: %s: Name of the block const titleFormat = Platform.OS === 'android' - ? __( "'%s' isn't yet supported on WordPress for Android" ) - : __( "'%s' isn't yet supported on WordPress for iOS" ); + ? // translators: %s: Name of the block + __( "'%s' isn't yet supported on WordPress for Android" ) + : // translators: %s: Name of the block + __( "'%s' isn't yet supported on WordPress for iOS" ); const infoTitle = sprintf( titleFormat, title ); return ( diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index 09fc6ae3726738..b20ca1e528eef6 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -228,11 +228,6 @@ function NavigationLinkEdit( { 'core/strikethrough', ] } /> - { showSubmenuIcon && ( - <span className="wp-block-navigation-link__submenu-icon"> - <ItemSubmenuIcon /> - </span> - ) } { isLinkOpen && ( <Popover position="bottom center" @@ -285,6 +280,11 @@ function NavigationLinkEdit( { </Popover> ) } </div> + { showSubmenuIcon && ( + <span className="wp-block-navigation-link__submenu-icon"> + <ItemSubmenuIcon /> + </span> + ) } <InnerBlocks allowedBlocks={ [ 'core/navigation-link' ] } renderAppender={ diff --git a/packages/block-library/src/navigation/edit.js b/packages/block-library/src/navigation/edit.js index 36039e879fdcee..357811b021c91a 100644 --- a/packages/block-library/src/navigation/edit.js +++ b/packages/block-library/src/navigation/edit.js @@ -32,7 +32,8 @@ import { import { compose } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { menu } from '@wordpress/icons'; - +import { addQueryArgs } from '@wordpress/url'; +import { useApiFetch } from '@wordpress/api-fetch'; /** * Internal dependencies */ @@ -46,9 +47,6 @@ function Navigation( { clientId, fontSize, hasExistingNavItems, - hasResolvedPages, - isRequestingPages, - pages, setAttributes, setFontSize, updateNavItemBlocks, @@ -57,16 +55,9 @@ function Navigation( { // // HOOKS // - /* eslint-disable @wordpress/no-unused-vars-before-return */ const ref = useRef(); const { selectBlock } = useDispatch( 'core/block-editor' ); - - const { - TextColor, - BackgroundColor, - InspectorControlsColorPanel, - ColorPanel, - } = __experimentalUseColors( + const { TextColor, BackgroundColor, ColorPanel } = __experimentalUseColors( [ { name: 'textColor', property: 'color' }, { name: 'backgroundColor', className: 'has-background' }, @@ -87,14 +78,35 @@ function Navigation( { [ fontSize.size ] ); - /* eslint-enable @wordpress/no-unused-vars-before-return */ const { navigatorToolbarButton, navigatorModal } = useBlockNavigator( clientId ); + const baseUrl = '/wp/v2/pages'; + + // "view" is required to ensure Pages are returned by REST API + // for users with lower capabilities such as "Contributor" otherwise + // Pages are not returned in the request if "edit" context is set + const context = 'view'; + + const filterDefaultPages = { + parent: 0, + order: 'asc', + orderby: 'id', + context, + }; + + const queryPath = addQueryArgs( baseUrl, filterDefaultPages ); + + const { isLoading: isRequestingPages, data: pages } = useApiFetch( + queryPath + ); + + const hasPages = !! pages; + // Builds navigation links from default Pages. const defaultPagesNavigationItems = useMemo( () => { - if ( ! pages ) { + if ( ! hasPages ) { return null; } @@ -134,12 +146,6 @@ function Navigation( { selectBlock( clientId ); } - const hasPages = hasResolvedPages && pages && pages.length; - - const blockClassNames = classnames( className, { - [ `items-justified-${ attributes.itemsJustification }` ]: attributes.itemsJustification, - [ fontSize.class ]: fontSize.class, - } ); const blockInlineStyles = { fontSize: fontSize.size ? fontSize.size + 'px' : undefined, }; @@ -184,6 +190,12 @@ function Navigation( { ); } + const blockClassNames = classnames( className, { + [ `items-justified-${ attributes.itemsJustification }` ]: attributes.itemsJustification, + [ fontSize.class ]: fontSize.class, + 'is-vertical': attributes.orientation === 'vertical', + } ); + // UI State: rendered Block UI return ( <Fragment> @@ -243,7 +255,6 @@ function Navigation( { /> </PanelBody> </InspectorControls> - { InspectorControlsColorPanel } <InspectorControls> <PanelBody title={ __( 'Display settings' ) }> <ToggleControl @@ -270,12 +281,19 @@ function Navigation( { ref={ ref } allowedBlocks={ [ 'core/navigation-link' ] } templateInsertUpdatesSelection={ false } - __experimentalMoverDirection={ 'horizontal' } + __experimentalMoverDirection={ + attributes.orientation + } __experimentalTagName="ul" __experimentalAppenderTagName="li" __experimentalPassedProps={ { className: 'wp-block-navigation__container', } } + __experimentalCaptureToolbars={ true } + // Template lock set to false here so that the Nav + // Block on the experimental menus screen does not + // inherit templateLock={ 'all' }. + templateLock={ false } /> </Block.nav> </BackgroundColor> @@ -289,31 +307,8 @@ export default compose( [ withSelect( ( select, { clientId } ) => { const innerBlocks = select( 'core/block-editor' ).getBlocks( clientId ); - const filterDefaultPages = { - parent: 0, - order: 'asc', - orderby: 'id', - }; - - const pagesSelect = [ - 'core', - 'getEntityRecords', - [ 'postType', 'page', filterDefaultPages ], - ]; - return { hasExistingNavItems: !! innerBlocks.length, - pages: select( 'core' ).getEntityRecords( - 'postType', - 'page', - filterDefaultPages - ), - isRequestingPages: select( 'core/data' ).isResolving( - ...pagesSelect - ), - hasResolvedPages: select( 'core/data' ).hasFinishedResolution( - ...pagesSelect - ), }; } ), withDispatch( ( dispatch, { clientId } ) => { diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss index 7b7f4a3a192e87..4098185c23a59e 100644 --- a/packages/block-library/src/navigation/editor.scss +++ b/packages/block-library/src/navigation/editor.scss @@ -19,6 +19,10 @@ $navigation-item-height: 46px; align-items: center; } +.wp-block-navigation.is-vertical .block-list-appender { + margin: $grid-unit-10; +} + .wp-block-navigation__inserter-content { padding: $grid-unit-20; } diff --git a/packages/block-library/src/navigation/index.js b/packages/block-library/src/navigation/index.js index 08030d5b8895d5..db72a33515837d 100644 --- a/packages/block-library/src/navigation/index.js +++ b/packages/block-library/src/navigation/index.js @@ -32,6 +32,22 @@ export const settings = { lightBlockWrapper: true, }, + variations: [ + { + name: 'horizontal', + isDefault: true, + title: __( 'Navigation (horizontal)' ), + description: __( 'Links shown in a row.' ), + attributes: { orientation: 'horizontal' }, + }, + { + name: 'vertical', + title: __( 'Navigation (vertical)' ), + description: __( 'Links shown in a column.' ), + attributes: { orientation: 'vertical' }, + }, + ], + example: { innerBlocks: [ { diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 8afba2b584d8cb..e0332a5ab206d3 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -255,6 +255,9 @@ function block_core_navigation_build_html( $attributes, $block, $colors, $font_s $html .= '</span>'; + $html .= '</a>'; + // End anchor tag content. + // Append submenu icon to top-level item. // it shows the icon as default, when 'showSubmenuIcon' is not set, // or when it's set and also not False. @@ -268,9 +271,6 @@ function block_core_navigation_build_html( $attributes, $block, $colors, $font_s $html .= '<span class="wp-block-navigation-link__submenu-icon">' . block_core_navigation_render_submenu_icon() . '</span>'; } - $html .= '</a>'; - // End anchor tag content. - if ( $has_submenu ) { $html .= block_core_navigation_build_html( $attributes, $block, $colors, $font_sizes ); } @@ -292,6 +292,9 @@ function register_block_core_navigation() { 'core/navigation', array( 'attributes' => array( + 'orientation' => array( + 'type' => 'string', + ), 'className' => array( 'type' => 'string', ), diff --git a/packages/block-library/src/navigation/style.scss b/packages/block-library/src/navigation/style.scss index 6d8fa6f441e2e2..0f824d083670a6 100644 --- a/packages/block-library/src/navigation/style.scss +++ b/packages/block-library/src/navigation/style.scss @@ -1,267 +1,132 @@ -$navigation-menu-height: $grid-unit-10 * 7; -$navigation-sub-menu-height: $grid-unit-10 * 5; -$navigation-sub-menu-width: $grid-unit-10 * 25; - -/* -* Reset the default list styles -*/ - -.wp-block-navigation > ul { - display: block; +.wp-block-navigation__container { + // Reset the default list styles list-style: none; margin: 0; padding-left: 0; - @include break-small { - display: flex; - flex-wrap: wrap; - } + // Horizontal layout + display: flex; + flex-wrap: wrap; - // Submenu - ul { - list-style: none; - padding-left: 0; - margin-top: 0; - margin-left: 0; + // Vertical layout - li { - margin: 0; - } + .is-vertical & { + display: block; } } -/* -* Styles for submenu flyout -*/ - -.wp-block-navigation > ul { - li { - z-index: 1; - - &:hover, - &:focus-within { - cursor: pointer; - } - - // Submenu Display - &:hover > ul, - &:focus-within > ul, - & ul:hover, - & ul:focus { - visibility: visible; - opacity: 1; - display: flex; - flex-direction: column; - } - } +.wp-block-navigation-link { + display: flex; + align-items: center; + position: relative; + margin: 0; + padding: $grid-unit-10; +} - & > li ul { +// Styles for submenu flyout +.has-child { + .wp-block-navigation__container { + border: $border-width solid rgba(0, 0, 0, 0.15); + padding: $grid-unit-10 * 0.75 $grid-unit-10 * 2; + background-color: inherit; + color: inherit; position: absolute; left: 0; top: 100%; - min-width: $navigation-sub-menu-width; - max-width: $navigation-sub-menu-width; + z-index: 1; opacity: 0; transition: opacity 0.1s linear; visibility: hidden; - } -} -/* -* Styles shared between editor and frontend -*/ -.wp-block-navigation, -.wp-block-navigation .block-editor-block-list__layout { - display: flex; - flex-wrap: wrap; -} - -.wp-block-navigation { - - // set a width on the editor submenus - .block-editor-block-list__layout .block-editor-block-list__layout { - width: $navigation-sub-menu-width; - } - - &, - > .wp-block-navigation__container { - align-items: center; - width: 100%; - - > .wp-block-navigation-link { - display: flex; - margin-top: 0; - margin-bottom: 0; - } - } - - // Main menu - .wp-block-navigation-link { - position: relative; - margin: 0; - min-height: $navigation-menu-height; - display: flex; - line-height: 1.4; - - // Sub menus - .wp-block, - .wp-block-navigation-link { - min-height: auto; // reset the min-height and rely on padding - padding: 0; - } - - // Sub menus (editor canvas) - .wp-block .wp-block-navigation-link { - margin: 0; - } - - &.has-child > .wp-block-navigation__container { - // Box model - display: flex; - border: $border-width solid rgba(0, 0, 0, 0.15); - - // Position (first level) - position: absolute; - z-index: 1; - top: 100%; - left: 0; // just under the main menu item. - - // Position (nested levels) - .block-editor-inner-blocks, + // Nested submenus sit to the left on large breakpoints + @include break-medium { .wp-block-navigation__container { left: 100%; - top: - $border-width; + top: -$border-width; } } + } + // Separating out hover and focus-within so hover works again on IE: https://davidwalsh.name/css-focus-within#comment-513401 + // We will need to replace focus-within with a JS solution for IE keyboard support. + &:hover { + cursor: pointer; - // Inherit colors from menu - .wp-block-navigation__container { - background-color: inherit; - color: inherit; - } - - // All links - .wp-block-navigation-link__content { + > .wp-block-navigation__container { + visibility: visible; + opacity: 1; display: flex; - align-items: center; - width: max-content; - padding: $grid-unit-10 * 0.75 $grid-unit-10 * 2; - } - - // Submenu links only - .wp-block-navigation-link { - - &:first-child:not(:only-child) .wp-block-navigation-link__content { - padding-top: $grid-unit-10; - } - - &:last-child .wp-block-navigation-link__content { - padding-bottom: $grid-unit-10; - } - } - - &.has-child .wp-block-navigation-link__content { - min-width: 100%; - padding-right: $grid-unit-10 * 4; - position: relative; - } - - .wp-block-navigation-link__submenu-icon { - position: absolute; - right: $grid-unit-10 * 2; - - svg { - fill: currentColor; - } + flex-direction: column; } + } - // reset rotation of submenu indicator icons on nested levels - .wp-block-navigation-link svg { - transform: rotate(0); - } + &:focus-within { + cursor: pointer; - &.has-text-color .wp-block-navigation-link__content { - color: inherit; + > .wp-block-navigation__container { + visibility: visible; + opacity: 1; + display: flex; + flex-direction: column; } } } -// Styles -.wp-block-navigation { +// All links +.wp-block-navigation-link__content { + padding: $grid-unit-10 * 0.75 $grid-unit-10 * 2; - // Default / Light styles - .wp-block-navigation-link, - &.is-style-light .wp-block-navigation-link { - // No text color - &:not(.has-text-color) > .wp-block-navigation__container { - color: $light-style-sub-menu-text-color; - } - - // No background color - &:not(.has-background) > .wp-block-navigation__container { - background-color: $light-style-sub-menu-background-color; - } + @include break-small { + width: max-content; } - // Dark styles. - &.is-style-dark .wp-block-navigation-link { - // No text color - &:not(.has-text-color) > .wp-block-navigation__container { - color: $dark-style-sub-menu-text-color; - } - - // No background color - &:not(.has-background) > .wp-block-navigation__container { - background-color: $dark-style-sub-menu-background-color; - } + .has-text-color & { + color: inherit; } } -/* -* Non-shared styles & overrides -*/ +.wp-block-navigation-link__submenu-icon { + padding: $grid-unit-10 * 0.75 $grid-unit-10 * 2; -.wp-block-navigation { + svg { + fill: currentColor; - .wp-block-navigation-link.has-child > .wp-block-navigation__container { - display: flex; - flex-direction: column; - padding: 0; + @include break-medium { + // reset rotation of submenu indicator icons on nested levels + transform: rotate(0); + } } } -/* -* TODO: organize/untangle styles below this line -*/ - -.wp-block-navigation { - - & > ul { - & > li { - & > a { - display: flex; - align-items: center; - } - - &:first-of-type > a { - padding-left: 0; - } - - &:last-of-type > a { - padding-right: 0; - } - } +// Default / Light styles +.wp-block-navigation-link, +.is-style-light .wp-block-navigation-link { + &:not(.has-text-color) .wp-block-navigation-link__content { + color: $light-style-sub-menu-text-color; } +} +.is-style-light:not(.has-background) .wp-block-navigation__container { + background-color: $light-style-sub-menu-background-color; +} - &.items-justified-left > ul { - justify-content: flex-start; +// Dark styles. +.is-style-dark .wp-block-navigation-link { + &:not(.has-text-color) .wp-block-navigation-link__content { + color: $dark-style-sub-menu-text-color; } +} +.is-style-dark:not(.has-background) .wp-block-navigation__container { + background-color: $dark-style-sub-menu-background-color; +} - &.items-justified-center > ul { - justify-content: center; - } +// Jutification. +.items-justified-left > ul { + justify-content: flex-start; +} - &.items-justified-right > ul { - justify-content: flex-end; - } +.items-justified-center > ul { + justify-content: center; +} + +.items-justified-right > ul { + justify-content: flex-end; } diff --git a/packages/block-library/src/navigation/theme.scss b/packages/block-library/src/navigation/theme.scss index 0b80d85004697a..d628390770ebbc 100644 --- a/packages/block-library/src/navigation/theme.scss +++ b/packages/block-library/src/navigation/theme.scss @@ -4,3 +4,8 @@ list-style: none; } } + +// Overrides generic ".entry-content li" styles on the front end. +.wp-block-navigation-link.wp-block-navigation-link { + margin: 0; +} diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index 4f1d668b7c4d5c..acd5e48f0f63e0 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -18,27 +18,12 @@ "placeholder": { "type": "string" }, - "textColor": { - "type": "string" - }, - "customTextColor": { - "type": "string" - }, - "backgroundColor": { - "type": "string" - }, - "customBackgroundColor": { - "type": "string" - }, - "fontSize": { - "type": "string" - }, - "customFontSize": { - "type": "number" - }, "direction": { "type": "string", - "enum": [ "ltr", "rtl" ] + "enum": [ + "ltr", + "rtl" + ] } } } diff --git a/packages/block-library/src/paragraph/deprecated.js b/packages/block-library/src/paragraph/deprecated.js index 8c0502d808079f..24896a034207d0 100644 --- a/packages/block-library/src/paragraph/deprecated.js +++ b/packages/block-library/src/paragraph/deprecated.js @@ -38,31 +38,133 @@ const blockAttributes = { textColor: { type: 'string', }, - customTextColor: { - type: 'string', - }, backgroundColor: { type: 'string', }, - customBackgroundColor: { - type: 'string', - }, fontSize: { type: 'string', }, - customFontSize: { - type: 'number', - }, direction: { type: 'string', enum: [ 'ltr', 'rtl' ], }, + style: { + type: 'object', + }, +}; + +const migrateCustomColorsAndFontSizes = ( attributes ) => { + if ( + ! attributes.customTextColor && + ! attributes.customBackgroundColor && + ! attributes.customFontSize + ) { + return attributes; + } + const style = {}; + if ( attributes.customTextColor || attributes.customBackgroundColor ) { + style.color = {}; + } + if ( attributes.customTextColor ) { + style.color.text = attributes.customTextColor; + } + if ( attributes.customBackgroundColor ) { + style.color.background = attributes.customBackgroundColor; + } + if ( attributes.customFontSize ) { + style.typography = { fontSize: attributes.customFontSize }; + } + return { + ...omit( attributes, [ + 'customTextColor', + 'customBackgroundColor', + 'customFontSize', + ] ), + style, + }; }; const deprecated = [ { supports, - attributes: blockAttributes, + attributes: { + ...omit( blockAttributes, [ 'style' ] ), + customTextColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + customFontSize: { + type: 'number', + }, + }, + migrate: migrateCustomColorsAndFontSizes, + save( { attributes } ) { + const { + align, + content, + dropCap, + backgroundColor, + textColor, + customBackgroundColor, + customTextColor, + fontSize, + customFontSize, + direction, + } = attributes; + + const textClass = getColorClassName( 'color', textColor ); + const backgroundClass = getColorClassName( + 'background-color', + backgroundColor + ); + const fontSizeClass = getFontSizeClass( fontSize ); + + const className = classnames( { + 'has-text-color': textColor || customTextColor, + 'has-background': backgroundColor || customBackgroundColor, + 'has-drop-cap': dropCap, + [ `has-text-align-${ align }` ]: align, + [ fontSizeClass ]: fontSizeClass, + [ textClass ]: textClass, + [ backgroundClass ]: backgroundClass, + } ); + + const styles = { + backgroundColor: backgroundClass + ? undefined + : customBackgroundColor, + color: textClass ? undefined : customTextColor, + fontSize: fontSizeClass ? undefined : customFontSize, + }; + + return ( + <RichText.Content + tagName="p" + style={ styles } + className={ className ? className : undefined } + value={ content } + dir={ direction } + /> + ); + }, + }, + { + supports, + attributes: { + ...omit( blockAttributes, [ 'style' ] ), + customTextColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + customFontSize: { + type: 'number', + }, + }, + migrate: migrateCustomColorsAndFontSizes, save( { attributes } ) { const { align, @@ -116,11 +218,21 @@ const deprecated = [ { supports, attributes: { - ...blockAttributes, + ...omit( blockAttributes, [ 'style' ] ), + customTextColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + customFontSize: { + type: 'number', + }, width: { type: 'string', }, }, + migrate: migrateCustomColorsAndFontSizes, save( { attributes } ) { const { width, @@ -179,9 +291,7 @@ const deprecated = [ type: 'number', }, }, - 'customFontSize', - 'customTextColor', - 'customBackgroundColor' + [ 'style' ] ), save( { attributes } ) { const { @@ -215,8 +325,8 @@ const deprecated = [ ); }, migrate( attributes ) { - return omit( - { + return migrateCustomColorsAndFontSizes( + omit( { ...attributes, customFontSize: isFinite( attributes.fontSize ) ? attributes.fontSize @@ -231,8 +341,8 @@ const deprecated = [ '#' === attributes.backgroundColor[ 0 ] ? attributes.backgroundColor : undefined, - }, - [ 'fontSize', 'textColor', 'backgroundColor' ] + } ), + [ 'fontSize', 'textColor', 'backgroundColor', 'style' ] ); }, }, diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index 105b1a502c763e..bcae630f0e5ac9 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -11,15 +11,12 @@ import { PanelBody, ToggleControl, ToolbarGroup } from '@wordpress/components'; import { AlignmentToolbar, BlockControls, - FontSizePicker, InspectorControls, RichText, - withFontSizes, - __experimentalUseColors, __experimentalBlock as Block, + getFontSize, } from '@wordpress/block-editor'; import { createBlock } from '@wordpress/blocks'; -import { compose } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; import { useEffect, useState, useRef } from '@wordpress/element'; import { formatLtr } from '@wordpress/icons'; @@ -75,39 +72,32 @@ function useDropCapMinimumHeight( isDropCap, deps ) { function ParagraphBlock( { attributes, - fontSize, mergeBlocks, onReplace, setAttributes, - setFontSize, } ) { - const { align, content, dropCap, placeholder, direction } = attributes; - + const { + align, + content, + direction, + dropCap, + placeholder, + fontSize, + style, + } = attributes; + const { fontSizes } = useSelect( ( select ) => + select( 'core/block-editor' ).getSettings() + ); const ref = useRef(); + const fontSizeObject = getFontSize( fontSizes, fontSize, style?.fontSize ); const dropCapMinimumHeight = useDropCapMinimumHeight( dropCap, [ - fontSize.size, + fontSizeObject.size, ] ); - const { - TextColor, - BackgroundColor, - InspectorControlsColorPanel, - } = __experimentalUseColors( - [ - { name: 'textColor', property: 'color' }, - { name: 'backgroundColor', className: 'has-background' }, - ], - { - contrastCheckers: [ - { - backgroundColor: true, - textColor: true, - fontSize: fontSize.size, - }, - ], - colorDetector: { targetRef: ref }, - }, - [ fontSize.size ] - ); + + const styles = { + direction, + minHeight: dropCapMinimumHeight, + }; return ( <> @@ -127,10 +117,6 @@ function ParagraphBlock( { </BlockControls> <InspectorControls> <PanelBody title={ __( 'Text settings' ) }> - <FontSizePicker - value={ fontSize.size } - onChange={ setFontSize } - /> <ToggleControl label={ __( 'Drop cap' ) } checked={ !! dropCap } @@ -145,66 +131,48 @@ function ParagraphBlock( { /> </PanelBody> </InspectorControls> - { InspectorControlsColorPanel } - <BackgroundColor> - <TextColor> - <RichText - ref={ ref } - identifier="content" - tagName={ Block.p } - className={ classnames( { - 'has-drop-cap': dropCap, - [ `has-text-align-${ align }` ]: align, - [ fontSize.class ]: fontSize.class, - } ) } - style={ { - fontSize: fontSize.size - ? fontSize.size + 'px' - : undefined, - direction, - minHeight: dropCapMinimumHeight, - } } - value={ content } - onChange={ ( newContent ) => - setAttributes( { content: newContent } ) - } - onSplit={ ( value ) => { - if ( ! value ) { - return createBlock( name ); - } + <RichText + ref={ ref } + identifier="content" + tagName={ Block.p } + className={ classnames( { + 'has-drop-cap': dropCap, + [ `has-text-align-${ align }` ]: align, + } ) } + style={ styles } + value={ content } + onChange={ ( newContent ) => + setAttributes( { content: newContent } ) + } + onSplit={ ( value ) => { + if ( ! value ) { + return createBlock( name ); + } - return createBlock( name, { - ...attributes, - content: value, - } ); - } } - onMerge={ mergeBlocks } - onReplace={ onReplace } - onRemove={ - onReplace ? () => onReplace( [] ) : undefined - } - aria-label={ - content - ? __( 'Paragraph block' ) - : __( - 'Empty block; start writing or type forward slash to choose a block' - ) - } - placeholder={ - placeholder || - __( 'Start writing or type / to choose a block' ) - } - __unstableEmbedURLOnPaste - __unstableAllowPrefixTransformations - /> - </TextColor> - </BackgroundColor> + return createBlock( name, { + ...attributes, + content: value, + } ); + } } + onMerge={ mergeBlocks } + onReplace={ onReplace } + onRemove={ onReplace ? () => onReplace( [] ) : undefined } + aria-label={ + content + ? __( 'Paragraph block' ) + : __( + 'Empty block; start writing or type forward slash to choose a block' + ) + } + placeholder={ + placeholder || + __( 'Start writing or type / to choose a block' ) + } + __unstableEmbedURLOnPaste + __unstableAllowPrefixTransformations + /> </> ); } -const ParagraphEdit = compose( [ withFontSizes( 'fontSize' ) ] )( - ParagraphBlock -); - -export default ParagraphEdit; +export default ParagraphBlock; diff --git a/packages/block-library/src/paragraph/edit.native.js b/packages/block-library/src/paragraph/edit.native.js index b02cdc3662125a..1027f46371508a 100644 --- a/packages/block-library/src/paragraph/edit.native.js +++ b/packages/block-library/src/paragraph/edit.native.js @@ -7,7 +7,6 @@ import { AlignmentToolbar, BlockControls, RichText, - __experimentalUseColors, } from '@wordpress/block-editor'; const name = 'core/paragraph'; @@ -17,56 +16,52 @@ function ParagraphBlock( { mergeBlocks, onReplace, setAttributes, - style, + style: oldStyle, } ) { - const { align, content, placeholder } = attributes; + const { align, content, placeholder, style } = attributes; - /* eslint-disable @wordpress/no-unused-vars-before-return */ - const { TextColor } = __experimentalUseColors( [ - { name: 'textColor', property: 'color' }, - ] ); - /* eslint-enable @wordpress/no-unused-vars-before-return */ + const styles = { + ...oldStyle, + color: style && style.color && style.color.text, + }; return ( <> <BlockControls> <AlignmentToolbar - isCollapsed={ false } value={ align } onChange={ ( nextAlign ) => { setAttributes( { align: nextAlign } ); } } /> </BlockControls> - <TextColor> - <RichText - identifier="content" - tagName="p" - value={ content } - deleteEnter={ true } - style={ style } - onChange={ ( nextContent ) => { - setAttributes( { - content: nextContent, - } ); - } } - onSplit={ ( value ) => { - if ( ! value ) { - return createBlock( name ); - } + <RichText + identifier="content" + tagName="p" + value={ content } + deleteEnter={ true } + style={ styles } + onChange={ ( nextContent ) => { + setAttributes( { + content: nextContent, + } ); + } } + onSplit={ ( value ) => { + if ( ! value ) { + return createBlock( name ); + } - return createBlock( name, { - ...attributes, - content: value, - } ); - } } - onMerge={ mergeBlocks } - onReplace={ onReplace } - onRemove={ onReplace ? () => onReplace( [] ) : undefined } - placeholder={ placeholder || __( 'Start writing…' ) } - textAlign={ align } - /> - </TextColor> + return createBlock( name, { + ...attributes, + content: value, + } ); + } } + onMerge={ mergeBlocks } + onReplace={ onReplace } + onRemove={ onReplace ? () => onReplace( [] ) : undefined } + placeholder={ placeholder || __( 'Start writing…' ) } + textAlign={ align } + /> </> ); } diff --git a/packages/block-library/src/paragraph/editor.scss b/packages/block-library/src/paragraph/editor.scss index 20b0f6a4311cd9..d0afb9ca839208 100644 --- a/packages/block-library/src/paragraph/editor.scss +++ b/packages/block-library/src/paragraph/editor.scss @@ -3,34 +3,6 @@ min-height: auto !important; } - -// Show a footprint fade effect when first selecting any block. -.block-editor-block-list__block[data-type="core/paragraph"].is-selected { - &::before { - position: absolute; - z-index: 1; - pointer-events: none; - content: ""; - top: 0; - bottom: 0; - left: 0; - right: 0; - animation: block-editor-block-list__block-fade-out-animation 0.3s ease-out 0.2s; - animation-fill-mode: forwards; - @include reduce-motion("animation"); - } - - // Only flash it if you're not typing. - &:not(.is-typing)::before { - background: rgba($black, 0.03); - - // Flash a white color for dark themes. - .is-dark-theme & { - background: rgba($white, 0.1); - } - } -} - @keyframes block-editor-block-list__block-fade-out-animation { from { opacity: 1; diff --git a/packages/block-library/src/paragraph/index.js b/packages/block-library/src/paragraph/index.js index 7fa310086cb459..0e76e74adc338f 100644 --- a/packages/block-library/src/paragraph/index.js +++ b/packages/block-library/src/paragraph/index.js @@ -32,7 +32,11 @@ export const settings = { content: __( 'In a village of La Mancha, the name of which I have no desire to call to mind, there lived not long since one of those gentlemen that keep a lance in the lance-rack, an old buckler, a lean hack, and a greyhound for coursing.' ), - customFontSize: 28, + style: { + typography: { + fontSize: 28, + }, + }, dropCap: true, }, }, @@ -40,6 +44,9 @@ export const settings = { className: false, __unstablePasteTextInline: true, lightBlockWrapper: true, + __experimentalColor: true, + __experimentalLineHeight: true, + __experimentalFontSize: true, }, __experimentalLabel( attributes, { context } ) { if ( context === 'accessibility' ) { diff --git a/packages/block-library/src/paragraph/save.js b/packages/block-library/src/paragraph/save.js index 2cdeeb46e60c9c..434cc022295588 100644 --- a/packages/block-library/src/paragraph/save.js +++ b/packages/block-library/src/paragraph/save.js @@ -6,53 +6,19 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { - getColorClassName, - getFontSizeClass, - RichText, -} from '@wordpress/block-editor'; +import { RichText } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { - align, - content, - dropCap, - backgroundColor, - textColor, - customBackgroundColor, - customTextColor, - fontSize, - customFontSize, - direction, - } = attributes; - - const textClass = getColorClassName( 'color', textColor ); - const backgroundClass = getColorClassName( - 'background-color', - backgroundColor - ); - const fontSizeClass = getFontSizeClass( fontSize ); + const { align, content, dropCap, direction } = attributes; const className = classnames( { - 'has-text-color': textColor || customTextColor, - 'has-background': backgroundColor || customBackgroundColor, 'has-drop-cap': dropCap, [ `has-text-align-${ align }` ]: align, - [ fontSizeClass ]: fontSizeClass, - [ textClass ]: textClass, - [ backgroundClass ]: backgroundClass, } ); - const styles = { - backgroundColor: backgroundClass ? undefined : customBackgroundColor, - color: textClass ? undefined : customTextColor, - fontSize: fontSizeClass ? undefined : customFontSize, - }; - return ( <RichText.Content tagName="p" - style={ styles } className={ className ? className : undefined } value={ content } dir={ direction } diff --git a/packages/block-library/src/post-author/edit.js b/packages/block-library/src/post-author/edit.js index 9ca968c5679f70..05ab61f3ef92a7 100644 --- a/packages/block-library/src/post-author/edit.js +++ b/packages/block-library/src/post-author/edit.js @@ -13,7 +13,13 @@ function PostAuthorDisplay() { [ authorId ] ); return author ? ( - <address>{ sprintf( __( 'By %s' ), author.name ) }</address> + <address> + { sprintf( + /* translators: %s: author name. */ + __( 'By %s' ), + author.name + ) } + </address> ) : null; } diff --git a/packages/block-library/src/post-author/index.php b/packages/block-library/src/post-author/index.php index 6dc30ea5b4ba18..57f1895f6cb0c6 100644 --- a/packages/block-library/src/post-author/index.php +++ b/packages/block-library/src/post-author/index.php @@ -23,16 +23,10 @@ function render_block_core_post_author() { * Registers the `core/post-author` block on the server. */ function register_block_core_post_author() { - $path = __DIR__ . '/post-author/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_author', - ) + register_block_type_from_metadata( + __DIR__ . '/post-author', + array( + 'render_callback' => 'render_block_core_post_author', ) ); } diff --git a/packages/block-library/src/post-comments-count/index.php b/packages/block-library/src/post-comments-count/index.php index 0c22f35068f175..a7e811b8157324 100644 --- a/packages/block-library/src/post-comments-count/index.php +++ b/packages/block-library/src/post-comments-count/index.php @@ -32,21 +32,15 @@ function render_block_core_post_comments_count( $attributes ) { * Registers the `core/post-comments-count` block on the server. */ function register_block_core_post_comments_count() { - $path = __DIR__ . '/post-comments-count/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'attributes' => array( - 'className' => array( - 'type' => 'string', - ), + register_block_type_from_metadata( + __DIR__ . '/post-comments-count', + array( + 'attributes' => array( + 'className' => array( + 'type' => 'string', ), - 'render_callback' => 'render_block_core_post_comments_count', - ) + ), + 'render_callback' => 'render_block_core_post_comments_count', ) ); } diff --git a/packages/block-library/src/post-comments-form/index.php b/packages/block-library/src/post-comments-form/index.php index cb1aff17fc5af1..9d5e78cffa5cfa 100644 --- a/packages/block-library/src/post-comments-form/index.php +++ b/packages/block-library/src/post-comments-form/index.php @@ -26,16 +26,10 @@ function render_block_core_post_comments_form() { * Registers the `core/post-comments-form` block on the server. */ function register_block_core_post_comments_form() { - $path = __DIR__ . '/post-comments-form/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_comments_form', - ) + register_block_type_from_metadata( + __DIR__ . '/post-comments-form', + array( + 'render_callback' => 'render_block_core_post_comments_form', ) ); } diff --git a/packages/block-library/src/post-comments/index.php b/packages/block-library/src/post-comments/index.php index d9f35117a74da3..85780230704ecd 100644 --- a/packages/block-library/src/post-comments/index.php +++ b/packages/block-library/src/post-comments/index.php @@ -15,17 +15,12 @@ function render_block_core_post_comments() { if ( ! $post ) { return ''; } - $comments = get_comments( - array( - 'post_id' => $post->ID, - ) - ); - $output = ''; - // TODO: Handle nested comments. - foreach ( $comments as $comment ) { - $output .= '<p>' . $comment->comment_author . '<br />' . $comment->comment_content . '</p>'; - } - return $output; + + // This generates a deprecate message. + // Ideally this deprecation is removed. + ob_start(); + comments_template(); + return ob_get_clean(); } /** diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js index d80b308b384b16..3336e0d8199676 100644 --- a/packages/block-library/src/post-content/edit.js +++ b/packages/block-library/src/post-content/edit.js @@ -1,3 +1,9 @@ export default function PostContentEdit() { - return 'Post Content Placeholder'; + return ( + <p> + { + 'Welcome to WordPress and the wonderful world of blocks. This content represents how a post would look when editing block templates.' + } + </p> + ); } diff --git a/packages/block-library/src/post-content/index.php b/packages/block-library/src/post-content/index.php index 1e6870fd0b3134..dc7eebdf00ffa2 100644 --- a/packages/block-library/src/post-content/index.php +++ b/packages/block-library/src/post-content/index.php @@ -26,16 +26,10 @@ function render_block_core_post_content() { * Registers the `core/post-content` block on the server. */ function register_block_core_post_content() { - $path = __DIR__ . '/post-content/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_content', - ) + register_block_type_from_metadata( + __DIR__ . '/post-content', + array( + 'render_callback' => 'render_block_core_post_content', ) ); } diff --git a/packages/block-library/src/post-date/edit.js b/packages/block-library/src/post-date/edit.js index 5c04fe66cbb091..fae4aceef783df 100644 --- a/packages/block-library/src/post-date/edit.js +++ b/packages/block-library/src/post-date/edit.js @@ -90,7 +90,7 @@ export default function PostDateEdit( { setAttributes, } ) { if ( ! useEntityId( 'postType', 'post' ) ) { - return 'Post Date Placeholder'; + return <p>{ 'Jan 1st, 1440' }</p>; } return <PostDateEditor format={ format } setAttributes={ setAttributes } />; } diff --git a/packages/block-library/src/post-date/index.php b/packages/block-library/src/post-date/index.php index 22e4c53e311eaf..dd86ff7e8c92ca 100644 --- a/packages/block-library/src/post-date/index.php +++ b/packages/block-library/src/post-date/index.php @@ -27,16 +27,10 @@ function render_block_core_post_date( $attributes ) { * Registers the `core/post-date` block on the server. */ function register_block_core_post_date() { - $path = __DIR__ . '/post-date/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_date', - ) + register_block_type_from_metadata( + __DIR__ . '/post-date', + array( + 'render_callback' => 'render_block_core_post_date', ) ); } diff --git a/packages/block-library/src/post-excerpt/index.php b/packages/block-library/src/post-excerpt/index.php index 5d2ee7755beee4..7f5ab586670fa8 100644 --- a/packages/block-library/src/post-excerpt/index.php +++ b/packages/block-library/src/post-excerpt/index.php @@ -47,16 +47,10 @@ function render_block_core_post_excerpt( $attributes ) { * Registers the `core/post-excerpt` block on the server. */ function register_block_core_post_excerpt() { - $path = __DIR__ . '/post-excerpt/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_excerpt', - ) + register_block_type_from_metadata( + __DIR__ . '/post-excerpt', + array( + 'render_callback' => 'render_block_core_post_excerpt', ) ); } diff --git a/packages/block-library/src/post-featured-image/index.php b/packages/block-library/src/post-featured-image/index.php index 4a03b2e4d30284..9a80c2525fa3ee 100644 --- a/packages/block-library/src/post-featured-image/index.php +++ b/packages/block-library/src/post-featured-image/index.php @@ -22,16 +22,10 @@ function render_block_core_post_featured_image() { * Registers the `core/post-featured-image` block on the server. */ function register_block_core_post_featured_image() { - $path = __DIR__ . '/post-featured-image/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_featured_image', - ) + register_block_type_from_metadata( + __DIR__ . '/post-featured-image', + array( + 'render_callback' => 'render_block_core_post_featured_image', ) ); } diff --git a/packages/block-library/src/post-tags/index.php b/packages/block-library/src/post-tags/index.php index 4fff8d0014c840..ed03b6055f7cfa 100644 --- a/packages/block-library/src/post-tags/index.php +++ b/packages/block-library/src/post-tags/index.php @@ -29,16 +29,10 @@ function render_block_core_post_tags() { * Registers the `core/post-tags` block on the server. */ function register_block_core_post_tags() { - $path = __DIR__ . '/post-tags/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_tags', - ) + register_block_type_from_metadata( + __DIR__ . '/post-tags', + array( + 'render_callback' => 'render_block_core_post_tags', ) ); } diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index ed9782fa4b5892..aa31586b212ab3 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -1,3 +1,3 @@ export default function PostTitleEdit() { - return 'Post Title Placeholder'; + return <h2>{ 'Hello world!' }</h2>; } diff --git a/packages/block-library/src/post-title/index.php b/packages/block-library/src/post-title/index.php index c635ad2a0f0eb9..d1b6f245b2e627 100644 --- a/packages/block-library/src/post-title/index.php +++ b/packages/block-library/src/post-title/index.php @@ -22,16 +22,10 @@ function render_block_core_post_title() { * Registers the `core/post-title` block on the server. */ function register_block_core_post_title() { - $path = __DIR__ . '/post-title/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_post_title', - ) + register_block_type_from_metadata( + __DIR__ . '/post-title', + array( + 'render_callback' => 'render_block_core_post_title', ) ); } diff --git a/packages/block-library/src/preformatted/edit.js b/packages/block-library/src/preformatted/edit.js index 6a9bd052f0b59c..0acc7f26ae6c2a 100644 --- a/packages/block-library/src/preformatted/edit.js +++ b/packages/block-library/src/preformatted/edit.js @@ -2,7 +2,10 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { RichText } from '@wordpress/block-editor'; +import { + RichText, + __experimentalBlock as Block, +} from '@wordpress/block-editor'; export default function PreformattedEdit( { attributes, @@ -15,7 +18,7 @@ export default function PreformattedEdit( { return ( <RichText - tagName="pre" + tagName={ Block.pre } identifier="content" preserveWhiteSpace value={ content } diff --git a/packages/block-library/src/preformatted/index.js b/packages/block-library/src/preformatted/index.js index cd18c639f7db1d..3fe52d58965739 100644 --- a/packages/block-library/src/preformatted/index.js +++ b/packages/block-library/src/preformatted/index.js @@ -24,13 +24,18 @@ export const settings = { icon, example: { attributes: { + /* eslint-disable @wordpress/i18n-no-collapsible-whitespace */ // translators: Sample content for the Preformatted block. Can be replaced with a more locale-adequate work. content: __( 'EXT. XANADU - FAINT DAWN - 1940 (MINIATURE)\nWindow, very small in the distance, illuminated.\nAll around this is an almost totally black screen. Now, as the camera moves slowly towards the window which is almost a postage stamp in the frame, other forms appear;' ), + /* eslint-enable @wordpress/i18n-no-collapsible-whitespace */ }, }, transforms, + supports: { + lightBlockWrapper: true, + }, edit, save, merge( attributes, attributesToMerge ) { diff --git a/packages/block-library/src/pullquote/blockquote.js b/packages/block-library/src/pullquote/blockquote.js new file mode 100644 index 00000000000000..287f2eef158466 --- /dev/null +++ b/packages/block-library/src/pullquote/blockquote.js @@ -0,0 +1 @@ +export const BlockQuote = 'blockquote'; diff --git a/packages/block-library/src/pullquote/blockquote.native.js b/packages/block-library/src/pullquote/blockquote.native.js new file mode 100644 index 00000000000000..36bfa0c582eef7 --- /dev/null +++ b/packages/block-library/src/pullquote/blockquote.native.js @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; +/** + * WordPress dependencies + */ +import { Children, cloneElement } from '@wordpress/element'; +/** + * Internal dependencies + */ +import styles from './blockquote.scss'; + +export const BlockQuote = ( props ) => { + const newChildren = Children.map( props.children, ( child ) => { + if ( child && child.props.identifier === 'value' ) { + return cloneElement( child, { + style: styles.quote, + } ); + } + if ( child && child.props.identifier === 'citation' ) { + return cloneElement( child, { + style: styles.citation, + } ); + } + return child; + } ); + return <View>{ newChildren }</View>; +}; diff --git a/packages/block-library/src/pullquote/blockquote.native.scss b/packages/block-library/src/pullquote/blockquote.native.scss new file mode 100644 index 00000000000000..e8022091e99c68 --- /dev/null +++ b/packages/block-library/src/pullquote/blockquote.native.scss @@ -0,0 +1,8 @@ +.quote { + font-size: 18px; +} + +.citation { + font-size: 14px; + margin-top: 12px; +} diff --git a/packages/block-library/src/pullquote/edit.js b/packages/block-library/src/pullquote/edit.js index 5fead7277ec98b..5a7dae5a5f8451 100644 --- a/packages/block-library/src/pullquote/edit.js +++ b/packages/block-library/src/pullquote/edit.js @@ -16,6 +16,11 @@ import { withColors, PanelColorSettings, } from '@wordpress/block-editor'; +/** + * Internal dependencies + */ +import { Figure } from './figure'; +import { BlockQuote } from './blockquote'; /** * Internal dependencies @@ -124,12 +129,13 @@ class PullQuoteEdit extends Component { return ( <> - <figure style={ figureStyles } className={ figureClasses }> - <blockquote + <Figure style={ figureStyles } className={ figureClasses }> + <BlockQuote style={ blockquoteStyles } className={ blockquoteClasses } > <RichText + identifier="value" multiline value={ value } onChange={ ( nextValue ) => @@ -141,9 +147,11 @@ class PullQuoteEdit extends Component { // translators: placeholder text used for the quote __( 'Write quote…' ) } + textAlign="center" /> { ( ! RichText.isEmpty( citation ) || isSelected ) && ( <RichText + identifier="citation" value={ citation } placeholder={ // translators: placeholder text used for the citation @@ -155,10 +163,12 @@ class PullQuoteEdit extends Component { } ) } className="wp-block-pullquote__citation" + __unstableMobileNoFocusOnMount + textAlign="center" /> ) } - </blockquote> - </figure> + </BlockQuote> + </Figure> <InspectorControls> <PanelColorSettings title={ __( 'Color settings' ) } diff --git a/packages/block-library/src/pullquote/figure.js b/packages/block-library/src/pullquote/figure.js new file mode 100644 index 00000000000000..648af9ec6d5145 --- /dev/null +++ b/packages/block-library/src/pullquote/figure.js @@ -0,0 +1 @@ +export const Figure = 'figure'; diff --git a/packages/block-library/src/pullquote/figure.native.js b/packages/block-library/src/pullquote/figure.native.js new file mode 100644 index 00000000000000..57323c46ab6aec --- /dev/null +++ b/packages/block-library/src/pullquote/figure.native.js @@ -0,0 +1,23 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; +/** + * WordPress dependencies + */ +import { withPreferredColorScheme } from '@wordpress/compose'; +/** + * Internal dependencies + */ +import styles from './figure.scss'; + +export const Figure = withPreferredColorScheme( ( props ) => { + const { children, getStylesFromColorScheme } = props; + + const wpPullquoteFigure = getStylesFromColorScheme( + styles.light, + styles.dark + ); + + return <View style={ wpPullquoteFigure }>{ children }</View>; +} ); diff --git a/packages/block-library/src/pullquote/figure.native.scss b/packages/block-library/src/pullquote/figure.native.scss new file mode 100644 index 00000000000000..e4f12c8c415fdc --- /dev/null +++ b/packages/block-library/src/pullquote/figure.native.scss @@ -0,0 +1,16 @@ +%shared { + border-width: 3px 0; + padding: 21px 16px; +} + +.light { + @extend %shared; + border-top-color: $gray-lighten-20; + border-bottom-color: $gray-lighten-20; +} + +.dark { + @extend %shared; + border-top-color: $gray-50; + border-bottom-color: $gray-50; +} diff --git a/packages/block-library/src/separator/style.scss b/packages/block-library/src/separator/style.scss index a4cf1f2fdb6d27..8decc9d0ba52dd 100644 --- a/packages/block-library/src/separator/style.scss +++ b/packages/block-library/src/separator/style.scss @@ -22,6 +22,7 @@ color: currentColor; font-size: 20px; letter-spacing: 2em; + /*rtl:ignore*/ padding-left: 2em; font-family: serif; } diff --git a/packages/block-library/src/shortcode/index.php b/packages/block-library/src/shortcode/index.php index cfa8ab97dfa2bc..97a40b386d9c92 100644 --- a/packages/block-library/src/shortcode/index.php +++ b/packages/block-library/src/shortcode/index.php @@ -21,15 +21,10 @@ function render_block_core_shortcode( $attributes, $content ) { * Registers the `core/shortcode` block on server. */ function register_block_core_shortcode() { - $path = __DIR__ . '/shortcode/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_shortcode', - ) + register_block_type_from_metadata( + __DIR__ . '/shortcode', + array( + 'render_callback' => 'render_block_core_shortcode', ) ); } diff --git a/packages/block-library/src/site-title/index.php b/packages/block-library/src/site-title/index.php index a63760983436e2..7241bc50dffa56 100644 --- a/packages/block-library/src/site-title/index.php +++ b/packages/block-library/src/site-title/index.php @@ -24,16 +24,10 @@ function render_block_core_site_title( $attributes ) { * Registers the `core/site-title` block on the server. */ function register_block_core_site_title() { - $path = __DIR__ . '/site-title/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_site_title', - ) + register_block_type_from_metadata( + __DIR__ . '/site-title', + array( + 'render_callback' => 'render_block_core_site_title', ) ); } diff --git a/packages/block-library/src/social-link/block.json b/packages/block-library/src/social-link/block.json index 977f5731fd961a..a9725b56781f58 100644 --- a/packages/block-library/src/social-link/block.json +++ b/packages/block-library/src/social-link/block.json @@ -1,7 +1,6 @@ { "name": "core/social-link", "category": "widgets", - "icon": "share", "attributes": { "url": { "type": "string" diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 2dd4e747638c28..7d6dace9ef0c7a 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -33,7 +33,11 @@ const SocialLinkEdit = ( { attributes, setAttributes, isSelected } ) => { 'wp-social-link__is-incomplete': ! url, } ); - // Import icon. + // Disable reason: The rule is currently not considering use as JSX tagName. + // + // See: https://github.com/WordPress/gutenberg/issues/16418 + + // eslint-disable-next-line @wordpress/no-unused-vars-before-return const IconComponent = getIconBySite( service ); const socialLinkName = getNameBySite( service ); @@ -41,7 +45,11 @@ const SocialLinkEdit = ( { attributes, setAttributes, isSelected } ) => { <Fragment> <InspectorControls> <PanelBody - title={ sprintf( __( '%s label' ), socialLinkName ) } + title={ sprintf( + /* translators: %s: name of the social service. */ + __( '%s label' ), + socialLinkName + ) } initialOpen={ false } > <PanelRow> diff --git a/packages/block-library/src/social-link/icons/tumblr.js b/packages/block-library/src/social-link/icons/tumblr.js index 5999fe4ead681d..e696d2955fb444 100644 --- a/packages/block-library/src/social-link/icons/tumblr.js +++ b/packages/block-library/src/social-link/icons/tumblr.js @@ -5,6 +5,6 @@ import { Path, SVG } from '@wordpress/primitives'; export const TumblrIcon = () => ( <SVG width="24" height="24" viewBox="0 0 24 24" version="1.1"> - <Path d="M16.749,17.396c-0.357,0.17-1.041,0.319-1.551,0.332c-1.539,0.041-1.837-1.081-1.85-1.896V9.847h3.861V6.937h-3.847V2.039 c0,0-2.77,0-2.817,0c-0.046,0-0.127,0.041-0.138,0.144c-0.165,1.499-0.867,4.13-3.783,5.181v2.484h1.945v6.282 c0,2.151,1.587,5.206,5.775,5.135c1.413-0.024,2.982-0.616,3.329-1.126L16.749,17.396z" /> + <Path d="M17.04 21.28h-3.28c-2.84 0-4.94-1.37-4.94-5.02v-5.67H6.08V7.5c2.93-.73 4.11-3.3 4.3-5.48h3.01v4.93h3.47v3.65H13.4v4.93c0 1.47.73 2.01 1.92 2.01h1.73v3.75z" /> </SVG> ); diff --git a/packages/block-library/src/social-link/index.js b/packages/block-library/src/social-link/index.js index bebeaad5832af4..771f364541f3e1 100644 --- a/packages/block-library/src/social-link/index.js +++ b/packages/block-library/src/social-link/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { share as icon } from '@wordpress/icons'; /** * Internal dependencies @@ -21,6 +22,7 @@ export const settings = { reusable: false, html: false, }, + icon, edit, description: __( 'Display an icon linking to a social media profile or website.' diff --git a/packages/block-library/src/social-link/index.php b/packages/block-library/src/social-link/index.php index 1c8d367606f6b9..dc732a7a1f90ed 100644 --- a/packages/block-library/src/social-link/index.php +++ b/packages/block-library/src/social-link/index.php @@ -13,12 +13,9 @@ * @return string Rendered HTML of the referenced block. */ function render_block_core_social_link( $attributes ) { - $service = ( isset( $attributes['service'] ) ) ? $attributes['service'] : 'Icon'; - $url = ( isset( $attributes['url'] ) ) ? $attributes['url'] : false; - $label = ( isset( $attributes['label'] ) ) ? - $attributes['label'] : - /* translators: %s: Social Link service name */ - sprintf( __( 'Link to %s' ), block_core_social_link_get_name( $service ) ); + $service = ( isset( $attributes['service'] ) ) ? $attributes['service'] : 'Icon'; + $url = ( isset( $attributes['url'] ) ) ? $attributes['url'] : false; + $label = ( isset( $attributes['label'] ) ) ? $attributes['label'] : block_core_social_link_get_name( $service ); $class_name = isset( $attributes['className'] ) ? ' ' . $attributes['className'] : false; // Don't render a link if there is no URL set. @@ -34,16 +31,10 @@ function render_block_core_social_link( $attributes ) { * Registers the `core/social-link` blocks. */ function register_block_core_social_link() { - $path = __DIR__ . '/social-link/block.json'; - $metadata = json_decode( file_get_contents( $path ), true ); - - register_block_type( - $metadata['name'], - array_merge( - $metadata, - array( - 'render_callback' => 'render_block_core_social_link', - ) + register_block_type_from_metadata( + __DIR__ . '/social-link', + array( + 'render_callback' => 'render_block_core_social_link', ) ); } @@ -218,7 +209,7 @@ function block_core_social_link_services( $service = '', $field = '' ) { ), 'tumblr' => array( 'name' => 'Tumblr', - 'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" role="img" aria-hidden="true" focusable="false"><path d="M16.749,17.396c-0.357,0.17-1.041,0.319-1.551,0.332c-1.539,0.041-1.837-1.081-1.85-1.896V9.847h3.861V6.937h-3.847V2.039 c0,0-2.77,0-2.817,0c-0.046,0-0.127,0.041-0.138,0.144c-0.165,1.499-0.867,4.13-3.783,5.181v2.484h1.945v6.282 c0,2.151,1.587,5.206,5.775,5.135c1.413-0.024,2.982-0.616,3.329-1.126L16.749,17.396z"></path></svg>', + 'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" role="img" aria-hidden="true" focusable="false"><path d="M17.04 21.28h-3.28c-2.84 0-4.94-1.37-4.94-5.02v-5.67H6.08V7.5c2.93-.73 4.11-3.3 4.3-5.48h3.01v4.93h3.47v3.65H13.4v4.93c0 1.47.73 2.01 1.92 2.01h1.73v3.75z" /></path></svg>', ), 'twitch' => array( 'name' => 'Twitch', @@ -250,7 +241,7 @@ function block_core_social_link_services( $service = '', $field = '' ) { ), 'share' => array( 'name' => 'Share Icon', - 'icon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" role="img" aria-hidden="true" focusable="false"><rect x="0" fill="none" width="20" height="20"/><g><path d="M14.5 12c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3c0-.24.03-.46.09-.69l-4.38-2.3c-.55.61-1.33.99-2.21.99-1.66 0-3-1.34-3-3s1.34-3 3-3c.88 0 1.66.39 2.21.99l4.38-2.3c-.06-.23-.09-.45-.09-.69 0-1.66 1.34-3 3-3s3 1.34 3 3-1.34 3-3 3c-.88 0-1.66-.39-2.21-.99l-4.38 2.3c.06.23.09.45.09.69s-.03.46-.09.69l4.38 2.3c.55-.61 1.33-.99 2.21-.99z"/></g></svg>', + 'icon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9 11.8l6.1-4.5c.1.4.4.7.9.7h2c.6 0 1-.4 1-1V5c0-.6-.4-1-1-1h-2c-.6 0-1 .4-1 1v.4l-6.4 4.8c-.2-.1-.4-.2-.6-.2H6c-.6 0-1 .4-1 1v2c0 .6.4 1 1 1h2c.2 0 .4-.1.6-.2l6.4 4.8v.4c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-2c0-.6-.4-1-1-1h-2c-.5 0-.8.3-.9.7L9 12.2v-.4z"/></svg>', ), ); diff --git a/packages/block-library/src/social-links/block.json b/packages/block-library/src/social-links/block.json index 6d25baacb1a857..3019a7f5c3b397 100644 --- a/packages/block-library/src/social-links/block.json +++ b/packages/block-library/src/social-links/block.json @@ -1,6 +1,5 @@ { "name": "core/social-links", "category": "widgets", - "icon": "share", "attributes": {} } diff --git a/packages/block-library/src/social-links/index.js b/packages/block-library/src/social-links/index.js index 3eb0027959a09d..2c27f8daad2b65 100644 --- a/packages/block-library/src/social-links/index.js +++ b/packages/block-library/src/social-links/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { __, _x } from '@wordpress/i18n'; +import { share as icon } from '@wordpress/icons'; /** * Internal dependencies @@ -53,6 +54,7 @@ export const settings = { { name: 'logos-only', label: __( 'Logos Only' ) }, { name: 'pill-shape', label: __( 'Pill Shape' ) }, ], + icon, edit, save, }; diff --git a/packages/block-library/src/social-links/style.scss b/packages/block-library/src/social-links/style.scss index 3bfa4992e224a8..9a6f2adabea130 100644 --- a/packages/block-library/src/social-links/style.scss +++ b/packages/block-library/src/social-links/style.scss @@ -102,7 +102,7 @@ } .wp-social-link-facebook { - background-color: #1977f2; + background-color: #1778f2; color: #fff; } @@ -147,7 +147,7 @@ } .wp-social-link-linkedin { - background-color: #0577b5; + background-color: #0d66c2; color: #fff; } @@ -213,7 +213,7 @@ } .wp-social-link-twitter { - background-color: #21a1f3; + background-color: #1da1f2; color: #fff; } @@ -238,7 +238,7 @@ } .wp-social-link-youtube { - background-color: #ff0100; + background-color: #f00; color: #fff; } } @@ -289,7 +289,7 @@ } .wp-social-link-facebook { - color: #1977f2; + color: #1778f2; } .wp-social-link-fivehundredpx { @@ -325,7 +325,7 @@ } .wp-social-link-linkedin { - color: #0577b5; + color: #0d66c2; } .wp-social-link-mastodon { @@ -378,7 +378,7 @@ } .wp-social-link-twitter { - color: #21a1f3; + color: #1da1f2; } .wp-social-link-vimeo { @@ -399,7 +399,7 @@ } .wp-social-link-youtube { - color: #ff0100; + color: #f00; } } diff --git a/packages/block-library/src/spacer/edit.js b/packages/block-library/src/spacer/edit.js index 76993d3977207c..9a457c6e8ad173 100644 --- a/packages/block-library/src/spacer/edit.js +++ b/packages/block-library/src/spacer/edit.js @@ -11,6 +11,7 @@ import { InspectorControls } from '@wordpress/block-editor'; import { PanelBody, ResizableBox, RangeControl } from '@wordpress/components'; import { compose, withInstanceId } from '@wordpress/compose'; import { withDispatch } from '@wordpress/data'; +import { Platform } from '@wordpress/element'; const MIN_SPACER_HEIGHT = 20; const MAX_SPACER_HEIGHT = 500; @@ -72,7 +73,7 @@ const SpacerEdit = ( { separatorType={ 'none' } value={ height } onChange={ updateHeight } - step={ 10 } + step={ Platform.OS === 'web' ? 10 : 1 } /> </PanelBody> </InspectorControls> diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index bd8ab8a093bb5c..2cedc194e3b2e6 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -13,6 +13,7 @@ @import "./embed/style.scss"; @import "./file/style.scss"; @import "./gallery/style.scss"; +@import "./heading/style.scss"; @import "./image/style.scss"; @import "./latest-comments/style.scss"; @import "./latest-posts/style.scss"; @@ -215,28 +216,30 @@ // Font sizes. +:root { + .has-small-font-size { + font-size: 13px; + } -.has-small-font-size { - font-size: 13px; -} + .has-regular-font-size, // Not used now, kept because of backward compatibility. + .has-normal-font-size { + font-size: 16px; + } -.has-regular-font-size, // Not used now, kept because of backward compatibility. -.has-normal-font-size { - font-size: 16px; -} + .has-medium-font-size { + font-size: 20px; + } -.has-medium-font-size { - font-size: 20px; -} + .has-large-font-size { + font-size: 36px; + } -.has-large-font-size { - font-size: 36px; + .has-larger-font-size, // Not used now, kept because of backward compatibility. + .has-huge-font-size { + font-size: 42px; + } } -.has-larger-font-size, // Not used now, kept because of backward compatibility. -.has-huge-font-size { - font-size: 42px; -} // Text alignments. .has-text-align-center { diff --git a/packages/block-library/src/template-part/edit/placeholder.js b/packages/block-library/src/template-part/edit/placeholder.js index abeb2d12139ef8..f3b3f7bc43e48d 100644 --- a/packages/block-library/src/template-part/edit/placeholder.js +++ b/packages/block-library/src/template-part/edit/placeholder.js @@ -22,14 +22,14 @@ function TemplatePartPreview() { <div className="wp-block-template-part__placeholder-preview-title"> { __( 'Preview' ) } </div> - <BlockPreview blocks={ blocks } /> + <BlockPreview blocks={ blocks } viewportWidth={ 1200 } /> </div> ); } export default function TemplatePartPlaceholder( { setAttributes } ) { - const [ slug, _setSlug ] = useState(); - const [ theme, setTheme ] = useState(); + const [ slug, _setSlug ] = useState( '' ); + const [ theme, setTheme ] = useState( '' ); const [ help, setHelp ] = useState(); // Try to find an existing template part. diff --git a/packages/block-library/src/template-part/index.js b/packages/block-library/src/template-part/index.js index 86b2c4cd2742e4..135b7a560e6b30 100644 --- a/packages/block-library/src/template-part/index.js +++ b/packages/block-library/src/template-part/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import { startCase } from 'lodash'; + /** * WordPress dependencies */ @@ -17,5 +22,6 @@ export const settings = { supports: { html: false, }, + __experimentalLabel: ( { slug } ) => startCase( slug ), edit, }; diff --git a/packages/block-library/src/verse/edit.js b/packages/block-library/src/verse/edit.js index 82a184ce167904..2c33afb53fd818 100644 --- a/packages/block-library/src/verse/edit.js +++ b/packages/block-library/src/verse/edit.js @@ -11,6 +11,7 @@ import { RichText, BlockControls, AlignmentToolbar, + __experimentalBlock as Block, } from '@wordpress/block-editor'; export default function VerseEdit( { @@ -32,7 +33,7 @@ export default function VerseEdit( { /> </BlockControls> <RichText - tagName="pre" + tagName={ Block.pre } preserveWhiteSpace value={ content } onChange={ ( nextContent ) => { diff --git a/packages/block-library/src/verse/index.js b/packages/block-library/src/verse/index.js index e05ab62bf2f27f..04f41e2f6de0cf 100644 --- a/packages/block-library/src/verse/index.js +++ b/packages/block-library/src/verse/index.js @@ -25,12 +25,17 @@ export const settings = { icon, example: { attributes: { + /* eslint-disable @wordpress/i18n-no-collapsible-whitespace */ // translators: Sample content for the Verse block. Can be replaced with a more locale-adequate work. content: __( 'WHAT was he doing, the great god Pan,\n Down in the reeds by the river?\nSpreading ruin and scattering ban,\nSplashing and paddling with hoofs of a goat,\nAnd breaking the golden lilies afloat\n With the dragon-fly on the river.' ), + /* eslint-enable @wordpress/i18n-no-collapsible-whitespace */ }, }, + supports: { + lightBlockWrapper: true, + }, keywords: [ __( 'poetry' ), __( 'poem' ) ], transforms, deprecated, diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index fc359c655cb986..52a5db7c44fb12 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -200,6 +200,7 @@ class VideoEdit extends Component { <p id={ videoPosterDescription } hidden> { this.props.attributes.poster ? sprintf( + /* translators: %s: poster image URL. */ __( 'The current poster image url is %s' ), diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index fdefc9a59fa7bd..2b317e8f8f05b3 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -23,7 +23,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/block-serialization-default-parser/src/index.js b/packages/block-serialization-default-parser/src/index.js index cc6f61e5fe7352..c6a844d0cc6dd7 100644 --- a/packages/block-serialization-default-parser/src/index.js +++ b/packages/block-serialization-default-parser/src/index.js @@ -39,7 +39,7 @@ let stack; * once browsers reliably support atomic grouping or possessive * quantifiers natively we should remove this trick and simplify * - * @type RegExp + * @type {RegExp} * * @since 3.8.0 * @since 4.6.1 added optimization to prevent backtracking on attribute parsing diff --git a/packages/block-serialization-spec-parser/.eslintrc.json b/packages/block-serialization-spec-parser/.eslintrc.json index ffee0154641f1d..363e55181855b4 100644 --- a/packages/block-serialization-spec-parser/.eslintrc.json +++ b/packages/block-serialization-spec-parser/.eslintrc.json @@ -4,7 +4,10 @@ "files": [ "shared-tests.js" ], "extends": [ "plugin:@wordpress/eslint-plugin/test-unit" - ] + ], + "rules": { + "jest/no-export": "off" + } } ] } diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 9e6d1bbcf40fc7..9ec34c5fac6a2f 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -1,7 +1,5 @@ ## Master -## 6.13.0 (2020-04-01) - ### New Feature - Blocks can now be registered with an `defaultStylePicker` flag in the `supports` setting, allowing the default style picker to be removed. diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 23c28f04e2b160..dcc3d37d549471 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/autop": "file:../autop", "@wordpress/blob": "file:../blob", "@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser", @@ -41,7 +41,7 @@ "showdown": "^1.8.6", "simple-html-tokenizer": "^0.5.7", "tinycolor2": "^1.4.1", - "uuid": "^3.3.2" + "uuid": "^7.0.2" }, "publishConfig": { "access": "public" diff --git a/packages/blocks/src/api/factory.js b/packages/blocks/src/api/factory.js index 983bafd73caabe..8775b6f78ea013 100644 --- a/packages/blocks/src/api/factory.js +++ b/packages/blocks/src/api/factory.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import uuid from 'uuid/v4'; +import { v4 as uuid } from 'uuid'; import { every, reduce, diff --git a/packages/blocks/src/api/raw-handling/html-formatting-remover.js b/packages/blocks/src/api/raw-handling/html-formatting-remover.js index b44fbe71deff1f..b5a9f6b75420b6 100644 --- a/packages/blocks/src/api/raw-handling/html-formatting-remover.js +++ b/packages/blocks/src/api/raw-handling/html-formatting-remover.js @@ -25,9 +25,21 @@ export default function( node ) { return; } - // Ignore pre content. - if ( node.parentElement.closest( 'pre' ) ) { - return; + // Ignore pre content. Note that this does not use Element#closest due to + // a combination of (a) node may not be Element and (b) node.parentElement + // does not have full support in all browsers (Internet Exporer). + // + // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility + + /** @type {Node?} */ + let parent = node; + while ( ( parent = parent.parentNode ) ) { + if ( + parent.nodeType === window.Node.ELEMENT_NODE && + parent.nodeName === 'PRE' + ) { + return; + } } // First, replace any sequence of HTML formatting space with a single space. diff --git a/packages/blocks/src/api/raw-handling/test/html-formatting-remover.js b/packages/blocks/src/api/raw-handling/test/html-formatting-remover.js index d5efd50f4db857..64df51a4f781b6 100644 --- a/packages/blocks/src/api/raw-handling/test/html-formatting-remover.js +++ b/packages/blocks/src/api/raw-handling/test/html-formatting-remover.js @@ -2,7 +2,7 @@ * Internal dependencies */ import filter from '../html-formatting-remover'; -import { deepFilterHTML } from '../utils'; +import { deepFilterHTML, deepFilterNodeList } from '../utils'; describe( 'HTMLFormattingRemover', () => { it( 'should trim text node without parent', () => { @@ -102,6 +102,24 @@ describe( 'HTMLFormattingRemover', () => { expect( deepFilterHTML( input, [ filter ] ) ).toEqual( input ); } ); + it( 'should tolerate browser quirks of DOM parent property availability', () => { + const input = 'a'; + + const doc = document.implementation.createHTMLDocument( '' ); + doc.body.innerHTML = input; + + // Emulate absence of `parentElement` property. + // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility + Object.defineProperty( doc.body.firstChild, 'parentElement', { + get() { + return undefined; + }, + } ); + + deepFilterNodeList( doc.body.childNodes, [ filter ], doc ); + expect( doc.body.innerHTML ).toEqual( input ); + } ); + it( 'should not remove white space if next elemnt has none', () => { const input = `<div><strong>a </strong>b</div>`; const output = '<div><strong>a </strong>b</div>'; diff --git a/packages/blocks/src/api/utils.js b/packages/blocks/src/api/utils.js index 11b333d8bdef23..dbf1dc79049b9d 100644 --- a/packages/blocks/src/api/utils.js +++ b/packages/blocks/src/api/utils.js @@ -184,7 +184,7 @@ export function getAccessibleBlockLabel( if ( hasPosition && direction === 'vertical' ) { if ( hasLabel ) { return sprintf( - /* translators: accessibility text. %1: The block title, %2: The block row number, %3: The block label.. */ + /* translators: accessibility text. 1: The block title. 2: The block row number. 3: The block label.. */ __( '%1$s Block. Row %2$d. %3$s' ), title, position, @@ -193,15 +193,15 @@ export function getAccessibleBlockLabel( } return sprintf( - /* translators: accessibility text. %s: The block title, %d The block row number. */ - __( '%s Block. Row %d' ), + /* translators: accessibility text. 1: The block title. 2: The block row number. */ + __( '%1$s Block. Row %2$d' ), title, position ); } else if ( hasPosition && direction === 'horizontal' ) { if ( hasLabel ) { return sprintf( - /* translators: accessibility text. %1: The block title, %2: The block column number, %3: The block label.. */ + /* translators: accessibility text. 1: The block title. 2: The block column number. 3: The block label.. */ __( '%1$s Block. Column %2$d. %3$s' ), title, position, @@ -210,8 +210,8 @@ export function getAccessibleBlockLabel( } return sprintf( - /* translators: accessibility text. %s: The block title, %d The block column number. */ - __( '%s Block. Column %d' ), + /* translators: accessibility text. 1: The block title. 2: The block column number. */ + __( '%1$s Block. Column %2$d' ), title, position ); diff --git a/packages/components/package.json b/packages/components/package.json index afbfd07e5451b5..820d5e2f945118 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -24,7 +24,7 @@ "build-style/**" ], "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@emotion/core": "^10.0.22", "@emotion/css": "^10.0.22", "@emotion/native": "^10.0.22", @@ -48,15 +48,15 @@ "downshift": "^4.0.5", "gradient-parser": "^0.1.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "moment": "^2.22.1", "re-resizable": "^6.0.0", "react-dates": "^17.1.1", "react-spring": "^8.0.20", - "reakit": "^1.0.0-beta.12", + "reakit": "^1.0.0-rc.0", "rememo": "^3.0.0", "tinycolor2": "^1.4.1", - "uuid": "^3.3.2" + "uuid": "^7.0.2" }, "publishConfig": { "access": "public" diff --git a/packages/components/src/angle-picker-control/stories/index.js b/packages/components/src/angle-picker-control/stories/index.js index 0c861f1b414d44..5d88c9be90d59c 100644 --- a/packages/components/src/angle-picker-control/stories/index.js +++ b/packages/components/src/angle-picker-control/stories/index.js @@ -9,7 +9,7 @@ import { useState } from '@wordpress/element'; import AnglePickerControl from '../'; export default { - title: 'Components|AnglePickerControl', + title: 'Components/AnglePickerControl', component: AnglePickerControl, }; diff --git a/packages/components/src/autocomplete/index.js b/packages/components/src/autocomplete/index.js index 6466328cabd836..8517c7bfc83e0b 100644 --- a/packages/components/src/autocomplete/index.js +++ b/packages/components/src/autocomplete/index.js @@ -227,6 +227,7 @@ export class Autocomplete extends Component { if ( !! filteredOptions.length ) { debouncedSpeak( sprintf( + /* translators: %d: number of results. */ _n( '%d result found, use up and down arrow keys to navigate.', '%d results found, use up and down arrow keys to navigate.', diff --git a/packages/components/src/button-group/index.js b/packages/components/src/button-group/index.js index 6f4fb672c8c6ef..2ef2b5e94c6018 100644 --- a/packages/components/src/button-group/index.js +++ b/packages/components/src/button-group/index.js @@ -3,10 +3,15 @@ */ import classnames from 'classnames'; -function ButtonGroup( { className, ...props } ) { +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +function ButtonGroup( { className, ...props }, ref ) { const classes = classnames( 'components-button-group', className ); - return <div { ...props } className={ classes } role="group" />; + return <div ref={ ref } role="group" className={ classes } { ...props } />; } -export default ButtonGroup; +export default forwardRef( ButtonGroup ); diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index 2d0d325d6209f0..1ad73b8d4f142c 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -30,7 +30,7 @@ // Focus. // See https://github.com/WordPress/gutenberg/issues/13267 for more context on these selectors. &:focus:not(:disabled) { - box-shadow: 0 0 0 2px color($theme-color); + box-shadow: 0 0 0 $border-width-focus $theme-color; // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 1px solid transparent; @@ -59,7 +59,7 @@ } &:focus:not(:disabled) { - box-shadow: inset 0 0 0 1px $white, 0 0 0 2px color($theme-color); + box-shadow: inset 0 0 0 1px $white, 0 0 0 $border-width-focus $theme-color; // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 1px solid transparent; @@ -188,7 +188,7 @@ color: #124964; box-shadow: 0 0 0 $border-width #5b9dd9, - 0 0 2px $border-width rgba(30, 140, 190, 0.8); + 0 0 $border-width-focus $border-width rgba(30, 140, 190, 0.8); } } @@ -212,9 +212,18 @@ &.is-secondary.is-busy:disabled, &.is-secondary.is-busy[aria-disabled="true"] { animation: components-button__busy-animation 2500ms infinite linear; - background-size: 100px 100%; - background-image: repeating-linear-gradient(-45deg, $light-gray-500, $white 11px, $white 10px, $light-gray-500 20px); opacity: 1; + background-size: 100px 100%; + // Disable reason: This function call looks nicer when each argument is on its own line. + /* stylelint-disable */ + background-image: linear-gradient( + -45deg, + color($white shade(2%)) 28%, + color($white shade(12%)) 28%, + color($white shade(12%)) 72%, + color($white shade(2%)) 72% + ); + /* stylelint-enable */ } &.is-small { diff --git a/packages/components/src/card/styles/card-styles.js b/packages/components/src/card/styles/card-styles.js index 1afba2ab42f639..dfdeb37726db11 100644 --- a/packages/components/src/card/styles/card-styles.js +++ b/packages/components/src/card/styles/card-styles.js @@ -109,13 +109,13 @@ export function bodySize() { return ` &.is-size { &-large { - padding: 28px; + padding: 24px 32px; } &-medium { - padding: 20px; + padding: 16px 24px; } &-small { - padding: 12px; + padding: 16px; } &-extraSmall { padding: 8px; @@ -128,16 +128,16 @@ export function headerFooterSizes() { return ` &.is-size { &-large { - padding: 20px 28px; + padding: 24px 32px; } &-medium { - padding: 12px 20px; + padding: 16px 24px; } &-small { - padding: 8px 12px; + padding: 16px; } &-extraSmall { - padding: 4px 8px; + padding: 8px; } } `; diff --git a/packages/components/src/color-palette/test/__snapshots__/index.js.snap b/packages/components/src/color-palette/test/__snapshots__/index.js.snap index 760221f289041e..07eed8a9d5019f 100644 --- a/packages/components/src/color-palette/test/__snapshots__/index.js.snap +++ b/packages/components/src/color-palette/test/__snapshots__/index.js.snap @@ -367,9 +367,9 @@ exports[`ColorPalette should render a dynamic toolbar of colors 1`] = ` xmlns="http://www.w3.org/2000/svg" > <svg - aria-hidden="true" + aria-hidden={true} fill="#000000" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" diff --git a/packages/components/src/color-picker/test/__snapshots__/index.js.snap b/packages/components/src/color-picker/test/__snapshots__/index.js.snap index 434ed647095fdb..ee3e5fc66b2a31 100644 --- a/packages/components/src/color-picker/test/__snapshots__/index.js.snap +++ b/packages/components/src/color-picker/test/__snapshots__/index.js.snap @@ -155,8 +155,8 @@ exports[`ColorPicker should commit changes to all views on blur 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -329,8 +329,8 @@ exports[`ColorPicker should commit changes to all views on keyDown = DOWN 1`] = type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -503,8 +503,8 @@ exports[`ColorPicker should commit changes to all views on keyDown = ENTER 1`] = type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -677,8 +677,8 @@ exports[`ColorPicker should commit changes to all views on keyDown = UP 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -851,8 +851,8 @@ exports[`ColorPicker should only update input view for draft changes 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -1025,8 +1025,8 @@ exports[`ColorPicker should render color picker 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" diff --git a/packages/components/src/custom-select-control/style.scss b/packages/components/src/custom-select-control/style.scss index 7fd5bcc382821a..cf49b4f24d7687 100644 --- a/packages/components/src/custom-select-control/style.scss +++ b/packages/components/src/custom-select-control/style.scss @@ -9,17 +9,17 @@ } .components-custom-select-control__button { - border: 1px solid $dark-gray-200; - border-radius: 4px; - color: $dark-gray-500; + border: 1px solid $medium-gray-text; + border-radius: $radius-block-ui; display: inline; min-height: 30px; min-width: 130px; position: relative; text-align: left; - &:focus { - border-color: $blue-medium-500; + &:focus:not(:disabled) { + border-color: $theme-color; + box-shadow: 0 0 0 ($border-width-focus - $border-width) $theme-color; } &-icon { @@ -32,7 +32,17 @@ } .components-custom-select-control__menu { - background: $white; + background-color: $white; + + // Show border around the dropdown menu when open. + &:focus { + // Block UI appearance. + border: $border-width solid $dark-gray-primary; + border-radius: $radius-block-ui; + outline: none; + transition: none; + } + max-height: 400px; min-width: 100%; overflow: auto; diff --git a/packages/components/src/date-time/test/__snapshots__/time.js.snap b/packages/components/src/date-time/test/__snapshots__/time.js.snap index e27e600f089f22..b65d4fddd151c0 100644 --- a/packages/components/src/date-time/test/__snapshots__/time.js.snap +++ b/packages/components/src/date-time/test/__snapshots__/time.js.snap @@ -317,7 +317,7 @@ exports[`TimePicker matches the snapshot when the is12hour prop is specified 1`] value="00" /> </div> - <ButtonGroup + <ForwardRef(ButtonGroup) className="components-datetime__time-field components-datetime__time-field-am-pm" > <ForwardRef(Button) @@ -336,7 +336,7 @@ exports[`TimePicker matches the snapshot when the is12hour prop is specified 1`] > PM </ForwardRef(Button)> - </ButtonGroup> + </ForwardRef(ButtonGroup)> </div> </fieldset> </div> @@ -498,7 +498,7 @@ exports[`TimePicker matches the snapshot when the is12hour prop is true 1`] = ` value="00" /> </div> - <ButtonGroup + <ForwardRef(ButtonGroup) className="components-datetime__time-field components-datetime__time-field-am-pm" > <ForwardRef(Button) @@ -517,7 +517,7 @@ exports[`TimePicker matches the snapshot when the is12hour prop is true 1`] = ` > PM </ForwardRef(Button)> - </ButtonGroup> + </ForwardRef(ButtonGroup)> </div> </fieldset> </div> diff --git a/packages/components/src/disabled/stories/index.js b/packages/components/src/disabled/stories/index.js new file mode 100644 index 00000000000000..527c76899c6527 --- /dev/null +++ b/packages/components/src/disabled/stories/index.js @@ -0,0 +1,31 @@ +/** + * Internal dependencies + */ +import Disabled from '../'; +import SelectControl from '../../select-control/'; +import TextControl from '../../text-control/'; +import TextareaControl from '../../textarea-control/'; + +export default { + title: 'Components/Disabled', + component: Disabled, +}; + +export const _default = () => { + return ( + <Disabled> + <TextControl label="Text Control" /> + <TextareaControl label="TextArea Control" /> + <SelectControl + label="Select Control" + onChange={ () => {} } + options={ [ + { value: null, label: 'Select an option', disabled: true }, + { value: 'a', label: 'Option A' }, + { value: 'b', label: 'Option B' }, + { value: 'c', label: 'Option C' }, + ] } + /> + </Disabled> + ); +}; diff --git a/packages/components/src/dropdown-menu/index.native.js b/packages/components/src/dropdown-menu/index.native.js index 6243847023227e..d665e37e49cae3 100644 --- a/packages/components/src/dropdown-menu/index.native.js +++ b/packages/components/src/dropdown-menu/index.native.js @@ -1,5 +1,184 @@ -function DropdownMenu() { - return null; +/** + * External dependencies + */ +import classnames from 'classnames'; +import { flatMap, isEmpty, isFunction } from 'lodash'; +import { Platform } from 'react-native'; +/** + * WordPress dependencies + */ +import { DOWN } from '@wordpress/keycodes'; +import deprecated from '@wordpress/deprecated'; +import { BottomSheet, PanelBody } from '@wordpress/components'; +import { withPreferredColorScheme } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import Button from '../button'; +import Dropdown from '../dropdown'; + +function mergeProps( defaultProps = {}, props = {} ) { + const mergedProps = { + ...defaultProps, + ...props, + }; + + if ( props.className && defaultProps.className ) { + mergedProps.className = classnames( + props.className, + defaultProps.className + ); + } + + return mergedProps; +} + +function DropdownMenu( { + children, + className, + controls, + icon = 'menu', + label, + popoverProps, + toggleProps, + // The following props exist for backward compatibility. + menuLabel, + position, +} ) { + if ( menuLabel ) { + deprecated( '`menuLabel` prop in `DropdownComponent`', { + alternative: '`menuProps` object and its `aria-label` property', + plugin: 'Gutenberg', + } ); + } + + if ( position ) { + deprecated( '`position` prop in `DropdownComponent`', { + alternative: '`popoverProps` object and its `position` property', + plugin: 'Gutenberg', + } ); + } + + if ( isEmpty( controls ) && ! isFunction( children ) ) { + return null; + } + + // Normalize controls to nested array of objects (sets of controls) + let controlSets; + if ( ! isEmpty( controls ) ) { + controlSets = controls; + if ( ! Array.isArray( controlSets[ 0 ] ) ) { + controlSets = [ controlSets ]; + } + } + const mergedPopoverProps = mergeProps( + { + className: 'components-dropdown-menu__popover', + position, + }, + popoverProps + ); + + return ( + <Dropdown + className={ classnames( 'components-dropdown-menu', className ) } + popoverProps={ mergedPopoverProps } + renderToggle={ ( { isOpen, onToggle } ) => { + const openOnArrowDown = ( event ) => { + if ( ! isOpen && event.keyCode === DOWN ) { + event.preventDefault(); + event.stopPropagation(); + onToggle(); + } + }; + const mergedToggleProps = mergeProps( + { + className: classnames( + 'components-dropdown-menu__toggle', + { + 'is-opened': isOpen, + } + ), + }, + toggleProps + ); + + return ( + <Button + { ...mergedToggleProps } + icon={ icon } + onClick={ ( event ) => { + onToggle( event ); + if ( mergedToggleProps.onClick ) { + mergedToggleProps.onClick( event ); + } + } } + onKeyDown={ ( event ) => { + openOnArrowDown( event ); + if ( mergedToggleProps.onKeyDown ) { + mergedToggleProps.onKeyDown( event ); + } + } } + aria-haspopup="true" + aria-expanded={ isOpen } + label={ label } + showTooltip + > + { mergedToggleProps.children } + </Button> + ); + } } + renderContent={ ( { isOpen, onClose, ...props } ) => { + return ( + <BottomSheet + hideHeader={ true } + isVisible={ isOpen } + onClose={ onClose } + > + { isFunction( children ) ? children( props ) : null } + <PanelBody + title={ label } + style={ { paddingLeft: 0, paddingRight: 0 } } + > + { flatMap( + controlSets, + ( controlSet, indexOfSet ) => + controlSet.map( + ( control, indexOfControl ) => ( + <BottomSheet.Cell + key={ [ + indexOfSet, + indexOfControl, + ].join() } + label={ control.title } + onPress={ () => { + onClose(); + if ( control.onClick ) { + control.onClick(); + } + } } + editable={ false } + icon={ control.icon } + leftAlign={ true } + isSelected={ control.isActive } + separatorType={ + indexOfControl === + controlSet.length - 1 || + Platform.OS === 'android' + ? 'none' + : 'leftMargin' + } + /> + ) + ) + ) } + </PanelBody> + </BottomSheet> + ); + } } + /> + ); } -export default DropdownMenu; +export default withPreferredColorScheme( DropdownMenu ); diff --git a/packages/components/src/dropdown-menu/style.scss b/packages/components/src/dropdown-menu/style.scss index c69ecd8c80a8dd..8b6c26be120168 100644 --- a/packages/components/src/dropdown-menu/style.scss +++ b/packages/components/src/dropdown-menu/style.scss @@ -34,20 +34,19 @@ height: 1px; } - &.is-active { + &.is-active svg { // Block UI appearance. - border: $border-width solid $dark-gray-primary; - border-radius: $radius-block-ui; color: $white; background: $dark-gray-primary; + box-shadow: 0 0 0 $border-width $dark-gray-primary; + border-radius: $border-width; } // Formatting buttons > svg { - border-radius: $radius-round-rectangle; + border-radius: $radius-block-ui; width: $button-size-small; height: $button-size-small; - margin: -1px $grid-unit-10 -1px 0; } } diff --git a/packages/components/src/dropdown/index.js b/packages/components/src/dropdown/index.js index cf47a7ac188a4a..dbf8380b1ffa47 100644 --- a/packages/components/src/dropdown/index.js +++ b/packages/components/src/dropdown/index.js @@ -78,7 +78,7 @@ class Dropdown extends Component { const { renderContent, renderToggle, - position = 'bottom', + position = 'bottom right', className, contentClassName, expandOnMobile, diff --git a/packages/components/src/form-toggle/style.scss b/packages/components/src/form-toggle/style.scss index ebe43dc70441a6..8be2aa6655ea98 100644 --- a/packages/components/src/form-toggle/style.scss +++ b/packages/components/src/form-toggle/style.scss @@ -77,7 +77,11 @@ $toggle-border-width: 2px; } &__input:focus + .components-form-toggle__track { - @include switch-style__focus-active(); + box-shadow: 0 0 0 2px $white, 0 0 0 (2px + $border-width-focus) $theme-color; + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + outline-offset: 2px; } &.is-checked { diff --git a/packages/components/src/form-token-field/index.js b/packages/components/src/form-token-field/index.js index b2c81977a50fbc..0641a327c64734 100644 --- a/packages/components/src/form-token-field/index.js +++ b/packages/components/src/form-token-field/index.js @@ -514,6 +514,7 @@ class FormTokenField extends Component { const message = hasMatchingSuggestions ? sprintf( + /* translators: %d: number of results. */ _n( '%d result found, use up and down arrow keys to navigate.', '%d results found, use up and down arrow keys to navigate.', diff --git a/packages/components/src/guide/page-control.js b/packages/components/src/guide/page-control.js index 837a0b31e7d5ad..1a39fdd1426c8e 100644 --- a/packages/components/src/guide/page-control.js +++ b/packages/components/src/guide/page-control.js @@ -37,8 +37,8 @@ export default function PageControl( { isSelected={ page === currentPage } /> } - /* translators: %1$d: current page number %2$d: total number of pages */ aria-label={ sprintf( + /* translators: 1: current page number 2: total number of pages */ __( 'Page %1$d of %2$d' ), page + 1, numberOfPages diff --git a/packages/components/src/higher-order/with-focus-return/test/index.js b/packages/components/src/higher-order/with-focus-return/test/index.js index cd110d4fa7cd8e..67502237260b32 100644 --- a/packages/components/src/higher-order/with-focus-return/test/index.js +++ b/packages/components/src/higher-order/with-focus-return/test/index.js @@ -2,12 +2,12 @@ * External dependencies */ import renderer from 'react-test-renderer'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; /** * WordPress dependencies */ -import { Component, createElement } from '@wordpress/element'; +import { Component } from '@wordpress/element'; /** * Internal dependencies @@ -29,12 +29,8 @@ describe( 'withFocusReturn()', () => { const Composite = withFocusReturn( Test ); const activeElement = document.createElement( 'button' ); const switchFocusTo = document.createElement( 'input' ); - - const getInstance = ( wrapper ) => { - return wrapper.root.find( - ( node ) => node.instance instanceof Component - ).instance; - }; + document.body.appendChild( activeElement ); + document.body.appendChild( switchFocusTo ); beforeEach( () => { activeElement.focus(); @@ -74,72 +70,78 @@ describe( 'withFocusReturn()', () => { } ); it( 'should not switch focus back to the bound focus element', () => { - const mountedComposite = renderer.create( <Composite /> ); - - expect( getInstance( mountedComposite ).activeElementOnMount ).toBe( - activeElement - ); + const { unmount } = render( <Composite />, { + container: document.body.appendChild( + document.createElement( 'div' ) + ), + } ); // Change activeElement. switchFocusTo.focus(); expect( document.activeElement ).toBe( switchFocusTo ); // Should keep focus on switchFocusTo, because it is not within HOC. - mountedComposite.unmount(); + unmount(); expect( document.activeElement ).toBe( switchFocusTo ); } ); it( 'should switch focus back when unmounted while having focus', () => { - const wrapper = mount( <Composite /> ); - wrapper - .find( 'textarea' ) - .at( 0 ) - .simulate( 'focus' ); + const { container, unmount } = render( <Composite />, { + container: document.body.appendChild( + document.createElement( 'div' ) + ), + } ); + + const textarea = container.querySelector( 'textarea' ); + textarea.focus(); + expect( document.activeElement ).toBe( textarea ); // Should return to the activeElement saved with this component. - wrapper.unmount(); + unmount(); expect( document.activeElement ).toBe( activeElement ); } ); it( 'should switch focus to the most recent still-available focus target', () => { - const container = document.createElement( 'div' ); - document.body.appendChild( container ); - const wrapper = mount( - createElement( - ( props ) => ( - <Provider> - <input name="first" /> - { props.renderSecondInput && ( - <input name="second" /> - ) } - { props.renderComposite && <Composite /> } - </Provider> + const TestComponent = ( props ) => ( + <Provider> + <input name="first" /> + { props.renderSecondInput && <input name="second" /> } + { props.renderComposite && <Composite /> } + </Provider> + ); + + const { container, rerender } = render( + <TestComponent renderSecondInput />, + { + container: document.body.appendChild( + document.createElement( 'div' ) ), - { renderSecondInput: true } - ), - { attachTo: container } + } ); - function focus( selector ) { - const childWrapper = wrapper.find( selector ); - const childNode = childWrapper.getDOMNode(); - childWrapper.simulate( 'focus', { target: childNode } ); - } + const firstInput = container.querySelector( 'input[name="first"]' ); + firstInput.focus(); - focus( 'input[name="first"]' ); - jest.spyOn( - wrapper.find( 'input[name="first"]' ).getDOMNode(), - 'focus' + const secondInput = container.querySelector( + 'input[name="second"]' ); - focus( 'input[name="second"]' ); - wrapper.setProps( { renderComposite: true } ); - focus( 'textarea' ); - wrapper.setProps( { renderSecondInput: false } ); - wrapper.setProps( { renderComposite: false } ); - - expect( - wrapper.find( 'input[name="first"]' ).getDOMNode().focus - ).toHaveBeenCalled(); + secondInput.focus(); + + expect( document.activeElement ).toBe( secondInput ); + + rerender( <TestComponent renderSecondInput renderComposite /> ); + const textarea = container.querySelector( 'textarea' ); + textarea.focus(); + + expect( document.activeElement ).toBe( textarea ); + + rerender( <TestComponent renderComposite /> ); + + expect( document.activeElement ).toBe( textarea ); + + rerender( <TestComponent /> ); + + expect( document.activeElement ).toBe( firstInput ); } ); } ); } ); diff --git a/packages/components/src/higher-order/with-notices/index.js b/packages/components/src/higher-order/with-notices/index.js index 4806d6d8d6254c..0a1280438282cb 100644 --- a/packages/components/src/higher-order/with-notices/index.js +++ b/packages/components/src/higher-order/with-notices/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import uuid from 'uuid/v4'; +import { v4 as uuid } from 'uuid'; /** * WordPress dependencies diff --git a/packages/components/src/index.js b/packages/components/src/index.js index e02dde7f7217df..f5142afb2f86e0 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -62,6 +62,7 @@ export { default as Modal } from './modal'; export { default as ScrollLock } from './scroll-lock'; export { NavigableMenu, TabbableContainer } from './navigable-container'; export { default as Notice } from './notice'; +export { default as __experimentalNumberControl } from './number-control'; export { default as NoticeList } from './notice/list'; export { default as Panel } from './panel'; export { default as PanelBody } from './panel/body'; @@ -70,6 +71,8 @@ export { default as PanelRow } from './panel/row'; export { default as Placeholder } from './placeholder'; export { default as Popover } from './popover'; export { default as QueryControls } from './query-controls'; +export { default as __experimentalRadio } from './radio'; +export { default as __experimentalRadioGroup } from './radio-group'; export { default as RadioControl } from './radio-control'; export { default as RangeControl } from './range-control'; export { default as ResizableBox } from './resizable-box'; @@ -80,6 +83,7 @@ export { default as Snackbar } from './snackbar'; export { default as SnackbarList } from './snackbar/list'; export { default as Spinner } from './spinner'; export { default as TabPanel } from './tab-panel'; +export { default as __experimentalText } from './text'; export { default as TextControl } from './text-control'; export { default as TextareaControl } from './textarea-control'; export { default as TextHighlight } from './text-highlight'; @@ -91,6 +95,7 @@ export { default as ToolbarGroup } from './toolbar-group'; export { default as __experimentalToolbarItem } from './toolbar-item'; export { default as Tooltip } from './tooltip'; export { default as TreeSelect } from './tree-select'; +export { default as __experimentalUnitControl } from './unit-control'; export { default as VisuallyHidden } from './visually-hidden'; export { default as IsolatedEventContainer } from './isolated-event-container'; export { @@ -113,4 +118,3 @@ export { } from './higher-order/with-focus-return'; export { default as withNotices } from './higher-order/with-notices'; export { default as withSpokenMessages } from './higher-order/with-spoken-messages'; -export * from './text'; diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index abb7b278dc5723..5bbef298904d99 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -30,6 +30,7 @@ export { default as TextareaControl } from './textarea-control'; export { default as PanelBody } from './panel/body'; export { default as PanelActions } from './panel/actions'; export { default as Button } from './button'; +export { default as __experimentalText } from './text'; export { default as TextControl } from './text-control'; export { default as ToggleControl } from './toggle-control'; export { default as SelectControl } from './select-control'; @@ -46,6 +47,7 @@ export { default as withFocusOutside } from './higher-order/with-focus-outside'; export { default as withFocusReturn } from './higher-order/with-focus-return'; export { default as withNotices } from './higher-order/with-notices'; export { default as withSpokenMessages } from './higher-order/with-spoken-messages'; +export * from './text'; // Mobile Components export { default as BottomSheet } from './mobile/bottom-sheet'; diff --git a/packages/components/src/mobile/bottom-sheet/cell.native.js b/packages/components/src/mobile/bottom-sheet/cell.native.js index 37228c481eb59f..50d11a85017151 100644 --- a/packages/components/src/mobile/bottom-sheet/cell.native.js +++ b/packages/components/src/mobile/bottom-sheet/cell.native.js @@ -9,12 +9,13 @@ import { I18nManager, AccessibilityInfo, } from 'react-native'; -import { isEmpty } from 'lodash'; +import { isEmpty, get } from 'lodash'; /** * WordPress dependencies */ import { Icon } from '@wordpress/components'; +import { check } from '@wordpress/icons'; import { Component } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; import { withPreferredColorScheme } from '@wordpress/compose'; @@ -87,6 +88,7 @@ class BottomSheetCell extends Component { accessibilityHint, accessibilityRole, disabled = false, + activeOpacity, onPress, label, value, @@ -98,8 +100,10 @@ class BottomSheetCell extends Component { cellContainerStyle = {}, cellRowContainerStyle = {}, onChangeValue, + onSubmit, children, editable = true, + isSelected = false, separatorType, style = {}, getStylesFromColorScheme, @@ -127,7 +131,7 @@ class BottomSheetCell extends Component { ? cellLabelLeftAlignNoIconStyle : cellLabelCenteredStyle; const defaultLabelStyle = - showValue || icon !== undefined || customActionButton + showValue || customActionButton || icon ? cellLabelStyle : defaultMissingIconAndValue; @@ -226,6 +230,7 @@ class BottomSheetCell extends Component { } onFocus={ startEditing } onBlur={ finishEditing } + onSubmitEditing={ onSubmit } keyboardType={ this.typeToKeyboardType( type, step ) } { ...valueProps } /> @@ -271,6 +276,11 @@ class BottomSheetCell extends Component { this.state.isScreenReaderEnabled && accessible ? 'none' : 'auto'; const { title, handler } = customActionButton || {}; + const opacity = + activeOpacity !== undefined + ? activeOpacity + : get( platformStyles, 'activeOpacity.opacity' ); + return ( <TouchableOpacity accessible={ @@ -287,6 +297,7 @@ class BottomSheetCell extends Component { : accessibilityHint } disabled={ disabled } + activeOpacity={ opacity } onPress={ onCellPress } style={ [ styles.clipToBounds, style ] } > @@ -303,6 +314,7 @@ class BottomSheetCell extends Component { icon={ icon } size={ 24 } color={ iconStyle.color } + isPressed={ false } /> <View style={ @@ -326,6 +338,12 @@ class BottomSheetCell extends Component { </TouchableOpacity> ) } </View> + { isSelected && ( + <Icon + icon={ check } + fill={ platformStyles.isSelected.color } + /> + ) } { showValue && getValueComponent() } { children } </View> diff --git a/packages/components/src/mobile/bottom-sheet/cellStyles.android.scss b/packages/components/src/mobile/bottom-sheet/cellStyles.android.scss index 4feb815ba9bd07..0c823db8c3fc90 100644 --- a/packages/components/src/mobile/bottom-sheet/cellStyles.android.scss +++ b/packages/components/src/mobile/bottom-sheet/cellStyles.android.scss @@ -5,3 +5,7 @@ .separatorMarginLeft { margin-left: 56px; } + +.isSelected { + color: $blue-wordpress; +} diff --git a/packages/components/src/mobile/bottom-sheet/cellStyles.ios.scss b/packages/components/src/mobile/bottom-sheet/cellStyles.ios.scss index 45b97213d1768f..6cb9dead68b6f7 100644 --- a/packages/components/src/mobile/bottom-sheet/cellStyles.ios.scss +++ b/packages/components/src/mobile/bottom-sheet/cellStyles.ios.scss @@ -5,3 +5,11 @@ .separatorMarginLeft { margin-left: 36px; } + +.isSelected { + color: $blue-wordpress; +} + +.activeOpacity { + opacity: 1; +} diff --git a/packages/components/src/mobile/bottom-sheet/index.native.js b/packages/components/src/mobile/bottom-sheet/index.native.js index 4df6fc064a0884..826356958c9b71 100644 --- a/packages/components/src/mobile/bottom-sheet/index.native.js +++ b/packages/components/src/mobile/bottom-sheet/index.native.js @@ -13,6 +13,7 @@ import { } from 'react-native'; import Modal from 'react-native-modal'; import SafeArea from 'react-native-safe-area'; +import { subscribeAndroidModalClosed } from 'react-native-gutenberg-bridge'; /** * WordPress dependencies @@ -67,6 +68,14 @@ class BottomSheet extends Component { } componentDidMount() { + if ( Platform.OS === 'android' ) { + this.androidModalClosedSubscription = subscribeAndroidModalClosed( + () => { + this.props.onClose(); + } + ); + } + this.keyboardWillShowListener = Keyboard.addListener( 'keyboardWillShow', this.keyboardWillShow @@ -85,6 +94,9 @@ class BottomSheet extends Component { } componentWillUnmount() { + if ( this.androidModalClosedSubscription ) { + this.androidModalClosedSubscription.remove(); + } if ( this.safeAreaEventSubscription === null ) { return; } diff --git a/packages/components/src/mobile/bottom-sheet/range-cell.native.js b/packages/components/src/mobile/bottom-sheet/range-cell.native.js index 717ab84232a097..96867a38630719 100644 --- a/packages/components/src/mobile/bottom-sheet/range-cell.native.js +++ b/packages/components/src/mobile/bottom-sheet/range-cell.native.js @@ -133,6 +133,7 @@ class BottomSheetRangeCell extends Component { } announceCurrentValue( value ) { + /* translators: %s: current cell value. */ const announcement = sprintf( __( 'Current value is %s' ), value ); AccessibilityInfo.announceForAccessibility( announcement ); } @@ -182,6 +183,7 @@ class BottomSheetRangeCell extends Component { accessibilityRole={ 'none' } value={ '' } editable={ false } + activeOpacity={ 1 } accessible={ accessible } onPress={ this.onCellPress } accessibilityLabel={ accessibilityLabel } diff --git a/packages/components/src/mobile/bottom-sheet/stepper-cell/stepper.ios.js b/packages/components/src/mobile/bottom-sheet/stepper-cell/stepper.ios.js index a688bd46dc5c9a..e226b8adb4b20f 100644 --- a/packages/components/src/mobile/bottom-sheet/stepper-cell/stepper.ios.js +++ b/packages/components/src/mobile/bottom-sheet/stepper-cell/stepper.ios.js @@ -49,12 +49,7 @@ function Stepper( { onPressOut={ onPressOut } style={ [ buttonStyle, isMaxValue ? { opacity: 0.4 } : null ] } > - <Icon - icon={ plus } - size={ 24 } - color={ buttonStyle.color } - style={ styles.plus } - /> + <Icon icon={ plus } size={ 24 } color={ buttonStyle.color } /> </TouchableOpacity> </View> ); diff --git a/packages/components/src/mobile/bottom-sheet/stepper-cell/style.native.scss b/packages/components/src/mobile/bottom-sheet/stepper-cell/style.native.scss index d728d79909e507..597bb22dc726e7 100644 --- a/packages/components/src/mobile/bottom-sheet/stepper-cell/style.native.scss +++ b/packages/components/src/mobile/bottom-sheet/stepper-cell/style.native.scss @@ -64,8 +64,3 @@ .valueTextDark { color: $light-opacity-200; } - -.plus { - margin-top: 4px; - margin-right: 1px; -} diff --git a/packages/components/src/mobile/bottom-sheet/styles.native.scss b/packages/components/src/mobile/bottom-sheet/styles.native.scss index 254817bfb44490..4550fb21d0c52d 100644 --- a/packages/components/src/mobile/bottom-sheet/styles.native.scss +++ b/packages/components/src/mobile/bottom-sheet/styles.native.scss @@ -93,6 +93,7 @@ flex-direction: row; min-height: 48; align-items: center; + justify-content: space-between; } .clipToBounds { @@ -137,7 +138,7 @@ font-size: 17px; color: #2e4453; flex: 1; - margin-left: 12px; + margin-left: 0; } .cellValue { diff --git a/packages/components/src/mobile/image-with-focalpoint/index.native.js b/packages/components/src/mobile/image-with-focalpoint/index.native.js index 0e542eaad82770..440b8477ff2bcd 100644 --- a/packages/components/src/mobile/image-with-focalpoint/index.native.js +++ b/packages/components/src/mobile/image-with-focalpoint/index.native.js @@ -27,7 +27,7 @@ const ImageWithFocalPoint = ( { focalPoint, url } ) => { } ); } ); } - }, [] ); + }, [ url ] ); const onContainerLayout = ( event ) => { const { height, width } = event.nativeEvent.layout; @@ -97,18 +97,10 @@ const ImageWithFocalPoint = ( { focalPoint, url } ) => { return ( <View style={ styles.container } onLayout={ onContainerLayout }> <Image - aspectRatio={ - originalImageData - ? originalImageData.aspectRatio - : undefined - } + aspectRatio={ originalImageData?.aspectRatio } style={ [ styles.image, - { - height: containerSize - ? containerSize.height - : undefined, - }, + { height: containerSize?.height }, getImageStyles(), ] } source={ { uri: url } } diff --git a/packages/components/src/mobile/keyboard-aware-flat-list/index.ios.js b/packages/components/src/mobile/keyboard-aware-flat-list/index.ios.js index 83f8f64f84ff64..932e54646a9afe 100644 --- a/packages/components/src/mobile/keyboard-aware-flat-list/index.ios.js +++ b/packages/components/src/mobile/keyboard-aware-flat-list/index.ios.js @@ -50,6 +50,7 @@ export const KeyboardAwareFlatList = ( { onKeyboardWillShow={ () => { this.keyboardWillShowIndicator = true; } } + scrollEnabled={ listProps.scrollEnabled } onScroll={ ( event ) => { this.latestContentOffsetY = event.nativeEvent.contentOffset.y; } } diff --git a/packages/components/src/mobile/modal-header-bar/styles.native.scss b/packages/components/src/mobile/modal-header-bar/styles.native.scss index 0697ff71e7e55e..4ee1ebe584704d 100644 --- a/packages/components/src/mobile/modal-header-bar/styles.native.scss +++ b/packages/components/src/mobile/modal-header-bar/styles.native.scss @@ -56,5 +56,5 @@ } .separatorDark { - background-color: $gray-70; + background-color: #2d2d2d; } diff --git a/packages/components/src/mobile/readable-content-view/index.native.js b/packages/components/src/mobile/readable-content-view/index.native.js index a25048b0b5dffa..ec1f67a4d98f89 100644 --- a/packages/components/src/mobile/readable-content-view/index.native.js +++ b/packages/components/src/mobile/readable-content-view/index.native.js @@ -8,14 +8,15 @@ import { View, Dimensions } from 'react-native'; */ import styles from './style.scss'; -const ReadableContentView = ( { reversed, children } ) => ( +const ReadableContentView = ( { reversed, children, style } ) => ( <View style={ styles.container }> <View - style={ + style={ [ reversed ? styles.reversedCenteredContent - : styles.centeredContent - } + : styles.centeredContent, + style, + ] } > { children } </View> diff --git a/packages/components/src/navigable-container/test/menu.js b/packages/components/src/navigable-container/test/menu.js index eed4b235c91b4c..97609943740b80 100644 --- a/packages/components/src/navigable-container/test/menu.js +++ b/packages/components/src/navigable-container/test/menu.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { mount } from 'enzyme'; +import { fireEvent, render } from '@testing-library/react'; import { each } from 'lodash'; /** @@ -14,8 +14,8 @@ import { UP, DOWN, LEFT, RIGHT, SPACE } from '@wordpress/keycodes'; */ import { NavigableMenu } from '../menu'; -function simulateVisible( wrapper, selector ) { - const elements = wrapper.getDOMNode().querySelectorAll( selector ); +function simulateVisible( container, selector ) { + const elements = container.querySelectorAll( selector ); each( elements, ( elem ) => { elem.getClientRects = () => [ 'trick-jsdom-into-having-size-for-element-rect', @@ -23,7 +23,7 @@ function simulateVisible( wrapper, selector ) { } ); } -function fireKeyDown( container, keyCode, shiftKey ) { +function fireKeyDown( node, keyCode, shiftKey ) { const interaction = { stopped: false, }; @@ -35,7 +35,7 @@ function fireKeyDown( container, keyCode, shiftKey ) { event.stopImmediatePropagation = () => { interaction.stopped = true; }; - container.getDOMNode().dispatchEvent( event ); + fireEvent( node, event ); return interaction; } @@ -43,7 +43,7 @@ function fireKeyDown( container, keyCode, shiftKey ) { describe( 'NavigableMenu', () => { it( 'vertical: should navigate by up and down', () => { let currentIndex = 0; - const wrapper = mount( + const { container, getByRole } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -71,17 +71,17 @@ describe( 'NavigableMenu', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div' ); - wrapper - .getDOMNode() - .querySelector( '#btn1' ) - .focus(); + container.querySelector( '#btn1' ).focus(); // Navigate options function assertKeyDown( keyCode, expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode, false ); + const interaction = fireKeyDown( + getByRole( 'menu' ), + keyCode, + false + ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } @@ -101,7 +101,7 @@ describe( 'NavigableMenu', () => { it( 'vertical: should navigate by up and down, and stop at edges', () => { let currentIndex = 0; - const wrapper = mount( + const { container, getByRole } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -125,17 +125,17 @@ describe( 'NavigableMenu', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div' ); - wrapper - .getDOMNode() - .querySelector( '#btn1' ) - .focus(); + container.querySelector( '#btn1' ).focus(); // Navigate options function assertKeyDown( keyCode, expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode, false ); + const interaction = fireKeyDown( + getByRole( 'menu' ), + keyCode, + false + ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } @@ -153,7 +153,7 @@ describe( 'NavigableMenu', () => { it( 'horizontal: should navigate by left and right', () => { let currentIndex = 0; - const wrapper = mount( + const { container, getByRole } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -181,17 +181,17 @@ describe( 'NavigableMenu', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div' ); - wrapper - .getDOMNode() - .querySelector( '#btn1' ) - .focus(); + container.querySelector( '#btn1' ).focus(); // Navigate options function assertKeyDown( keyCode, expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode, false ); + const interaction = fireKeyDown( + getByRole( 'menu' ), + keyCode, + false + ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } @@ -211,7 +211,7 @@ describe( 'NavigableMenu', () => { it( 'horizontal: should navigate by left and right, and stop at edges', () => { let currentIndex = 0; - const wrapper = mount( + const { container, getByRole } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -235,17 +235,17 @@ describe( 'NavigableMenu', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div' ); - wrapper - .getDOMNode() - .querySelector( '#btn1' ) - .focus(); + container.querySelector( '#btn1' ).focus(); // Navigate options function assertKeyDown( keyCode, expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode, false ); + const interaction = fireKeyDown( + getByRole( 'menu' ), + keyCode, + false + ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } @@ -263,7 +263,7 @@ describe( 'NavigableMenu', () => { it( 'both: should navigate by up/down and left/right', () => { let currentIndex = 0; - const wrapper = mount( + const { container, getByRole } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -280,17 +280,13 @@ describe( 'NavigableMenu', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div' ); - wrapper - .getDOMNode() - .querySelector( '#btn1' ) - .focus(); + container.querySelector( '#btn1' ).focus(); // Navigate options function assertKeyDown( keyCode, expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode ); + const interaction = fireKeyDown( getByRole( 'menu' ), keyCode ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } diff --git a/packages/components/src/navigable-container/test/tabbable.js b/packages/components/src/navigable-container/test/tabbable.js index 323cad39f4dc22..127a91ea9a847a 100644 --- a/packages/components/src/navigable-container/test/tabbable.js +++ b/packages/components/src/navigable-container/test/tabbable.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { mount } from 'enzyme'; +import { fireEvent, render } from '@testing-library/react'; import { each } from 'lodash'; /** @@ -14,8 +14,8 @@ import { TAB, SPACE } from '@wordpress/keycodes'; */ import { TabbableContainer } from '../tabbable'; -function simulateVisible( wrapper, selector ) { - const elements = wrapper.getDOMNode().querySelectorAll( selector ); +function simulateVisible( container, selector ) { + const elements = container.querySelectorAll( selector ); each( elements, ( elem ) => { elem.getClientRects = () => [ 'trick-jsdom-into-having-size-for-element-rect', @@ -23,7 +23,7 @@ function simulateVisible( wrapper, selector ) { } ); } -function fireKeyDown( container, keyCode, shiftKey ) { +function fireKeyDown( node, keyCode, shiftKey ) { const interaction = { stopped: false, }; @@ -35,7 +35,7 @@ function fireKeyDown( container, keyCode, shiftKey ) { event.stopImmediatePropagation = () => { interaction.stopped = true; }; - container.getDOMNode().dispatchEvent( event ); + fireEvent( node, event ); return interaction; } @@ -43,7 +43,7 @@ function fireKeyDown( container, keyCode, shiftKey ) { describe( 'TabbableContainer', () => { it( 'should navigate by keypresses', () => { let currentIndex = 0; - const wrapper = mount( + const { container } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -71,13 +71,9 @@ describe( 'TabbableContainer', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div.wrapper' ); - wrapper - .getDOMNode() - .querySelector( '#section1' ) - .focus(); + container.querySelector( '#section1' ).focus(); // Navigate options function assertKeyDown( @@ -86,7 +82,11 @@ describe( 'TabbableContainer', () => { expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode, shiftKey ); + const interaction = fireKeyDown( + container.querySelector( '.wrapper' ), + keyCode, + shiftKey + ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } @@ -104,7 +104,7 @@ describe( 'TabbableContainer', () => { it( 'should navigate by keypresses and stop at edges', () => { let currentIndex = 0; - const wrapper = mount( + const { container } = render( /* Disabled because of our rule restricting literal IDs, preferring `withInstanceId`. In this case, it's fine to use literal IDs. @@ -128,13 +128,9 @@ describe( 'TabbableContainer', () => { /* eslint-enable no-restricted-syntax */ ); - simulateVisible( wrapper, '*' ); + simulateVisible( container, '*' ); - const container = wrapper.find( 'div.wrapper' ); - wrapper - .getDOMNode() - .querySelector( '#section1' ) - .focus(); + container.querySelector( '#section1' ).focus(); // Navigate options function assertKeyDown( @@ -143,7 +139,11 @@ describe( 'TabbableContainer', () => { expectedActiveIndex, expectedStop ) { - const interaction = fireKeyDown( container, keyCode, shiftKey ); + const interaction = fireKeyDown( + container.querySelector( '.wrapper' ), + keyCode, + shiftKey + ); expect( currentIndex ).toBe( expectedActiveIndex ); expect( interaction.stopped ).toBe( expectedStop ); } diff --git a/packages/components/src/notice/style.scss b/packages/components/src/notice/style.scss index d69edcc61d8000..3ffb738ebbe07b 100644 --- a/packages/components/src/notice/style.scss +++ b/packages/components/src/notice/style.scss @@ -79,12 +79,5 @@ display: block; margin-left: 0; margin-top: $grid-unit-10; - - // Beyond mobile, align the action button on the right to use the space, and reduce margins so they don't add too much extra line-height. - @include break-medium() { - float: right; - margin-top: -$grid-unit-05; - margin-bottom: -$grid-unit-05; - } } } diff --git a/packages/components/src/number-control/README.md b/packages/components/src/number-control/README.md new file mode 100644 index 00000000000000..218ae241a63888 --- /dev/null +++ b/packages/components/src/number-control/README.md @@ -0,0 +1,29 @@ +# NumberControl + +NumberControl is an enhanced HTML [`input[type="number]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) element. + +## Usage + +```jsx +import { __experimentalNumberControl as NumberControl } from '@wordpress/components'; + +const Example = () => { + const [value, setValue] = useState(10); + + return ( + <NumberControl + isShiftStepEnabled={ true } + onChange={ setValue } + shiftStep={ 10 } + value={ value } + /> + ) +}; +``` + +## Props + +Name | Type | Default | Description +--- | --- | --- | --- +`isShiftStepEnabled` | `boolean` | `true` | Determines if the unit `<select>` is tabbable. +`shiftStep` | `number` | `10` | Amount to increment by when the `shift` key is held down. \ No newline at end of file diff --git a/packages/components/src/number-control/index.js b/packages/components/src/number-control/index.js new file mode 100644 index 00000000000000..33914140975b06 --- /dev/null +++ b/packages/components/src/number-control/index.js @@ -0,0 +1,79 @@ +/** + * External dependencies + */ +import { clamp, noop } from 'lodash'; +import classNames from 'classnames'; + +/** + * WordPress dependencies + */ +import { UP, DOWN } from '@wordpress/keycodes'; + +export default function NumberControl( { + className, + isShiftStepEnabled = true, + max = Infinity, + min = -Infinity, + onChange = noop, + onKeyDown = noop, + shiftStep = 10, + step = 1, + ...props +} ) { + const baseValue = clamp( 0, min, max ); + + const handleOnKeyDown = ( event ) => { + onKeyDown( event ); + const { value } = event.target; + + const isEmpty = value === ''; + const enableShift = event.shiftKey && isShiftStepEnabled; + + const incrementalValue = enableShift + ? parseFloat( shiftStep ) + : parseFloat( step ); + let nextValue = isEmpty ? baseValue : value; + + // Convert to a number to use math + nextValue = parseFloat( nextValue ); + + switch ( event.keyCode ) { + case UP: + event.preventDefault(); + + nextValue = nextValue + incrementalValue; + nextValue = clamp( nextValue, min, max ); + + onChange( nextValue.toString(), { event } ); + + break; + + case DOWN: + event.preventDefault(); + + nextValue = nextValue - incrementalValue; + nextValue = clamp( nextValue, min, max ); + + onChange( nextValue.toString(), { event } ); + + break; + } + }; + + const handleOnChange = ( event ) => { + onChange( event.target.value, { event } ); + }; + + const classes = classNames( 'component-number-control', className ); + + return ( + <input + inputMode="numeric" + { ...props } + className={ classes } + type="number" + onChange={ handleOnChange } + onKeyDown={ handleOnKeyDown } + /> + ); +} diff --git a/packages/components/src/number-control/stories/index.js b/packages/components/src/number-control/stories/index.js new file mode 100644 index 00000000000000..b35af6a74eb11f --- /dev/null +++ b/packages/components/src/number-control/stories/index.js @@ -0,0 +1,35 @@ +/** + * External dependencies + */ +import { boolean, number } from '@storybook/addon-knobs'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import NumberControl from '../'; + +export default { + title: 'Components/NumberControl', + component: NumberControl, +}; + +function Example() { + const [ value, setValue ] = useState( '' ); + + const props = { + isShiftStepEnabled: boolean( 'isShiftStepEnabled', true ), + shiftStep: number( 'shiftStep', 10 ), + step: number( 'step', 1 ), + }; + + return <NumberControl { ...props } value={ value } onChange={ setValue } />; +} + +export const _default = () => { + return <Example />; +}; diff --git a/packages/components/src/number-control/test/index.js b/packages/components/src/number-control/test/index.js new file mode 100644 index 00000000000000..c946ba12aeb048 --- /dev/null +++ b/packages/components/src/number-control/test/index.js @@ -0,0 +1,303 @@ +/** + * External dependencies + */ +import { render, unmountComponentAtNode } from 'react-dom'; +import { act, Simulate } from 'react-dom/test-utils'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; +import { UP, DOWN } from '@wordpress/keycodes'; + +/** + * Internal dependencies + */ +import NumberControl from '../'; + +let container = null; + +function getInput() { + return container.querySelector( 'input' ); +} + +beforeEach( () => { + container = document.createElement( 'div' ); + document.body.appendChild( container ); +} ); + +afterEach( () => { + unmountComponentAtNode( container ); + container.remove(); + container = null; +} ); + +function StatefulNumberControl( props ) { + const [ value, setValue ] = useState( props.value ); + const handleOnChange = ( v ) => setValue( v ); + + return ( + <NumberControl + { ...props } + value={ value } + onChange={ handleOnChange } + /> + ); +} + +describe( 'NumberControl', () => { + describe( 'Basic rendering', () => { + it( 'should render', () => { + act( () => { + render( <NumberControl />, container ); + } ); + + const input = getInput(); + + expect( input ).not.toBeNull(); + } ); + + it( 'should render custom className', () => { + act( () => { + render( <NumberControl className="hello" />, container ); + } ); + + const input = getInput(); + + expect( input.classList.contains( 'hello' ) ).toBe( true ); + } ); + } ); + + describe( 'onChange handling', () => { + it( 'should provide onChange callback with string value', () => { + const spy = jest.fn(); + act( () => { + render( + <NumberControl value={ 5 } onChange={ spy } />, + container + ); + } ); + + const input = getInput(); + + input.value = 10; + Simulate.change( input ); + + expect( spy.mock.calls[ 0 ][ 0 ] ).toBe( '10' ); + } ); + } ); + + describe( 'Key UP interactions', () => { + it( 'should fire onKeyDown callback', () => { + const spy = jest.fn(); + act( () => { + render( + <StatefulNumberControl value={ 5 } onKeyDown={ spy } />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP } ); + + expect( spy ).toHaveBeenCalled(); + } ); + + it( 'should increment by step on key UP press', () => { + act( () => { + render( <StatefulNumberControl value={ 5 } />, container ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP } ); + + expect( input.value ).toBe( '6' ); + } ); + + it( 'should increment from a negative value', () => { + act( () => { + render( <StatefulNumberControl value={ -5 } />, container ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP } ); + + expect( input.value ).toBe( '-4' ); + } ); + + it( 'should increment by shiftStep on key UP + shift press', () => { + act( () => { + render( <StatefulNumberControl value={ 5 } />, container ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP, shiftKey: true } ); + + expect( input.value ).toBe( '15' ); + } ); + + it( 'should increment by custom shiftStep on key UP + shift press', () => { + act( () => { + render( + <StatefulNumberControl value={ 5 } shiftStep={ 100 } />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP, shiftKey: true } ); + + expect( input.value ).toBe( '105' ); + } ); + + it( 'should increment but be limited by max on shiftStep', () => { + act( () => { + render( + <StatefulNumberControl + value={ 5 } + shiftStep={ 100 } + max={ 99 } + />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP, shiftKey: true } ); + + expect( input.value ).toBe( '99' ); + } ); + + it( 'should not increment by shiftStep if disabled', () => { + act( () => { + render( + <StatefulNumberControl + value={ 5 } + shiftStep={ 100 } + isShiftStepEnabled={ false } + />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: UP, shiftKey: true } ); + + expect( input.value ).toBe( '6' ); + } ); + } ); + + describe( 'Key DOWN interactions', () => { + it( 'should fire onKeyDown callback', () => { + const spy = jest.fn(); + act( () => { + render( + <StatefulNumberControl value={ 5 } onKeyDown={ spy } />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN } ); + + expect( spy ).toHaveBeenCalled(); + } ); + + it( 'should decrement by step on key DOWN press', () => { + act( () => { + render( <StatefulNumberControl value={ 5 } />, container ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN } ); + + expect( input.value ).toBe( '4' ); + } ); + + it( 'should decrement from a negative value', () => { + act( () => { + render( <StatefulNumberControl value={ -5 } />, container ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN } ); + + expect( input.value ).toBe( '-6' ); + } ); + + it( 'should decrement by shiftStep on key DOWN + shift press', () => { + act( () => { + render( <StatefulNumberControl value={ 5 } />, container ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN, shiftKey: true } ); + + expect( input.value ).toBe( '-5' ); + } ); + + it( 'should decrement by custom shiftStep on key DOWN + shift press', () => { + act( () => { + render( + <StatefulNumberControl value={ 5 } shiftStep={ 100 } />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN, shiftKey: true } ); + + expect( input.value ).toBe( '-95' ); + } ); + + it( 'should decrement but be limited by min on shiftStep', () => { + act( () => { + render( + <StatefulNumberControl + value={ 5 } + shiftStep={ 100 } + min={ 4 } + />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN, shiftKey: true } ); + + expect( input.value ).toBe( '4' ); + } ); + + it( 'should not decrement by shiftStep if disabled', () => { + act( () => { + render( + <StatefulNumberControl + value={ 5 } + shiftStep={ 100 } + isShiftStepEnabled={ false } + />, + container + ); + } ); + + const input = getInput(); + + Simulate.keyDown( input, { keyCode: DOWN, shiftKey: true } ); + + expect( input.value ).toBe( '4' ); + } ); + } ); +} ); diff --git a/packages/components/src/panel/body.native.js b/packages/components/src/panel/body.native.js index 87c5eeb60bac7f..36126ea76a9f5b 100644 --- a/packages/components/src/panel/body.native.js +++ b/packages/components/src/panel/body.native.js @@ -19,10 +19,10 @@ export class PanelBody extends Component { } render() { - const { children, title } = this.props; + const { children, title, style = {} } = this.props; return ( - <View style={ styles.panelContainer }> + <View style={ [ styles.panelContainer, style ] }> { title && ( <Text style={ styles.sectionHeaderText }>{ title }</Text> ) } diff --git a/packages/components/src/panel/style.scss b/packages/components/src/panel/style.scss index 944186713453d9..fa53a3ceb130f4 100644 --- a/packages/components/src/panel/style.scss +++ b/packages/components/src/panel/style.scss @@ -70,8 +70,8 @@ // Hover States .components-panel__body > .components-panel__body-title:hover { // Override the default button hover style - background: $light-gray-200 !important; - border: none !important; + background: $light-gray-200; + border: none; } .components-panel__body-toggle.components-button { @@ -82,20 +82,15 @@ font-weight: 600; text-align: left; color: $dark-gray-900; - @include menu-style__neutral; + border: none; + box-shadow: none; transition: 0.1s background ease-in-out; @include reduce-motion("transition"); height: auto; - &:focus:not(:disabled):not([aria-disabled="true"]) { - @include menu-style__focus; - } - - &:hover { - // Override the default button hover style - background: transparent !important; - border: none !important; - box-shadow: none !important; + &:focus { + box-shadow: inset 0 0 0 $border-width-focus $theme-color; + border-radius: 0; } .components-panel__arrow { diff --git a/packages/components/src/placeholder/style.scss b/packages/components/src/placeholder/style.scss index 04efa290269387..2feaa22804b09b 100644 --- a/packages/components/src/placeholder/style.scss +++ b/packages/components/src/placeholder/style.scss @@ -22,7 +22,7 @@ // Block UI appearance. border-radius: $radius-block-ui; background-color: $white; - box-shadow: 0 0 0 $border-width $dark-gray-primary; + box-shadow: inset 0 0 0 $border-width $dark-gray-primary; outline: 1px solid transparent; // Shown for Windows 10 High Contrast mode. .components-base-control__label { diff --git a/packages/components/src/popover/README.md b/packages/components/src/popover/README.md index be0eca3d773580..6dc54e4e1f53cb 100644 --- a/packages/components/src/popover/README.md +++ b/packages/components/src/popover/README.md @@ -127,11 +127,22 @@ Opt-in prop to show popovers fullscreen on mobile, pass `false` in this prop to ### anchorRect -A custom `DOMRect` object at which to position the popover. +A custom `DOMRect` object at which to position the popover. `anchorRect` is used when the position (custom `DOMRect` object) of the popover needs to be fixed at one location all the time. - Type: `DOMRect` - Required: No +### getAnchorRect + +A callback function which is used to override the anchor value computation algorithm. `anchorRect` will take precedence over this prop, if both are passed together. + +If you need the `DOMRect` object i.e., the position of popover to be calculated on every time, the popover re-renders, then use `getAnchorRect`. + +`getAnchorRect` callback function receives a reference to the popover anchor element as a function parameter and it should return a `DOMRect` objcet. + +- Type: `Function` +- Required: No + ## Methods ### refresh diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index 2e06f907de8a75..13aa4b34dfe669 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -233,10 +233,11 @@ const Popover = ( { children, className, noArrow = true, + isAlternate, // Disable reason: We generate the `...contentProps` rest as remainder // of props which aren't explicitly handled by this component. /* eslint-disable no-unused-vars */ - position = 'top', + position = 'bottom right', range, focusOnMount = 'firstElement', anchorRef, @@ -270,6 +271,7 @@ const Popover = ( { useEffect( () => { if ( isExpanded ) { setClass( containerRef.current, 'is-without-arrow', noArrow ); + setClass( containerRef.current, 'is-alternate', isAlternate ); setAttribute( containerRef.current, 'data-x-axis' ); setAttribute( containerRef.current, 'data-y-axis' ); setStyle( containerRef.current, 'top' ); @@ -392,6 +394,7 @@ const Popover = ( { 'is-without-arrow', noArrow || ( xAxis === 'center' && yAxis === 'middle' ) ); + setClass( containerRef.current, 'is-alternate', isAlternate ); setAttribute( containerRef.current, 'data-x-axis', xAxis ); setAttribute( containerRef.current, 'data-y-axis', yAxis ); setStyle( @@ -575,6 +578,7 @@ const Popover = ( { { 'is-expanded': isExpanded, 'is-without-arrow': noArrow, + 'is-alternate': isAlternate, } ) } { ...contentProps } diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index 7ece47bcdb9d79..74a57d17197d29 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -140,6 +140,23 @@ $arrow-size: 8px; align-items: center; display: flex; } + + // Add spacing. + &.is-from-top { + margin-top: $grid-unit-15; + } + + &.is-from-bottom { + margin-top: -$grid-unit-15; + } + + &.is-from-left:not(.is-from-top):not(.is-from-bottom) { + margin-left: $grid-unit-15; + } + + &.is-from-right:not(.is-from-top):not(.is-from-bottom) { + margin-right: $grid-unit-15; + } } .components-popover__content { @@ -149,6 +166,12 @@ $arrow-size: 8px; box-shadow: $shadow-popover; border-radius: $radius-block-ui; + // Alternate treatment for popovers that put them at elevation zero with high contrast. + .is-alternate & { + border: $border-width solid $dark-gray-primary; + box-shadow: none; + } + .components-popover & { position: absolute; height: auto; diff --git a/packages/components/src/popover/test/index.js b/packages/components/src/popover/test/index.js index 8db3d9292cee3d..d46c54cd03a94f 100644 --- a/packages/components/src/popover/test/index.js +++ b/packages/components/src/popover/test/index.js @@ -1,26 +1,13 @@ /** * External dependencies */ -import TestUtils from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { Component } from '@wordpress/element'; +import { act, render } from '@testing-library/react'; /** * Internal dependencies */ import Popover from '../'; -jest.useFakeTimers(); - -class PopoverWrapper extends Component { - render() { - return <Popover { ...this.props } />; - } -} - describe( 'Popover', () => { afterEach( () => { if ( document.activeElement ) { @@ -34,61 +21,50 @@ describe( 'Popover', () => { document.dispatchEvent( new window.KeyboardEvent( 'keydown' ) ); document.dispatchEvent( new window.KeyboardEvent( 'keyup' ) ); + expect( document.activeElement ).toBe( document.body ); + // An ideal test here would mount with an input child and focus the // child, but in context of JSDOM the inputs are not visible and // are therefore skipped as tabbable, defaulting to popover. - let wrapper; - TestUtils.act( () => { - wrapper = TestUtils.renderIntoDocument( <PopoverWrapper /> ); + let result; + act( () => { + result = render( <Popover /> ); jest.advanceTimersByTime( 1 ); - - const content = TestUtils.findRenderedDOMComponentWithClass( - wrapper, - 'components-popover__content' - ); - expect( document.activeElement ).toBe( content ); } ); + + expect( document.activeElement ).toBe( + result.container.querySelector( '.components-popover__content' ) + ); } ); it( 'should allow focus-on-open behavior to be disabled', () => { - const activeElement = document.activeElement; - TestUtils.act( () => { - TestUtils.renderIntoDocument( <Popover focusOnMount={ false } /> ); + expect( document.activeElement ).toBe( document.body ); - jest.advanceTimersByTime( 1 ); + act( () => { + render( <Popover focusOnMount={ false } /> ); - expect( document.activeElement ).toBe( activeElement ); + jest.advanceTimersByTime( 1 ); } ); + + expect( document.activeElement ).toBe( document.body ); } ); it( 'should render content', () => { - let wrapper; - TestUtils.act( () => { - wrapper = TestUtils.renderIntoDocument( - <PopoverWrapper>Hello</PopoverWrapper> - ); + let result; + act( () => { + result = render( <Popover>Hello</Popover> ); } ); - const content = TestUtils.findRenderedDOMComponentWithTag( - wrapper, - 'span' - ); - expect( content ).toMatchSnapshot(); + expect( result.container.querySelector( 'span' ) ).toMatchSnapshot(); } ); it( 'should pass additional props to portaled element', () => { - let wrapper; - TestUtils.act( () => { - wrapper = TestUtils.renderIntoDocument( - <PopoverWrapper role="tooltip">Hello</PopoverWrapper> - ); + let result; + act( () => { + result = render( <Popover role="tooltip">Hello</Popover> ); } ); - const content = TestUtils.findRenderedDOMComponentWithTag( - wrapper, - 'span' - ); - expect( content ).toMatchSnapshot(); + expect( result.container.querySelector( 'span' ) ).toMatchSnapshot(); } ); } ); diff --git a/packages/components/src/radio-context/index.js b/packages/components/src/radio-context/index.js new file mode 100644 index 00000000000000..58a7783dcb84e0 --- /dev/null +++ b/packages/components/src/radio-context/index.js @@ -0,0 +1,11 @@ +/** + * WordPress dependencies + */ +import { createContext } from '@wordpress/element'; + +const RadioContext = createContext( { + state: null, + setState: () => {}, +} ); + +export default RadioContext; diff --git a/packages/components/src/radio-control/README.md b/packages/components/src/radio-control/README.md index 2a55a81718fb15..f08f7da87b4953 100644 --- a/packages/components/src/radio-control/README.md +++ b/packages/components/src/radio-control/README.md @@ -121,3 +121,4 @@ A function that receives the value of the new option that is being selected as i * To select one or more items from a set, use the `CheckboxControl` component. * To toggle a single setting on or off, use the `ToggleControl` component. +* To format as a button group, use the `RadioGroup` component. diff --git a/packages/components/src/radio-group/README.md b/packages/components/src/radio-group/README.md new file mode 100644 index 00000000000000..7c6eab29b0bf1e --- /dev/null +++ b/packages/components/src/radio-group/README.md @@ -0,0 +1,87 @@ +# RadioGroup + +Use a RadioGroup component when you want users to select one option from a small set of options. + +![RadioGroup component](https://wordpress.org/gutenberg/files/2018/12/s_96EC471FE9C9D91A996770229947AAB54A03351BDE98F444FD3C1BF0CED365EA_1541792995815_ButtonGroup.png) + +## Table of contents + +1. [Design guidelines](#design-guidelines) +2. [Development guidelines](#development-guidelines) +3. [Related components](#related-components) + +## Design guidelines + +### Usage + +#### Selected action + +Only one option in a radio group can be selected and active at a time. Selecting one option deselects any other. + +### Best practices + +Radio groups should: + +- **Be clearly and accurately labeled.** +- **Clearly communicate that clicking or tapping will trigger an action.** +- **Use established colors appropriately.** For example, only use red buttons for actions that are difficult or impossible to undo. +- **Have consistent locations in the interface.** +- **Have a default option already selected.** + +### States + +#### Active and available radio groups + +A radio group’s state makes it clear which option is active. Hover and focus states express the available selection options for buttons in a button group. + +#### Disabled radio groups + +Radio groups that cannot be selected can either be given a disabled state, or be hidden. + +## Development guidelines + +### Usage + +#### Controlled + +```jsx +import { Radio, RadioGroup } from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +const MyControlledRadioRadioGroup = () => { + const [ checked, setChecked ] = useState( '25' ); + return ( + <RadioGroup accessibilityLabel="Width" onChange={ setChecked } checked={ checked }> + <Radio value="25">25%</Radio> + <Radio value="50">50%</Radio> + <Radio value="75">75%</Radio> + <Radio value="100">100%</Radio> + </RadioGroup> + ); +}; +``` + +#### Uncontrolled + +When using the RadioGroup component as an uncontrolled component, the default value can be set with the `defaultChecked` prop. + +```jsx +import { Radio, RadioGroup } from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +const MyUncontrolledRadioRadioGroup = () => { + return ( + <RadioGroup accessibilityLabel="Width" defaultChecked="25"> + <Radio value="25">25%</Radio> + <Radio value="50">50%</Radio> + <Radio value="75">75%</Radio> + <Radio value="100">100%</Radio> + </RadioGroup> + ); +}; +``` + +## Related components + +- For simple buttons that are related, use a `ButtonGroup` component. +- For traditional radio options, use a `RadioControl` component. diff --git a/packages/components/src/radio-group/index.js b/packages/components/src/radio-group/index.js new file mode 100644 index 00000000000000..11f24605297923 --- /dev/null +++ b/packages/components/src/radio-group/index.js @@ -0,0 +1,53 @@ +/** + * External dependencies + */ +import { useRadioState, RadioGroup as ReakitRadioGroup } from 'reakit/Radio'; + +/** + * WordPress dependencies + */ +import { forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import ButtonGroup from '../button-group'; +import RadioContext from '../radio-context'; + +function RadioGroup( + { + accessibilityLabel, + checked, + defaultChecked, + disabled, + onChange, + ...props + }, + ref +) { + const radioState = useRadioState( { + state: defaultChecked, + baseId: props.id, + } ); + const radioContext = { + ...radioState, + disabled, + // controlled or uncontrolled + state: checked || radioState.state, + setState: onChange || radioState.setState, + }; + + return ( + <RadioContext.Provider value={ radioContext }> + <ReakitRadioGroup + ref={ ref } + as={ ButtonGroup } + aria-label={ accessibilityLabel } + { ...radioState } + { ...props } + /> + </RadioContext.Provider> + ); +} + +export default forwardRef( RadioGroup ); diff --git a/packages/components/src/radio-group/stories/index.js b/packages/components/src/radio-group/stories/index.js new file mode 100644 index 00000000000000..5844cd82016b57 --- /dev/null +++ b/packages/components/src/radio-group/stories/index.js @@ -0,0 +1,71 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Radio from '../../radio'; +import RadioGroup from '../'; + +export default { title: 'Components/RadioGroup', component: RadioGroup }; + +export const _default = () => { + /* eslint-disable no-restricted-syntax */ + return ( + <RadioGroup + // id is required for server side rendering + id="default-radiogroup" + accessibilityLabel="options" + defaultChecked="option2" + > + <Radio value="option1">Option 1</Radio> + <Radio value="option2">Option 2</Radio> + <Radio value="option3">Option 3</Radio> + </RadioGroup> + ); + /* eslint-enable no-restricted-syntax */ +}; + +export const disabled = () => { + /* eslint-disable no-restricted-syntax */ + return ( + <RadioGroup + // id is required for server side rendering + id="disabled-radiogroup" + disabled + accessibilityLabel="options" + defaultChecked="option2" + > + <Radio value="option1">Option 1</Radio> + <Radio value="option2">Option 2</Radio> + <Radio value="option3">Option 3</Radio> + </RadioGroup> + ); + /* eslint-enable no-restricted-syntax */ +}; + +const ControlledRadioGroupWithState = () => { + const [ checked, setChecked ] = useState( 'option2' ); + + /* eslint-disable no-restricted-syntax */ + return ( + <RadioGroup + // id is required for server side rendering + id="controlled-radiogroup" + accessibilityLabel="options" + checked={ checked } + onChange={ setChecked } + > + <Radio value="option1">Option 1</Radio> + <Radio value="option2">Option 2</Radio> + <Radio value="option3">Option 3</Radio> + </RadioGroup> + ); + /* eslint-enable no-restricted-syntax */ +}; + +export const controlled = () => { + return <ControlledRadioGroupWithState />; +}; diff --git a/packages/components/src/radio/index.js b/packages/components/src/radio/index.js new file mode 100644 index 00000000000000..6d7305002e3fce --- /dev/null +++ b/packages/components/src/radio/index.js @@ -0,0 +1,36 @@ +/** + * External dependencies + */ +import { Radio as ReakitRadio } from 'reakit/Radio'; + +/** + * WordPress dependencies + */ +import { useContext, forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Button from '../button'; +import RadioContext from '../radio-context'; + +function Radio( { children, value, ...props }, ref ) { + const radioContext = useContext( RadioContext ); + const checked = radioContext.state === value; + + return ( + <ReakitRadio + ref={ ref } + as={ Button } + isPrimary={ checked } + isSecondary={ ! checked } + value={ value } + { ...radioContext } + { ...props } + > + { children || value } + </ReakitRadio> + ); +} + +export default forwardRef( Radio ); diff --git a/packages/components/src/radio/stories/index.js b/packages/components/src/radio/stories/index.js new file mode 100644 index 00000000000000..b64c35ed7ba17f --- /dev/null +++ b/packages/components/src/radio/stories/index.js @@ -0,0 +1,20 @@ +/** + * Internal dependencies + */ +import RadioGroup from '../../radio-group'; +import Radio from '../'; + +export default { title: 'Components/Radio', component: Radio }; + +export const _default = () => { + // Radio components must be a descendent of a RadioGroup component. + /* eslint-disable no-restricted-syntax */ + return ( + // id is required for server side rendering + <RadioGroup id="default-radiogroup" accessibilityLabel="options"> + <Radio value="option1">Option 1</Radio> + <Radio value="option2">Option 2</Radio> + </RadioGroup> + ); + /* eslint-enable no-restricted-syntax */ +}; diff --git a/packages/components/src/range-control/index.js b/packages/components/src/range-control/index.js index cee2659ed04e85..d718dec1a229a0 100644 --- a/packages/components/src/range-control/index.js +++ b/packages/components/src/range-control/index.js @@ -64,7 +64,7 @@ const BaseRangeControl = forwardRef( renderTooltipContent = ( v ) => v, showTooltip: showTooltipProp, step = 1, - value: valueProp = 0, + value: valueProp, withInputField = true, ...props }, @@ -72,7 +72,9 @@ const BaseRangeControl = forwardRef( ) => { const isRTL = useRtl(); - const sliderValue = valueProp || initialPosition; + const sliderValue = + valueProp !== undefined ? valueProp : initialPosition; + const [ value, setValue ] = useControlledRangeValue( { min, max, @@ -95,8 +97,9 @@ const BaseRangeControl = forwardRef( const isThumbFocused = ! disabled && isFocused; const isValueReset = value === null; - const inputSliderValue = isValueReset ? '' : value; - const currentInputValue = isValueReset ? '' : value || currentInput; + const currentValue = value !== undefined ? value : currentInput; + + const inputSliderValue = isValueReset ? '' : currentValue; const rangeFillValue = isValueReset ? floatClamp( max / 2, min, max ) @@ -119,12 +122,20 @@ const BaseRangeControl = forwardRef( const enableTooltip = showTooltipProp !== false && isFinite( value ); const handleOnChange = ( event ) => { - if ( ! event.target.checkValidity() ) { + if ( + event.target.checkValidity && + ! event.target.checkValidity() + ) { return; } const nextValue = parseFloat( event.target.value ); + if ( isNaN( nextValue ) ) { + handleOnReset(); + return; + } + setValue( nextValue ); onChange( nextValue ); }; @@ -249,7 +260,7 @@ const BaseRangeControl = forwardRef( onChange={ handleOnChange } step={ step } type="number" - value={ currentInputValue } + value={ inputSliderValue } /> ) } { allowReset && ( diff --git a/packages/components/src/range-control/rail.js b/packages/components/src/range-control/rail.js index d0bedcf7ac82b6..111cf8d96972d7 100644 --- a/packages/components/src/range-control/rail.js +++ b/packages/components/src/range-control/rail.js @@ -1,7 +1,3 @@ -/** - * External dependencies - */ -import { isUndefined } from 'lodash'; /** * Internal dependencies */ @@ -78,7 +74,7 @@ function useMarks( { marks, min = 0, max = 100, step = 1, value = 0 } ) { } ) ); const enhancedMarks = marksArray.map( ( mark, index ) => { - const markValue = ! isUndefined( mark.value ) ? mark.value : value; + const markValue = mark.value !== undefined ? mark.value : value; const key = `mark-${ index }`; const isFilled = markValue * step <= value; diff --git a/packages/components/src/range-control/test/index.js b/packages/components/src/range-control/test/index.js index 4c67a4f9c1a8f6..31c72383a0271e 100644 --- a/packages/components/src/range-control/test/index.js +++ b/packages/components/src/range-control/test/index.js @@ -1,7 +1,8 @@ /** * External dependencies */ -import TestUtils, { act } from 'react-dom/test-utils'; +import { render, unmountComponentAtNode } from 'react-dom'; +import TestUtils, { act, Simulate } from 'react-dom/test-utils'; /** * Internal dependencies @@ -14,6 +15,19 @@ import RangeControl from '../'; import { Component } from '@wordpress/element'; import { Dashicon } from '@wordpress/components'; +let container = null; + +beforeEach( () => { + container = document.createElement( 'div' ); + document.body.appendChild( container ); +} ); + +afterEach( () => { + unmountComponentAtNode( container ); + container.remove(); + container = null; +} ); + describe( 'RangeControl', () => { class TestWrapper extends Component { render() { @@ -326,6 +340,79 @@ describe( 'RangeControl', () => { } ); } ); + describe( 'input field', () => { + it( 'should render an input field by default', () => { + act( () => { + render( <RangeControl />, container ); + } ); + const field = container.querySelector( 'input[type="number"]' ); + + expect( field ).toBeTruthy(); + } ); + + it( 'should not render an input field, if disabled', () => { + act( () => { + render( <RangeControl withInputField={ false } />, container ); + } ); + const field = container.querySelector( 'input[type="number"]' ); + + expect( field ).toBeFalsy(); + } ); + + it( 'should render a zero value into input range and field', () => { + act( () => { + render( <RangeControl value={ 0 } />, container ); + } ); + const range = container.querySelector( 'input[type="range"]' ); + const field = container.querySelector( 'input[type="number"]' ); + + expect( range.value ).toBe( '0' ); + expect( field.value ).toBe( '0' ); + } ); + + it( 'should update both field and range on change', () => { + act( () => { + render( <RangeControl value={ 0 } />, container ); + } ); + const range = container.querySelector( 'input[type="range"]' ); + const field = container.querySelector( 'input[type="number"]' ); + + act( () => { + Simulate.change( range, { target: { value: 13 } } ); + } ); + + expect( range.value ).toBe( '13' ); + expect( field.value ).toBe( '13' ); + + act( () => { + Simulate.change( field, { target: { value: 7 } } ); + } ); + + expect( range.value ).toBe( '7' ); + expect( field.value ).toBe( '7' ); + } ); + + it( 'should reset input values if next value is removed', () => { + act( () => { + render( <RangeControl value={ 13 } />, container ); + } ); + const range = container.querySelector( 'input[type="range"]' ); + const field = container.querySelector( 'input[type="number"]' ); + + expect( range.value ).toBe( '13' ); + expect( field.value ).toBe( '13' ); + + act( () => { + Simulate.change( field, { target: { value: undefined } } ); + } ); + + // Reset to 50. Median value of min: 0, max: 100 + expect( range.value ).toBe( '50' ); + // Input field should be blank + expect( field.value ).toBe( '' ); + } ); + } ); + describe( 'reset', () => { class StatefulTestWrapper extends Component { constructor( props ) { diff --git a/packages/components/src/range-control/utils.js b/packages/components/src/range-control/utils.js index d1fd148ec2a3fb..9d2aecfa5e7a70 100644 --- a/packages/components/src/range-control/utils.js +++ b/packages/components/src/range-control/utils.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { clamp, isFinite, noop } from 'lodash'; +import { clamp, noop } from 'lodash'; /** * WordPress dependencies diff --git a/packages/components/src/sandbox/index.js b/packages/components/src/sandbox/index.js index c52bce90880fa5..2fe01d33f86dbc 100644 --- a/packages/components/src/sandbox/index.js +++ b/packages/components/src/sandbox/index.js @@ -77,6 +77,7 @@ class Sandbox extends Component { } const body = this.iframe.current.contentDocument.body; + if ( ! forceRerender && null !== body.getAttribute( 'data-resizable-iframe-connected' ) @@ -232,7 +233,7 @@ class Sandbox extends Component { title={ title } className="components-sandbox" sandbox="allow-scripts allow-same-origin allow-presentation" - onLoad={ this.trySandbox } + onLoad={ () => this.trySandbox( false ) } onFocus={ onFocus } width={ Math.ceil( this.state.width ) } height={ Math.ceil( this.state.height ) } diff --git a/packages/components/src/sandbox/test/index.js b/packages/components/src/sandbox/test/index.js index 7888082f49459a..4a8343fd5514f4 100644 --- a/packages/components/src/sandbox/test/index.js +++ b/packages/components/src/sandbox/test/index.js @@ -1,8 +1,7 @@ /** * External dependencies */ -import ReactDOM from 'react-dom'; -import { act } from 'react-dom/test-utils'; +import { act, fireEvent, render } from '@testing-library/react'; /** * WordPress dependencies @@ -14,62 +13,67 @@ import { useState } from '@wordpress/element'; */ import Sandbox from '../'; -let container; +describe( 'Sandbox', () => { + const TestWrapper = () => { + const [ html, setHtml ] = useState( + '<iframe class="mock-iframe" src="https://super.embed"></iframe>' + ); -const TestWrapper = () => { - const [ html, setHtml ] = useState( - '<iframe class="mock-iframe" src="https://super.embed"></iframe>' - ); + const updateHtml = () => { + setHtml( + '<iframe class="mock-iframe" src="https://another.super.embed"></iframe>' + ); + }; - const updateHtml = () => { - setHtml( - '<iframe class="mock-iframe" src="https://another.super.embed"></iframe>' + return ( + <div> + <button onClick={ updateHtml } className="mock-button"> + Mock Button + </button> + <Sandbox html={ html } /> + </div> ); }; - return ( - <div> - <button onClick={ updateHtml } className="mock-button"> - Mock Button - </button> - <Sandbox html={ html } /> - </div> - ); -}; - -beforeEach( () => { - container = document.createElement( 'div' ); - document.body.appendChild( container ); -} ); - -afterEach( () => { - document.body.removeChild( container ); - container = null; -} ); + beforeAll( () => { + // MuatationObserver implmentation from JSDom does not work as intended + // with iframes so we need to ignore it for the time being. + jest.spyOn( + global.MutationObserver.prototype, + 'observe' + ).mockImplementation( () => {} ); + } ); -it( 'should rerender with new emdeded content if html prop changes', () => { - act( () => { - ReactDOM.render( <TestWrapper />, container ); + afterAll( () => { + global.MutationObserver.prototype.mockReset(); } ); - const button = container.querySelector( '.mock-button' ); - const iframe = container.querySelector( '.components-sandbox' ); + it( 'should rerender with new emdeded content if html prop changes', () => { + let result; + act( () => { + result = render( <TestWrapper /> ); + } ); - let sandboxedIframe = iframe.contentWindow.document.body.querySelector( - '.mock-iframe' - ); + const iframe = result.container.querySelector( '.components-sandbox' ); - expect( sandboxedIframe.src ).toEqual( 'https://super.embed/' ); + let sandboxedIframe = iframe.contentWindow.document.body.querySelector( + '.mock-iframe' + ); - act( () => { - button.dispatchEvent( - new window.MouseEvent( 'click', { bubbles: true } ) + expect( sandboxedIframe.getAttribute( 'src' ) ).toBe( + 'https://super.embed' ); - } ); - sandboxedIframe = iframe.contentWindow.document.body.querySelector( - '.mock-iframe' - ); + act( () => { + fireEvent.click( result.getByRole( 'button' ) ); + } ); + + sandboxedIframe = iframe.contentWindow.document.body.querySelector( + '.mock-iframe' + ); - expect( sandboxedIframe.src ).toEqual( 'https://another.super.embed/' ); + expect( sandboxedIframe.getAttribute( 'src' ) ).toBe( + 'https://another.super.embed' + ); + } ); } ); diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js index d487d98fbfa9a1..6d4b046a6271cf 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js +++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.js @@ -25,11 +25,10 @@ function useSlotRegistry() { const unregisterSlot = useCallback( ( name, ref ) => { setSlots( ( prevSlots ) => { - // eslint-disable-next-line no-unused-vars const { [ name ]: slot, ...nextSlots } = prevSlots; // Make sure we're not unregistering a slot registered by another element // See https://github.com/WordPress/gutenberg/pull/19242#issuecomment-590295412 - if ( slot.ref === ref ) { + if ( slot?.ref === ref ) { return nextSlots; } return prevSlots; diff --git a/packages/components/src/slot-fill/test/__snapshots__/slot.js.snap b/packages/components/src/slot-fill/test/__snapshots__/slot.js.snap index 79b43ad4c65c07..5cffdf5ec3f6ca 100644 --- a/packages/components/src/slot-fill/test/__snapshots__/slot.js.snap +++ b/packages/components/src/slot-fill/test/__snapshots__/slot.js.snap @@ -1,128 +1,166 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Slot bubblesVirtually false should subsume another slot by the same name 1`] = ` -Array [ +<div> <div data-position="first" - />, + /> <div data-position="second" > Content - </div>, -] + </div> +</div> `; exports[`Slot bubblesVirtually false should subsume another slot by the same name 2`] = ` -Array [ +<div> <div data-position="first" - />, + /> <div data-position="second" > Content - </div>, -] + </div> +</div> +`; + +exports[`Slot bubblesVirtually false should unmount two slots with the same name 1`] = ` +<div> + <div + data-position="first" + /> + <div + data-position="second" + /> +</div> `; exports[`Slot bubblesVirtually true should subsume another slot by the same name 1`] = ` -Array [ +<div> <div data-position="first" > <div /> - </div>, + </div> <div data-position="second" > - <div /> - </div>, -] + <div> + Content + </div> + </div> +</div> `; exports[`Slot bubblesVirtually true should subsume another slot by the same name 2`] = ` -Array [ +<div> <div data-position="first" - />, + /> <div data-position="second" > - <div /> - </div>, -] + <div> + Content + </div> + </div> +</div> +`; + +exports[`Slot bubblesVirtually true should unmount two slots with the same name 1`] = ` +<div> + <div + data-position="first" + /> + <div + data-position="second" + /> +</div> `; exports[`Slot should re-render Slot when not bubbling virtually 1`] = ` -Array [ +<div> <div> 1 - </div>, + </div> <button - onClick={[Function]} type="button" - />, -] + /> +</div> `; exports[`Slot should re-render Slot when not bubbling virtually 2`] = ` -Array [ +<div> <div> 2 - </div>, + </div> <button - onClick={[Function]} type="button" - />, -] + /> +</div> `; exports[`Slot should render a Fill containing an array 1`] = ` <div> - <span /> - <div /> - text + <div> + <span /> + <div /> + text + </div> </div> `; exports[`Slot should render a Fill containing an element 1`] = ` <div> - <span /> + <div> + <span /> + </div> </div> `; exports[`Slot should render a string Fill 1`] = ` <div> - content + <div> + content + </div> </div> `; exports[`Slot should render a string Fill with HTML wrapper when render props used 1`] = ` <div> - <blockquote> - content - </blockquote> + <div> + <blockquote> + content + </blockquote> + </div> </div> `; -exports[`Slot should render empty Fills 1`] = `<div />`; +exports[`Slot should render empty Fills 1`] = ` +<div> + <div /> +</div> +`; -exports[`Slot should render empty Fills without HTML wrapper when render props used 1`] = `<div />`; +exports[`Slot should render empty Fills without HTML wrapper when render props used 1`] = ` +<div> + <div /> +</div> +`; exports[`Slot should render in expected order 1`] = ` -Array [ +<div> <div> first second - </div>, + </div> <button - onClick={[Function]} type="button" - />, + /> <button - onClick={[Function]} type="button" - />, -] + /> +</div> `; diff --git a/packages/components/src/slot-fill/test/slot.js b/packages/components/src/slot-fill/test/slot.js index db935e6bc2ed29..398ea965924458 100644 --- a/packages/components/src/slot-fill/test/slot.js +++ b/packages/components/src/slot-fill/test/slot.js @@ -2,7 +2,7 @@ * External dependencies */ import { isEmpty } from 'lodash'; -import ReactTestRenderer from 'react-test-renderer'; +import { render, fireEvent } from '@testing-library/react'; /** * Internal dependencies @@ -38,33 +38,33 @@ class Filler extends Component { describe( 'Slot', () => { it( 'should render empty Fills', () => { - const tree = ReactTestRenderer.create( + const { container } = render( <Provider> <div> <Slot name="chicken" /> </div> <Fill name="chicken" /> </Provider> - ).toJSON(); + ); - expect( tree ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'should render a string Fill', () => { - const tree = ReactTestRenderer.create( + const { container } = render( <Provider> <div> <Slot name="chicken" /> </div> <Fill name="chicken">content</Fill> </Provider> - ).toJSON(); + ); - expect( tree ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'should render a Fill containing an element', () => { - const tree = ReactTestRenderer.create( + const { container } = render( <Provider> <div> <Slot name="chicken" /> @@ -73,13 +73,13 @@ describe( 'Slot', () => { <span /> </Fill> </Provider> - ).toJSON(); + ); - expect( tree ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'should render a Fill containing an array', () => { - const tree = ReactTestRenderer.create( + const { container } = render( <Provider> <div> <Slot name="chicken" /> @@ -88,15 +88,15 @@ describe( 'Slot', () => { { [ <span key="1" />, <div key="2" />, 'text' ] } </Fill> </Provider> - ).toJSON(); + ); - expect( tree ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'calls the functions passed as the Slot’s fillProps in the Fill', () => { const onClose = jest.fn(); - const testInstance = ReactTestRenderer.create( + const { getByText } = render( <Provider> <Slot name="chicken" fillProps={ { onClose } } /> <Fill name="chicken"> @@ -107,15 +107,15 @@ describe( 'Slot', () => { } } </Fill> </Provider> - ).root; + ); - testInstance.findByType( 'button' ).props.onClick(); + fireEvent.click( getByText( 'Click me' ) ); expect( onClose ).toHaveBeenCalledTimes( 1 ); } ); it( 'should render empty Fills without HTML wrapper when render props used', () => { - const tree = ReactTestRenderer.create( + const { container } = render( <Provider> <div> <Slot name="chicken"> @@ -128,13 +128,13 @@ describe( 'Slot', () => { </div> <Fill name="chicken" /> </Provider> - ).toJSON(); + ); - expect( tree ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'should render a string Fill with HTML wrapper when render props used', () => { - const tree = ReactTestRenderer.create( + const { container } = render( <Provider> <div> <Slot name="chicken"> @@ -145,13 +145,13 @@ describe( 'Slot', () => { </div> <Fill name="chicken">content</Fill> </Provider> - ).toJSON(); + ); - expect( tree ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'should re-render Slot when not bubbling virtually', () => { - const testRenderer = ReactTestRenderer.create( + const { container, getByRole } = render( <Provider> <div> <Slot name="egg" /> @@ -160,15 +160,15 @@ describe( 'Slot', () => { </Provider> ); - expect( testRenderer.toJSON() ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); - testRenderer.root.findByType( 'button' ).props.onClick(); + fireEvent.click( getByRole( 'button' ) ); - expect( testRenderer.toJSON() ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); it( 'should render in expected order', () => { - const testRenderer = ReactTestRenderer.create( + const { container, rerender } = render( <Provider> <div key="slot"> <Slot name="egg" /> @@ -176,7 +176,7 @@ describe( 'Slot', () => { </Provider> ); - testRenderer.update( + rerender( <Provider> <div key="slot"> <Slot name="egg" /> @@ -186,7 +186,7 @@ describe( 'Slot', () => { </Provider> ); - testRenderer.update( + rerender( <Provider> <div key="slot"> <Slot name="egg" /> @@ -195,7 +195,7 @@ describe( 'Slot', () => { </Provider> ); - testRenderer.update( + rerender( <Provider> <div key="slot"> <Slot name="egg" /> @@ -205,14 +205,14 @@ describe( 'Slot', () => { </Provider> ); - expect( testRenderer.toJSON() ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); } ); describe.each( [ false, true ] )( 'bubblesVirtually %p', ( bubblesVirtually ) => { it( 'should subsume another slot by the same name', () => { - const testRenderer = ReactTestRenderer.create( + const { container, rerender } = render( <Provider> <div data-position="first"> <Slot @@ -225,7 +225,7 @@ describe( 'Slot', () => { </Provider> ); - testRenderer.update( + rerender( <Provider> <div data-position="first"> <Slot @@ -243,9 +243,9 @@ describe( 'Slot', () => { </Provider> ); - expect( testRenderer.toJSON() ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); - testRenderer.update( + rerender( <Provider> <div data-position="first"></div> <div data-position="second"> @@ -258,7 +258,47 @@ describe( 'Slot', () => { </Provider> ); - expect( testRenderer.toJSON() ).toMatchSnapshot(); + expect( container ).toMatchSnapshot(); + } ); + + it( 'should unmount two slots with the same name', () => { + const { rerender, container } = render( + <Provider> + <div data-position="first"> + <Slot + name="egg" + bubblesVirtually={ bubblesVirtually } + /> + </div> + <div data-position="second"> + <Slot + name="egg" + bubblesVirtually={ bubblesVirtually } + /> + </div> + <Fill name="egg">Content</Fill> + </Provider> + ); + rerender( + <Provider> + <div data-position="first"> + <Slot + name="egg" + bubblesVirtually={ bubblesVirtually } + /> + </div> + <div data-position="second" /> + <Fill name="egg">Content</Fill> + </Provider> + ); + rerender( + <Provider> + <div data-position="first" /> + <div data-position="second" /> + <Fill name="egg">Content</Fill> + </Provider> + ); + expect( container ).toMatchSnapshot(); } ); } ); diff --git a/packages/components/src/tab-panel/style.scss b/packages/components/src/tab-panel/style.scss index f2048be4a19394..b4238983bb9b24 100644 --- a/packages/components/src/tab-panel/style.scss +++ b/packages/components/src/tab-panel/style.scss @@ -13,15 +13,8 @@ padding: 3px 15px; // Use padding to offset the is-active border, this benefits Windows High Contrast mode margin-left: 0; font-weight: 400; - @include square-style__neutral; transition: box-shadow 0.1s linear; - &:focus:enabled { - color: $dark-gray-900; - outline-offset: -1px; - outline: 1px dotted $dark-gray-500; - } - &:focus:enabled, &.is-active { box-shadow: inset 0 -3px theme(outlines); diff --git a/packages/components/src/text/README.md b/packages/components/src/text/README.md index 806c60d45a06bc..4a659b34fa4ccc 100644 --- a/packages/components/src/text/README.md +++ b/packages/components/src/text/README.md @@ -1,18 +1,54 @@ # Text -A text component for styling text. +A component for rendering text. ## Usage ```jsx -import {Text} from '@wordpress/components'; +import { Text } from '@wordpress/components'; const HeroPanel = () => ( <> - <Text variant="title.large" as="h1">Hello World!</Text> + <Text variant="title.large" as="h1"> + Hello World! + </Text> <Text variant="body">Greetings to you!</Text> </> ); ``` -> For most use-cases you can use this component instead of a `h1`, `h2`, `h3`, `h4`, `h5`, `h6` or `p`. +## Props + +The component accepts the following props: + +#### as + +Determines the HTML selector for the text. + +For most use-cases you can use this component instead of a `h1`, `h2`, `h3`, `h4`, `h5`, `h6` or `p`. + +- Type: `String` +- Required: No +- Default: '' + +#### variant + +Determines the style for the text. Available variants: + +- `title` +- `title.large` +- `title.medium` +- `title.small` +- `subtitle` +- `subtitle.large` +- `subtitle.small` +- `body` +- `body.large` +- `body.small` +- `button` +- `caption` +- `label` + +* Type: `String` +* Required: No +* Default: 'body' diff --git a/packages/components/src/text/index.js b/packages/components/src/text/index.js index c4ae06e2b4f97f..e502e39a59c49a 100644 --- a/packages/components/src/text/index.js +++ b/packages/components/src/text/index.js @@ -1 +1,19 @@ -export * from './text.styles'; +/** + * External dependencies + */ +import styled from '@emotion/styled'; + +/** + * Internal dependencies + */ +import { text } from './styles/text-mixins'; + +const Text = styled.p( + ` + box-sizing: border-box; + margin: 0; +`, + text +); + +export default Text; diff --git a/packages/components/src/text/text.styles.native.js b/packages/components/src/text/index.native.js similarity index 51% rename from packages/components/src/text/text.styles.native.js rename to packages/components/src/text/index.native.js index 2304de2efa62f3..8a52d4056d5578 100644 --- a/packages/components/src/text/text.styles.native.js +++ b/packages/components/src/text/index.native.js @@ -6,6 +6,8 @@ import styled from '@emotion/native'; /** * Internal dependencies */ -import { text } from './mixins'; +import { text } from './styles/text-mixins'; -export const __experimentalText = styled.Text( text ); +const Text = styled.Text( text ); + +export default Text; diff --git a/packages/components/src/text/stories/index.js b/packages/components/src/text/stories/index.js index f1dca3b2c819b6..aeb3cd330fdd3a 100644 --- a/packages/components/src/text/stories/index.js +++ b/packages/components/src/text/stories/index.js @@ -1,10 +1,10 @@ /** * Internal dependencies */ -import { __experimentalText as Text } from '../text.styles'; +import Text from '../index'; export default { - title: 'Components/Experimental/Text', + title: 'Components/Text', component: Text, }; @@ -28,31 +28,3 @@ export const _default = () => ( <Text variant="label">Label</Text> </> ); - -export const TitleLarge = () => ( - <Text variant="title.large" as="h1"> - Title Large - </Text> -); -export const TitleMedium = () => ( - <Text variant="title.medium" as="h2"> - Title Medium - </Text> -); -export const TitleSmall = () => ( - <Text variant="title.small" as="h3"> - Title Small - </Text> -); - -export const Subtitle = () => <Text variant="subtitle">Subtitle</Text>; -export const SubtitleSmall = () => ( - <Text variant="subtitle.small">Subtitle Small</Text> -); - -export const Body = () => <Text variant="body">Body</Text>; -export const BodySmall = () => <Text variant="body.small">Body Small</Text>; - -export const Button = () => <Text variant="button">Button</Text>; -export const Caption = () => <Text variant="caption">Caption</Text>; -export const Label = () => <Text variant="label">Label</Text>; diff --git a/packages/components/src/text/styles/emotion-css.js b/packages/components/src/text/styles/emotion-css.js new file mode 100644 index 00000000000000..c86ee0154e7630 --- /dev/null +++ b/packages/components/src/text/styles/emotion-css.js @@ -0,0 +1,6 @@ +/** + * External dependencies + */ +import { css } from '@emotion/core'; + +export default css; diff --git a/packages/components/src/text/styles/emotion-css.native.js b/packages/components/src/text/styles/emotion-css.native.js new file mode 100644 index 00000000000000..11ea92e4e705c3 --- /dev/null +++ b/packages/components/src/text/styles/emotion-css.native.js @@ -0,0 +1,6 @@ +/** + * External dependencies + */ +import { css } from '@emotion/native'; + +export default css; diff --git a/packages/components/src/text/font-family.js b/packages/components/src/text/styles/font-family.js similarity index 100% rename from packages/components/src/text/font-family.js rename to packages/components/src/text/styles/font-family.js diff --git a/packages/components/src/text/font-family.native.js b/packages/components/src/text/styles/font-family.native.js similarity index 100% rename from packages/components/src/text/font-family.native.js rename to packages/components/src/text/styles/font-family.native.js diff --git a/packages/components/src/text/mixins.js b/packages/components/src/text/styles/text-mixins.js similarity index 87% rename from packages/components/src/text/mixins.js rename to packages/components/src/text/styles/text-mixins.js index dfa3dfecc38979..d2463e80310a49 100644 --- a/packages/components/src/text/mixins.js +++ b/packages/components/src/text/styles/text-mixins.js @@ -1,11 +1,8 @@ -/** - * External dependencies - */ -import css from '@emotion/css'; /** * Internal dependencies */ import { fontFamily } from './font-family'; +import css from './emotion-css'; const fontWeightNormal = `font-weight: 400;`; const fontWeightSemibold = `font-weight: 600;`; @@ -78,13 +75,13 @@ const label = ` `; /** - * @typedef {'title.large'|'title.medium'|'title.small'|'subtitle'|'subtitle.small'|'body'|'body.small'|'button'|'caption'|'label'} TextVariant + * @typedef {'title.large'|'title.medium'|'title.small'|'subtitle'|'subtitle.small'|'body'|'body.large'|'body.small'|'button'|'caption'|'label'} TextVariant */ /** * @param {TextVariant} variantName */ -const variant = ( variantName ) => { +const variant = ( variantName = 'body' ) => { switch ( variantName ) { case 'title.large': return css` @@ -114,6 +111,10 @@ const variant = ( variantName ) => { `; case 'body': + return css` + ${body} + `; + case 'body.large': return css` ${body} ${bodyLarge} @@ -137,7 +138,7 @@ const variant = ( variantName ) => { /** * @typedef {Object} TextProps - * @property {TextVariant} variant + * @property {TextVariant} variant one of TextVariant to be used */ /** diff --git a/packages/components/src/text/test/index.js b/packages/components/src/text/test/index.js new file mode 100644 index 00000000000000..dfa504018ed5dd --- /dev/null +++ b/packages/components/src/text/test/index.js @@ -0,0 +1,94 @@ +/** + * External dependencies + */ +import { render, unmountComponentAtNode } from 'react-dom'; +import { act } from 'react-dom/test-utils'; + +/** + * Internal dependencies + */ +import Text from '../'; + +let container = null; + +beforeEach( () => { + container = document.createElement( 'div' ); + document.body.appendChild( container ); +} ); + +afterEach( () => { + unmountComponentAtNode( container ); + container.remove(); + container = null; +} ); + +function getTextStyle( node ) { + const text = node || container.children[ 0 ]; + return window.getComputedStyle( text ); +} + +describe( 'Text', () => { + describe( 'Basic rendering', () => { + it( 'should render', () => { + act( () => { + render( <Text>Hello</Text>, container ); + } ); + + const [ text ] = container.children; + + expect( text.innerHTML ).toBe( 'Hello' ); + } ); + + it( 'should render as a <p>, by default', () => { + act( () => { + render( <Text />, container ); + } ); + + const [ text ] = container.children; + + expect( text.tagName ).toBe( 'P' ); + } ); + + it( 'should render as another selector, if specified', () => { + act( () => { + render( + <> + <Text as="h1" /> + <Text as="h2" /> + <Text as="span" /> + <Text as="div" /> + </>, + container + ); + } ); + + const [ h1, h2, span, div ] = container.children; + + expect( h1.tagName ).toBe( 'H1' ); + expect( h2.tagName ).toBe( 'H2' ); + expect( span.tagName ).toBe( 'SPAN' ); + expect( div.tagName ).toBe( 'DIV' ); + } ); + } ); + + describe( 'Variants', () => { + it( 'should render with specified variantion styles', () => { + act( () => { + render( + <> + <Text>Base</Text> + <Text variant="title.large">Title Large</Text> + <Text variant="caption">Caption</Text> + </>, + container + ); + } ); + + const [ base, title, caption ] = container.children; + + expect( getTextStyle( base ).fontSize ).toBeFalsy(); + expect( getTextStyle( title ).fontSize ).toBe( '32px' ); + expect( getTextStyle( caption ).fontSize ).toBe( '12px' ); + } ); + } ); +} ); diff --git a/packages/components/src/text/text.styles.js b/packages/components/src/text/text.styles.js deleted file mode 100644 index 67545507f0d0b5..00000000000000 --- a/packages/components/src/text/text.styles.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * External dependencies - */ -import styled from '@emotion/styled'; - -/** - * Internal dependencies - */ -import { text } from './mixins'; - -export const __experimentalText = styled.p( `margin: 0;`, text ); diff --git a/packages/components/src/toolbar-button/index.js b/packages/components/src/toolbar-button/index.js index 4d56476caadc8b..347fd5fd0d7e60 100644 --- a/packages/components/src/toolbar-button/index.js +++ b/packages/components/src/toolbar-button/index.js @@ -48,8 +48,9 @@ function ToolbarButton( { isPressed={ props.isActive } disabled={ props.isDisabled } { ...extraProps } - /> - { children } + > + { children } + </Button> </ToolbarButtonContainer> ); } diff --git a/packages/components/src/toolbar-group/style.scss b/packages/components/src/toolbar-group/style.scss index da98306f2c402f..a804663d4ef793 100644 --- a/packages/components/src/toolbar-group/style.scss +++ b/packages/components/src/toolbar-group/style.scss @@ -1,9 +1,10 @@ .components-toolbar-group { - border: $border-width solid $light-gray-500; + min-height: $block-toolbar-height; + border-right: $border-width solid $dark-gray-primary; background-color: $white; - display: flex; + display: inline-flex; flex-shrink: 0; - margin-right: -$border-width; + flex-wrap: wrap; & & { border-width: 0; @@ -16,11 +17,14 @@ // Legacy toolbar group // External code references to it, so we can't change it? .components-toolbar { + min-height: $block-toolbar-height; margin: 0; - border: $border-width solid $light-gray-500; + border: $border-width solid $dark-gray-primary; + border-radius: $radius-block-ui; background-color: $white; - display: flex; + display: inline-flex; flex-shrink: 0; + flex-wrap: wrap; } div.components-toolbar { @@ -54,3 +58,60 @@ div.components-toolbar { } } } + +// Size multiple sequential buttons to be optically balanced. +// Icons are 36px, as set by a 24px icon and 12px padding. +.components-accessible-toolbar .components-toolbar-group > .components-button.components-button.has-icon, +.components-toolbar div > .components-button.components-button.has-icon { + min-width: $block-toolbar-height - $grid-unit-15; + padding-left: $grid-unit-15 / 2; // 6px. + padding-right: $grid-unit-15 / 2; + + svg { + min-width: $button-size-small; // This is the optimal icon size, and we size the whole button after this. + } + + &::before { + left: 2px; + right: 2px; + } +} + +// First button in a group. +.components-accessible-toolbar .components-toolbar-group > .components-button:first-child.has-icon, +.components-toolbar div:first-child .components-button.has-icon { + min-width: $block-toolbar-height - $grid-unit-15 / 2; + padding-left: $grid-unit-15 - $border-width; + padding-right: $grid-unit-15 / 2; + + &::before { + left: $grid-unit-10; + right: 2px; + } +} + +// Last button in a group. +.components-accessible-toolbar .components-toolbar-group > .components-button:last-child.has-icon, +.components-toolbar div:last-child .components-button.has-icon { + min-width: $block-toolbar-height - $grid-unit-15 / 2; + padding-left: $grid-unit-15 / 2; + padding-right: $grid-unit-15 - $border-width; + + &::before { + left: 2px; + right: $grid-unit-10; + } +} + +// Single buttons should remain 48px. +.components-accessible-toolbar .components-toolbar-group > .components-button:first-child:last-child.has-icon, +.components-toolbar div:first-child:last-child > .components-button.has-icon { + min-width: $block-toolbar-height; + padding-left: $grid-unit-15; + padding-right: $grid-unit-15; + + &::before { + left: $grid-unit-10; + right: $grid-unit-10; + } +} diff --git a/packages/components/src/toolbar-group/test/index.js b/packages/components/src/toolbar-group/test/index.js index c2aa53a165f17e..4bd6951caf477b 100644 --- a/packages/components/src/toolbar-group/test/index.js +++ b/packages/components/src/toolbar-group/test/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { mount } from 'enzyme'; +import { fireEvent, render } from '@testing-library/react'; /** * Internal dependencies @@ -11,13 +11,15 @@ import ToolbarGroup from '../'; describe( 'ToolbarGroup', () => { describe( 'basic rendering', () => { it( 'should render an empty node, when controls are not passed', () => { - const wrapper = mount( <ToolbarGroup /> ); - expect( wrapper.html() ).toBeNull(); + const { container } = render( <ToolbarGroup /> ); + + expect( container.innerHTML ).toBe( '' ); } ); it( 'should render an empty node, when controls are empty', () => { - const wrapper = mount( <ToolbarGroup controls={ [] } /> ); - expect( wrapper.html() ).toBeNull(); + const { container } = render( <ToolbarGroup controls={ [] } /> ); + + expect( container.innerHTML ).toBe( '' ); } ); it( 'should render a list of controls with buttons', () => { @@ -30,15 +32,16 @@ describe( 'ToolbarGroup', () => { isActive: false, }, ]; - const wrapper = mount( <ToolbarGroup controls={ controls } /> ); - const button = wrapper - .find( '[aria-label="WordPress"]' ) - .hostNodes(); - expect( button.props() ).toMatchObject( { - 'aria-label': 'WordPress', - 'aria-pressed': false, - type: 'button', - } ); + + const { getByLabelText } = render( + <ToolbarGroup controls={ controls } /> + ); + + const toolbarButton = getByLabelText( 'WordPress' ); + expect( toolbarButton.getAttribute( 'aria-pressed' ) ).toBe( + 'false' + ); + expect( toolbarButton.getAttribute( 'type' ) ).toBe( 'button' ); } ); it( 'should render a list of controls with buttons and active control', () => { @@ -51,15 +54,16 @@ describe( 'ToolbarGroup', () => { isActive: true, }, ]; - const wrapper = mount( <ToolbarGroup controls={ controls } /> ); - const button = wrapper - .find( '[aria-label="WordPress"]' ) - .hostNodes(); - expect( button.props() ).toMatchObject( { - 'aria-label': 'WordPress', - 'aria-pressed': true, - type: 'button', - } ); + + const { getByLabelText } = render( + <ToolbarGroup controls={ controls } /> + ); + + const toolbarButton = getByLabelText( 'WordPress' ); + expect( toolbarButton.getAttribute( 'aria-pressed' ) ).toBe( + 'true' + ); + expect( toolbarButton.getAttribute( 'type' ) ).toBe( 'button' ); } ); it( 'should render a nested list of controls with separator between', () => { @@ -80,14 +84,15 @@ describe( 'ToolbarGroup', () => { ], ]; - const wrapper = mount( <ToolbarGroup controls={ controls } /> ); - const buttons = wrapper.find( 'button' ).hostNodes(); - const hasLeftDivider = wrapper - .find( '.has-left-divider' ) - .hostNodes(); + const { container, getAllByRole } = render( + <ToolbarGroup controls={ controls } /> + ); + + const buttons = getAllByRole( 'button' ); expect( buttons ).toHaveLength( 2 ); - expect( hasLeftDivider ).toHaveLength( 1 ); - expect( hasLeftDivider.html() ).toContain( buttons.at( 1 ).html() ); + expect( + container.querySelector( '.has-left-divider button' ) + ).toBe( buttons[ 1 ] ); } ); it( 'should call the clickHandler on click.', () => { @@ -100,11 +105,11 @@ describe( 'ToolbarGroup', () => { isActive: true, }, ]; - const wrapper = mount( <ToolbarGroup controls={ controls } /> ); - const button = wrapper - .find( '[aria-label="WordPress"]' ) - .hostNodes(); - button.simulate( 'click' ); + const { getByLabelText } = render( + <ToolbarGroup controls={ controls } /> + ); + + fireEvent.click( getByLabelText( 'WordPress' ) ); expect( clickHandler ).toHaveBeenCalledTimes( 1 ); } ); } ); diff --git a/packages/components/src/toolbar-group/toolbar-group-collapsed.native.js b/packages/components/src/toolbar-group/toolbar-group-collapsed.native.js index a890645928854a..411a4e6edbd604 100644 --- a/packages/components/src/toolbar-group/toolbar-group-collapsed.native.js +++ b/packages/components/src/toolbar-group/toolbar-group-collapsed.native.js @@ -1,10 +1,36 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; +/** + * WordPress dependencies + */ +import { withPreferredColorScheme } from '@wordpress/compose'; /** * Internal dependencies */ import DropdownMenu from '../dropdown-menu'; +import styles from './style.scss'; -function ToolbarGroupCollapsed( { controls = [], ...props } ) { - return <DropdownMenu controls={ controls } { ...props } />; +function ToolbarGroupCollapsed( { + controls = [], + getStylesFromColorScheme, + passedStyle, + ...props +} ) { + return ( + <View + style={ [ + getStylesFromColorScheme( + styles.container, + styles.containerDark + ), + passedStyle, + ] } + > + <DropdownMenu controls={ controls } { ...props } /> + </View> + ); } -export default ToolbarGroupCollapsed; +export default withPreferredColorScheme( ToolbarGroupCollapsed ); diff --git a/packages/components/src/toolbar/stories/index.js b/packages/components/src/toolbar/stories/index.js index d4edace706f17a..2749329089b775 100644 --- a/packages/components/src/toolbar/stories/index.js +++ b/packages/components/src/toolbar/stories/index.js @@ -126,3 +126,57 @@ export const withoutGroup = () => { ); }; /* eslint-enable no-restricted-syntax */ + +export const toolbars = () => { + return ( + <div> + <div style={ { padding: '20px' } }> + <h2>Icon-only Toolbar</h2> + <Toolbar> + <ToolbarButton icon={ formatBold } title="Bold" /> + <ToolbarButton + icon={ formatItalic } + title="Italic" + isActive + /> + <ToolbarButton icon={ link } title="Link" /> + </Toolbar> + </div> + + <div style={ { padding: '20px' } }> + <h2>Text-only Toolbar</h2> + <Toolbar> + <ToolbarButton>Bold Format</ToolbarButton> + <ToolbarButton isActive>Italic Format</ToolbarButton> + <ToolbarButton>Link Format</ToolbarButton> + </Toolbar> + </div> + + <div style={ { padding: '20px' } }> + <h2>Text and Icon Toolbar</h2> + <Toolbar> + <ToolbarButton icon={ formatBold } title="Bold" /> + <ToolbarButton isActive>Bold Format</ToolbarButton> + <ToolbarButton icon={ formatItalic } title="Italic" /> + <ToolbarButton>Italic Format</ToolbarButton> + <ToolbarButton icon={ link } title="Link" /> + <ToolbarButton>Link Format</ToolbarButton> + </Toolbar> + </div> + + <div style={ { padding: '20px' } }> + <h2>Single Icon Button Toolbar</h2> + <Toolbar> + <ToolbarButton icon={ formatBold } title="Bold" /> + </Toolbar> + </div> + + <div style={ { padding: '20px' } }> + <h2>Single Text Button toolbar</h2> + <Toolbar> + <ToolbarButton>Bold Toolbar</ToolbarButton> + </Toolbar> + </div> + </div> + ); +}; diff --git a/packages/components/src/toolbar/style.scss b/packages/components/src/toolbar/style.scss index 2dc89b9b4e5f8f..74afbf16b7c812 100644 --- a/packages/components/src/toolbar/style.scss +++ b/packages/components/src/toolbar/style.scss @@ -1,11 +1,102 @@ .components-accessible-toolbar { - // Required for IE11. display: inline-flex; + border: $border-width solid $dark-gray-primary; + border-radius: $radius-block-ui; + flex-shrink: 0; - // IE11 doesn't read rules inside this query. They are applied only to modern browsers. - @supports (position: sticky) { - display: flex; + .components-toolbar-group:last-child { + border-right: none; } +} - flex-shrink: 0; +.components-accessible-toolbar, +.components-toolbar { + .components-button { + position: relative; + height: $block-toolbar-height; + z-index: 1; + + // Give all buttons extra padding to fit text. + padding-left: $grid-unit-20; + padding-right: $grid-unit-20; + + // Don't show the focus inherited by the Button component. + &:focus:enabled { + box-shadow: none; + outline: none; + } + + // Focus and toggle pseudo elements. + &::before { + content: ""; + position: absolute; + display: block; + border-radius: $radius-block-ui; + height: 32px; + min-width: 32px; + + // Position the focus rectangle. + left: $grid-unit-10; + right: $grid-unit-10; + z-index: -1; + + // Animate in. + animation: components-button__appear-animation 0.1s ease; + animation-fill-mode: forwards; + @include reduce-motion("animation"); + } + + svg { + position: relative; + + // Center the icon inside. + margin-left: auto; + margin-right: auto; + } + + // Toggled style. + &.is-pressed { + color: $white; + + &::before { + background: $dark-gray-primary; + } + } + + // Focus style. + &:focus::before { + @include block-toolbar-button-style__focus(); + } + + // Ensure the icon buttons remain square. + &.has-icon { + // Reduce the default padding when a button only has an icon. + padding-left: $grid-unit-10; + padding-right: $grid-unit-10; + min-width: $block-toolbar-height; + justify-content: center; + } + + // @todo: We should extract the tabs styles to the tabs component itself + &.components-tab-button { + font-weight: 500; + + span { + display: inline-block; + padding-left: 0; + padding-right: 0; + position: relative; + } + } + } +} + + +@keyframes components-button__appear-animation { + from { + transform: scaleY(0); + } + to { + transform: scaleY(1); + } } diff --git a/packages/components/src/toolbar/test/index.js b/packages/components/src/toolbar/test/index.js index 748d8a500fc600..d5de14b4a86c57 100644 --- a/packages/components/src/toolbar/test/index.js +++ b/packages/components/src/toolbar/test/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; /** * Internal dependencies @@ -12,51 +12,60 @@ import ToolbarButton from '../../toolbar-button'; describe( 'Toolbar', () => { describe( 'basic rendering', () => { it( 'should render a toolbar with toolbar buttons', () => { - const wrapper = mount( + const { getByLabelText } = render( <Toolbar __experimentalAccessibilityLabel="blocks"> <ToolbarButton label="control1" /> <ToolbarButton label="control2" /> </Toolbar> ); - const control1 = wrapper.find( 'button[aria-label="control1"]' ); - const control2 = wrapper.find( 'button[aria-label="control1"]' ); - expect( control1 ).toHaveLength( 1 ); - expect( control2 ).toHaveLength( 1 ); + + expect( + getByLabelText( 'control1', { selector: 'button' } ) + ).toBeTruthy(); + expect( + getByLabelText( 'control2', { selector: 'button' } ) + ).toBeTruthy(); } ); } ); describe( 'ToolbarGroup', () => { it( 'should render an empty node, when controls are not passed', () => { - const wrapper = mount( <Toolbar /> ); - expect( wrapper.html() ).toBeNull(); + const { container } = render( <Toolbar /> ); + + expect( container.innerHTML ).toBe( '' ); } ); it( 'should render an empty node, when controls are empty', () => { - const wrapper = mount( <Toolbar controls={ [] } /> ); - expect( wrapper.html() ).toBeNull(); + const { container } = render( <Toolbar controls={ [] } /> ); + + expect( container.innerHTML ).toBe( '' ); } ); it( 'should render a list of controls with buttons', () => { - const clickHandler = ( event ) => event; const controls = [ { icon: 'wordpress', title: 'WordPress', subscript: 'wp', - onClick: clickHandler, + onClick: () => {}, isActive: false, }, ]; - const wrapper = mount( <Toolbar controls={ controls } /> ); - const button = wrapper - .find( '[aria-label="WordPress"]' ) - .hostNodes(); - expect( button.props() ).toMatchObject( { - 'aria-label': 'WordPress', - 'aria-pressed': false, - 'data-subscript': 'wp', - type: 'button', - } ); + const { getByLabelText } = render( + <Toolbar controls={ controls } /> + ); + + const toolbarButton = getByLabelText( 'WordPress' ); + expect( toolbarButton.getAttribute( 'aria-label' ) ).toBe( + 'WordPress' + ); + expect( toolbarButton.getAttribute( 'aria-pressed' ) ).toBe( + 'false' + ); + expect( toolbarButton.getAttribute( 'data-subscript' ) ).toBe( + 'wp' + ); + expect( toolbarButton.getAttribute( 'type' ) ).toBe( 'button' ); } ); } ); } ); diff --git a/packages/components/src/toolbar/toolbar-container.js b/packages/components/src/toolbar/toolbar-container.js index d40843ddab3f3f..2ea7cfc7fee8c9 100644 --- a/packages/components/src/toolbar/toolbar-container.js +++ b/packages/components/src/toolbar/toolbar-container.js @@ -15,7 +15,9 @@ import ToolbarContext from '../toolbar-context'; function ToolbarContainer( { accessibilityLabel, ...props }, ref ) { // https://reakit.io/docs/basic-concepts/#state-hooks - const toolbarState = useToolbarState( { loop: true } ); + // Passing baseId for server side rendering (which includes snapshots) + // If an id prop is passed to Toolbar, toolbar items will use it as a base for their ids + const toolbarState = useToolbarState( { loop: true, baseId: props.id } ); return ( // This will provide state for `ToolbarButton`'s diff --git a/packages/components/src/tree-select/stories/index.js b/packages/components/src/tree-select/stories/index.js new file mode 100644 index 00000000000000..c4f299bde2b4cf --- /dev/null +++ b/packages/components/src/tree-select/stories/index.js @@ -0,0 +1,77 @@ +/** + * External dependencies + */ +import { boolean, object, text } from '@storybook/addon-knobs'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import TreeSelect from '../'; + +export default { + title: 'Components/TreeSelect', + component: TreeSelect, +}; + +const TreeSelectWithState = ( props ) => { + const [ selection, setSelection ] = useState(); + + return ( + <TreeSelect + { ...props } + onChange={ setSelection } + selectedId={ selection } + /> + ); +}; + +export const _default = () => { + const label = text( 'Label', 'Label Text' ); + const noOptionLabel = text( 'No Option Label', 'No parent page' ); + const hideLabelFromVision = boolean( 'Hide Label From Vision', false ); + const help = text( + 'Help Text', + 'Help text to explain the select control.' + ); + const tree = object( 'Tree', [ + { + name: 'Page 1', + id: 'p1', + children: [ + { name: 'Descend 1 of page 1', id: 'p11' }, + { name: 'Descend 2 of page 1', id: 'p12' }, + ], + }, + { + name: 'Page 2', + id: 'p2', + children: [ + { + name: 'Descend 1 of page 2', + id: 'p21', + children: [ + { + name: 'Descend 1 of Descend 1 of page 2', + id: 'p211', + }, + ], + }, + ], + }, + ] ); + + return ( + <TreeSelectWithState + label={ label } + noOptionLabel={ noOptionLabel } + hideLabelFromVision={ hideLabelFromVision } + help={ help } + tree={ tree } + /> + ); +}; diff --git a/packages/components/src/unit-control/README.md b/packages/components/src/unit-control/README.md new file mode 100644 index 00000000000000..79100d9cfe4fcb --- /dev/null +++ b/packages/components/src/unit-control/README.md @@ -0,0 +1,37 @@ +# UnitControl + +UnitControl allows the user to set a value as well as a unit (e.g. `px`). + +## Usage + +```jsx +import { __experimentalUnitControl as UnitControl } from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +const Example = () => { + const [value, setValue] = useState(10); + const [unit, setUnit] = useState('px'); + + return ( + <UnitControl + onChange={ setValue } + onUnitChange={ setUnit } + unit={ unit } + value={ value} + /> + ) +}; +``` + +## Props + +Name | Type | Default | Description +--- | --- | --- | --- +`isUnitSelectTabbable` | `boolean` | `true` | Determines if the unit `<select>` is tabbable. +`label` | `string` | | Aria label for the control. +`onChange` | `Function` | `noop` | Callback when the `value` changes. +`onUnitChange` | `Function` | `noop` | Callback when the `unit` changes. +`size` | `string` | `default` | Determines the height of the control. +`unit` | `string` | `px` | Current unit value. +`units` | `Array<string>` | | Collection of available units. +`value` | `number` | | Current number value. \ No newline at end of file diff --git a/packages/components/src/unit-control/index.js b/packages/components/src/unit-control/index.js new file mode 100644 index 00000000000000..7276b10141a55f --- /dev/null +++ b/packages/components/src/unit-control/index.js @@ -0,0 +1,61 @@ +/** + * External dependencies + */ +import { isUndefined, noop } from 'lodash'; +import classnames from 'classnames'; +/** + * Internal dependencies + */ +import { Root, ValueInput } from './styles/unit-control-styles'; +import UnitSelectControl from './unit-select-control'; +import { CSS_UNITS } from './utils'; + +export default function UnitControl( { + className, + isUnitSelectTabbable = true, + isResetValueOnUnitChange = true, + label, + onChange = noop, + onUnitChange = noop, + size = 'default', + style, + unit = 'px', + units = CSS_UNITS, + value, + ...props +} ) { + const handleOnUnitChange = ( unitValue, changeProps ) => { + const { data } = changeProps; + onUnitChange( unitValue, changeProps ); + + if ( isResetValueOnUnitChange && ! isUndefined( data.default ) ) { + onChange( data.default, changeProps ); + } + }; + + const classes = classnames( 'component-unit-control', className ); + + return ( + <Root className={ classes } style={ style }> + <ValueInput + aria-label={ label } + { ...props } + className="component-unit-control__input" + value={ value } + onChange={ onChange } + size={ size } + type="number" + /> + <UnitSelectControl + className="component-unit-control__select" + isTabbable={ isUnitSelectTabbable } + options={ units } + onChange={ handleOnUnitChange } + size={ size } + value={ unit } + /> + </Root> + ); +} + +UnitControl.__defaultUnits = CSS_UNITS; diff --git a/packages/components/src/unit-control/stories/index.js b/packages/components/src/unit-control/stories/index.js new file mode 100644 index 00000000000000..bf5680c6ae630f --- /dev/null +++ b/packages/components/src/unit-control/stories/index.js @@ -0,0 +1,60 @@ +/** + * External dependencies + */ +import { boolean, number, select } from '@storybook/addon-knobs'; +import styled from '@emotion/styled'; + +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import UnitControl from '../'; + +export default { + title: 'Components/UnitControl', + component: UnitControl, +}; + +function Example() { + const [ value, setValue ] = useState( '' ); + const [ unit, setUnit ] = useState( 'px' ); + + const props = { + isShiftStepEnabled: boolean( 'isShiftStepEnabled', true ), + isUnitSelectTabbable: boolean( 'isUnitSelectTabbable', true ), + shiftStep: number( 'shiftStep', 10 ), + size: select( + 'size', + { + default: 'default', + small: 'small', + }, + 'default' + ), + step: number( 'step', 1 ), + }; + + return ( + <ControlWrapperView> + <UnitControl + { ...props } + value={ value } + onChange={ setValue } + unit={ unit } + onUnitChange={ setUnit } + /> + </ControlWrapperView> + ); +} + +export const _default = () => { + return <Example />; +}; + +const ControlWrapperView = styled.div` + max-width: 80px; +`; diff --git a/packages/components/src/unit-control/styles/unit-control-styles.js b/packages/components/src/unit-control/styles/unit-control-styles.js new file mode 100644 index 00000000000000..eb17bdf1d87fb8 --- /dev/null +++ b/packages/components/src/unit-control/styles/unit-control-styles.js @@ -0,0 +1,153 @@ +/** + * External dependencies + */ +import { css } from '@emotion/core'; +import styled from '@emotion/styled'; +/** + * Internal dependencies + */ +import { color, rtl } from '../../utils/style-mixins'; +import NumberControl from '../../number-control'; + +export const Root = styled.div` + box-sizing: border-box; + position: relative; +`; + +const fontSizeStyles = ( { size } ) => { + const sizes = { + default: null, + small: '11px', + }; + + const fontSize = sizes[ size ]; + + if ( ! fontSize ) return ''; + + return css` + @media ( min-width: 600px ) { + font-size: ${fontSize}; + } + `; +}; + +const sizeStyles = ( { size } ) => { + const sizes = { + default: { + height: 30, + lineHeight: 30, + minHeight: 30, + }, + small: { + height: 24, + lineHeight: 24, + minHeight: 24, + }, + }; + + const style = sizes[ size ] || sizes.default; + + return css( style ); +}; + +// TODO: Resolve need to use &&& to increase specificity +// https://github.com/WordPress/gutenberg/issues/18483 + +export const ValueInput = styled( NumberControl )` + &&& { + appearance: none; + -moz-appearance: textfield; + box-sizing: border-box; + border: 1px solid ${color( 'ui.border' )}; + border-radius: 2px; + padding: 3px 8px; + display: block; + width: 100%; + + &::-webkit-outer-spin-button, + &::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + ${rtl( { paddingRight: 20 } )} + ${fontSizeStyles}; + ${sizeStyles}; + } +`; + +const unitSizeStyles = ( { size } ) => { + const sizes = { + default: { + top: 5, + height: 20, + minHeight: 20, + }, + small: { + top: 4, + height: 16, + minHeight: 16, + }, + }; + + return css( sizes[ size ] ); +}; + +const baseUnitLabelStyles = ( props ) => { + return css` + appearance: none; + background: ${color( 'ui.background' )}; + border-radius: 2px; + border: none; + box-sizing: border-box; + color: ${color( 'darkGray.500' )}; + display: block; + font-size: 8px; + line-height: 1; + letter-spacing: -0.5px; + outline: none; + padding: 2px 2px; + position: absolute; + text-align-last: center; + text-transform: uppercase; + width: 22px; + z-index: 1; + + ${rtl( { right: 4 } )()} + ${unitSizeStyles( props )} + `; +}; + +const unitLabelPaddingStyles = ( { size } ) => { + const sizes = { + default: '6px 2px', + small: '4px 2px', + }; + + return css( { padding: sizes[ size ] } ); +}; + +export const UnitLabel = styled.div` + &&& { + ${baseUnitLabelStyles}; + ${unitLabelPaddingStyles}; + } +`; + +export const UnitSelect = styled.select` + &&& { + ${baseUnitLabelStyles}; + cursor: pointer; + border: 1px solid transparent; + + &:hover { + background-color: ${color( 'lightGray.300' )}; + } + + &:focus { + border-color: ${color( 'ui.borderFocus' )}; + outline: 2px solid transparent; + outline-offset: 0; + } + } +`; diff --git a/packages/components/src/unit-control/test/index.js b/packages/components/src/unit-control/test/index.js new file mode 100644 index 00000000000000..32bad94884076d --- /dev/null +++ b/packages/components/src/unit-control/test/index.js @@ -0,0 +1,283 @@ +/** + * External dependencies + */ +import { render, unmountComponentAtNode } from 'react-dom'; +import { act, Simulate } from 'react-dom/test-utils'; + +/** + * WordPress dependencies + */ +import { UP, DOWN } from '@wordpress/keycodes'; + +/** + * Internal dependencies + */ +import UnitControl from '../'; + +let container = null; + +beforeEach( () => { + container = document.createElement( 'div' ); + document.body.appendChild( container ); +} ); + +afterEach( () => { + unmountComponentAtNode( container ); + container.remove(); + container = null; +} ); + +const getComponent = () => container.querySelector( '.component-unit-control' ); +const getInput = () => + container.querySelector( '.component-unit-control__input' ); +const getSelect = () => + container.querySelector( '.component-unit-control__select' ); + +describe( 'UnitControl', () => { + describe( 'Basic rendering', () => { + it( 'should render', () => { + act( () => { + render( <UnitControl />, container ); + } ); + const input = getInput(); + const select = getSelect(); + + expect( input ).toBeTruthy(); + expect( select ).toBeTruthy(); + } ); + + it( 'should render custom className', () => { + act( () => { + render( <UnitControl className="hello" />, container ); + } ); + + const el = getComponent(); + + expect( el.classList.contains( 'hello' ) ).toBe( true ); + } ); + + it( 'should not render select, if units are disabled', () => { + act( () => { + render( <UnitControl unit="em" units={ false } />, container ); + } ); + const input = getInput(); + const select = getSelect(); + + expect( input ).toBeTruthy(); + expect( select ).toBeFalsy(); + } ); + } ); + + describe( 'Value', () => { + it( 'should update value on change', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + act( () => { + render( + <UnitControl value={ state } onChange={ setState } />, + container + ); + } ); + + const input = getInput(); + + act( () => { + Simulate.change( input, { target: { value: 62 } } ); + } ); + + expect( state ).toBe( 62 ); + } ); + + it( 'should increment value on UP press', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + act( () => { + render( + <UnitControl value={ state } onChange={ setState } />, + container + ); + } ); + + const input = getInput(); + + act( () => { + Simulate.keyDown( input, { keyCode: UP } ); + } ); + + expect( state ).toBe( '51' ); + } ); + + it( 'should increment value on UP + SHIFT press, with step', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + act( () => { + render( + <UnitControl value={ state } onChange={ setState } />, + container + ); + } ); + + const input = getInput(); + + act( () => { + Simulate.keyDown( input, { keyCode: UP, shiftKey: true } ); + } ); + + expect( state ).toBe( '60' ); + } ); + + it( 'should decrement value on DOWN press', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + act( () => { + render( + <UnitControl value={ state } onChange={ setState } />, + container + ); + } ); + + const input = getInput(); + + act( () => { + Simulate.keyDown( input, { keyCode: DOWN } ); + } ); + + expect( state ).toBe( '49' ); + } ); + + it( 'should decrement value on DOWN + SHIFT press, with step', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + act( () => { + render( + <UnitControl value={ state } onChange={ setState } />, + container + ); + } ); + + const input = getInput(); + + act( () => { + Simulate.keyDown( input, { keyCode: DOWN, shiftKey: true } ); + } ); + + expect( state ).toBe( '40' ); + } ); + } ); + + describe( 'Unit', () => { + it( 'should update unit value on change', () => { + let state = 'px'; + const setState = ( nextState ) => ( state = nextState ); + + act( () => { + render( + <UnitControl unit={ state } onUnitChange={ setState } />, + container + ); + } ); + + const select = getSelect(); + + act( () => { + Simulate.change( select, { target: { value: 'em' } } ); + } ); + + expect( state ).toBe( 'em' ); + } ); + + it( 'should render customized units, if defined', () => { + const units = [ + { value: 'pt', label: 'pt', default: 0 }, + { value: 'vmax', label: 'vmax', default: 10 }, + ]; + act( () => { + render( <UnitControl units={ units } />, container ); + } ); + + const select = getSelect(); + const options = select.querySelectorAll( 'option' ); + + expect( options.length ).toBe( 2 ); + + const [ pt, vmax ] = options; + + expect( pt.value ).toBe( 'pt' ); + expect( vmax.value ).toBe( 'vmax' ); + } ); + + it( 'should reset value on unit change, if unit has default value', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + const units = [ + { value: 'pt', label: 'pt', default: 25 }, + { value: 'vmax', label: 'vmax', default: 75 }, + ]; + act( () => { + render( + <UnitControl + units={ units } + onChange={ setState } + value={ state } + />, + container + ); + } ); + + const select = getSelect(); + + act( () => { + Simulate.change( select, { target: { value: 'vmax' } } ); + } ); + + expect( state ).toBe( 75 ); + + act( () => { + Simulate.change( select, { target: { value: 'pt' } } ); + } ); + + expect( state ).toBe( 25 ); + } ); + + it( 'should not reset value on unit change, if disabled', () => { + let state = 50; + const setState = ( nextState ) => ( state = nextState ); + + const units = [ + { value: 'pt', label: 'pt', default: 25 }, + { value: 'vmax', label: 'vmax', default: 75 }, + ]; + act( () => { + render( + <UnitControl + isResetValueOnUnitChange={ false } + value={ state } + units={ units } + onChange={ setState } + />, + container + ); + } ); + + const select = getSelect(); + + act( () => { + Simulate.change( select, { target: { value: 'vmax' } } ); + } ); + + expect( state ).toBe( 50 ); + + act( () => { + Simulate.change( select, { target: { value: 'pt' } } ); + } ); + + expect( state ).toBe( 50 ); + } ); + } ); +} ); diff --git a/packages/components/src/unit-control/unit-select-control.js b/packages/components/src/unit-control/unit-select-control.js new file mode 100644 index 00000000000000..6844b5c959963a --- /dev/null +++ b/packages/components/src/unit-control/unit-select-control.js @@ -0,0 +1,55 @@ +/** + * External dependencies + */ +import { noop, isEmpty } from 'lodash'; +import classnames from 'classnames'; + +/** + * Internal dependencies + */ +import { UnitSelect, UnitLabel } from './styles/unit-control-styles'; +import { CSS_UNITS } from './utils'; + +/** + * Renders a `select` if there are multiple units. + * Otherwise, renders a non-selectable label. + */ +export default function UnitSelectControl( { + className, + isTabbable = true, + options = CSS_UNITS, + onChange = noop, + size = 'default', + value = 'px', + ...props +} ) { + if ( isEmpty( options ) || options.length === 1 || options === false ) { + return <UnitLabel size={ size }>{ value }</UnitLabel>; + } + + const handleOnChange = ( event ) => { + const { value: unitValue } = event.target; + const data = options.find( ( option ) => option.value === unitValue ); + + onChange( unitValue, { event, data } ); + }; + + const classes = classnames( 'component-unit-control__select', className ); + + return ( + <UnitSelect + className={ classes } + onChange={ handleOnChange } + size={ size } + tabIndex={ isTabbable ? null : '-1' } + value={ value } + { ...props } + > + { options.map( ( option ) => ( + <option value={ option.value } key={ option.value }> + { option.label } + </option> + ) ) } + </UnitSelect> + ); +} diff --git a/packages/components/src/unit-control/utils.js b/packages/components/src/unit-control/utils.js new file mode 100644 index 00000000000000..aa886479f27d2a --- /dev/null +++ b/packages/components/src/unit-control/utils.js @@ -0,0 +1,8 @@ +export const CSS_UNITS = [ + { value: 'px', label: 'px', default: 0 }, + { value: '%', label: '%', default: 10 }, + { value: 'em', label: 'em', default: 0 }, + { value: 'rem', label: 'rem', default: 0 }, + { value: 'vw', label: 'vw', default: 10 }, + { value: 'vh', label: 'vh', default: 10 }, +]; diff --git a/packages/components/src/utils/colors-values.js b/packages/components/src/utils/colors-values.js index 537a8e7810300b..7e152a4263cc8f 100644 --- a/packages/components/src/utils/colors-values.js +++ b/packages/components/src/utils/colors-values.js @@ -1,12 +1,44 @@ +/** + * External dependencies + */ +import { merge } from 'lodash'; + /** * Internal dependencies */ import { rgba } from './colors'; + export const BASE = { black: '#000', white: '#fff', }; +/** + * TODO: Continue to update values as "G2" design evolves. + * + * "G2" refers to the movement to advance the interface of the block editor. + * https://github.com/WordPress/gutenberg/issues/18667 + */ +export const G2 = { + blue: { + medium: { + focus: '#007cba', + focusDark: '#fff', + }, + }, + darkGray: { + primary: '#1e1e1e', + }, + mediumGray: { + text: '#757575', + }, + lightGray: { + ui: '#949494', + secondary: '#ccc', + tertiary: '#e7e8e9', + }, +}; + export const DARK_GRAY = { 900: '#191e23', 800: '#23282d', @@ -101,15 +133,24 @@ export const ALERT = { green: '#4ab866', }; +// Namespaced values for raw colors hex codes +export const UI = { + background: BASE.white, + border: BASE.black, + borderFocus: BLUE.medium.focus, +}; + export const COLORS = { ...BASE, - darkGray: DARK_GRAY, + darkGray: merge( {}, DARK_GRAY, G2.darkGray ), darkOpacity: DARK_OPACITY, darkOpacityLight: DARK_OPACITY_LIGHT, - lightGray: LIGHT_GRAY, + mediumGray: G2.mediumGray, + lightGray: merge( {}, LIGHT_GRAY, G2.lightGray ), lightGrayLight: LIGHT_OPACITY_LIGHT, - blue: BLUE, + blue: merge( {}, BLUE, G2.blue ), alert: ALERT, + ui: UI, }; export default COLORS; diff --git a/packages/components/src/utils/reduce-motion.js b/packages/components/src/utils/reduce-motion.js index b3651d494c66eb..16b79b37944309 100644 --- a/packages/components/src/utils/reduce-motion.js +++ b/packages/components/src/utils/reduce-motion.js @@ -2,7 +2,7 @@ * Allows users to opt-out of animations via OS-level preferences. * * @param {string} prop CSS Property name - * @return {string} + * @return {string} Generated CSS code for the reduced style */ export function reduceMotion( prop = 'transition' ) { let style; diff --git a/packages/compose/package.json b/packages/compose/package.json index f48813760f4f16..352ec323ee9bab 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -23,7 +23,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/element": "file:../element", "@wordpress/is-shallow-equal": "file:../is-shallow-equal", "lodash": "^4.17.15", diff --git a/packages/core-data/README.md b/packages/core-data/README.md index a2bb3ccbe6deeb..c63333f9f149cd 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -40,7 +40,7 @@ const MyAuthorsList = withSelect( ( select ) => ( { The following set of dispatching action creators are available on the object returned by `wp.data.dispatch( 'core' )`: -<!-- START TOKEN(Autogenerated actions) --> +<!-- START TOKEN(Autogenerated actions|src/actions.js) --> <a name="addEntities" href="#addEntities">#</a> **addEntities** @@ -211,13 +211,13 @@ _Parameters_ Action triggered to undo the last edit to an entity record, if any. -<!-- END TOKEN(Autogenerated actions) --> +<!-- END TOKEN(Autogenerated actions|src/actions.js) --> ## Selectors The following selectors are available on the object returned by `wp.data.select( 'core' )`: -<!-- START TOKEN(Autogenerated selectors) --> +<!-- START TOKEN(Autogenerated selectors|src/selectors.js) --> <a name="canUser" href="#canUser">#</a> **canUser** @@ -655,6 +655,6 @@ _Returns_ - `boolean`: Whether the entity record is saving or not. -<!-- END TOKEN(Autogenerated selectors) --> +<!-- END TOKEN(Autogenerated selectors|src/selectors.js) --> <br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> diff --git a/packages/core-data/package.json b/packages/core-data/package.json index fdfeba54c70216..5cd39bfece2210 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -22,7 +22,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blocks": "file:../blocks", "@wordpress/data": "file:../data", diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 2e8ae68a88dd41..8a9fa25ce3c648 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -22,6 +22,9 @@ export const defaultEntities = [ name: 'site', kind: 'root', baseURL: '/wp/v2/settings', + getTitle: ( record ) => { + return get( record, [ 'title' ], __( 'Site Title' ) ); + }, }, { label: __( 'Post Type' ), @@ -67,6 +70,27 @@ export const defaultEntities = [ plural: 'comments', label: __( 'Comment' ), }, + { + name: 'menu', + kind: 'root', + baseURL: '/__experimental/menus', + plural: 'menus', + label: __( 'Menu' ), + }, + { + name: 'menuItem', + kind: 'root', + baseURL: '/__experimental/menu-items', + plural: 'menuItems', + label: __( 'Menu Item' ), + }, + { + name: 'menuLocation', + kind: 'root', + baseURL: '/__experimental/menu-locations', + plural: 'menuLocations', + label: __( 'Menu Location' ), + }, ]; export const kinds = [ diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 935db8124f3fd0..2adea266a25d4f 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -1,7 +1,5 @@ ## Master -## 0.10.0 (2020-04-01) - ### New Features - Added readme.txt file to the existing templates to make your entry in the plugin browser most useful ([#20694](https://github.com/WordPress/gutenberg/pull/20694)). diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 977b70b851b9a7..880da35e5938fa 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -30,11 +30,11 @@ "wp-create-block": "./index.js" }, "dependencies": { - "chalk": "^2.4.2", + "chalk": "^4.0.0", "check-node-version": "^3.1.1", "commander": "^4.1.0", "execa": "^4.0.0", - "inquirer": "^7.0.3", + "inquirer": "^7.1.0", "lodash": "^4.17.15", "make-dir": "^3.0.0", "mustache": "^4.0.0", diff --git a/packages/data/README.md b/packages/data/README.md index 5e53e5c406f5c4..fc904d64e3a861 100644 --- a/packages/data/README.md +++ b/packages/data/README.md @@ -100,20 +100,20 @@ registerStore( 'my-shop', { } ); ``` -The return value of `registerStore` is a [Redux-like store object](https://redux.js.org/docs/basics/Store.html) with the following methods: +The return value of `registerStore` is a [Redux-like store object](https://redux.js.org/basics/store) with the following methods: - `store.getState()`: Returns the state value of the registered reducer - - _Redux parallel:_ [`getState`](https://redux.js.org/api-reference/store#getState) + - _Redux parallel:_ [`getState`](https://redux.js.org/api/store#getstate) - `store.subscribe( listener: Function )`: Registers a function called any time the value of state changes. - - _Redux parallel:_ [`subscribe`](https://redux.js.org/api-reference/store#subscribe(listener)) + - _Redux parallel:_ [`subscribe`](https://redux.js.org/api/store#subscribelistener) - `store.dispatch( action: Object )`: Given an action object, calls the registered reducer and updates the state value. - - _Redux parallel:_ [`dispatch`](https://redux.js.org/api-reference/store#dispatch(action)) + - _Redux parallel:_ [`dispatch`](https://redux.js.org/api/store#dispatchaction) ### Options #### `reducer` -A [**reducer**](https://redux.js.org/docs/basics/Reducers.html) is a function accepting the previous `state` and `action` as arguments and returns an updated `state` value. +A [**reducer**](https://redux.js.org/basics/reducers) is a function accepting the previous `state` and `action` as arguments and returns an updated `state` value. #### `actions` @@ -148,7 +148,7 @@ The `@wordpress/data` module offers a more advanced and generic interface for th - `getSelectors()`: Returns an object of selector functions, pre-mapped to the store. - `getActions()`: Returns an object of action functions, pre-mapped to the store. - `subscribe( listener: Function )`: Registers a function called any time the value of state changes. - - Behaves as Redux [`subscribe`](https://redux.js.org/api-reference/store#subscribe(listener)) + - Behaves as Redux [`subscribe`](https://redux.js.org/api/store#subscribelistener) with the following differences: - Doesn't have to implement an unsubscribe, since the registry never uses it. \- Only has to support one listener (the registry). diff --git a/packages/data/package.json b/packages/data/package.json index 420f4d51d82951..d7779ab1aad227 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -22,7 +22,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:../compose", "@wordpress/deprecated": "file:../deprecated", "@wordpress/element": "file:../element", @@ -32,7 +32,7 @@ "equivalent-key-map": "^0.2.2", "is-promise": "^2.1.0", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "redux": "^4.0.0", "turbo-combine-reducers": "^1.0.2", "use-memo-one": "^1.1.1" diff --git a/packages/data/src/namespace-store/test/index.js b/packages/data/src/namespace-store/test/index.js index 5f0eb4cb792d39..915b9bbfe65e8e 100644 --- a/packages/data/src/namespace-store/test/index.js +++ b/packages/data/src/namespace-store/test/index.js @@ -42,7 +42,7 @@ describe( 'controls', () => { } ); } ); - it( 'resolves in expected order', ( done ) => { + it( 'resolves in expected order', async () => { const actions = { wait: () => ( { type: 'WAIT' } ), receive: ( items ) => ( { type: 'RECEIVE', items } ), @@ -74,21 +74,23 @@ describe( 'controls', () => { }, } ); - registry.subscribe( () => { - const isFinished = registry - .select( 'store' ) - .hasFinishedResolution( 'getItems' ); - if ( isFinished ) { - expect( registry.select( 'store' ).getItems() ).toEqual( [ - 1, - 2, - 3, - ] ); - done(); - } - } ); + return new Promise( ( resolve ) => { + registry.subscribe( () => { + const isFinished = registry + .select( 'store' ) + .hasFinishedResolution( 'getItems' ); + if ( isFinished ) { + expect( registry.select( 'store' ).getItems() ).toEqual( [ + 1, + 2, + 3, + ] ); + } + resolve(); + } ); - registry.select( 'store' ).getItems(); + registry.select( 'store' ).getItems(); + } ); } ); describe( 'selectors have expected value for the `hasResolver` property', () => { it( 'when custom store has resolvers defined', () => { diff --git a/packages/data/src/plugins/persistence/test/index.js b/packages/data/src/plugins/persistence/test/index.js index 4d91648ce81da3..818f075640ae56 100644 --- a/packages/data/src/plugins/persistence/test/index.js +++ b/packages/data/src/plugins/persistence/test/index.js @@ -11,7 +11,7 @@ import objectStorage from '../storage/object'; import { createRegistry } from '../../../'; describe( 'persistence', () => { - let registry, originalRegisterStore; + let registry; beforeAll( () => { jest.spyOn( objectStorage, 'setItem' ); @@ -21,18 +21,8 @@ describe( 'persistence', () => { objectStorage.clear(); objectStorage.setItem.mockClear(); - // Since the exposed `registerStore` is a proxying function, mimic - // intercept of original call by adding an initial plugin. // TODO: Remove the `use` function in favor of `registerGenericStore` - registry = createRegistry() - .use( ( originalRegistry ) => { - originalRegisterStore = jest.spyOn( - originalRegistry, - 'registerStore' - ); - return {}; - } ) - .use( plugin, { storage: objectStorage } ); + registry = createRegistry().use( plugin, { storage: objectStorage } ); } ); it( 'should not mutate options', () => { @@ -181,17 +171,6 @@ describe( 'persistence', () => { expect( registry.select( 'test' ).getState() ).toBe( 1 ); } ); - it( 'override values passed to registerStore', () => { - const options = { persist: true, reducer() {} }; - - registry.registerStore( 'test', options ); - - expect( originalRegisterStore ).toHaveBeenCalledWith( 'test', { - persist: true, - reducer: expect.any( Function ), - } ); - } ); - it( 'should not persist if option not passed', () => { const initialState = { foo: 'bar', baz: 'qux' }; function reducer( state = initialState, action ) { diff --git a/packages/data/src/registry.js b/packages/data/src/registry.js index adb11b40c75dfa..4f74d4cb1ea512 100644 --- a/packages/data/src/registry.js +++ b/packages/data/src/registry.js @@ -32,6 +32,8 @@ import createCoreDataStore from './store'; /** * @typedef {Object} WPDataPlugin An object of registry function overrides. + * + * @property {Function} registerStore registers store. */ /** diff --git a/packages/data/src/test/registry.js b/packages/data/src/test/registry.js index 02242ecc5b283c..879050388a9512 100644 --- a/packages/data/src/test/registry.js +++ b/packages/data/src/test/registry.js @@ -396,7 +396,7 @@ describe( 'createRegistry', () => { return promise; } ); - it( 'should resolve promise non-action to dispatch', ( done ) => { + it( 'should resolve promise non-action to dispatch', () => { let shouldThrow = false; registry.registerStore( 'demo', { reducer: ( state = 'OK' ) => { @@ -417,9 +417,7 @@ describe( 'createRegistry', () => { registry.select( 'demo' ).getValue(); - process.nextTick( () => { - done(); - } ); + return new Promise( ( resolve ) => process.nextTick( resolve ) ); } ); it( 'should not dispatch resolved promise action on subsequent selector calls', () => { diff --git a/packages/date/README.md b/packages/date/README.md index e45bb664c85519..954ea388ece67d 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -18,26 +18,40 @@ _This package assumes that your code will run in an **ES2015+** environment. If <a name="date" href="#date">#</a> **date** -Formats a date (like `date()` in PHP), in the site's timezone. +Formats a date (like `date()` in PHP). + +_Related_ + +- <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones> +- <https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC> _Parameters_ - _dateFormat_ `string`: PHP-style formatting string. See php.net/date. - _dateValue_ `(Date|string|Moment|null)`: Date object or string, parsable by moment.js. +- _timezone_ `(string|number|null)`: Timezone to output result in or a UTC offset. Defaults to timezone from site. _Returns_ -- `string`: Formatted date. +- `string`: Formatted date in English. <a name="dateI18n" href="#dateI18n">#</a> **dateI18n** -Formats a date (like `date_i18n()` in PHP). +Formats a date (like `wp_date()` in PHP), translating it into site's locale. + +Backward Compatibility Notice: if `timezone` is set to `true`, the function +behaves like `gmdateI18n`. + +_Related_ + +- <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones> +- <https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC> _Parameters_ - _dateFormat_ `string`: PHP-style formatting string. See php.net/date. - _dateValue_ `(Date|string|Moment|null)`: Date object or string, parsable by moment.js. -- _gmt_ `boolean`: True for GMT/UTC, false for site's timezone. +- _timezone_ `(string|number|boolean|null)`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons. _Returns_ @@ -79,6 +93,20 @@ _Parameters_ _Returns_ +- `string`: Formatted date in English. + +<a name="gmdateI18n" href="#gmdateI18n">#</a> **gmdateI18n** + +Formats a date (like `wp_date()` in PHP), translating it into site's locale +and using the UTC timezone. + +_Parameters_ + +- _dateFormat_ `string`: PHP-style formatting string. See php.net/date. +- _dateValue_ `(Date|string|Moment|null)`: Date object or string, parsable by moment.js. + +_Returns_ + - `string`: Formatted date. <a name="isInTheFuture" href="#isInTheFuture">#</a> **isInTheFuture** diff --git a/packages/date/package.json b/packages/date/package.json index c095c6a6a8aac9..8485398932e706 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "moment": "^2.22.1", "moment-timezone": "^0.5.16" }, diff --git a/packages/date/src/index.js b/packages/date/src/index.js index 6251e1c82c04bf..25697d8fadd596 100644 --- a/packages/date/src/index.js +++ b/packages/date/src/index.js @@ -9,6 +9,10 @@ import 'moment-timezone/moment-timezone-utils'; const WP_ZONE = 'WP'; +// This regular expression tests positive for UTC offsets as described in ISO 8601. +// See: https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC +const VALID_UTC_OFFSET = /^[+-][0-1][0-9](:?[0-9][0-9])?$/; + // Changes made here will likely need to be made in `lib/client-assets.php` as // well because it uses the `setSettings()` function to change these settings. let settings = { @@ -318,10 +322,10 @@ const formatMap = { /** * Formats a date. Does not alter the date's timezone. * - * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. - * @param {(Date|string|Moment|null)} dateValue Date object or string, - * parsable by moment.js. + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Date|string|Moment|null} dateValue Date object or string, + * parsable by moment.js. * * @return {string} Formatted date. */ @@ -357,30 +361,35 @@ export function format( dateFormat, dateValue = new Date() ) { } /** - * Formats a date (like `date()` in PHP), in the site's timezone. + * Formats a date (like `date()` in PHP). * - * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. - * @param {(Date|string|Moment|null)} dateValue Date object or string, - * parsable by moment.js. + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Date|string|Moment|null} dateValue Date object or string, parsable + * by moment.js. + * @param {string|number|null} timezone Timezone to output result in or a + * UTC offset. Defaults to timezone from + * site. * - * @return {string} Formatted date. + * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC + * + * @return {string} Formatted date in English. */ -export function date( dateFormat, dateValue = new Date() ) { - const offset = settings.timezone.offset * HOUR_IN_MINUTES; - const dateMoment = momentLib( dateValue ).utcOffset( offset, true ); +export function date( dateFormat, dateValue = new Date(), timezone ) { + const dateMoment = buildMoment( dateValue, timezone ); return format( dateFormat, dateMoment ); } /** * Formats a date (like `date()` in PHP), in the UTC timezone. * - * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. - * @param {(Date|string|Moment|null)} dateValue Date object or string, - * parsable by moment.js. + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Date|string|Moment|null} dateValue Date object or string, + * parsable by moment.js. * - * @return {string} Formatted date. + * @return {string} Formatted date in English. */ export function gmdate( dateFormat, dateValue = new Date() ) { const dateMoment = momentLib( dateValue ).utc(); @@ -388,26 +397,54 @@ export function gmdate( dateFormat, dateValue = new Date() ) { } /** - * Formats a date (like `date_i18n()` in PHP). + * Formats a date (like `wp_date()` in PHP), translating it into site's locale. + * + * Backward Compatibility Notice: if `timezone` is set to `true`, the function + * behaves like `gmdateI18n`. + * + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Date|string|Moment|null} dateValue Date object or string, parsable by + * moment.js. + * @param {string|number|boolean|null} timezone Timezone to output result in or a + * UTC offset. Defaults to timezone from + * site. Notice: `boolean` is effectively + * deprecated, but still supported for + * backward compatibility reasons. * - * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. - * @param {(Date|string|Moment|null)} dateValue Date object or string, - * parsable by moment.js. - * @param {boolean} gmt True for GMT/UTC, false for - * site's timezone. + * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC * * @return {string} Formatted date. */ -export function dateI18n( dateFormat, dateValue = new Date(), gmt = false ) { - // Defaults. - const offset = gmt ? 0 : settings.timezone.offset * HOUR_IN_MINUTES; - // Convert to moment object. - const dateMoment = momentLib( dateValue ).utcOffset( offset, true ); +export function dateI18n( dateFormat, dateValue = new Date(), timezone ) { + if ( true === timezone ) { + return gmdateI18n( dateFormat, dateValue ); + } + + if ( false === timezone ) { + timezone = undefined; + } - // Set the locale. + const dateMoment = buildMoment( dateValue, timezone ); + dateMoment.locale( settings.l10n.locale ); + return format( dateFormat, dateMoment ); +} + +/** + * Formats a date (like `wp_date()` in PHP), translating it into site's locale + * and using the UTC timezone. + * + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Date|string|Moment|null} dateValue Date object or string, + * parsable by moment.js. + * + * @return {string} Formatted date. + */ +export function gmdateI18n( dateFormat, dateValue = new Date() ) { + const dateMoment = momentLib( dateValue ).utc(); dateMoment.locale( settings.l10n.locale ); - // Format and return. return format( dateFormat, dateMoment ); } @@ -440,4 +477,51 @@ export function getDate( dateString ) { return momentLib.tz( dateString, WP_ZONE ).toDate(); } +/** + * Creates a moment instance using the given timezone or, if none is provided, using global settings. + * + * @param {Date|string|Moment|null} dateValue Date object or string, parsable + * by moment.js. + * @param {string|number|null} timezone Timezone to output result in or a + * UTC offset. Defaults to timezone from + * site. + * + * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + * @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC + * + * @return {Moment} a moment instance. + */ +function buildMoment( dateValue, timezone = '' ) { + const dateMoment = momentLib( dateValue ); + + if ( timezone && ! isUTCOffset( timezone ) ) { + return dateMoment.tz( timezone ); + } + + if ( timezone && isUTCOffset( timezone ) ) { + return dateMoment.utcOffset( timezone ); + } + + if ( settings.timezone.string ) { + return dateMoment.tz( settings.timezone.string ); + } + + return dateMoment.utcOffset( settings.timezone.offset ); +} + +/** + * Returns whether a certain UTC offset is valid or not. + * + * @param {number|string} offset a UTC offset. + * + * @return {boolean} whether a certain UTC offset is valid or not. + */ +function isUTCOffset( offset ) { + if ( 'number' === typeof offset ) { + return true; + } + + return VALID_UTC_OFFSET.test( offset ); +} + setupWPTimezone(); diff --git a/packages/date/src/test/index.js b/packages/date/src/test/index.js index 69368b1fb630b5..d9b832e528ce6b 100644 --- a/packages/date/src/test/index.js +++ b/packages/date/src/test/index.js @@ -2,10 +2,14 @@ * Internal dependencies */ import { - isInTheFuture, + __experimentalGetSettings, + date as dateNoI18n, + dateI18n, getDate, + gmdate, + gmdateI18n, + isInTheFuture, setSettings, - __experimentalGetSettings, } from '../'; describe( 'isInTheFuture', () => { @@ -16,7 +20,7 @@ describe( 'isInTheFuture', () => { expect( isInTheFuture( date ) ).toBe( true ); } ); - it( 'should return true if the date is in the past', () => { + it( 'should return false if the date is in the past', () => { // Create a Date object 1 minute in the past. const date = new Date( Number( getDate() ) - 1000 * 60 ); @@ -44,6 +48,433 @@ describe( 'isInTheFuture', () => { } ); } ); +describe( 'Function date', () => { + it( 'should format date in English, ignoring locale settings', () => { + const settings = __experimentalGetSettings(); + + // Simulate different locale + const l10n = settings.l10n; + setSettings( { + ...settings, + l10n: { + ...l10n, + locale: 'es', + months: l10n.months.map( ( month ) => `es_${ month }` ), + monthsShort: l10n.monthsShort.map( + ( month ) => `es_${ month }` + ), + weekdays: l10n.weekdays.map( ( weekday ) => `es_${ weekday }` ), + weekdaysShort: l10n.weekdaysShort.map( + ( weekday ) => `es_${ weekday }` + ), + }, + } ); + + // Check + const formattedDate = dateNoI18n( + 'F M l D', + '2019-06-18T11:00:00.000Z' + ); + expect( formattedDate ).toBe( 'June Jun Tuesday Tue' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses site’s timezone, if no timezone was provided and there’s a site timezone set', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const winterFormattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-01-18T11:00:00.000Z' + ); + expect( winterFormattedDate ).toBe( '2019-01-18 06:00' ); + + const summerFormattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z' + ); + expect( summerFormattedDate ).toBe( '2019-06-18 07:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses site’s UTC offset setting, if no timezone was provided and there isn’t a timezone set in the site', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: '' }, + } ); + + // Check + const winterFormattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-01-18T11:00:00.000Z' + ); + expect( winterFormattedDate ).toBe( '2019-01-18 07:00' ); + + const summerFormattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z' + ); + expect( summerFormattedDate ).toBe( '2019-06-18 07:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses the given timezone, if said timezone is valid', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const formattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + 'Asia/Macau' + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses the given UTC offset, if given timezone is actually a UTC offset', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + let formattedDate; + formattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + '+08:00' + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + formattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + 8 + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + formattedDate = dateNoI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + 480 + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + // Restore default settings + setSettings( settings ); + } ); +} ); + +describe( 'Function gmdate', () => { + it( 'should format date in English, ignoring locale settings', () => { + const settings = __experimentalGetSettings(); + + // Simulate different locale + const l10n = settings.l10n; + setSettings( { + ...settings, + l10n: { + ...l10n, + locale: 'es', + months: l10n.months.map( ( month ) => `es_${ month }` ), + monthsShort: l10n.monthsShort.map( + ( month ) => `es_${ month }` + ), + weekdays: l10n.weekdays.map( ( weekday ) => `es_${ weekday }` ), + weekdaysShort: l10n.weekdaysShort.map( + ( weekday ) => `es_${ weekday }` + ), + }, + } ); + + // Check + const formattedDate = gmdate( 'F M l D', '2019-06-18T11:00:00.000Z' ); + expect( formattedDate ).toBe( 'June Jun Tuesday Tue' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a UTC date', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const formattedDate = gmdate( 'Y-m-d H:i', '2019-06-18T11:00:00.000Z' ); + expect( formattedDate ).toBe( '2019-06-18 11:00' ); + + // Restore default settings + setSettings( settings ); + } ); +} ); + +describe( 'Function dateI18n', () => { + it( 'should format date using locale settings', () => { + const settings = __experimentalGetSettings(); + + // Simulate different locale + const l10n = settings.l10n; + setSettings( { + ...settings, + l10n: { + ...l10n, + locale: 'es', + months: l10n.months.map( ( month ) => `es_${ month }` ), + monthsShort: l10n.monthsShort.map( + ( month ) => `es_${ month }` + ), + weekdays: l10n.weekdays.map( ( weekday ) => `es_${ weekday }` ), + weekdaysShort: l10n.weekdaysShort.map( + ( weekday ) => `es_${ weekday }` + ), + }, + } ); + + // Check + const formattedDate = dateI18n( + 'F M l D', + '2019-06-18T11:00:00.000Z', + true + ); + expect( formattedDate ).toBe( 'es_June es_Jun es_Tuesday es_Tue' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses site’s timezone, if no timezone was provided and there’s a site timezone set', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const winterFormattedDate = dateI18n( + 'Y-m-d H:i', + '2019-01-18T11:00:00.000Z' + ); + expect( winterFormattedDate ).toBe( '2019-01-18 06:00' ); + + const summerFormattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z' + ); + expect( summerFormattedDate ).toBe( '2019-06-18 07:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses site’s UTC offset setting, if no timezone was provided and there isn’t a timezone set in the site', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: '' }, + } ); + + // Check + const winterFormattedDate = dateI18n( + 'Y-m-d H:i', + '2019-01-18T11:00:00.000Z' + ); + expect( winterFormattedDate ).toBe( '2019-01-18 07:00' ); + + const summerFormattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z' + ); + expect( summerFormattedDate ).toBe( '2019-06-18 07:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses the given timezone, if said timezone is valid', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const formattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + 'Asia/Macau' + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses the given UTC offset, if given timezone is actually a UTC offset', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + let formattedDate; + formattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + '+08:00' + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + formattedDate = dateI18n( 'Y-m-d H:i', '2019-06-18T11:00:00.000Z', 8 ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + formattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + 480 + ); + expect( formattedDate ).toBe( '2019-06-18 19:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a UTC date if `gmt` is set to `true`', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const formattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + true + ); + expect( formattedDate ).toBe( '2019-06-18 11:00' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a date that uses site’s timezone if `gmt` is set to `false`', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const formattedDate = dateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z', + false + ); + expect( formattedDate ).toBe( '2019-06-18 07:00' ); + + // Restore default settings + setSettings( settings ); + } ); +} ); + +describe( 'Function gmdateI18n', () => { + it( 'should format date using locale settings', () => { + const settings = __experimentalGetSettings(); + + // Simulate different locale + const l10n = settings.l10n; + setSettings( { + ...settings, + l10n: { + ...l10n, + locale: 'es', + months: l10n.months.map( ( month ) => `es_${ month }` ), + monthsShort: l10n.monthsShort.map( + ( month ) => `es_${ month }` + ), + weekdays: l10n.weekdays.map( ( weekday ) => `es_${ weekday }` ), + weekdaysShort: l10n.weekdaysShort.map( + ( weekday ) => `es_${ weekday }` + ), + }, + } ); + + // Check + const formattedDate = gmdateI18n( + 'F M l D', + '2019-06-18T11:00:00.000Z' + ); + expect( formattedDate ).toBe( 'es_June es_Jun es_Tuesday es_Tue' ); + + // Restore default settings + setSettings( settings ); + } ); + + it( 'should format date into a UTC date', () => { + const settings = __experimentalGetSettings(); + + // Simulate different timezone + setSettings( { + ...settings, + timezone: { offset: -4, string: 'America/New_York' }, + } ); + + // Check + const formattedDate = gmdateI18n( + 'Y-m-d H:i', + '2019-06-18T11:00:00.000Z' + ); + expect( formattedDate ).toBe( '2019-06-18 11:00' ); + + // Restore default settings + setSettings( settings ); + } ); +} ); + describe( 'Moment.js Localization', () => { it( 'should change the relative time strings', () => { const settings = __experimentalGetSettings(); diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 8755a3340d97c2..3505c6e0b62c1b 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -1,7 +1,5 @@ ## Master -## 2.5.0 (2020-04-01) - ### New Features - The plugin now supports an optional `combinedOutputFile` option that is useful only when another `combineAssets` option is enabled. It allows providing a custom output file for the generated single assets file ([#20844](https://github.com/WordPress/gutenberg/pull/20844)). diff --git a/packages/dependency-extraction-webpack-plugin/util.js b/packages/dependency-extraction-webpack-plugin/util.js index 5185c24682fb6d..e515f752094c63 100644 --- a/packages/dependency-extraction-webpack-plugin/util.js +++ b/packages/dependency-extraction-webpack-plugin/util.js @@ -1,5 +1,5 @@ const WORDPRESS_NAMESPACE = '@wordpress/'; -const BUNDLED_PACKAGES = [ '@wordpress/icons' ]; +const BUNDLED_PACKAGES = [ '@wordpress/icons', '@wordpress/interface' ]; /** * Default request to global transformation diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index fd5b82f0a52da1..e2096e8a06d0d3 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -22,7 +22,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/hooks": "file:../hooks" }, "publishConfig": { diff --git a/packages/docgen/README.md b/packages/docgen/README.md index c62b96fc4e44b4..e39594cb4fc644 100644 --- a/packages/docgen/README.md +++ b/packages/docgen/README.md @@ -33,9 +33,9 @@ This command will generate a file named `entry-point-api.md` containing all the * **--output** `(String)`: Output file that will contain the API documentation. * **--to-section** `(String)`: Append generated documentation to this section in the Markdown output. To be used by the default Markdown formatter. Depends on `--output` and bypasses the custom `--formatter` passed, if any. * **--to-token**: Embed generated documentation within the start and end tokens in the Markdown output. To be used by the default Markdown formatter.Depends on `--output` and bypasses the custom `--formatter` passed, if any. - * Start token: `<!-- START TOKEN(Autogenerated API docs) -->` - * End token: `<!-- END TOKEN(Autogenerated API docs) -->` -* **--use-token** `(String)`: This options allows you to customize the string between the tokens. For example, `--use-token my-api` will look up for the start token `<!-- START TOKEN(my-api) -->` and the end token `<!-- END TOKEN(my-api) -->`. Depends on `--to-token`. + * Start token: <code>&lt;!-- START TOKEN(Autogenerated API docs) --&gt;</code> + * End token: <code>&lt;!-- END TOKEN(Autogenerated API docs) --&gt;</code> +* **--use-token** `(String)`: This options allows you to customize the string between the tokens. For example, `--use-token my-api` will look up for the start token <code>&lt;!-- START TOKEN(my-api) --&gt;</code> and the end token <code>&lt;!-- END TOKEN(my-api) --&gt;</code>. Depends on `--to-token`. * **--debug**: Run in debug mode, which outputs some intermediate files useful for debugging. ## Examples diff --git a/packages/docgen/src/test/fixtures/tags-function/code.js b/packages/docgen/src/test/fixtures/tags-function/code.js index cbde0e0b9b0456..4e0bd9644fb90b 100644 --- a/packages/docgen/src/test/fixtures/tags-function/code.js +++ b/packages/docgen/src/test/fixtures/tags-function/code.js @@ -2,7 +2,7 @@ * A function that adds two parameters. * * @deprecated Use native addition instead. - * @since v2 + * @since 2.0.0 * * @see addition * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index 116d21d37d4214..1d18cce33a0aa6 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 2.0.0 (2018-09-05) ### Breaking Change diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 332a6a89045a10..12c5abc4cb1f61 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -20,9 +20,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/dom-ready/tsconfig.json b/packages/dom-ready/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/dom-ready/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/dom/README.md b/packages/dom/README.md index d52e47552f342e..d45b8439915786 100644 --- a/packages/dom/README.md +++ b/packages/dom/README.md @@ -118,6 +118,19 @@ _Returns_ - `boolean`: True if at the horizontal edge, false if not. +<a name="isNumberInput" href="#isNumberInput">#</a> **isNumberInput** + +Check whether the given element is an input field of type number +and has a valueAsNumber + +_Parameters_ + +- _element_ `HTMLElement`: The HTML element. + +_Returns_ + +- `boolean`: True if the element is input and holds a number. + <a name="isTextField" href="#isTextField">#</a> **isTextField** Check whether the given element is a text field, where text field is defined diff --git a/packages/dom/package.json b/packages/dom/package.json index e0199899bb23a3..5db51b7bb8fa62 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -23,7 +23,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15" }, "publishConfig": { diff --git a/packages/dom/src/dom.js b/packages/dom/src/dom.js index c1ae1fbc17395d..8271abe1efcd9f 100644 --- a/packages/dom/src/dom.js +++ b/packages/dom/src/dom.js @@ -469,6 +469,20 @@ export function isTextField( element ) { } } +/** + * Check whether the given element is an input field of type number + * and has a valueAsNumber + * + * @param {HTMLElement} element The HTML element. + * + * @return {boolean} True if the element is input and holds a number. + */ +export function isNumberInput( element ) { + const { nodeName, type, valueAsNumber } = element; + + return nodeName === 'INPUT' && type === 'number' && !! valueAsNumber; +} + /** * Check wether the current document has a selection. * This checks both for focus in an input field and general text selection. @@ -480,6 +494,10 @@ export function documentHasSelection() { return true; } + if ( isNumberInput( document.activeElement ) ) { + return true; + } + const selection = window.getSelection(); const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null; diff --git a/packages/dom/src/test/dom.js b/packages/dom/src/test/dom.js index a2352d75efbd8a..eabb2ed968bd1a 100644 --- a/packages/dom/src/test/dom.js +++ b/packages/dom/src/test/dom.js @@ -6,6 +6,7 @@ import { placeCaretAtHorizontalEdge, isTextField, __unstableStripHTML as stripHTML, + isNumberInput, } from '../dom'; describe( 'DOM', () => { @@ -143,6 +144,21 @@ describe( 'DOM', () => { ); } ); + it( 'should return false for empty input element of type number', () => { + const input = document.createElement( 'input' ); + input.type = 'number'; + + expect( isNumberInput( input ) ).toBe( false ); + } ); + + it( 'should return true for an input element of type number', () => { + const input = document.createElement( 'input' ); + input.type = 'number'; + input.valueAsNumber = 23; + + expect( isNumberInput( input ) ).toBe( true ); + } ); + it( 'should return true for a contenteditable element', () => { const div = document.createElement( 'div' ); diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index f995fb1336bcf4..208af790e2e0b1 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -1,3 +1,13 @@ +## Master + +### Enhancements + +- `visitAdminPage` will now throw an error (emit a test failure) when there are unexpected errors on hte page. + +### New Features + +- Added `getPageError` function, returning a promise which resolves to an error message present in the page, if any exists. + ## 4.0.0 (2019-12-19) ### Breaking Changes diff --git a/packages/e2e-test-utils/README.md b/packages/e2e-test-utils/README.md index d397bce0bf6470..e8af181a034c1b 100644 --- a/packages/e2e-test-utils/README.md +++ b/packages/e2e-test-utils/README.md @@ -252,6 +252,21 @@ _Returns_ - `Promise`: Promise resolving with post content markup. +<a name="getPageError" href="#getPageError">#</a> **getPageError** + +Returns a promise resolving to one of either a string or null. A string will +be resolved if an error message is present in the contents of the page. If no +error is present, a null value will be resolved instead. This requires the +environment be configured to display errors. + +_Related_ + +- <http://php.net/manual/en/function.error-reporting.php> + +_Returns_ + +- `Promise<?string>`: Promise resolving to a string or null, depending whether a page error is present. + <a name="hasBlockSwitcher" href="#hasBlockSwitcher">#</a> **hasBlockSwitcher** Returns a boolean indicating if the current selected block has a block switcher or not. diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 284c3be0a91eba..8775a4b37050c6 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -28,7 +28,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/keycodes": "file:../keycodes", "@wordpress/url": "file:../url", "lodash": "^4.17.15", diff --git a/packages/e2e-test-utils/src/get-page-error.js b/packages/e2e-test-utils/src/get-page-error.js new file mode 100644 index 00000000000000..0182119ce7e38e --- /dev/null +++ b/packages/e2e-test-utils/src/get-page-error.js @@ -0,0 +1,25 @@ +/** + * Regular expression matching a displayed PHP error within a markup string. + * + * @see https://github.com/php/php-src/blob/598175e/main/main.c#L1257-L1297 + * + * @type {RegExp} + */ +const REGEXP_PHP_ERROR = /(<b>)?(Fatal error|Recoverable fatal error|Warning|Parse error|Notice|Strict Standards|Deprecated|Unknown error)(<\/b>)?: (.*?) in (.*?) on line (<b>)?\d+(<\/b>)?/; + +/** + * Returns a promise resolving to one of either a string or null. A string will + * be resolved if an error message is present in the contents of the page. If no + * error is present, a null value will be resolved instead. This requires the + * environment be configured to display errors. + * + * @see http://php.net/manual/en/function.error-reporting.php + * + * @return {Promise<?string>} Promise resolving to a string or null, depending + * whether a page error is present. + */ +export async function getPageError() { + const content = await page.content(); + const match = content.match( REGEXP_PHP_ERROR ); + return match ? match[ 0 ] : null; +} diff --git a/packages/e2e-test-utils/src/index.js b/packages/e2e-test-utils/src/index.js index 136496058223b4..d71cacc1cd70c6 100644 --- a/packages/e2e-test-utils/src/index.js +++ b/packages/e2e-test-utils/src/index.js @@ -22,6 +22,7 @@ export { getAvailableBlockTransforms } from './get-available-block-transforms'; export { getBlockSetting } from './get-block-setting'; export { getEditedPostContent } from './get-edited-post-content'; export { hasBlockSwitcher } from './has-block-switcher'; +export { getPageError } from './get-page-error'; export { insertBlock } from './insert-block'; export { installPlugin } from './install-plugin'; export { isCurrentURL } from './is-current-url'; diff --git a/packages/e2e-test-utils/src/test/get-page-error.js b/packages/e2e-test-utils/src/test/get-page-error.js new file mode 100644 index 00000000000000..ef8c113372f35c --- /dev/null +++ b/packages/e2e-test-utils/src/test/get-page-error.js @@ -0,0 +1,44 @@ +/** + * Internal dependencies + */ +import { getPageError } from '../get-page-error'; + +describe( 'getPageError', () => { + let originalPage; + + beforeEach( () => { + originalPage = global.page; + } ); + + afterEach( () => { + global.page = originalPage; + } ); + + it( 'resolves to null if there is no error', async () => { + global.page = { + content: () => 'Happy!', + }; + + expect( await getPageError() ).toBe( null ); + } ); + + it.each( [ + [ + 'PHP, HTML', + '<b>Notice</b>: Undefined property: WP_Block_Type_Registry::$x in <b>/var/www/html/wp-content/plugins/gutenberg/lib/blocks.php</b> on line <b>47</b>', + ], + [ + 'PHP, Plaintext', + 'Notice: Undefined property: WP_Block_Type_Registry::$x in /var/www/html/wp-content/plugins/gutenberg/lib/blocks.php on line 47', + ], + ] )( + 'resolves to the error message if there is an error (%s)', + async ( _variant, error ) => { + global.page = { + content: () => error, + }; + + expect( await getPageError() ).toBe( error ); + } + ); +} ); diff --git a/packages/e2e-test-utils/src/visit-admin-page.js b/packages/e2e-test-utils/src/visit-admin-page.js index ac74c4ce688182..8f4a6c7260d34a 100644 --- a/packages/e2e-test-utils/src/visit-admin-page.js +++ b/packages/e2e-test-utils/src/visit-admin-page.js @@ -9,6 +9,7 @@ import { join } from 'path'; import { createURL } from './create-url'; import { isCurrentURL } from './is-current-url'; import { loginUser } from './login-user'; +import { getPageError } from './get-page-error'; /** * Visits admin page; if user is not logged in then it logging in it first, then visits admin page. @@ -23,4 +24,9 @@ export async function visitAdminPage( adminPath, query ) { await loginUser(); await visitAdminPage( adminPath, query ); } + + const error = await getPageError(); + if ( error ) { + throw new Error( 'Unexpected error in page content: ' + error ); + } } diff --git a/packages/e2e-tests/config/performance-reporter.js b/packages/e2e-tests/config/performance-reporter.js index 03bb99795f848b..32ea362973ed1f 100644 --- a/packages/e2e-tests/config/performance-reporter.js +++ b/packages/e2e-tests/config/performance-reporter.js @@ -1,4 +1,5 @@ const { readFileSync, existsSync } = require( 'fs' ); +const chalk = require( 'chalk' ); function average( array ) { return array.reduce( ( a, b ) => a + b ) / array.length; @@ -9,6 +10,9 @@ function round( number, decimalPlaces = 2 ) { return Math.round( number * factor ) / factor; } +const title = chalk.bold; +const success = chalk.bold.green; + class PerformanceReporter { onRunComplete() { const path = __dirname + '/../specs/performance/results.json'; @@ -18,16 +22,46 @@ class PerformanceReporter { } const results = readFileSync( path, 'utf8' ); - const { load, domcontentloaded, type } = JSON.parse( results ); + const { load, domcontentloaded, type, focus } = JSON.parse( results ); + + if ( load && load.length ) { + // eslint-disable-next-line no-console + console.log( ` +${ title( 'Loading Time:' ) } +Average time to load: ${ success( round( average( load ) ) + 'ms' ) } +Average time to DOM content load: ${ success( + round( average( domcontentloaded ) ) + 'ms' + ) }` ); + } + + if ( type && type.length ) { + // eslint-disable-next-line no-console + console.log( ` +${ title( 'Typing Performance:' ) } +Average time to type character: ${ success( round( average( type ) ) + 'ms' ) } +Slowest time to type character: ${ success( + round( Math.max( ...type ) ) + 'ms' + ) } +Fastest time to type character: ${ success( + round( Math.min( ...type ) ) + 'ms' + ) }` ); + } + + if ( focus && focus.length ) { + // eslint-disable-next-line no-console + console.log( ` +${ title( 'Block Selection Performance:' ) } +Average time to select a block: ${ success( round( average( focus ) ) + 'ms' ) } +Slowest time to select a block: ${ success( + round( Math.max( ...focus ) ) + 'ms' + ) } +Fastest time to select a block: ${ success( + round( Math.min( ...focus ) ) + 'ms' + ) }` ); + } // eslint-disable-next-line no-console - console.log( ` -Average time to load: ${ round( average( load ) ) }ms -Average time to DOM content load: ${ round( average( domcontentloaded ) ) }ms -Average time to type character: ${ round( average( type ) ) }ms -Slowest time to type character: ${ round( Math.max( ...type ) ) }ms -Fastest time to type character: ${ round( Math.min( ...type ) ) }ms - ` ); + console.log( '' ); } } diff --git a/packages/e2e-tests/fixtures/blocks/core__button__center.serialized.html b/packages/e2e-tests/fixtures/blocks/core__button__center.serialized.html deleted file mode 100644 index 3d88c7ec1a551a..00000000000000 --- a/packages/e2e-tests/fixtures/blocks/core__button__center.serialized.html +++ /dev/null @@ -1,3 +0,0 @@ -<!-- wp:button {"align":"center"} --> -<div class="wp-block-button aligncenter"><a class="wp-block-button__link" href="https://github.com/WordPress/gutenberg">Help build Gutenberg</a></div> -<!-- /wp:button --> diff --git a/packages/e2e-tests/fixtures/blocks/core__button__center.html b/packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.html similarity index 100% rename from packages/e2e-tests/fixtures/blocks/core__button__center.html rename to packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.html diff --git a/packages/e2e-tests/fixtures/blocks/core__button__center.json b/packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.json similarity index 100% rename from packages/e2e-tests/fixtures/blocks/core__button__center.json rename to packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.json diff --git a/packages/e2e-tests/fixtures/blocks/core__button__center.parsed.json b/packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.parsed.json similarity index 100% rename from packages/e2e-tests/fixtures/blocks/core__button__center.parsed.json rename to packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.parsed.json diff --git a/packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.serialized.html b/packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.serialized.html new file mode 100644 index 00000000000000..5fee004c30ddd6 --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__button__center__deprecated.serialized.html @@ -0,0 +1,3 @@ +<!-- wp:button {"align":"center"} --> +<a class="wp-block-button aligncenter wp-block-button__link" href="https://github.com/WordPress/gutenberg">Help build Gutenberg</a> +<!-- /wp:button --> diff --git a/packages/e2e-tests/fixtures/blocks/core__button__squared.html b/packages/e2e-tests/fixtures/blocks/core__button__squared.html index ddf0e54bc46cd3..d7a2b6f5f95908 100644 --- a/packages/e2e-tests/fixtures/blocks/core__button__squared.html +++ b/packages/e2e-tests/fixtures/blocks/core__button__squared.html @@ -1,3 +1,3 @@ -<!-- wp:button {"customBackgroundColor":"#aa5a20","customTextColor":"#1b9b6c","className":"is-style-squared"} --> -<div class="wp-block-button is-style-squared"><a class="wp-block-button__link has-text-color has-background" style="background-color:#aa5a20;color:#1b9b6c">My button</a></div> +<!-- wp:button {"borderRadius":0,"align":"none","style":{"color":{"text":"#1b9b6c","background":"#aa5a20"}}} --> +<a class="wp-block-button wp-block-button__link no-border-radius has-text-color has-background" style="background-color:#aa5a20;color:#1b9b6c">My button</a> <!-- /wp:button --> diff --git a/packages/e2e-tests/fixtures/blocks/core__button__squared.json b/packages/e2e-tests/fixtures/blocks/core__button__squared.json index aa0b51793a6465..f3aa8241d516f0 100644 --- a/packages/e2e-tests/fixtures/blocks/core__button__squared.json +++ b/packages/e2e-tests/fixtures/blocks/core__button__squared.json @@ -5,12 +5,16 @@ "isValid": true, "attributes": { "text": "My button", - "align": "none", - "customBackgroundColor": "#aa5a20", - "customTextColor": "#1b9b6c", + "align": "none", + "style": { + "color": { + "background": "#aa5a20", + "text": "#1b9b6c" + } + }, "borderRadius": 0 }, "innerBlocks": [], - "originalContent": "<div class=\"wp-block-button is-style-squared\"><a class=\"wp-block-button__link has-text-color has-background\" style=\"background-color:#aa5a20;color:#1b9b6c\">My button</a></div>" + "originalContent": "<a class=\"wp-block-button wp-block-button__link no-border-radius has-text-color has-background\" style=\"background-color:#aa5a20;color:#1b9b6c\">My button</a>" } ] diff --git a/packages/e2e-tests/fixtures/blocks/core__button__squared.parsed.json b/packages/e2e-tests/fixtures/blocks/core__button__squared.parsed.json index 61facd925b7497..dc1ea8f2ca3470 100644 --- a/packages/e2e-tests/fixtures/blocks/core__button__squared.parsed.json +++ b/packages/e2e-tests/fixtures/blocks/core__button__squared.parsed.json @@ -2,14 +2,19 @@ { "blockName": "core/button", "attrs": { - "customBackgroundColor": "#aa5a20", - "customTextColor": "#1b9b6c", - "className": "is-style-squared" + "align": "none", + "borderRadius": 0, + "style": { + "color": { + "background": "#aa5a20", + "text": "#1b9b6c" + } + } }, "innerBlocks": [], - "innerHTML": "\n<div class=\"wp-block-button is-style-squared\"><a class=\"wp-block-button__link has-text-color has-background\" style=\"background-color:#aa5a20;color:#1b9b6c\">My button</a></div>\n", + "innerHTML": "\n<a class=\"wp-block-button wp-block-button__link no-border-radius has-text-color has-background\" style=\"background-color:#aa5a20;color:#1b9b6c\">My button</a>\n", "innerContent": [ - "\n<div class=\"wp-block-button is-style-squared\"><a class=\"wp-block-button__link has-text-color has-background\" style=\"background-color:#aa5a20;color:#1b9b6c\">My button</a></div>\n" + "\n<a class=\"wp-block-button wp-block-button__link no-border-radius has-text-color has-background\" style=\"background-color:#aa5a20;color:#1b9b6c\">My button</a>\n" ] }, { diff --git a/packages/e2e-tests/fixtures/blocks/core__button__squared.serialized.html b/packages/e2e-tests/fixtures/blocks/core__button__squared.serialized.html index 3d492c6ee0fe81..d7a2b6f5f95908 100644 --- a/packages/e2e-tests/fixtures/blocks/core__button__squared.serialized.html +++ b/packages/e2e-tests/fixtures/blocks/core__button__squared.serialized.html @@ -1,3 +1,3 @@ -<!-- wp:button {"customBackgroundColor":"#aa5a20","customTextColor":"#1b9b6c","borderRadius":0,"align":"none"} --> -<div class="wp-block-button"><a class="wp-block-button__link has-text-color has-background no-border-radius" style="background-color:#aa5a20;color:#1b9b6c">My button</a></div> +<!-- wp:button {"borderRadius":0,"align":"none","style":{"color":{"text":"#1b9b6c","background":"#aa5a20"}}} --> +<a class="wp-block-button wp-block-button__link no-border-radius has-text-color has-background" style="background-color:#aa5a20;color:#1b9b6c">My button</a> <!-- /wp:button --> diff --git a/packages/e2e-tests/fixtures/blocks/core__buttons.html b/packages/e2e-tests/fixtures/blocks/core__buttons.html index e70af7acc72ad4..02f5487560cee4 100644 --- a/packages/e2e-tests/fixtures/blocks/core__buttons.html +++ b/packages/e2e-tests/fixtures/blocks/core__buttons.html @@ -1,11 +1,11 @@ <!-- wp:buttons --> <div class="wp-block-buttons"> <!-- wp:button --> - <div class="wp-block-button"><a class="wp-block-button__link">My button 1</a></div> + <a class="wp-block-button wp-block-button__link">My button 1</a> <!-- /wp:button --> <!-- wp:button --> - <div class="wp-block-button"><a class="wp-block-button__link">My button 2</a></div> + <a class="wp-block-button wp-block-button__link">My button 2</a> <!-- /wp:button --> </div> <!-- /wp:buttons --> diff --git a/packages/e2e-tests/fixtures/blocks/core__buttons.json b/packages/e2e-tests/fixtures/blocks/core__buttons.json index 044daeb82101ac..d77d9752de37b0 100644 --- a/packages/e2e-tests/fixtures/blocks/core__buttons.json +++ b/packages/e2e-tests/fixtures/blocks/core__buttons.json @@ -13,7 +13,7 @@ "text": "My button 1" }, "innerBlocks": [], - "originalContent": "<div class=\"wp-block-button\"><a class=\"wp-block-button__link\">My button 1</a></div>" + "originalContent": "<a class=\"wp-block-button wp-block-button__link\">My button 1</a>" }, { "clientId": "_clientId_1", @@ -23,7 +23,7 @@ "text": "My button 2" }, "innerBlocks": [], - "originalContent": "<div class=\"wp-block-button\"><a class=\"wp-block-button__link\">My button 2</a></div>" + "originalContent": "<a class=\"wp-block-button wp-block-button__link\">My button 2</a>" } ], "originalContent": "<div class=\"wp-block-buttons\">\n\t\n\n\t\n</div>" diff --git a/packages/e2e-tests/fixtures/blocks/core__buttons.parsed.json b/packages/e2e-tests/fixtures/blocks/core__buttons.parsed.json index b96b1f50db1fc9..ee9dd97313a48b 100644 --- a/packages/e2e-tests/fixtures/blocks/core__buttons.parsed.json +++ b/packages/e2e-tests/fixtures/blocks/core__buttons.parsed.json @@ -7,18 +7,18 @@ "blockName": "core/button", "attrs": {}, "innerBlocks": [], - "innerHTML": "\n\t<div class=\"wp-block-button\"><a class=\"wp-block-button__link\">My button 1</a></div>\n\t", + "innerHTML": "\n\t<a class=\"wp-block-button wp-block-button__link\">My button 1</a>\n\t", "innerContent": [ - "\n\t<div class=\"wp-block-button\"><a class=\"wp-block-button__link\">My button 1</a></div>\n\t" + "\n\t<a class=\"wp-block-button wp-block-button__link\">My button 1</a>\n\t" ] }, { "blockName": "core/button", "attrs": {}, "innerBlocks": [], - "innerHTML": "\n\t<div class=\"wp-block-button\"><a class=\"wp-block-button__link\">My button 2</a></div>\n\t", + "innerHTML": "\n\t<a class=\"wp-block-button wp-block-button__link\">My button 2</a>\n\t", "innerContent": [ - "\n\t<div class=\"wp-block-button\"><a class=\"wp-block-button__link\">My button 2</a></div>\n\t" + "\n\t<a class=\"wp-block-button wp-block-button__link\">My button 2</a>\n\t" ] } ], diff --git a/packages/e2e-tests/fixtures/blocks/core__buttons.serialized.html b/packages/e2e-tests/fixtures/blocks/core__buttons.serialized.html index baf0a0226c066c..18eb4b31eda593 100644 --- a/packages/e2e-tests/fixtures/blocks/core__buttons.serialized.html +++ b/packages/e2e-tests/fixtures/blocks/core__buttons.serialized.html @@ -1,9 +1,9 @@ <!-- wp:buttons --> <div class="wp-block-buttons"><!-- wp:button --> -<div class="wp-block-button"><a class="wp-block-button__link">My button 1</a></div> +<a class="wp-block-button wp-block-button__link">My button 1</a> <!-- /wp:button --> <!-- wp:button --> -<div class="wp-block-button"><a class="wp-block-button__link">My button 2</a></div> +<a class="wp-block-button wp-block-button__link">My button 2</a> <!-- /wp:button --></div> <!-- /wp:buttons --> diff --git a/packages/e2e-tests/fixtures/blocks/core__columns.serialized.html b/packages/e2e-tests/fixtures/blocks/core__columns.serialized.html index 664beb08154a7f..2b95373d1a7b83 100644 --- a/packages/e2e-tests/fixtures/blocks/core__columns.serialized.html +++ b/packages/e2e-tests/fixtures/blocks/core__columns.serialized.html @@ -1,5 +1,5 @@ <!-- wp:columns {"backgroundColor":"secondary"} --> -<div class="wp-block-columns has-background has-secondary-background-color"><!-- wp:column --> +<div class="wp-block-columns has-secondary-background-color has-background"><!-- wp:column --> <div class="wp-block-column"><!-- wp:paragraph --> <p>Column One, Paragraph One</p> <!-- /wp:paragraph --> diff --git a/packages/e2e-tests/fixtures/blocks/core__group.html b/packages/e2e-tests/fixtures/blocks/core__group.html index 09fd95cfc9d5a4..e5df0f2fce926a 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group.html +++ b/packages/e2e-tests/fixtures/blocks/core__group.html @@ -1,4 +1,4 @@ -<!-- wp:group {"backgroundColor":"secondary","align":"full"} --> +<!-- wp:group {"align":"full","backgroundColor":"secondary"} --> <div class="wp-block-group alignfull has-secondary-background-color has-background"> <div class="wp-block-group__inner-container"> <!-- wp:paragraph --> diff --git a/packages/e2e-tests/fixtures/blocks/core__group.json b/packages/e2e-tests/fixtures/blocks/core__group.json index 71d94f926dcccf..526a8d70fbcdfa 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group.json +++ b/packages/e2e-tests/fixtures/blocks/core__group.json @@ -4,8 +4,9 @@ "name": "core/group", "isValid": true, "attributes": { - "backgroundColor": "secondary", - "align": "full" + "tagName": "div", + "align": "full", + "backgroundColor": "secondary" }, "innerBlocks": [ { diff --git a/packages/e2e-tests/fixtures/blocks/core__group.parsed.json b/packages/e2e-tests/fixtures/blocks/core__group.parsed.json index bf2b50feb5fd1f..ba86ac5a02d6bd 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group.parsed.json +++ b/packages/e2e-tests/fixtures/blocks/core__group.parsed.json @@ -2,8 +2,8 @@ { "blockName": "core/group", "attrs": { - "backgroundColor": "secondary", - "align": "full" + "align": "full", + "backgroundColor": "secondary" }, "innerBlocks": [ { diff --git a/packages/e2e-tests/fixtures/blocks/core__group.serialized.html b/packages/e2e-tests/fixtures/blocks/core__group.serialized.html index 2c398b530dedc5..8ac236255f9f61 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group.serialized.html +++ b/packages/e2e-tests/fixtures/blocks/core__group.serialized.html @@ -1,4 +1,4 @@ -<!-- wp:group {"backgroundColor":"secondary","align":"full"} --> +<!-- wp:group {"align":"full","backgroundColor":"secondary"} --> <div class="wp-block-group alignfull has-secondary-background-color has-background"><div class="wp-block-group__inner-container"><!-- wp:paragraph --> <p>This is a group block.</p> <!-- /wp:paragraph --> diff --git a/packages/e2e-tests/fixtures/blocks/core__group__deprecated-2.json b/packages/e2e-tests/fixtures/blocks/core__group__deprecated-2.json index 38addc059eec30..7bfd9dafac7069 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group__deprecated-2.json +++ b/packages/e2e-tests/fixtures/blocks/core__group__deprecated-2.json @@ -4,7 +4,8 @@ "name": "core/group", "isValid": true, "attributes": { - "textColor": "accent" + "textColor": "accent", + "tagName": "div" }, "innerBlocks": [ { diff --git a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.html b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.html index bd111993515f16..9b71121607e437 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.html +++ b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.html @@ -1,4 +1,4 @@ -<!-- wp:group {"backgroundColor":"lighter-blue","align":"full"} --> +<!-- wp:group {"align":"full","backgroundColor":"lighter-blue"} --> <div class="wp-block-group alignfull has-lighter-blue-background-color has-background" id="test-id"> <!-- wp:paragraph --> <p>test</p> diff --git a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.json b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.json index c86392f55adb97..7f1f51c3644e40 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.json +++ b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.json @@ -6,7 +6,8 @@ "attributes": { "backgroundColor": "lighter-blue", "align": "full", - "anchor": "test-id" + "anchor": "test-id", + "tagName": "div" }, "innerBlocks": [ { diff --git a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.parsed.json b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.parsed.json index 20116913b718f1..09778708d0b9e3 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.parsed.json +++ b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.parsed.json @@ -2,8 +2,8 @@ { "blockName": "core/group", "attrs": { - "backgroundColor": "lighter-blue", - "align": "full" + "align": "full", + "backgroundColor": "lighter-blue" }, "innerBlocks": [ { diff --git a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.serialized.html b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.serialized.html index 891c48e13ef040..b9f1dc3ba37e12 100644 --- a/packages/e2e-tests/fixtures/blocks/core__group__deprecated.serialized.html +++ b/packages/e2e-tests/fixtures/blocks/core__group__deprecated.serialized.html @@ -1,4 +1,4 @@ -<!-- wp:group {"backgroundColor":"lighter-blue","align":"full"} --> +<!-- wp:group {"align":"full","backgroundColor":"lighter-blue"} --> <div class="wp-block-group alignfull has-lighter-blue-background-color has-background" id="test-id"><div class="wp-block-group__inner-container"><!-- wp:paragraph --> <p>test</p> <!-- /wp:paragraph --></div></div> diff --git a/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.json b/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.json index ba5b3079e888c4..d4d93c52448969 100644 --- a/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.json +++ b/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.json @@ -6,7 +6,11 @@ "attributes": { "content": "Text", "level": 2, - "customTextColor": "#268ebb" + "style": { + "color": { + "text": "#268ebb" + } + } }, "innerBlocks": [], "originalContent": "<h2 style=\"color:#268ebb\">Text</h2>" diff --git a/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.serialized.html b/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.serialized.html index 7efa248386cefd..c2c4470e500f1e 100644 --- a/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.serialized.html +++ b/packages/e2e-tests/fixtures/blocks/core__heading__deprecated-3.serialized.html @@ -1,3 +1,3 @@ -<!-- wp:heading {"customTextColor":"#268ebb"} --> +<!-- wp:heading {"style":{"color":{"text":"#268ebb"}}} --> <h2 class="has-text-color" style="color:#268ebb">Text</h2> <!-- /wp:heading --> diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 02c52eeedf4f92..666fa6355231a4 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -27,9 +27,10 @@ "@wordpress/jest-puppeteer-axe": "file:../jest-puppeteer-axe", "@wordpress/scripts": "file:../scripts", "@wordpress/url": "file:../url", - "expect-puppeteer": "^4.3.0", + "chalk": "^4.0.0", + "expect-puppeteer": "^4.4.0", "lodash": "^4.17.15", - "uuid": "^3.3.2" + "uuid": "^7.0.2" }, "peerDependencies": { "jest": ">=24", diff --git a/packages/e2e-tests/plugins/inner-blocks-allowed-blocks/index.js b/packages/e2e-tests/plugins/inner-blocks-allowed-blocks/index.js index f6f61c27d5c82c..f85721b0d15e78 100644 --- a/packages/e2e-tests/plugins/inner-blocks-allowed-blocks/index.js +++ b/packages/e2e-tests/plugins/inner-blocks-allowed-blocks/index.js @@ -4,19 +4,20 @@ const { createElement: el } = wp.element; const { InnerBlocks } = wp.blockEditor; const __ = wp.i18n.__; - const divProps = { className: 'product', style: { outline: '1px solid gray', padding: 5 } }; + const divProps = { + className: 'product', + style: { outline: '1px solid gray', padding: 5 }, + }; const template = [ [ 'core/image' ], [ 'core/paragraph', { placeholder: __( 'Add a description' ) } ], - [ 'core/quote' ] + [ 'core/quote' ], ]; const allowedBlocksWhenSingleEmptyChild = [ 'core/image', 'core/list' ]; const allowedBlocksWhenMultipleChildren = [ 'core/gallery', 'core/video' ]; const save = function() { - return el( 'div', divProps, - el( InnerBlocks.Content ) - ); + return el( 'div', divProps, el( InnerBlocks.Content ) ); }; registerBlockType( 'test/allowed-blocks-unset', { title: 'Allowed Blocks Unset', @@ -24,9 +25,7 @@ category: 'common', edit() { - return el( 'div', divProps, - el( InnerBlocks, { template } ) - ); + return el( 'div', divProps, el( InnerBlocks, { template } ) ); }, save, @@ -38,20 +37,19 @@ category: 'common', edit() { - return el( 'div', divProps, - el( - InnerBlocks, - { - template, - allowedBlocks: [ - 'core/button', - 'core/gallery', - 'core/list', - 'core/media-text', - 'core/quote', - ], - } - ) + return el( + 'div', + divProps, + el( InnerBlocks, { + template, + allowedBlocks: [ + 'core/button', + 'core/gallery', + 'core/list', + 'core/media-text', + 'core/quote', + ], + } ) ); }, @@ -69,19 +67,21 @@ numberOfChildren: getBlockOrder( ownProps.clientId ).length, }; } )( function( props ) { - return el( 'div', divProps, - el( - InnerBlocks, - { - allowedBlocks: props.numberOfChildren < 2 ? - allowedBlocksWhenSingleEmptyChild : - allowedBlocksWhenMultipleChildren, - } - ) + return el( + 'div', + { + ...divProps, + 'data-number-of-children': props.numberOfChildren, + }, + el( InnerBlocks, { + allowedBlocks: + props.numberOfChildren < 2 + ? allowedBlocksWhenSingleEmptyChild + : allowedBlocksWhenMultipleChildren, + } ) ); } ), save, } ); - } )(); diff --git a/packages/e2e-tests/specs/editor/blocks/__snapshots__/buttons.test.js.snap b/packages/e2e-tests/specs/editor/blocks/__snapshots__/buttons.test.js.snap index 66f803ddcf139f..08a92e1fd8820f 100644 --- a/packages/e2e-tests/specs/editor/blocks/__snapshots__/buttons.test.js.snap +++ b/packages/e2e-tests/specs/editor/blocks/__snapshots__/buttons.test.js.snap @@ -3,7 +3,7 @@ exports[`Buttons can jump to the link editor using the keyboard shortcut 1`] = ` "<!-- wp:buttons --> <div class=\\"wp-block-buttons\\"><!-- wp:button --> -<div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\" href=\\"https://www.wordpress.org/\\">WordPress</a></div> +<a class=\\"wp-block-button wp-block-button__link\\" href=\\"https://www.wordpress.org/\\">WordPress</a> <!-- /wp:button --></div> <!-- /wp:buttons -->" `; @@ -11,7 +11,7 @@ exports[`Buttons can jump to the link editor using the keyboard shortcut 1`] = ` exports[`Buttons dismisses link editor when escape is pressed 1`] = ` "<!-- wp:buttons --> <div class=\\"wp-block-buttons\\"><!-- wp:button --> -<div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\">WordPress</a></div> +<a class=\\"wp-block-button wp-block-button__link\\">WordPress</a> <!-- /wp:button --></div> <!-- /wp:buttons -->" `; @@ -19,7 +19,7 @@ exports[`Buttons dismisses link editor when escape is pressed 1`] = ` exports[`Buttons has focus on button content 1`] = ` "<!-- wp:buttons --> <div class=\\"wp-block-buttons\\"><!-- wp:button --> -<div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\">Content</a></div> +<a class=\\"wp-block-button wp-block-button__link\\">Content</a> <!-- /wp:button --></div> <!-- /wp:buttons -->" `; diff --git a/packages/e2e-tests/specs/editor/blocks/__snapshots__/heading.test.js.snap b/packages/e2e-tests/specs/editor/blocks/__snapshots__/heading.test.js.snap index d36b3e658b5f84..c8edb2f56cf352 100644 --- a/packages/e2e-tests/specs/editor/blocks/__snapshots__/heading.test.js.snap +++ b/packages/e2e-tests/specs/editor/blocks/__snapshots__/heading.test.js.snap @@ -13,7 +13,7 @@ exports[`Heading can be created by prefixing number sign and a space 1`] = ` `; exports[`Heading it should correctly apply custom colors 1`] = ` -"<!-- wp:heading {\\"level\\":3,\\"customTextColor\\":\\"#7700ff\\"} --> +"<!-- wp:heading {\\"level\\":3,\\"style\\":{\\"color\\":{\\"text\\":\\"#7700ff\\"}}} --> <h3 class=\\"has-text-color\\" style=\\"color:#7700ff\\">Heading</h3> <!-- /wp:heading -->" `; diff --git a/packages/e2e-tests/specs/editor/blocks/classic.test.js b/packages/e2e-tests/specs/editor/blocks/classic.test.js index b8295c64d53df1..2e2f1274878166 100644 --- a/packages/e2e-tests/specs/editor/blocks/classic.test.js +++ b/packages/e2e-tests/specs/editor/blocks/classic.test.js @@ -4,7 +4,7 @@ import path from 'path'; import fs from 'fs'; import os from 'os'; -import uuid from 'uuid/v4'; +import { v4 as uuid } from 'uuid'; /** * WordPress dependencies diff --git a/packages/e2e-tests/specs/editor/blocks/image.test.js b/packages/e2e-tests/specs/editor/blocks/image.test.js index 51c4987857898f..1f81dc89df39d7 100644 --- a/packages/e2e-tests/specs/editor/blocks/image.test.js +++ b/packages/e2e-tests/specs/editor/blocks/image.test.js @@ -4,7 +4,7 @@ import path from 'path'; import fs from 'fs'; import os from 'os'; -import uuid from 'uuid/v4'; +import { v4 as uuid } from 'uuid'; /** * WordPress dependencies @@ -31,7 +31,9 @@ async function upload( selector ) { const tmpFileName = path.join( os.tmpdir(), filename + '.png' ); fs.copyFileSync( testImagePath, tmpFileName ); await inputElement.uploadFile( tmpFileName ); - await page.waitForSelector( '.wp-block-image img[src^="http"]' ); + await page.waitForSelector( + `.wp-block-image img[src$="${ filename }.png"]` + ); return filename; } diff --git a/packages/e2e-tests/specs/editor/plugins/__snapshots__/plugins-api.test.js.snap b/packages/e2e-tests/specs/editor/plugins/__snapshots__/plugins-api.test.js.snap index 8d2ca2c2bd9a78..db4a3f806de5b8 100644 --- a/packages/e2e-tests/specs/editor/plugins/__snapshots__/plugins-api.test.js.snap +++ b/packages/e2e-tests/specs/editor/plugins/__snapshots__/plugins-api.test.js.snap @@ -2,6 +2,6 @@ exports[`Using Plugins API Document Setting Custom Panel Should render a custom panel inside Document Setting sidebar 1`] = `"My Custom Panel"`; -exports[`Using Plugins API Sidebar Medium screen Should open plugins sidebar using More Menu item and render content 1`] = `"<div class=\\"components-panel__header edit-post-sidebar-header__small\\"><span class=\\"edit-post-sidebar-header__title\\">(no title)</span><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel__header edit-post-sidebar-header\\" tabindex=\\"-1\\"><strong>Sidebar title plugin</strong><button type=\\"button\\" aria-pressed=\\"true\\" aria-expanded=\\"true\\" class=\\"components-button is-pressed has-icon\\" aria-label=\\"Unpin from toolbar\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2 -2 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M10 1l3 6 6 .75-4.12 4.62L16 19l-6-3-6 3 1.13-6.63L1 7.75 7 7z\\"></path></svg></button><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel\\"><div class=\\"components-panel__body is-opened\\"><div class=\\"components-panel__row\\"><label for=\\"title-plain-text\\">Title:</label><textarea class=\\"block-editor-plain-text\\" id=\\"title-plain-text\\" placeholder=\\"(no title)\\" rows=\\"1\\" style=\\"overflow: hidden; overflow-wrap: break-word; resize: none; height: 18px;\\"></textarea></div><div class=\\"components-panel__row\\"><button type=\\"button\\" class=\\"components-button is-primary\\">Reset</button></div></div></div>"`; +exports[`Using Plugins API Sidebar Medium screen Should open plugins sidebar using More Menu item and render content 1`] = `"<div class=\\"components-panel__header interface-complementary-area-header__small\\"><span class=\\"interface-complementary-area-header__small-title\\">(no title)</span><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel__header interface-complementary-area-header\\" tabindex=\\"-1\\"><strong>Sidebar title plugin</strong><button type=\\"button\\" aria-pressed=\\"false\\" aria-expanded=\\"false\\" class=\\"components-button interface-complementary-area__pin-unpin-item has-icon\\" aria-label=\\"Pin to toolbar\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2 -2 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M10 1L7 7l-6 .75 4.13 4.62L4 19l6-3 6 3-1.12-6.63L19 7.75 13 7zm0 2.24l2.34 4.69 4.65.58-3.18 3.56.87 5.15L10 14.88l-4.68 2.34.87-5.15-3.18-3.56 4.65-.58z\\"></path></svg></button><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel\\"><div class=\\"components-panel__body is-opened\\"><div class=\\"components-panel__row\\"><label for=\\"title-plain-text\\">Title:</label><textarea class=\\"block-editor-plain-text\\" id=\\"title-plain-text\\" placeholder=\\"(no title)\\" rows=\\"1\\" style=\\"overflow: hidden; overflow-wrap: break-word; resize: none; height: 18px;\\"></textarea></div><div class=\\"components-panel__row\\"><button type=\\"button\\" class=\\"components-button is-primary\\">Reset</button></div></div></div>"`; -exports[`Using Plugins API Sidebar Should open plugins sidebar using More Menu item and render content 1`] = `"<div class=\\"components-panel__header edit-post-sidebar-header__small\\"><span class=\\"edit-post-sidebar-header__title\\">(no title)</span><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel__header edit-post-sidebar-header\\" tabindex=\\"-1\\"><strong>Sidebar title plugin</strong><button type=\\"button\\" aria-pressed=\\"true\\" aria-expanded=\\"true\\" class=\\"components-button is-pressed has-icon\\" aria-label=\\"Unpin from toolbar\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2 -2 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M10 1l3 6 6 .75-4.12 4.62L16 19l-6-3-6 3 1.13-6.63L1 7.75 7 7z\\"></path></svg></button><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel\\"><div class=\\"components-panel__body is-opened\\"><div class=\\"components-panel__row\\"><label for=\\"title-plain-text\\">Title:</label><textarea class=\\"block-editor-plain-text\\" id=\\"title-plain-text\\" placeholder=\\"(no title)\\" rows=\\"1\\" style=\\"overflow: hidden; overflow-wrap: break-word; resize: none; height: 18px;\\"></textarea></div><div class=\\"components-panel__row\\"><button type=\\"button\\" class=\\"components-button is-primary\\">Reset</button></div></div></div>"`; +exports[`Using Plugins API Sidebar Should open plugins sidebar using More Menu item and render content 1`] = `"<div class=\\"components-panel__header interface-complementary-area-header__small\\"><span class=\\"interface-complementary-area-header__small-title\\">(no title)</span><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel__header interface-complementary-area-header\\" tabindex=\\"-1\\"><strong>Sidebar title plugin</strong><button type=\\"button\\" aria-pressed=\\"false\\" aria-expanded=\\"false\\" class=\\"components-button interface-complementary-area__pin-unpin-item has-icon\\" aria-label=\\"Pin to toolbar\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2 -2 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M10 1L7 7l-6 .75 4.13 4.62L4 19l6-3 6 3-1.12-6.63L19 7.75 13 7zm0 2.24l2.34 4.69 4.65.58-3.18 3.56.87 5.15L10 14.88l-4.68 2.34.87-5.15-3.18-3.56 4.65-.58z\\"></path></svg></button><button type=\\"button\\" class=\\"components-button has-icon\\" aria-label=\\"Close plugin\\"><svg width=\\"24\\" height=\\"24\\" xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z\\"></path></svg></button></div><div class=\\"components-panel\\"><div class=\\"components-panel__body is-opened\\"><div class=\\"components-panel__row\\"><label for=\\"title-plain-text\\">Title:</label><textarea class=\\"block-editor-plain-text\\" id=\\"title-plain-text\\" placeholder=\\"(no title)\\" rows=\\"1\\" style=\\"overflow: hidden; overflow-wrap: break-word; resize: none; height: 18px;\\"></textarea></div><div class=\\"components-panel__row\\"><button type=\\"button\\" class=\\"components-button is-primary\\">Reset</button></div></div></div>"`; diff --git a/packages/e2e-tests/specs/editor/plugins/inner-blocks-allowed-blocks.test.js b/packages/e2e-tests/specs/editor/plugins/inner-blocks-allowed-blocks.test.js index 5d5318b97337c4..ec7396b2dc30fc 100644 --- a/packages/e2e-tests/specs/editor/plugins/inner-blocks-allowed-blocks.test.js +++ b/packages/e2e-tests/specs/editor/plugins/inner-blocks-allowed-blocks.test.js @@ -73,6 +73,7 @@ describe( 'Allowed Blocks Setting on InnerBlocks ', () => { )[ 0 ]; await insertButton.click(); await insertBlock( 'Image' ); + await page.waitForSelector( '.product[data-number-of-children="2"]' ); await page.click( appenderSelector ); await openAllBlockInserterCategories(); expect( await getAllBlockInserterItemTitles() ).toEqual( [ diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap index 4ee1d7710bbe18..14f85661ea22e0 100644 --- a/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap @@ -49,3 +49,15 @@ exports[`Navigating the block hierarchy should navigate using the block hierarch <!-- /wp:column --></div> <!-- /wp:columns -->" `; + +exports[`Navigating the block hierarchy should select the wrapper div for a group 1`] = ` +"<!-- wp:group --> +<div class=\\"wp-block-group\\"><div class=\\"wp-block-group__inner-container\\"><!-- wp:paragraph --> +<p>just a paragraph</p> +<!-- /wp:paragraph --> + +<!-- wp:separator --> +<hr class=\\"wp-block-separator\\"/> +<!-- /wp:separator --></div></div> +<!-- /wp:group -->" +`; diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/duplicating-blocks.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/duplicating-blocks.test.js.snap new file mode 100644 index 00000000000000..bb8192de22cb94 --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/duplicating-blocks.test.js.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Duplicating blocks should duplicate blocks using the block settings menu 1`] = ` +"<!-- wp:paragraph --> +<p>Clone me</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>Clone me</p> +<!-- /wp:paragraph -->" +`; + +exports[`Duplicating blocks should duplicate blocks using the keyboard shortcut 1`] = ` +"<!-- wp:paragraph --> +<p>Clone me</p> +<!-- /wp:paragraph --> + +<!-- wp:paragraph --> +<p>Clone me</p> +<!-- /wp:paragraph -->" +`; diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/font-size-picker.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/font-size-picker.test.js.snap index 90f0c982aeca9e..bc58980c7ce536 100644 --- a/packages/e2e-tests/specs/editor/various/__snapshots__/font-size-picker.test.js.snap +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/font-size-picker.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Font Size Picker should apply a custom font size using the font size input 1`] = ` -"<!-- wp:paragraph {\\"customFontSize\\":23} --> +"<!-- wp:paragraph {\\"style\\":{\\"typography\\":{\\"fontSize\\":23}}} --> <p style=\\"font-size:23px\\">Paragraph to be made \\"small\\"</p> <!-- /wp:paragraph -->" `; diff --git a/packages/e2e-tests/specs/editor/various/adding-blocks.test.js b/packages/e2e-tests/specs/editor/various/adding-blocks.test.js index ed5244c50c189a..11f78fe278ab8a 100644 --- a/packages/e2e-tests/specs/editor/various/adding-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/adding-blocks.test.js @@ -42,7 +42,7 @@ describe( 'adding blocks', () => { // Click below editor to focus last field (block appender) await clickAtBottom( - await page.$( '.block-editor-editor-skeleton__content' ) + await page.$( '.interface-interface-skeleton__content' ) ); expect( await page.$( '[data-type="core/paragraph"]' ) ).not.toBeNull(); await page.keyboard.type( 'Paragraph block' ); diff --git a/packages/e2e-tests/specs/editor/various/adding-inline-tokens.test.js b/packages/e2e-tests/specs/editor/various/adding-inline-tokens.test.js index 0049bdd1d5c3f2..6c1017c6d53589 100644 --- a/packages/e2e-tests/specs/editor/various/adding-inline-tokens.test.js +++ b/packages/e2e-tests/specs/editor/various/adding-inline-tokens.test.js @@ -4,7 +4,7 @@ import path from 'path'; import fs from 'fs'; import os from 'os'; -import uuid from 'uuid/v4'; +import { v4 as uuid } from 'uuid'; /** * WordPress dependencies diff --git a/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js b/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js index 643998905e00e3..5aab0d85e31b91 100644 --- a/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js +++ b/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js @@ -91,7 +91,7 @@ describe( 'Navigating the block hierarchy', () => { await pressKeyWithModifier( 'ctrl', '`' ); await pressKeyWithModifier( 'ctrl', '`' ); await pressKeyWithModifier( 'ctrl', '`' ); - await pressKeyTimes( 'Tab', 4 ); + await pressKeyTimes( 'Tab', 5 ); // Tweak the columns count by increasing it by one. await page.keyboard.press( 'ArrowRight' ); @@ -135,4 +135,42 @@ describe( 'Navigating the block hierarchy', () => { expect( await getEditedPostContent() ).toMatchSnapshot(); } ); + + it( 'should select the wrapper div for a group ', async () => { + // Insert a group block + await insertBlock( 'Group' ); + + // Insert some random blocks. + // The last block shouldn't be a textual block. + await page.click( '.block-list-appender .block-editor-inserter' ); + const paragraphMenuItem = ( + await page.$x( `//button//span[contains(text(), 'Paragraph')]` ) + )[ 0 ]; + await paragraphMenuItem.click(); + await page.keyboard.type( 'just a paragraph' ); + await insertBlock( 'Separator' ); + + // Check the Group block content + expect( await getEditedPostContent() ).toMatchSnapshot(); + + // Unselect the blocks + await page.click( '.editor-post-title' ); + + // Try selecting the group block using the block navigation + await page.click( '[aria-label="Block navigation"]' ); + const groupMenuItem = ( + await page.$x( + "//button[contains(@class,'block-editor-block-navigation__item') and contains(text(), 'Group')]" + ) + )[ 0 ]; + await groupMenuItem.click(); + + // The group block's wrapper should be selected. + const isGroupBlockSelected = await page.evaluate( + () => + document.activeElement.getAttribute( 'data-type' ) === + 'core/group' + ); + expect( isGroupBlockSelected ).toBe( true ); + } ); } ); diff --git a/packages/e2e-tests/specs/editor/various/convert-block-type.test.js b/packages/e2e-tests/specs/editor/various/convert-block-type.test.js index 2c71a3d3a139f2..101a40b6dd2299 100644 --- a/packages/e2e-tests/specs/editor/various/convert-block-type.test.js +++ b/packages/e2e-tests/specs/editor/various/convert-block-type.test.js @@ -17,8 +17,7 @@ describe( 'Code block', () => { const code = 'print "Hello Dolly!"'; await insertBlock( 'Code' ); - - await page.type( '.block-editor-block-list__block textarea', code ); + await page.keyboard.type( code ); // Verify the content starts out as a Code block. const originalPostContent = await getEditedPostContent(); diff --git a/packages/e2e-tests/specs/editor/various/duplicating-blocks.test.js b/packages/e2e-tests/specs/editor/various/duplicating-blocks.test.js new file mode 100644 index 00000000000000..a5aadb7766a793 --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/duplicating-blocks.test.js @@ -0,0 +1,49 @@ +/** + * WordPress dependencies + */ +import { + createNewPost, + insertBlock, + getEditedPostContent, + clickBlockToolbarButton, + pressKeyWithModifier, +} from '@wordpress/e2e-test-utils'; + +describe( 'Duplicating blocks', () => { + beforeEach( async () => { + await createNewPost(); + } ); + + it( 'should duplicate blocks using the block settings menu', async () => { + await insertBlock( 'Paragraph' ); + await page.keyboard.type( 'Clone me' ); + + // Select the test we just typed + // This doesn't do anything but we previously had a duplicationi bug + // When the selection was not collapsed + await pressKeyWithModifier( 'primary', 'a' ); + + await clickBlockToolbarButton( 'More options' ); + const duplicateButton = await page.waitForXPath( + '//button[text()="Duplicate"]' + ); + await duplicateButton.click(); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); + + it( 'should duplicate blocks using the keyboard shortcut', async () => { + await insertBlock( 'Paragraph' ); + await page.keyboard.type( 'Clone me' ); + + // Select the test we just typed + // This doesn't do anything but we previously had a duplicationi bug + // When the selection was not collapsed + await pressKeyWithModifier( 'primary', 'a' ); + + // Duplicate using the keyboard shortccut + await pressKeyWithModifier( 'primaryShift', 'd' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); +} ); diff --git a/packages/e2e-tests/specs/editor/various/embedding.test.js b/packages/e2e-tests/specs/editor/various/embedding.test.js index b33a24fd787208..9e30ec116f3c37 100644 --- a/packages/e2e-tests/specs/editor/various/embedding.test.js +++ b/packages/e2e-tests/specs/editor/various/embedding.test.js @@ -307,7 +307,7 @@ describe( 'Embedding content', () => { await page.keyboard.type( 'Hello there!' ); await publishPost(); const postUrl = await page.$eval( - '[id^=inspector-text-control-]', + '.editor-post-publish-panel [id^=inspector-text-control-]', ( el ) => el.value ); diff --git a/packages/e2e-tests/specs/editor/various/is-typing.test.js b/packages/e2e-tests/specs/editor/various/is-typing.test.js new file mode 100644 index 00000000000000..8161118d65944d --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/is-typing.test.js @@ -0,0 +1,99 @@ +/** + * WordPress dependencies + */ +import { clickBlockAppender, createNewPost } from '@wordpress/e2e-test-utils'; + +describe( 'isTyping', () => { + beforeEach( async () => { + await createNewPost(); + } ); + + it( 'should hide the toolbar when typing', async () => { + const blockToolbarSelector = '.block-editor-block-toolbar'; + + await clickBlockAppender(); + + // Type in a paragraph + await page.keyboard.type( 'Type' ); + + // Toolbar is hidden + let blockToolbar = await page.$( blockToolbarSelector ); + expect( blockToolbar ).toBe( null ); + + // Moving the mouse shows the toolbar + await page.mouse.move( 0, 0 ); + await page.mouse.move( 10, 10 ); + + // Toolbar is visible + blockToolbar = await page.$( blockToolbarSelector ); + expect( blockToolbar ).not.toBe( null ); + + // Typing again hides the toolbar + await page.keyboard.type( ' and continue' ); + + // Toolbar is hidden again + blockToolbar = await page.$( blockToolbarSelector ); + expect( blockToolbar ).toBe( null ); + } ); + + it( 'should not close the dropdown when typing in it', async () => { + // Adds a Dropdown with an input to all blocks + await page.evaluate( () => { + const { Dropdown, Button, Fill } = wp.components; + const { createElement: el, Fragment } = wp.element; + function AddDropdown( BlockListBlock ) { + return ( props ) => { + return el( + Fragment, + {}, + el( + Fill, + { name: 'BlockControls' }, + el( Dropdown, { + renderToggle: ( { onToggle } ) => + el( + Button, + { + onClick: onToggle, + className: 'dropdown-open', + }, + 'Open Dropdown' + ), + renderContent: () => + el( 'input', { + className: 'dropdown-input', + } ), + } ) + ), + el( BlockListBlock, props ) + ); + }; + } + + wp.hooks.addFilter( + 'editor.BlockListBlock', + 'e2e-test/add-dropdown', + AddDropdown + ); + } ); + + await clickBlockAppender(); + + // Type in a paragraph + await page.keyboard.type( 'Type' ); + + // Show Toolbar + await page.mouse.move( 0, 0 ); + await page.mouse.move( 10, 10 ); + + // Open the dropdown + await page.click( '.dropdown-open' ); + + // Type inside the dropdown's input + await page.type( '.dropdown-input', 'Random' ); + + // The input should still be visible + const input = await page.$( '.dropdown-input' ); + expect( input ).not.toBe( null ); + } ); +} ); diff --git a/packages/e2e-tests/specs/editor/various/keyboard-navigable-blocks.test.js b/packages/e2e-tests/specs/editor/various/keyboard-navigable-blocks.test.js index 7226e0750e5726..8f3854fb8ef4f1 100644 --- a/packages/e2e-tests/specs/editor/various/keyboard-navigable-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/keyboard-navigable-blocks.test.js @@ -149,7 +149,7 @@ describe( 'Order of block keyboard navigation', () => { await page.evaluate( () => { document.querySelector( '.edit-post-visual-editor' ).focus(); document - .querySelector( '.block-editor-editor-skeleton__sidebar' ) + .querySelector( '.interface-interface-skeleton__sidebar' ) .focus(); } ); diff --git a/packages/e2e-tests/specs/editor/various/links.test.js b/packages/e2e-tests/specs/editor/various/links.test.js index 8d6c27869cd72e..c0df0b5f31f8fd 100644 --- a/packages/e2e-tests/specs/editor/various/links.test.js +++ b/packages/e2e-tests/specs/editor/various/links.test.js @@ -9,12 +9,6 @@ import { pressKeyWithModifier, } from '@wordpress/e2e-test-utils'; -/** - * The modifier keys needed to invoke a 'select the next word' keyboard shortcut. - * - * @type {string} - */ - describe( 'Links', () => { beforeEach( async () => { await createNewPost(); @@ -26,6 +20,42 @@ describe( 'Links', () => { ); }; + it( 'will use Post title as link text if link to existing post is created without any text selected', async () => { + const titleText = 'Post to create a link to'; + await createPostWithTitle( titleText ); + + await createNewPost(); + await clickBlockAppender(); + + // Now in a new post and try to create a link from an autocomplete suggestion using the keyboard. + await page.keyboard.type( 'Here comes a link: ' ); + + // Press Cmd+K to insert a link + await pressKeyWithModifier( 'primary', 'K' ); + + // Wait for the URL field to auto-focus + await waitForAutoFocus(); + expect( + await page.$( + '.components-popover__content .block-editor-link-control' + ) + ).not.toBeNull(); + + // Trigger the autocomplete suggestion list and select the first suggestion. + await page.keyboard.type( titleText.substr( 0, titleText.length - 2 ) ); + await page.waitForSelector( '.block-editor-link-control__search-item' ); + await page.keyboard.press( 'ArrowDown' ); + + await page.keyboard.press( 'Enter' ); + + const actualText = await page.evaluate( + () => + document.querySelector( '.block-editor-rich-text__editable a' ) + .textContent + ); + expect( actualText ).toBe( titleText ); + } ); + it( 'can be created by selecting text and clicking Link', async () => { // Create a block with some text await clickBlockAppender(); diff --git a/packages/e2e-tests/specs/editor/various/sidebar.test.js b/packages/e2e-tests/specs/editor/various/sidebar.test.js index ab2043f17b887a..a9d4dfdd2135e2 100644 --- a/packages/e2e-tests/specs/editor/various/sidebar.test.js +++ b/packages/e2e-tests/specs/editor/various/sidebar.test.js @@ -87,8 +87,7 @@ describe( 'Sidebar', () => { await setBrowserViewport( 'large' ); - const sidebarsDesktop = await page.$$( SIDEBAR_SELECTOR ); - expect( sidebarsDesktop ).toHaveLength( 1 ); + await page.waitForSelector( SIDEBAR_SELECTOR ); } ); it( 'should preserve tab order while changing active tab', async () => { diff --git a/packages/e2e-tests/specs/experiments/__snapshots__/navigation.test.js.snap b/packages/e2e-tests/specs/experiments/__snapshots__/navigation.test.js.snap index 9bef34b8e46192..e41ca54dee0304 100644 --- a/packages/e2e-tests/specs/experiments/__snapshots__/navigation.test.js.snap +++ b/packages/e2e-tests/specs/experiments/__snapshots__/navigation.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Navigation allows a navigation menu to be created from an empty menu using a mixture of internal and external links 1`] = ` -"<!-- wp:navigation --> +"<!-- wp:navigation {\\"orientation\\":\\"horizontal\\"} --> <!-- wp:navigation-link {\\"label\\":\\"WP\\",\\"id\\":\\"https://wordpress.org\\",\\"url\\":\\"https://wordpress.org\\"} /--> <!-- wp:navigation-link {\\"label\\":\\"Contact\\",\\"id\\":1,\\"url\\":\\"https://this/is/a/test/search/get-in-touch\\"} /--> @@ -9,7 +9,7 @@ exports[`Navigation allows a navigation menu to be created from an empty menu us `; exports[`Navigation allows a navigation menu to be created using existing pages 1`] = ` -"<!-- wp:navigation --> +"<!-- wp:navigation {\\"orientation\\":\\"horizontal\\"} --> <!-- wp:navigation-link {\\"label\\":\\"Home\\",\\"type\\":\\"page\\",\\"id\\":1,\\"url\\":\\"https://this/is/a/test/page/home\\"} /--> <!-- wp:navigation-link {\\"label\\":\\"About\\",\\"type\\":\\"page\\",\\"id\\":2,\\"url\\":\\"https://this/is/a/test/page/about\\"} /--> @@ -19,7 +19,7 @@ exports[`Navigation allows a navigation menu to be created using existing pages `; exports[`Navigation allows pages to be created from the navigation block and their links added to menu 1`] = ` -"<!-- wp:navigation --> +"<!-- wp:navigation {\\"orientation\\":\\"horizontal\\"} --> <!-- wp:navigation-link {\\"label\\":\\"A really long page name that will not exist\\",\\"id\\":1,\\"url\\":\\"https://this/is/a/test/create/page/my-new-page\\"} /--> <!-- /wp:navigation -->" `; diff --git a/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js b/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js new file mode 100644 index 00000000000000..9f98918c20868b --- /dev/null +++ b/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js @@ -0,0 +1,178 @@ +/** + * WordPress dependencies + */ +import { + createNewPost, + insertBlock, + disablePrePublishChecks, + publishPostWithPrePublishChecksDisabled, + visitAdminPage, +} from '@wordpress/e2e-test-utils'; +import { addQueryArgs } from '@wordpress/url'; + +/** + * Internal dependencies + */ +import { + enableExperimentalFeatures, + disableExperimentalFeatures, +} from '../../experimental-features'; + +describe( 'Multi-entity save flow', () => { + // Selectors. + const checkboxSelector = '.components-checkbox-control__checked'; + const templatePartSelector = '*[data-type="core/template-part"]'; + const saveButtonSelector = '.editor-post-publish-button__button'; + const multisaveSelector = + '.editor-post-publish-button__button.has-changes-dot'; + const entitiesSaveSelector = '.editor-entities-saved-states__save-button'; + const saveSiteSelector = '.edit-site-save-button__button'; + + // Setup & Teardown. + const requiredExperiments = [ + '#gutenberg-full-site-editing', + '#gutenberg-full-site-editing-demo', + ]; + beforeAll( async () => { + await enableExperimentalFeatures( requiredExperiments ); + } ); + afterAll( async () => { + await disableExperimentalFeatures( requiredExperiments ); + } ); + + describe( 'Post Editor', () => { + const assertMultiSaveEnabled = async () => { + const multiSaveButton = await page.waitForSelector( + multisaveSelector + ); + expect( multiSaveButton ).not.toBeNull(); + }; + + const assertMultiSaveDisabled = async () => { + const multiSaveButton = await page.$( multisaveSelector ); + expect( multiSaveButton ).toBeNull(); + }; + + describe( 'Pre-Publish state', () => { + it( 'Should not trigger multi-entity save button with only post edited', async () => { + await createNewPost(); + await disablePrePublishChecks(); + // Edit the page some. + await page.click( '.editor-post-title' ); + await page.keyboard.type( 'Test Post...' ); + await page.keyboard.press( 'Enter' ); + + await assertMultiSaveDisabled(); + } ); + + it( 'Should trigger multi-entity save button once template part edited', async () => { + // Create new template part. + await insertBlock( 'Template Part' ); + await page.keyboard.type( 'test-template-part' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.type( 'test-theme' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.press( 'Enter' ); + + // Make some changes in new Template Part. + await page.waitForSelector( + `${ templatePartSelector } .block-editor-inner-blocks` + ); + await page.click( templatePartSelector ); + await page.keyboard.type( 'some words...' ); + + await assertMultiSaveEnabled(); + } ); + + it( 'Clicking should open modal with boxes checked by default', async () => { + await page.click( saveButtonSelector ); + const checkedBoxes = await page.$$( checkboxSelector ); + expect( checkedBoxes.length ).toBe( 2 ); + } ); + + it( 'Saving should result in items being saved', async () => { + await page.click( entitiesSaveSelector ); + + // Verify post is saved. + const draftSaved = await page.waitForSelector( + '.editor-post-saved-state.is-saved' + ); + expect( draftSaved ).not.toBeNull(); + + // Verify template part is saved. + await assertMultiSaveDisabled(); + } ); + } ); + + describe( 'Published state', () => { + it( 'Update button disabled after publish', async () => { + await publishPostWithPrePublishChecksDisabled(); + const disabledSaveButton = await page.$( + `${ saveButtonSelector }[aria-disabled=true]` + ); + expect( disabledSaveButton ).not.toBeNull(); + } ); + + it( 'Update button enabled after editing post', async () => { + await page.click( '.editor-post-title' ); + await page.keyboard.type( '...more title!' ); + + // Verify update button is enabled. + const enabledSaveButton = await page.$( + `${ saveButtonSelector }[aria-disabled=false]` + ); + expect( enabledSaveButton ).not.toBeNull(); + + // Verify is not for multi-entity saving. + await assertMultiSaveDisabled(); + } ); + + it( 'Multi-save button triggered after editing template part.', async () => { + await page.click( templatePartSelector ); + await page.keyboard.type( '...some more words...' ); + await page.keyboard.press( 'Enter' ); + await assertMultiSaveEnabled(); + } ); + } ); + } ); + + describe.skip( 'Site Editor', () => { + async function assertSaveDisabled() { + const disabledButton = await page.waitForSelector( + `${ saveSiteSelector }[aria-disabled=true]` + ); + expect( disabledButton ).not.toBeNull(); + } + const activeButtonSelector = `${ saveSiteSelector }[aria-disabled=false]`; + + it( 'Save button should be disabled by default', async () => { + // Navigate to site editor. + const query = addQueryArgs( '', { + page: 'gutenberg-edit-site', + } ).slice( 1 ); + await visitAdminPage( 'admin.php', query ); + + await assertSaveDisabled(); + } ); + + it( 'Should be enabled after edits', async () => { + await page.click( templatePartSelector ); + await page.keyboard.type( 'some words...' ); + const enabledButton = await page.waitForSelector( + activeButtonSelector + ); + expect( enabledButton ).not.toBeNull(); + } ); + + it( 'Clicking button should open modal with boxes checked', async () => { + await page.click( activeButtonSelector ); + const checkedBoxes = await page.$$( checkboxSelector ); + expect( checkedBoxes ).not.toHaveLength( 0 ); + } ); + + it( 'Saving should result in items being saved', async () => { + await page.click( entitiesSaveSelector ); + await assertSaveDisabled(); + } ); + } ); +} ); diff --git a/packages/e2e-tests/specs/experiments/navigation.test.js b/packages/e2e-tests/specs/experiments/navigation.test.js index fc11a057968fa2..dab5989d0439ab 100644 --- a/packages/e2e-tests/specs/experiments/navigation.test.js +++ b/packages/e2e-tests/specs/experiments/navigation.test.js @@ -77,9 +77,10 @@ async function mockCreatePageResponse( title, slug ) { /** * Interacts with the LinkControl to perform a search and select a returned suggestion * - * @param {string} url What will be typed in the search input - * @param {string} label What the resulting label will be in the creating Navigation Link Block after the block is created. - * @param {string} type What kind of suggestion should be clicked, ie. 'url', 'create', or 'entity' + * @param {Object} link link object to be tested + * @param {string} link.url What will be typed in the search input + * @param {string} link.label What the resulting label will be in the creating Navigation Link Block after the block is created. + * @param {string} link.type What kind of suggestion should be clicked, ie. 'url', 'create', or 'entity' */ async function updateActiveNavigationLink( { url, label, type } ) { const typeClasses = { diff --git a/packages/e2e-tests/specs/performance/performance.test.js b/packages/e2e-tests/specs/performance/performance.test.js index b4ba1419bb9475..9360c98a6d313e 100644 --- a/packages/e2e-tests/specs/performance/performance.test.js +++ b/packages/e2e-tests/specs/performance/performance.test.js @@ -47,13 +47,17 @@ function isKeyUpEvent( item ) { return isKeyEvent( item ) && item.args.data.type === 'keyup'; } +function isFocusEvent( item ) { + return isKeyEvent( item ) && item.args.data.type === 'focus'; +} + function getEventDurationsForType( trace, filterFunction ) { return trace.traceEvents .filter( filterFunction ) .map( ( item ) => item.dur / 1000 ); } -function getEventDurations( trace ) { +function getTypingEventDurations( trace ) { return [ getEventDurationsForType( trace, isKeyDownEvent ), getEventDurationsForType( trace, isKeyPressEvent ), @@ -61,8 +65,21 @@ function getEventDurations( trace ) { ]; } +function getSelectionEventDurations( trace ) { + return [ getEventDurationsForType( trace, isFocusEvent ) ]; +} + +jest.setTimeout( 1000000 ); + describe( 'Performance', () => { - it( '1000 paragraphs', async () => { + it( 'Loading, typing and selecting blocks', async () => { + const results = { + load: [], + domcontentloaded: [], + type: [], + focus: [], + }; + const html = readFile( join( __dirname, '../../assets/large-post.html' ) ); @@ -84,14 +101,9 @@ describe( 'Performance', () => { }, html ); await saveDraft(); - const results = { - load: [], - domcontentloaded: [], - type: [], - }; - let i = 1; + // Measuring loading time while ( i-- ) { await page.reload( { waitUntil: [ 'domcontentloaded', 'load' ] } ); const timings = JSON.parse( @@ -110,29 +122,26 @@ describe( 'Performance', () => { ); } + // Measuring typing performance await insertBlock( 'Paragraph' ); - i = 200; const traceFile = __dirname + '/trace.json'; - await page.tracing.start( { path: traceFile, screenshots: false, categories: [ 'devtools.timeline' ], } ); - while ( i-- ) { await page.keyboard.type( 'x' ); } await page.tracing.stop(); - - const traceResults = JSON.parse( readFile( traceFile ) ); + let traceResults = JSON.parse( readFile( traceFile ) ); const [ keyDownEvents, keyPressEvents, keyUpEvents, - ] = getEventDurations( traceResults ); + ] = getTypingEventDurations( traceResults ); if ( keyDownEvents.length === keyPressEvents.length && @@ -145,6 +154,34 @@ describe( 'Performance', () => { } } + // Measuring block selection performance + await createNewPost(); + await page.evaluate( () => { + const { createBlock } = window.wp.blocks; + const { dispatch } = window.wp.data; + const blocks = window.lodash + .times( 1000 ) + .map( () => createBlock( 'core/paragraph' ) ); + dispatch( 'core/block-editor' ).resetBlocks( blocks ); + } ); + + const paragraphs = await page.$$( '.wp-block' ); + + await page.tracing.start( { + path: traceFile, + screenshots: false, + categories: [ 'devtools.timeline' ], + } ); + for ( let j = 0; j < 10; j++ ) { + await paragraphs[ j ].click(); + } + + await page.tracing.stop(); + + traceResults = JSON.parse( readFile( traceFile ) ); + const [ focusEvents ] = getSelectionEventDurations( traceResults ); + results.focus = focusEvents; + writeFileSync( __dirname + '/results.json', JSON.stringify( results, null, 2 ) diff --git a/packages/edit-navigation/.npmrc b/packages/edit-navigation/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/edit-navigation/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/edit-navigation/README.md b/packages/edit-navigation/README.md new file mode 100644 index 00000000000000..b4df65e94c0ce4 --- /dev/null +++ b/packages/edit-navigation/README.md @@ -0,0 +1,5 @@ +- Package name +- Package description +- Installation details +- Usage example +- `Code is Poetry` logo (`<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>`) diff --git a/packages/edit-navigation/package.json b/packages/edit-navigation/package.json new file mode 100644 index 00000000000000..58d02a507f0cd2 --- /dev/null +++ b/packages/edit-navigation/package.json @@ -0,0 +1,45 @@ +{ + "name": "@wordpress/edit-navigation", + "version": "1.0.0-beta.0", + "private": true, + "description": "Module for the Navigation page in WordPress.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/edit-navigation/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/edit-navigation" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "react-native": "src/index", + "dependencies": { + "@babel/runtime": "^7.9.2", + "@wordpress/block-editor": "file:../block-editor", + "@wordpress/block-library": "file:../block-library", + "@wordpress/blocks": "file:../blocks", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/data-controls": "file:../data-controls", + "@wordpress/dom-ready": "file:../dom-ready", + "@wordpress/element": "file:../element", + "@wordpress/hooks": "file:../hooks", + "@wordpress/i18n": "file:../i18n", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", + "@wordpress/media-utils": "file:../media-utils", + "@wordpress/notices": "file:../notices", + "lodash": "^4.17.15", + "rememo": "^3.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js new file mode 100644 index 00000000000000..a79bbc922917ff --- /dev/null +++ b/packages/edit-navigation/src/components/layout/index.js @@ -0,0 +1,61 @@ +/** + * WordPress dependencies + */ +import { + DropZoneProvider, + FocusReturnProvider, + Popover, + SlotFillProvider, + TabPanel, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import MenusEditor from '../menus-editor'; +import MenuLocationsEditor from '../menu-locations-editor'; + +export default function Layout( { blockEditorSettings } ) { + return ( + <> + <SlotFillProvider> + <DropZoneProvider> + <FocusReturnProvider> + { /* <Notices /> */ } + <Popover.Slot name="block-toolbar" /> + <TabPanel + className="edit-navigation-layout__tab-panel" + tabs={ [ + { + name: 'menus', + title: __( 'Edit Navigation' ), + }, + { + name: 'menu-locations', + title: __( 'Manage Locations' ), + }, + ] } + > + { ( tab ) => ( + <> + { tab.name === 'menus' && ( + <MenusEditor + blockEditorSettings={ + blockEditorSettings + } + /> + ) } + { tab.name === 'menu-locations' && ( + <MenuLocationsEditor /> + ) } + </> + ) } + </TabPanel> + <Popover.Slot /> + </FocusReturnProvider> + </DropZoneProvider> + </SlotFillProvider> + </> + ); +} diff --git a/packages/edit-navigation/src/components/layout/style.scss b/packages/edit-navigation/src/components/layout/style.scss new file mode 100644 index 00000000000000..b533f3cd3b20a3 --- /dev/null +++ b/packages/edit-navigation/src/components/layout/style.scss @@ -0,0 +1,12 @@ +.edit-navigation-layout__tab-panel { + // Matches the padding-left applied by default to the `#wpcontent` element. + margin-right: 10px; + + @include break-medium { + margin-right: 20px; + } + + .components-tab-panel__tabs { + margin-bottom: 10px; + } +} diff --git a/packages/edit-navigation/src/components/menu-editor/index.js b/packages/edit-navigation/src/components/menu-editor/index.js new file mode 100644 index 00000000000000..5ac2a1959e0201 --- /dev/null +++ b/packages/edit-navigation/src/components/menu-editor/index.js @@ -0,0 +1,77 @@ +/** + * WordPress dependencies + */ +import { + BlockEditorKeyboardShortcuts, + BlockEditorProvider, + BlockList, + ObserveTyping, + WritingFlow, + __experimentalBlockNavigationList, +} from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { Panel, PanelBody, Button } from '@wordpress/components'; +import { useViewportMatch } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import useNavigationBlocks from './use-navigation-blocks'; +import MenuEditorShortcuts from './shortcuts'; + +export default function MenuEditor( { menuId, blockEditorSettings } ) { + const [ blocks, setBlocks, saveBlocks ] = useNavigationBlocks( menuId ); + const isLargeViewport = useViewportMatch( 'medium' ); + + return ( + <div className="edit-navigation-menu-editor"> + <BlockEditorKeyboardShortcuts.Register /> + <MenuEditorShortcuts.Register /> + + <BlockEditorProvider + value={ blocks } + onInput={ ( updatedBlocks ) => setBlocks( updatedBlocks ) } + onChange={ ( updatedBlocks ) => setBlocks( updatedBlocks ) } + settings={ { + ...blockEditorSettings, + templateLock: 'all', + } } + > + <BlockEditorKeyboardShortcuts /> + <MenuEditorShortcuts saveBlocks={ saveBlocks } /> + <Panel className="edit-navigation-menu-editor__panel"> + <PanelBody + title={ __( 'Navigation structure' ) } + initialOpen={ isLargeViewport } + > + { !! blocks.length && ( + <__experimentalBlockNavigationList + blocks={ blocks } + selectedBlockClientId={ blocks[ 0 ].clientId } + selectBlock={ () => {} } + showNestedBlocks + showAppender + /> + ) } + </PanelBody> + </Panel> + <Panel + header={ + <Button isPrimary onClick={ saveBlocks }> + { __( 'Save navigation' ) } + </Button> + } + className="edit-navigation-menu-editor__panel" + > + <PanelBody title={ __( 'Navigation menu' ) }> + <WritingFlow> + <ObserveTyping> + <BlockList /> + </ObserveTyping> + </WritingFlow> + </PanelBody> + </Panel> + </BlockEditorProvider> + </div> + ); +} diff --git a/packages/edit-navigation/src/components/menu-editor/shortcuts.js b/packages/edit-navigation/src/components/menu-editor/shortcuts.js new file mode 100644 index 00000000000000..96889b67a8daa9 --- /dev/null +++ b/packages/edit-navigation/src/components/menu-editor/shortcuts.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { useEffect, useCallback } from '@wordpress/element'; +import { useDispatch } from '@wordpress/data'; +import { useShortcut } from '@wordpress/keyboard-shortcuts'; +import { __ } from '@wordpress/i18n'; + +function MenuEditorShortcuts( { saveBlocks } ) { + useShortcut( + 'core/edit-navigation/save-menu', + useCallback( ( event ) => { + event.preventDefault(); + saveBlocks(); + } ), + { + bindGlobal: true, + } + ); + + return null; +} + +function RegisterMenuEditorShortcuts() { + const { registerShortcut } = useDispatch( 'core/keyboard-shortcuts' ); + useEffect( () => { + registerShortcut( { + name: 'core/edit-navigation/save-menu', + category: 'global', + description: __( 'Save the menu currently being edited.' ), + keyCombination: { + modifier: 'primary', + character: 's', + }, + } ); + }, [ registerShortcut ] ); + + return null; +} + +MenuEditorShortcuts.Register = RegisterMenuEditorShortcuts; + +export default MenuEditorShortcuts; diff --git a/packages/edit-navigation/src/components/menu-editor/style.scss b/packages/edit-navigation/src/components/menu-editor/style.scss new file mode 100644 index 00000000000000..1c6ddda2c7bce6 --- /dev/null +++ b/packages/edit-navigation/src/components/menu-editor/style.scss @@ -0,0 +1,8 @@ +.edit-navigation-menu-editor { + display: grid; + grid-gap: 10px; + + @include break-medium { + grid-template-columns: 280px 1fr; + } +} diff --git a/packages/edit-navigation/src/components/menu-editor/use-navigation-blocks.js b/packages/edit-navigation/src/components/menu-editor/use-navigation-blocks.js new file mode 100644 index 00000000000000..3dc27c54a7644d --- /dev/null +++ b/packages/edit-navigation/src/components/menu-editor/use-navigation-blocks.js @@ -0,0 +1,98 @@ +/** + * External dependencies + */ +import { isEqual, difference } from 'lodash'; + +/** + * WordPress dependencies + */ +import { createBlock } from '@wordpress/blocks'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { useState, useRef, useEffect } from '@wordpress/element'; + +function createBlockFromMenuItem( menuItem ) { + return createBlock( 'core/navigation-link', { + label: menuItem.title.raw, + url: menuItem.url, + } ); +} + +function createMenuItemAttributesFromBlock( block ) { + return { + title: block.attributes.label, + url: block.attributes.url, + }; +} + +export default function useNavigationBlocks( menuId ) { + const menuItems = useSelect( + ( select ) => select( 'core' ).getMenuItems( { menus: menuId } ), + [ menuId ] + ); + + const { saveMenuItem } = useDispatch( 'core' ); + + const [ blocks, setBlocks ] = useState( [] ); + + const menuItemsRef = useRef( {} ); + + useEffect( () => { + if ( ! menuItems ) { + return; + } + + menuItemsRef.current = {}; + + const innerBlocks = []; + + for ( const menuItem of menuItems ) { + const block = createBlockFromMenuItem( menuItem ); + menuItemsRef.current[ block.clientId ] = menuItem; + innerBlocks.push( block ); + } + + setBlocks( [ createBlock( 'core/navigation', {}, innerBlocks ) ] ); + }, [ menuItems ] ); + + const saveBlocks = () => { + const { innerBlocks } = blocks[ 0 ]; + + for ( const block of innerBlocks ) { + const menuItem = menuItemsRef.current[ block.clientId ]; + + if ( ! menuItem ) { + saveMenuItem( { + ...createMenuItemAttributesFromBlock( block ), + menus: menuId, + } ); + continue; + } + + if ( + ! isEqual( + block.attributes, + createBlockFromMenuItem( menuItem ).attributes + ) + ) { + saveMenuItem( { + ...menuItem, + ...createMenuItemAttributesFromBlock( block ), + menus: menuId, // Gotta do this because REST API doesn't like receiving an array here. Maybe a bug in the REST API? + } ); + } + } + + const deletedClientIds = difference( + Object.keys( menuItemsRef.current ), + innerBlocks.map( ( block ) => block.clientId ) + ); + + // Disable reason, this code will eventually be implemented. + // eslint-disable-next-line no-unused-vars + for ( const clientId of deletedClientIds ) { + // TODO - delete menu items. + } + }; + + return [ blocks, setBlocks, saveBlocks ]; +} diff --git a/packages/edit-navigation/src/components/menu-locations-editor/index.js b/packages/edit-navigation/src/components/menu-locations-editor/index.js new file mode 100644 index 00000000000000..4d69195006cc74 --- /dev/null +++ b/packages/edit-navigation/src/components/menu-locations-editor/index.js @@ -0,0 +1,3 @@ +export default function MenuLocationsEditor() { + return <>Menu locations editor</>; +} diff --git a/packages/edit-navigation/src/components/menus-editor/index.js b/packages/edit-navigation/src/components/menus-editor/index.js new file mode 100644 index 00000000000000..b3513b1115044b --- /dev/null +++ b/packages/edit-navigation/src/components/menus-editor/index.js @@ -0,0 +1,54 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { useState, useEffect } from '@wordpress/element'; +import { Card, CardBody, Spinner, SelectControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import MenuEditor from '../menu-editor'; + +export default function MenusEditor( { blockEditorSettings } ) { + const menus = useSelect( ( select ) => select( 'core' ).getMenus() ); + + const [ menuId, setMenuId ] = useState( 0 ); + + useEffect( () => { + if ( menus?.length ) { + setMenuId( menus[ 0 ].id ); + } + }, [ menus ] ); + + if ( ! menus ) { + return <Spinner />; + } + + return ( + <> + <Card className="edit-navigation-menus-editor__menu-selection-card"> + <CardBody> + <SelectControl + className="edit-navigation-menus-editor__menu-select-control" + label={ __( 'Select navigation to edit:' ) } + options={ menus.map( ( menu ) => ( { + value: menu.id, + label: menu.name, + } ) ) } + onChange={ ( selectedMenuId ) => + setMenuId( selectedMenuId ) + } + /> + </CardBody> + </Card> + { !! menuId && ( + <MenuEditor + menuId={ menuId } + blockEditorSettings={ blockEditorSettings } + /> + ) } + </> + ); +} diff --git a/packages/edit-navigation/src/components/menus-editor/style.scss b/packages/edit-navigation/src/components/menus-editor/style.scss new file mode 100644 index 00000000000000..8276863c97f964 --- /dev/null +++ b/packages/edit-navigation/src/components/menus-editor/style.scss @@ -0,0 +1,17 @@ +.edit-navigation-menus-editor__menu-selection-card { + margin-bottom: 10px; +} + +.edit-navigation-menus-editor__menu-select-control { + @include break-small { + .components-base-control__field { + display: flex; + flex-direction: row; + align-items: baseline; + margin-bottom: 0; + } + .components-base-control__label { + margin-right: 1ch; + } + } +} diff --git a/packages/edit-navigation/src/index.js b/packages/edit-navigation/src/index.js new file mode 100644 index 00000000000000..4d3b0005c00672 --- /dev/null +++ b/packages/edit-navigation/src/index.js @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { + registerCoreBlocks, + __experimentalRegisterExperimentalCoreBlocks, +} from '@wordpress/block-library'; +import { render } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import Layout from './components/layout'; + +export function initialize( id, settings ) { + registerCoreBlocks(); + if ( process.env.GUTENBERG_PHASE === 2 ) { + __experimentalRegisterExperimentalCoreBlocks( settings ); + } + render( + <Layout blockEditorSettings={ settings } />, + document.getElementById( id ) + ); +} diff --git a/packages/edit-navigation/src/style.scss b/packages/edit-navigation/src/style.scss new file mode 100644 index 00000000000000..1e907633b0724f --- /dev/null +++ b/packages/edit-navigation/src/style.scss @@ -0,0 +1,3 @@ +@import "./components/layout/style.scss"; +@import "./components/menu-editor/style.scss"; +@import "./components/menus-editor/style.scss"; diff --git a/packages/edit-post/README.md b/packages/edit-post/README.md index 641bb89209f185..5a1908b8cc05a9 100644 --- a/packages/edit-post/README.md +++ b/packages/edit-post/README.md @@ -438,10 +438,6 @@ _Parameters_ - _props.isPinnable_ `[boolean]`: Whether to allow to pin sidebar to toolbar. - _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. -_Returns_ - -- `WPComponent`: Plugin sidebar component. - <a name="PluginSidebarMoreMenuItem" href="#PluginSidebarMoreMenuItem">#</a> **PluginSidebarMoreMenuItem** Renders a menu item in `Plugins` group in `More Menu` drop down, diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 0caf0d0159e926..098c0c375a176c 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:../a11y", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/block-editor": "file:../block-editor", @@ -31,11 +31,13 @@ "@wordpress/compose": "file:../compose", "@wordpress/core-data": "file:../core-data", "@wordpress/data": "file:../data", + "@wordpress/data-controls": "file:../data-controls", "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/media-utils": "file:../media-utils", @@ -46,7 +48,7 @@ "@wordpress/viewport": "file:../viewport", "classnames": "^2.2.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "refx": "^3.0.0", "rememo": "^3.0.0" }, diff --git a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js index b23a62b33655a2..f87ddf23923e06 100644 --- a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js +++ b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js @@ -38,7 +38,8 @@ const shouldRenderItem = ( selectedBlocks, allowedBlocks ) => * @param {string} props.label The menu item text. * @param {Function} props.onClick Callback function to be executed when the user click the menu item. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -61,7 +62,8 @@ const shouldRenderItem = ( selectedBlocks, allowedBlocks ) => * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * import { __ } from wp.i18n; diff --git a/packages/edit-post/src/components/header/fullscreen-mode-close/index.js b/packages/edit-post/src/components/header/fullscreen-mode-close/index.js index 63869c6ac30b72..27cadc4f67b365 100644 --- a/packages/edit-post/src/components/header/fullscreen-mode-close/index.js +++ b/packages/edit-post/src/components/header/fullscreen-mode-close/index.js @@ -8,15 +8,9 @@ import { get } from 'lodash'; */ import { useSelect } from '@wordpress/data'; import { Button } from '@wordpress/components'; -import { Path, SVG } from '@wordpress/primitives'; import { __ } from '@wordpress/i18n'; import { addQueryArgs } from '@wordpress/url'; - -const wordPressLogo = ( - <SVG width="28" height="28" viewBox="0 0 128 128" version="1.1"> - <Path d="M100 61.3c0-6.6-2.4-11.2-4.4-14.7-2.7-4.4-5.2-8.1-5.2-12.5 0-4.9 3.7-9.5 9-9.5h.7c-9.5-8.7-22.1-14-36-14-18.6 0-35 9.6-44.6 24 1.3 0 2.4.1 3.4.1 5.6 0 14.2-.7 14.2-.7 2.9-.2 3.2 4.1.3 4.4 0 0-2.9.3-6.1.5l19.4 57.8 11.7-35L54.1 39c-2.9-.2-5.6-.5-5.6-.5-2.9-.2-2.5-4.6.3-4.4 0 0 8.8.7 14 .7 5.6 0 14.2-.7 14.2-.7 2.9-.2 3.2 4.1.3 4.4 0 0-2.9.3-6.1.5l19.3 57.3L96 78.9c2.6-7.6 4-13 4-17.6zM10.7 64c0 21.1 12.3 39.4 30.1 48L15.3 42.3c-3 6.6-4.6 14-4.6 21.7zm54.2 4.7l-16 46.5c4.8 1.4 9.8 2.2 15.1 2.2 6.2 0 12.2-1.1 17.7-3-.1-.2-.3-.5-.4-.7l-16.4-45zM64 0C28.7 0 0 28.7 0 64s28.7 64 64 64 64-28.7 64-64S99.3 0 64 0zm49.9 97.6c-2.2 3.2-4.6 6.2-7.3 8.9s-5.7 5.2-8.9 7.3c-3.2 2.2-6.7 4-10.2 5.5-7.4 3.1-15.3 4.7-23.4 4.7s-16-1.6-23.4-4.7c-3.6-1.5-7-3.4-10.2-5.5-3.2-2.2-6.2-4.6-8.9-7.3s-5.2-5.7-7.3-8.9c-2.2-3.2-4-6.7-5.5-10.2-3.4-7.4-5-15.3-5-23.4s1.6-16 4.7-23.4c1.5-3.6 3.4-7 5.5-10.2 2.2-3.2 4.6-6.2 7.3-8.9s5.7-5.2 8.9-7.3c3.2-2.2 6.7-4 10.2-5.5C48 5.4 55.9 3.8 64 3.8s16 1.6 23.4 4.7c3.6 1.5 7 3.4 10.2 5.5 3.2 2.2 6.2 4.6 8.9 7.3s5.2 5.7 7.3 8.9c2.2 3.2 4 6.7 5.5 10.2 3.1 7.4 4.7 15.3 4.7 23.4s-1.6 16-4.7 23.4c-1.4 3.8-3.2 7.2-5.4 10.4zm-2.7-53.7c0 5.4-1 11.5-4.1 19.1l-16.3 47.1c15.9-9.2 26.5-26.4 26.5-46.1 0-9.3-2.4-18-6.5-25.6.2 1.7.4 3.5.4 5.5z" /> - </SVG> -); +import { wordpress } from '@wordpress/icons'; function FullscreenModeClose() { const { isActive, postType } = useSelect( ( select ) => { @@ -37,7 +31,7 @@ function FullscreenModeClose() { return ( <Button className="edit-post-fullscreen-mode-close" - icon={ wordPressLogo } + icon={ wordpress } iconSize={ 36 } href={ addQueryArgs( 'edit.php', { post_type: postType.slug, diff --git a/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss b/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss index ad47bee1fb331f..2997e7745387b6 100644 --- a/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss +++ b/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss @@ -23,7 +23,7 @@ } &:focus { - box-shadow: inset 0 0 0 2px color($theme-color), inset 0 0 0 3px $white; + box-shadow: inset 0 0 0 $border-width-focus $theme-color, inset 0 0 0 ($border-width-focus + 1px) $white; } } } diff --git a/packages/edit-post/src/components/header/header-toolbar/index.native.js b/packages/edit-post/src/components/header/header-toolbar/index.native.js index 4e38926a1c4836..08c49b0c0d63ac 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.native.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.native.js @@ -25,7 +25,6 @@ import { import styles from './style.scss'; function HeaderToolbar( { - hasFixedToolbar, hasRedo, hasUndo, redo, @@ -76,7 +75,7 @@ function HeaderToolbar( { hint: __( 'Double tap to redo last change' ), } } /> - { hasFixedToolbar && <BlockToolbar /> } + <BlockToolbar /> </ScrollView> { showKeyboardHideButton && ( <Toolbar passedStyle={ styles.keyboardHideContainer }> @@ -98,9 +97,6 @@ export default compose( [ withSelect( ( select ) => ( { hasRedo: select( 'core/editor' ).hasEditorRedo(), hasUndo: select( 'core/editor' ).hasEditorUndo(), - hasFixedToolbar: select( 'core/edit-post' ).isFeatureActive( - 'fixedToolbar' - ), // This setting (richEditingEnabled) should not live in the block editor's setting. showInserter: select( 'core/edit-post' ).getEditorMode() === 'visual' && diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js index 347a673d0ff2f3..7dca19d07f57a5 100644 --- a/packages/edit-post/src/components/header/index.js +++ b/packages/edit-post/src/components/header/index.js @@ -6,6 +6,7 @@ import { Button } from '@wordpress/components'; import { PostPreviewButton, PostSavedState } from '@wordpress/editor'; import { useSelect, useDispatch } from '@wordpress/data'; import { cog } from '@wordpress/icons'; +import { PinnedItems } from '@wordpress/interface'; /** * Internal dependencies @@ -13,7 +14,6 @@ import { cog } from '@wordpress/icons'; import FullscreenModeClose from './fullscreen-mode-close'; import HeaderToolbar from './header-toolbar'; import MoreMenu from './more-menu'; -import PinnedPlugins from './pinned-plugins'; import PostPublishButtonOrToggle from './post-publish-button-or-toggle'; import PreviewOptions from '../preview-options'; @@ -94,7 +94,7 @@ function Header() { aria-expanded={ isEditorSidebarOpened } shortcut={ shortcut } /> - <PinnedPlugins.Slot /> + <PinnedItems.Slot scope="core/edit-post" /> <MoreMenu /> </div> </div> diff --git a/packages/edit-post/src/components/header/index.native.js b/packages/edit-post/src/components/header/index.native.js index 727061f24aa465..787c35b527a2ab 100644 --- a/packages/edit-post/src/components/header/index.native.js +++ b/packages/edit-post/src/components/header/index.native.js @@ -7,6 +7,7 @@ import { Keyboard } from 'react-native'; * WordPress dependencies */ import { Component } from '@wordpress/element'; +import '@wordpress/interface'; /** * Internal dependencies diff --git a/packages/edit-post/src/components/header/mode-switcher/index.js b/packages/edit-post/src/components/header/mode-switcher/index.js index 78a522470f729a..5ee3ec93747978 100644 --- a/packages/edit-post/src/components/header/mode-switcher/index.js +++ b/packages/edit-post/src/components/header/mode-switcher/index.js @@ -42,6 +42,10 @@ function ModeSwitcher() { ); const { switchEditorMode } = useDispatch( 'core/edit-post' ); + if ( ! isRichEditingEnabled || ! isCodeEditingEnabled ) { + return null; + } + const choices = MODES.map( ( choice ) => { if ( choice.value !== mode ) { return { ...choice, shortcut }; @@ -49,10 +53,6 @@ function ModeSwitcher() { return choice; } ); - if ( ! isRichEditingEnabled || ! isCodeEditingEnabled ) { - return null; - } - return ( <MenuGroup label={ __( 'Editor' ) }> <MenuItemsChoice diff --git a/packages/edit-post/src/components/header/more-menu/test/__snapshots__/index.js.snap b/packages/edit-post/src/components/header/more-menu/test/__snapshots__/index.js.snap index 909241a36eaa02..9296591a638592 100644 --- a/packages/edit-post/src/components/header/more-menu/test/__snapshots__/index.js.snap +++ b/packages/edit-post/src/components/header/more-menu/test/__snapshots__/index.js.snap @@ -99,8 +99,8 @@ exports[`MoreMenu should match snapshot 1`] = ` xmlns="http://www.w3.org/2000/svg" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" diff --git a/packages/edit-post/src/components/header/pinned-plugins/index.js b/packages/edit-post/src/components/header/pinned-plugins/index.js deleted file mode 100644 index 35f07ab0678d8b..00000000000000 --- a/packages/edit-post/src/components/header/pinned-plugins/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * External dependencies - */ -import { isEmpty } from 'lodash'; - -/** - * WordPress dependencies - */ -import { createSlotFill } from '@wordpress/components'; - -const { Fill: PinnedPlugins, Slot } = createSlotFill( 'PinnedPlugins' ); - -PinnedPlugins.Slot = ( props ) => ( - <Slot { ...props }> - { ( fills ) => - ! isEmpty( fills ) && ( - <div className="edit-post-pinned-plugins">{ fills }</div> - ) - } - </Slot> -); - -export default PinnedPlugins; diff --git a/packages/edit-post/src/components/header/pinned-plugins/style.scss b/packages/edit-post/src/components/header/pinned-plugins/style.scss deleted file mode 100644 index f8020c349699ad..00000000000000 --- a/packages/edit-post/src/components/header/pinned-plugins/style.scss +++ /dev/null @@ -1,45 +0,0 @@ -.edit-post-pinned-plugins { - display: none; - - @include break-small() { - display: flex; - } - - .components-button { - margin-left: 4px; - - &.is-pressed { - margin-left: 5px; - } - - svg { - max-width: 24px; - max-height: 24px; - } - } - - // Colorize plugin icons to ensure contrast and cohesion, but allow plugin developers to override. - .components-button:not(.is-pressed) svg, - .components-button:not(.is-pressed) svg * { - stroke: $dark-gray-primary; - fill: $dark-gray-primary; - stroke-width: 0; // !important is omitted here, so stroke-only icons can override easily. - } - - // Forcefully colorize hover and toggled plugin icon states to ensure legibility and consistency. - .components-button.is-pressed svg, - .components-button.is-pressed svg *, - .components-button.is-pressed:hover svg, - .components-button.is-pressed:hover svg * { - stroke: $white !important; - fill: $white !important; - stroke-width: 0; // !important is omitted here, so stroke-only icons can override easily. - } - - .components-button:hover svg, - .components-button:hover svg * { - stroke: $blue-medium-focus !important; - fill: $blue-medium-focus !important; - stroke-width: 0; // !important is omitted here, so stroke-only icons can override easily. - } -} diff --git a/packages/edit-post/src/components/header/plugin-more-menu-item/index.js b/packages/edit-post/src/components/header/plugin-more-menu-item/index.js index fa8d21caf7759b..ebcef732abeab4 100644 --- a/packages/edit-post/src/components/header/plugin-more-menu-item/index.js +++ b/packages/edit-post/src/components/header/plugin-more-menu-item/index.js @@ -36,7 +36,8 @@ const PluginMoreMenuItem = ( { onClick = noop, ...props } ) => ( * @param {Function} [props.onClick=noop] The callback function to be executed when the user clicks the menu item. * @param {...*} [props.other] Any additional props are passed through to the underlying [MenuItem](/packages/components/src/menu-item/README.md) component. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -59,7 +60,8 @@ const PluginMoreMenuItem = ( { onClick = noop, ...props } ) => ( * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * import { __ } from '@wordpress/i18n'; diff --git a/packages/edit-post/src/components/header/plugin-more-menu-item/test/__snapshots__/index.js.snap b/packages/edit-post/src/components/header/plugin-more-menu-item/test/__snapshots__/index.js.snap index d847aadaff72ca..44ebe7ba7b2138 100644 --- a/packages/edit-post/src/components/header/plugin-more-menu-item/test/__snapshots__/index.js.snap +++ b/packages/edit-post/src/components/header/plugin-more-menu-item/test/__snapshots__/index.js.snap @@ -22,9 +22,9 @@ exports[`PluginMoreMenuItem renders menu item as button properly 1`] = ` type="button" > <svg - aria-hidden="true" + aria-hidden={true} className="components-menu-items__item-icon" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" diff --git a/packages/edit-post/src/components/header/plugin-sidebar-more-menu-item/index.js b/packages/edit-post/src/components/header/plugin-sidebar-more-menu-item/index.js index 2667a70f0d0f64..791f66dafaa580 100644 --- a/packages/edit-post/src/components/header/plugin-sidebar-more-menu-item/index.js +++ b/packages/edit-post/src/components/header/plugin-sidebar-more-menu-item/index.js @@ -36,7 +36,8 @@ const PluginSidebarMoreMenuItem = ( { * @param {string} props.target A string identifying the target sidebar you wish to be activated by this menu item. Must be the same as the `name` prop you have given to that sidebar. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered to the left of the menu item label. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -55,7 +56,8 @@ const PluginSidebarMoreMenuItem = ( { * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * import { __ } from '@wordpress/i18n'; diff --git a/packages/edit-post/src/components/header/style.scss b/packages/edit-post/src/components/header/style.scss index 3ba75c71689c08..15447502320285 100644 --- a/packages/edit-post/src/components/header/style.scss +++ b/packages/edit-post/src/components/header/style.scss @@ -80,6 +80,13 @@ .components-button.is-pressed { color: $white; background: $dark-gray-primary; + + &:focus:not(:disabled) { + box-shadow: inset 0 0 0 1px $white, 0 0 0 $border-width-focus $theme-color; + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + } } // Adjust button paddings to scale better to mobile. diff --git a/packages/edit-post/src/components/keyboard-shortcuts/index.js b/packages/edit-post/src/components/keyboard-shortcuts/index.js index e7bf499207b944..3e2e4938cc7f19 100644 --- a/packages/edit-post/src/components/keyboard-shortcuts/index.js +++ b/packages/edit-post/src/components/keyboard-shortcuts/index.js @@ -30,6 +30,7 @@ function KeyboardShortcuts() { switchEditorMode, openGeneralSidebar, closeGeneralSidebar, + toggleFeature, } = useDispatch( 'core/edit-post' ); const { registerShortcut } = useDispatch( 'core/keyboard-shortcuts' ); @@ -44,6 +45,16 @@ function KeyboardShortcuts() { }, } ); + registerShortcut( { + name: 'core/edit-post/toggle-fullscreen', + category: 'global', + description: __( 'Toggle fullscreen mode.' ), + keyCombination: { + modifier: 'secondary', + character: 'f', + }, + } ); + registerShortcut( { name: 'core/edit-post/toggle-block-navigation', category: 'global', @@ -120,6 +131,16 @@ function KeyboardShortcuts() { } ); + useShortcut( + 'core/edit-post/toggle-fullscreen', + () => { + toggleFeature( 'fullscreenMode' ); + }, + { + bindGlobal: true, + } + ); + useShortcut( 'core/edit-post/toggle-sidebar', ( event ) => { diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 7ce59cf49882aa..de11658f603ad9 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -15,11 +15,7 @@ import { EditorKeyboardShortcutsRegister, } from '@wordpress/editor'; import { useSelect, useDispatch } from '@wordpress/data'; -import { - BlockBreadcrumb, - __experimentalEditorSkeleton as EditorSkeleton, - __experimentalFullscreenMode as FullscreenMode, -} from '@wordpress/block-editor'; +import { BlockBreadcrumb } from '@wordpress/block-editor'; import { Button, ScrollLock, @@ -29,6 +25,11 @@ import { import { useViewportMatch } from '@wordpress/compose'; import { PluginArea } from '@wordpress/plugins'; import { __ } from '@wordpress/i18n'; +import { + ComplementaryArea, + FullscreenMode, + InterfaceSkeleton, +} from '@wordpress/interface'; /** * Internal dependencies @@ -42,7 +43,6 @@ import OptionsModal from '../options-modal'; import BrowserURL from '../browser-url'; import Header from '../header'; import SettingsSidebar from '../sidebar/settings-sidebar'; -import Sidebar from '../sidebar'; import MetaBoxes from '../meta-boxes'; import PluginPostPublishPanel from '../sidebar/plugin-post-publish-panel'; import PluginPrePublishPanel from '../sidebar/plugin-pre-publish-panel'; @@ -122,7 +122,7 @@ function Layout() { <EditPostKeyboardShortcuts /> <EditorKeyboardShortcutsRegister /> <FocusReturnProvider> - <EditorSkeleton + <InterfaceSkeleton className={ className } header={ <Header /> } sidebar={ @@ -145,7 +145,7 @@ function Layout() { </div> ) } <SettingsSidebar /> - <Sidebar.Slot /> + <ComplementaryArea.Slot scope="core/edit-post" /> </> ) } @@ -176,7 +176,7 @@ function Layout() { </div> ) } - publish={ + actions={ publishSidebarOpened ? ( <PostPublishPanel onClose={ closePublishSidebar } diff --git a/packages/edit-post/src/components/layout/index.native.js b/packages/edit-post/src/components/layout/index.native.js index 2c8b049dcbc558..9384a0da52b2c0 100644 --- a/packages/edit-post/src/components/layout/index.native.js +++ b/packages/edit-post/src/components/layout/index.native.js @@ -13,7 +13,7 @@ import { withSelect } from '@wordpress/data'; import { BottomSheetSettings, __experimentalPageTemplatePicker, - __experimentalWithPageTemplatePickerVisible, + __experimentalWithPageTemplatePicker, } from '@wordpress/block-editor'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { HTMLTextInput, KeyboardAvoidingView } from '@wordpress/components'; @@ -94,9 +94,10 @@ class Layout extends Component { render() { const { - mode, getStylesFromColorScheme, - showPageTemplatePicker, + isTemplatePickerAvailable, + isTemplatePickerVisible, + mode, } = this.props; const isHtmlView = mode === 'text'; @@ -143,8 +144,10 @@ class Layout extends Component { parentHeight={ this.state.rootViewHeight } style={ toolbarKeyboardAvoidingViewStyle } > - { showPageTemplatePicker && ( - <__experimentalPageTemplatePicker /> + { isTemplatePickerAvailable && ( + <__experimentalPageTemplatePicker + visible={ isTemplatePickerVisible } + /> ) } <Header /> <BottomSheetSettings /> @@ -168,5 +171,5 @@ export default compose( [ }; } ), withPreferredColorScheme, - __experimentalWithPageTemplatePickerVisible, + __experimentalWithPageTemplatePicker, ] )( Layout ); diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss index 8a6df093381c39..cdab72c4bed4c3 100644 --- a/packages/edit-post/src/components/layout/style.scss +++ b/packages/edit-post/src/components/layout/style.scss @@ -15,7 +15,7 @@ .edit-post-layout .components-editor-notices__snackbar { position: fixed; right: 0; - bottom: 20px; + bottom: 40px; padding-left: 16px; padding-right: 16px; } @@ -57,7 +57,7 @@ } } -.block-editor-editor-skeleton__sidebar > div { +.interface-interface-skeleton__sidebar > div { height: 100%; } @@ -82,10 +82,10 @@ display: flex; justify-content: center; - .block-editor-editor-skeleton__publish:focus &, - .block-editor-editor-skeleton__publish:focus-within &, - .block-editor-editor-skeleton__sidebar:focus &, - .block-editor-editor-skeleton__sidebar:focus-within & { + .interface-interface-skeleton__actions:focus &, + .interface-interface-skeleton__actions:focus-within &, + .interface-interface-skeleton__actions:focus &, + .interface-interface-skeleton__actions:focus-within & { top: auto; bottom: 0; } @@ -106,7 +106,7 @@ } } -.edit-post-layout .block-editor-editor-skeleton__content { +.edit-post-layout .interface-interface-skeleton__content { background-color: $light-gray-700; } diff --git a/packages/edit-post/src/components/manage-blocks-modal/manager.js b/packages/edit-post/src/components/manage-blocks-modal/manager.js index bdb8349be888f7..41eba0b4f97e9a 100644 --- a/packages/edit-post/src/components/manage-blocks-modal/manager.js +++ b/packages/edit-post/src/components/manage-blocks-modal/manager.js @@ -52,9 +52,10 @@ function BlockManager( { { !! numberOfHiddenBlocks && ( <div className="edit-post-manage-blocks-modal__disabled-blocks-count"> { sprintf( + /* translators: %d: number of blocks. */ _n( - '%1$d block is disabled.', - '%1$d blocks are disabled.', + '%d block is disabled.', + '%d blocks are disabled.', numberOfHiddenBlocks ), numberOfHiddenBlocks diff --git a/packages/edit-post/src/components/options-modal/options/test/__snapshots__/enable-custom-fields.js.snap b/packages/edit-post/src/components/options-modal/options/test/__snapshots__/enable-custom-fields.js.snap index fd30201bd3b8d6..eb27081e91dc8f 100644 --- a/packages/edit-post/src/components/options-modal/options/test/__snapshots__/enable-custom-fields.js.snap +++ b/packages/edit-post/src/components/options-modal/options/test/__snapshots__/enable-custom-fields.js.snap @@ -22,9 +22,9 @@ exports[`EnableCustomFieldsOption renders a checked checkbox and a confirmation value="1" /> <svg - aria-hidden="true" + aria-hidden={true} className="components-checkbox-control__checked" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -80,9 +80,9 @@ exports[`EnableCustomFieldsOption renders a checked checkbox when custom fields value="1" /> <svg - aria-hidden="true" + aria-hidden={true} className="components-checkbox-control__checked" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" diff --git a/packages/edit-post/src/components/preview-options/style.scss b/packages/edit-post/src/components/preview-options/style.scss index d56693cfa1adad..de88a83faa7b2b 100644 --- a/packages/edit-post/src/components/preview-options/style.scss +++ b/packages/edit-post/src/components/preview-options/style.scss @@ -10,7 +10,7 @@ padding: 0 $grid-unit-10 0 $grid-unit-15; &:focus:not(:disabled) { - box-shadow: inset 0 0 0 1px $white, 0 0 0 2px color($theme-color); + box-shadow: inset 0 0 0 1px $white, 0 0 0 $border-width-focus $theme-color; } svg { diff --git a/packages/edit-post/src/components/sidebar/index.js b/packages/edit-post/src/components/sidebar/index.js deleted file mode 100644 index e6175b72b2685a..00000000000000 --- a/packages/edit-post/src/components/sidebar/index.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - -/** - * WordPress dependencies - */ -import { - createSlotFill, - withFocusReturn, - Animate, -} from '@wordpress/components'; -import { withSelect } from '@wordpress/data'; -import { ifCondition, compose } from '@wordpress/compose'; - -const { Fill, Slot } = createSlotFill( 'Sidebar' ); - -/** - * Renders a sidebar with its content. - * - * @return {Object} The rendered sidebar. - */ -function Sidebar( { children, className } ) { - return ( - <div className={ classnames( 'edit-post-sidebar', className ) }> - { children } - </div> - ); -} - -Sidebar = withFocusReturn( { - onFocusReturn() { - const button = document.querySelector( - '.edit-post-header__settings [aria-label="Settings"]' - ); - if ( button ) { - button.focus(); - return false; - } - }, -} )( Sidebar ); - -function AnimatedSidebarFill( props ) { - return ( - <Fill> - <Animate type="slide-in" options={ { origin: 'left' } }> - { () => <Sidebar { ...props } /> } - </Animate> - </Fill> - ); -} - -const WrappedSidebar = compose( - withSelect( ( select, { name } ) => ( { - isActive: - select( 'core/edit-post' ).getActiveGeneralSidebarName() === name, - } ) ), - ifCondition( ( { isActive } ) => isActive ) -)( AnimatedSidebarFill ); - -WrappedSidebar.Slot = Slot; - -export default WrappedSidebar; diff --git a/packages/edit-post/src/components/sidebar/plugin-document-setting-panel/index.js b/packages/edit-post/src/components/sidebar/plugin-document-setting-panel/index.js index 757e4965e5d991..56133e8162aad6 100644 --- a/packages/edit-post/src/components/sidebar/plugin-document-setting-panel/index.js +++ b/packages/edit-post/src/components/sidebar/plugin-document-setting-panel/index.js @@ -59,7 +59,8 @@ const PluginDocumentSettingFill = ( { * @param {string} [props.title] The title of the panel * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var el = wp.element.createElement; @@ -83,7 +84,8 @@ const PluginDocumentSettingFill = ( { * } ); * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * const { registerPlugin } = wp.plugins; diff --git a/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/index.js b/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/index.js index 43d1fc2d1eaac4..73fabe8a32f48b 100644 --- a/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/index.js +++ b/packages/edit-post/src/components/sidebar/plugin-post-publish-panel/index.js @@ -35,7 +35,8 @@ const PluginPostPublishPanelFill = ( { * @param {boolean} [props.initialOpen=false] Whether to have the panel initially opened. When no title is provided it is always opened. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -54,7 +55,8 @@ const PluginPostPublishPanelFill = ( { * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * const { __ } = wp.i18n; diff --git a/packages/edit-post/src/components/sidebar/plugin-post-status-info/index.js b/packages/edit-post/src/components/sidebar/plugin-post-status-info/index.js index 10259358e764f9..b43199112901b1 100644 --- a/packages/edit-post/src/components/sidebar/plugin-post-status-info/index.js +++ b/packages/edit-post/src/components/sidebar/plugin-post-status-info/index.js @@ -17,7 +17,8 @@ export const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' ); * @param {Object} props Component properties. * @param {string} [props.className] An optional class name added to the row. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -34,7 +35,8 @@ export const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' ); * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * const { __ } = wp.i18n; diff --git a/packages/edit-post/src/components/sidebar/plugin-pre-publish-panel/index.js b/packages/edit-post/src/components/sidebar/plugin-pre-publish-panel/index.js index db6900995db37d..8f39c8e1ee5313 100644 --- a/packages/edit-post/src/components/sidebar/plugin-pre-publish-panel/index.js +++ b/packages/edit-post/src/components/sidebar/plugin-pre-publish-panel/index.js @@ -38,7 +38,8 @@ const PluginPrePublishPanelFill = ( { * icon slug string, or an SVG WP element, to be rendered when * the sidebar is pinned to toolbar. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -57,7 +58,8 @@ const PluginPrePublishPanelFill = ( { * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * const { __ } = wp.i18n; diff --git a/packages/edit-post/src/components/sidebar/plugin-sidebar/index.js b/packages/edit-post/src/components/sidebar/plugin-sidebar/index.js index deb007a37d82dc..3034d5bab9165f 100644 --- a/packages/edit-post/src/components/sidebar/plugin-sidebar/index.js +++ b/packages/edit-post/src/components/sidebar/plugin-sidebar/index.js @@ -1,71 +1,9 @@ /** * WordPress dependencies */ -import { Button, Panel } from '@wordpress/components'; -import { withDispatch, withSelect } from '@wordpress/data'; +import { ComplementaryArea } from '@wordpress/interface'; +import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { withPluginContext } from '@wordpress/plugins'; -import { compose } from '@wordpress/compose'; -import { starEmpty, starFilled } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import PinnedPlugins from '../../header/pinned-plugins'; -import Sidebar from '../'; -import SidebarHeader from '../sidebar-header'; - -function PluginSidebar( props ) { - const { - children, - className, - icon, - isActive, - isPinnable = true, - isPinned, - sidebarName, - title, - togglePin, - toggleSidebar, - } = props; - - return ( - <> - { isPinnable && ( - <PinnedPlugins> - { isPinned && ( - <Button - icon={ icon } - label={ title } - onClick={ toggleSidebar } - isPressed={ isActive } - aria-expanded={ isActive } - /> - ) } - </PinnedPlugins> - ) } - <Sidebar name={ sidebarName }> - <SidebarHeader closeLabel={ __( 'Close plugin' ) }> - <strong>{ title }</strong> - { isPinnable && ( - <Button - icon={ isPinned ? starFilled : starEmpty } - label={ - isPinned - ? __( 'Unpin from toolbar' ) - : __( 'Pin to toolbar' ) - } - onClick={ togglePin } - isPressed={ isPinned } - aria-expanded={ isPinned } - /> - ) } - </SidebarHeader> - <Panel className={ className }>{ children }</Panel> - </Sidebar> - </> - ); -} /** * Renders a sidebar when activated. The contents within the `PluginSidebar` will appear as content within the sidebar. @@ -84,7 +22,8 @@ function PluginSidebar( props ) { * @param {boolean} [props.isPinnable=true] Whether to allow to pin sidebar to toolbar. * @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element, to be rendered when the sidebar is pinned to toolbar. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var __ = wp.i18n.__; @@ -110,7 +49,8 @@ function PluginSidebar( props ) { * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```jsx * // Using ESNext syntax * import { __ } from '@wordpress/i18n'; @@ -130,44 +70,26 @@ function PluginSidebar( props ) { * </PluginSidebar> * ); * ``` - * - * @return {WPComponent} Plugin sidebar component. */ -export default compose( - withPluginContext( ( context, ownProps ) => { +export default function PluginSidebarEditPost( { className, ...props } ) { + const { postTitle, shortcut } = useSelect( ( select ) => { return { - icon: ownProps.icon || context.icon, - sidebarName: `${ context.name }/${ ownProps.name }`, + postTitle: select( 'core/editor' ).getEditedPostAttribute( + 'title' + ), + shortcut: select( + 'core/keyboard-shortcuts' + ).getShortcutRepresentation( 'core/edit-post/toggle-sidebar' ), }; - } ), - withSelect( ( select, { sidebarName } ) => { - const { getActiveGeneralSidebarName, isPluginItemPinned } = select( - 'core/edit-post' - ); - - return { - isActive: getActiveGeneralSidebarName() === sidebarName, - isPinned: isPluginItemPinned( sidebarName ), - }; - } ), - withDispatch( ( dispatch, { isActive, sidebarName } ) => { - const { - closeGeneralSidebar, - openGeneralSidebar, - togglePinnedPluginItem, - } = dispatch( 'core/edit-post' ); - - return { - togglePin() { - togglePinnedPluginItem( sidebarName ); - }, - toggleSidebar() { - if ( isActive ) { - closeGeneralSidebar(); - } else { - openGeneralSidebar( sidebarName ); - } - }, - }; - } ) -)( PluginSidebar ); + } ); + return ( + <ComplementaryArea + panelClassName={ className } + className="edit-post-sidebar" + smallScreenTitle={ postTitle || __( '(no title)' ) } + scope="core/edit-post" + toggleShortcut={ shortcut } + { ...props } + /> + ); +} diff --git a/packages/edit-post/src/components/sidebar/settings-header/index.js b/packages/edit-post/src/components/sidebar/settings-header/index.js index 4f2a2d4ebe9ff2..b4317b9217906f 100644 --- a/packages/edit-post/src/components/sidebar/settings-header/index.js +++ b/packages/edit-post/src/components/sidebar/settings-header/index.js @@ -5,11 +5,6 @@ import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { withDispatch } from '@wordpress/data'; -/** - * Internal dependencies - */ -import SidebarHeader from '../sidebar-header'; - const SettingsHeader = ( { openDocumentSettings, openBlockSettings, @@ -30,35 +25,30 @@ const SettingsHeader = ( { : // translators: ARIA label for the Settings Sidebar tab, not selected. [ __( 'Block' ), '' ]; + /* Use a list so screen readers will announce how many tabs there are. */ return ( - <SidebarHeader - className="edit-post-sidebar__panel-tabs" - closeLabel={ __( 'Close settings' ) } - > - { /* Use a list so screen readers will announce how many tabs there are. */ } - <ul> - <li> - <Button - onClick={ openDocumentSettings } - className={ `edit-post-sidebar__panel-tab ${ documentActiveClass }` } - aria-label={ documentAriaLabel } - data-label={ __( 'Document' ) } - > - { __( 'Document' ) } - </Button> - </li> - <li> - <Button - onClick={ openBlockSettings } - className={ `edit-post-sidebar__panel-tab ${ blockActiveClass }` } - aria-label={ blockAriaLabel } - data-label={ blockLabel } - > - { blockLabel } - </Button> - </li> - </ul> - </SidebarHeader> + <ul> + <li> + <Button + onClick={ openDocumentSettings } + className={ `edit-post-sidebar__panel-tab ${ documentActiveClass }` } + aria-label={ documentAriaLabel } + data-label={ __( 'Document' ) } + > + { __( 'Document' ) } + </Button> + </li> + <li> + <Button + onClick={ openBlockSettings } + className={ `edit-post-sidebar__panel-tab ${ blockActiveClass }` } + aria-label={ blockAriaLabel } + data-label={ blockLabel } + > + { blockLabel } + </Button> + </li> + </ul> ); }; diff --git a/packages/edit-post/src/components/sidebar/settings-header/style.scss b/packages/edit-post/src/components/sidebar/settings-header/style.scss index 5411341b547e3c..04684bc06b4232 100644 --- a/packages/edit-post/src/components/sidebar/settings-header/style.scss +++ b/packages/edit-post/src/components/sidebar/settings-header/style.scss @@ -13,6 +13,8 @@ } .components-button.edit-post-sidebar__panel-tab { + border-radius: 0; + height: 50px - $border-width; background: transparent; border: none; box-shadow: none; @@ -22,9 +24,6 @@ margin-left: 0; font-weight: 400; color: $dark-gray-900; - @include square-style__neutral; - transition: box-shadow 0.1s linear; - @include reduce-motion("transition"); // This pseudo-element "duplicates" the tab label and sets the text to bold. // This ensures that the tab doesn't change width when selected. @@ -40,7 +39,8 @@ } &.is-active { - box-shadow: inset 0 -4px theme(outlines); + // The transparent shadow ensures no jumpiness when focus animates on an active tab. + box-shadow: inset 0 0 0 $border-width-focus transparent, inset 0 0 -$border-width-tab 0 0 $theme-color; font-weight: 600; position: relative; @@ -52,12 +52,15 @@ bottom: 1px; right: 0; left: 0; - border-bottom: 4px solid transparent; + border-bottom: $border-width-tab solid transparent; } } &:focus { - background-color: transparent; - @include square-style__focus; + box-shadow: inset 0 0 0 $border-width-focus $theme-color; + } + + &.is-active:focus { + box-shadow: inset 0 0 0 $border-width-focus $theme-color, inset 0 0 -$border-width-tab 0 0 $theme-color; } } diff --git a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js index df162808e438d5..4a408b1b63f350 100644 --- a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js +++ b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js @@ -1,15 +1,11 @@ /** * WordPress dependencies */ -import { Panel } from '@wordpress/components'; -import { compose, ifCondition } from '@wordpress/compose'; -import { withSelect } from '@wordpress/data'; import { BlockInspector } from '@wordpress/block-editor'; /** * Internal dependencies */ -import Sidebar from '../'; import SettingsHeader from '../settings-header'; import PostStatus from '../post-status'; import LastRevision from '../last-revision'; @@ -21,11 +17,30 @@ import DiscussionPanel from '../discussion-panel'; import PageAttributes from '../page-attributes'; import MetaBoxes from '../../meta-boxes'; import PluginDocumentSettingPanel from '../plugin-document-setting-panel'; +import PluginSidebarEditPost from '../../sidebar/plugin-sidebar'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; -const SettingsSidebar = ( { sidebarName } ) => ( - <Sidebar name={ sidebarName }> - <SettingsHeader sidebarName={ sidebarName } /> - <Panel> +const SettingsSidebar = () => { + const sidebarName = useSelect( + ( select ) => + select( 'core/interface' ).getActiveComplementaryArea( + 'core/edit-post' + ), + [] + ); + if ( + ! [ 'edit-post/document', 'edit-post/block' ].includes( sidebarName ) + ) { + return null; + } + return ( + <PluginSidebarEditPost + complementaryAreaIdentifier={ sidebarName } + header={ <SettingsHeader sidebarName={ sidebarName } /> } + closeLabel={ __( 'Close settings' ) } + headerClassName="edit-post-sidebar__panel-tabs" + > { sidebarName === 'edit-post/document' && ( <> <PostStatus /> @@ -41,20 +56,8 @@ const SettingsSidebar = ( { sidebarName } ) => ( </> ) } { sidebarName === 'edit-post/block' && <BlockInspector /> } - </Panel> - </Sidebar> -); + </PluginSidebarEditPost> + ); +}; -export default compose( - withSelect( ( select ) => { - const { getActiveGeneralSidebarName, isEditorSidebarOpened } = select( - 'core/edit-post' - ); - - return { - isEditorSidebarOpened: isEditorSidebarOpened(), - sidebarName: getActiveGeneralSidebarName(), - }; - } ), - ifCondition( ( { isEditorSidebarOpened } ) => isEditorSidebarOpened ) -)( SettingsSidebar ); +export default SettingsSidebar; diff --git a/packages/edit-post/src/components/sidebar/sidebar-header/index.js b/packages/edit-post/src/components/sidebar/sidebar-header/index.js deleted file mode 100644 index 748992e82b0426..00000000000000 --- a/packages/edit-post/src/components/sidebar/sidebar-header/index.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { Button } from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { close } from '@wordpress/icons'; - -const SidebarHeader = ( { children, className, closeLabel } ) => { - const { shortcut, title } = useSelect( - ( select ) => ( { - shortcut: select( - 'core/keyboard-shortcuts' - ).getShortcutRepresentation( 'core/edit-post/toggle-sidebar' ), - title: select( 'core/editor' ).getEditedPostAttribute( 'title' ), - } ), - [] - ); - const { closeGeneralSidebar } = useDispatch( 'core/edit-post' ); - - // The `tabIndex` serves the purpose of normalizing browser behavior of - // button clicks and focus. Notably, without making the header focusable, a - // Button click would not trigger a focus event in macOS Firefox. Thus, when - // the sidebar is unmounted, the corresponding "focus return" behavior to - // shift focus back to the heading toolbar would not be run. - // - // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus - - return ( - <> - <div className="components-panel__header edit-post-sidebar-header__small"> - <span className="edit-post-sidebar-header__title"> - { title || __( '(no title)' ) } - </span> - <Button - onClick={ closeGeneralSidebar } - icon={ close } - label={ closeLabel } - /> - </div> - <div - className={ classnames( - 'components-panel__header edit-post-sidebar-header', - className - ) } - tabIndex={ -1 } - > - { children } - <Button - onClick={ closeGeneralSidebar } - icon={ close } - label={ closeLabel } - shortcut={ shortcut } - /> - </div> - </> - ); -}; - -export default SidebarHeader; diff --git a/packages/edit-post/src/components/sidebar/style.scss b/packages/edit-post/src/components/sidebar/style.scss index f960c6757c3033..d3be8c5f30caa5 100644 --- a/packages/edit-post/src/components/sidebar/style.scss +++ b/packages/edit-post/src/components/sidebar/style.scss @@ -1,107 +1,3 @@ -.edit-post-sidebar { - background: $white; - color: $dark-gray-500; - overflow: visible; - - @include break-small() { - z-index: auto; - height: 100%; - overflow: auto; - -webkit-overflow-scrolling: touch; - } - - @include break-medium() { - width: $sidebar-width; - } - - > .components-panel { - border-left: none; - border-right: none; - overflow: auto; - -webkit-overflow-scrolling: touch; - height: auto; - max-height: calc(100vh - #{ $admin-bar-height-big + $panel-header-height + $panel-header-height }); - margin-top: -1px; - margin-bottom: -1px; - position: relative; - - @include break-small() { - overflow: visible; - height: auto; - max-height: none; - } - } - - > .components-panel .components-panel__header { - position: fixed; - z-index: z-index(".components-panel__header"); - top: 0; - left: 0; - right: 0; - height: $panel-header-height; - - @include break-small() { - position: inherit; - top: auto; - left: auto; - right: auto; - } - } - - p { - margin-top: 0; - } - - h2, - h3 { - font-size: $default-font-size; - color: $dark-gray-500; - margin-bottom: 1.5em; - } - - hr { - border-top: none; - border-bottom: 1px solid $light-gray-500; - margin: 1.5em 0; - } - - div.components-toolbar { - box-shadow: none; - margin-bottom: 1.5em; - &:last-child { - margin-bottom: 0; - } - } - - p + div.components-toolbar { - margin-top: -1em; - } - - .block-editor-skip-to-selected-block:focus { - top: auto; - right: 10px; - bottom: 10px; - left: auto; - } -} - -/* Text Editor specific */ -.components-panel__header.edit-post-sidebar__header { - background: $white; - padding-right: $panel-padding / 2; - - .edit-post-sidebar__title { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - } - - @include break-medium() { - display: none; - } -} - .components-panel__header.edit-post-sidebar__panel-tabs { justify-content: flex-start; padding-left: 0; @@ -118,40 +14,3 @@ } } } - -.edit-post-sidebar__panel-tab { - background: transparent; - border: none; - border-radius: 0; - box-shadow: none; - cursor: pointer; - height: 50px; - padding: 3px 15px; // Use padding to offset the is-active border, this benefits Windows High Contrast mode - margin-left: 0; - font-weight: 400; - @include square-style__neutral; - transition: box-shadow 0.1s linear; - @include reduce-motion("transition"); - - &.is-active { - box-shadow: inset 0 -3px theme(outlines); - font-weight: 600; - position: relative; - - // This border appears in Windows High Contrast mode instead of the box-shadow. - &::before { - content: ""; - position: absolute; - top: 0; - bottom: 1px; - right: 0; - left: 0; - border-bottom: 3px solid transparent; - } - } - - &:focus:not(:disabled) { - @include square-style__focus; - box-shadow: none; - } -} diff --git a/packages/edit-post/src/components/text-editor/style.scss b/packages/edit-post/src/components/text-editor/style.scss index 9bbb44b8ee96ad..368c843a72f465 100644 --- a/packages/edit-post/src/components/text-editor/style.scss +++ b/packages/edit-post/src/components/text-editor/style.scss @@ -5,7 +5,7 @@ flex-grow: 1; // Always show outlines in code editor - .editor-post-title__block { + .editor-post-title { textarea { border: $border-width solid $light-gray-500; margin-bottom: $block-spacing; @@ -16,20 +16,8 @@ border: $border-width solid $black; } } - } - - .editor-post-permalink { - margin-top: -6px; - // Hide the thick left border in the code editor. - box-shadow: none; - border: none; - outline: $border-width solid $dark-gray-primary; - } - - @include break-small() { - .editor-post-title, - .editor-post-title__block { + @include break-small() { padding: 0; } } diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js index b34d8a1375b66c..9929a6699674f3 100644 --- a/packages/edit-post/src/components/visual-editor/index.js +++ b/packages/edit-post/src/components/visual-editor/index.js @@ -39,7 +39,9 @@ function VisualEditor() { <WritingFlow> <ObserveTyping> <CopyHandler> - <PostTitle /> + <div className="edit-post-visual-editor__post-title-wrapper"> + <PostTitle /> + </div> <BlockList /> </CopyHandler> </ObserveTyping> diff --git a/packages/edit-post/src/components/visual-editor/style.native.scss b/packages/edit-post/src/components/visual-editor/style.native.scss index 77c87b662c0bbe..223cbacd08bd6b 100644 --- a/packages/edit-post/src/components/visual-editor/style.native.scss +++ b/packages/edit-post/src/components/visual-editor/style.native.scss @@ -5,8 +5,6 @@ border-right-width: $block-selected-border-width; border-radius: 4px; border-style: solid; - margin-left: $block-selected-margin; - margin-right: $block-selected-margin; } .blockHolderFocused { diff --git a/packages/edit-post/src/components/visual-editor/style.scss b/packages/edit-post/src/components/visual-editor/style.scss index b29292d18308af..acdf055d22faa1 100644 --- a/packages/edit-post/src/components/visual-editor/style.scss +++ b/packages/edit-post/src/components/visual-editor/style.scss @@ -42,40 +42,27 @@ margin-right: auto; } +// Ideally this wrapper div is not needed but if we waant to match the positionning of blocks +// .block-editor-block-list__layout and block-editor-block-list__block +// We need to have two DOM elements. +.edit-post-visual-editor__post-title-wrapper { + // This padding is needed to match the block root container padding + padding-left: $block-padding; + padding-right: $block-padding; -// The base width of the title should match that of blocks even if it isn't a block. -// @todo: This duplicates CSS from line 49 in block-list/style.scss, and should be -// removed when the Title field becomes an actual block. -.editor-post-title { - // Beyond the mobile breakpoint, compensate for side UI. @include break-small() { - padding-left: $block-padding + $block-side-ui-width + $block-padding + $border-width * 2; - padding-right: $block-padding + $block-side-ui-width + $block-padding + $border-width * 2; + padding-left: $block-side-ui-width; + padding-right: $block-side-ui-width; } -} - -.edit-post-visual-editor .editor-post-title__block { - // Center. - margin-left: auto; - margin-right: auto; - // Apply default block margin below the post title. - // This ensures the first block on the page is in a good position. - // This rule can be retired once the title becomes an actual block. - margin-bottom: ($block-padding * 2) + $block-spacing; // This matches 2em in the vanilla style. + .editor-post-title { + // Center. + margin-left: auto; + margin-right: auto; - // Stack borders. - > div { - margin-left: 0; - margin-right: 0; - } - - // Stretch to mimic outline padding on desktop. - // Note that we can't target the textarea as it can't be stretched. - @include break-small() { - > div { - margin-left: -$block-padding - $block-side-ui-clearance; - margin-right: -$block-padding - $block-side-ui-clearance; - } + // Apply default block margin below the post title. + // This ensures the first block on the page is in a good position. + // This rule can be retired once the title becomes an actual block. + margin-bottom: ($block-padding * 2) + $block-spacing; // This matches 2em in the vanilla style. } } diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 086553ee738b61..1d5475c63535f8 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -113,14 +113,14 @@ export function initializeEditor( // Without this hack the browser scrolls the mobile toolbar off-screen. // Once supported in Safari we can replace this in favor of preventScroll. // For details see issue #18632 and PR #18686 - // Specifically, we scroll `block-editor-editor-skeleton__body` to enable a fixed top toolbar. + // Specifically, we scroll `interface-interface-skeleton__body` to enable a fixed top toolbar. // But Mobile Safari forces the `html` element to scroll upwards, hiding the toolbar. const isIphone = window.navigator.userAgent.indexOf( 'iPhone' ) !== -1; if ( isIphone ) { window.addEventListener( 'scroll', function( event ) { const editorScrollContainer = document.getElementsByClassName( - 'block-editor-editor-skeleton__body' + 'interface-interface-skeleton__body' )[ 0 ]; if ( event.target === document ) { // Scroll element into view by scrolling the editor container by the same amount diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index eec8afd6b38240..33140b34f7d09d 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -3,29 +3,38 @@ */ import { castArray } from 'lodash'; +/** + * WordPress dependencies + */ +import { dispatch } from '@wordpress/data-controls'; + /** * Returns an action object used in signalling that the user opened an editor sidebar. * - * @param {string} name Sidebar name to be opened. + * @param {?string} name Sidebar name to be opened. * - * @return {Object} Action object. + * @yield {Object} Action object. */ -export function openGeneralSidebar( name ) { - return { - type: 'OPEN_GENERAL_SIDEBAR', - name, - }; +export function* openGeneralSidebar( name ) { + yield dispatch( + 'core/interface', + 'enableComplementaryArea', + 'core/edit-post', + name + ); } /** * Returns an action object signalling that the user closed the sidebar. * - * @return {Object} Action object. + * @yield {Object} Action object. */ -export function closeGeneralSidebar() { - return { - type: 'CLOSE_GENERAL_SIDEBAR', - }; +export function* closeGeneralSidebar() { + yield dispatch( + 'core/interface', + 'disableComplementaryArea', + 'core/edit-post' + ); } /** diff --git a/packages/edit-post/src/store/defaults.js b/packages/edit-post/src/store/defaults.js index 1b90986e222a9a..64435c05ce74c1 100644 --- a/packages/edit-post/src/store/defaults.js +++ b/packages/edit-post/src/store/defaults.js @@ -1,6 +1,5 @@ export const PREFERENCES_DEFAULTS = { editorMode: 'visual', - isGeneralSidebarDismissed: false, panels: { 'post-status': { opened: true, @@ -11,7 +10,6 @@ export const PREFERENCES_DEFAULTS = { welcomeGuide: true, fullscreenMode: true, }, - pinnedPluginItems: {}, hiddenBlockTypes: [], preferredStyleVariations: {}, localAutosaveInterval: 15, diff --git a/packages/edit-post/src/store/defaults.native.js b/packages/edit-post/src/store/defaults.native.js deleted file mode 100644 index 7ac420b872cadc..00000000000000 --- a/packages/edit-post/src/store/defaults.native.js +++ /dev/null @@ -1,14 +0,0 @@ -export const PREFERENCES_DEFAULTS = { - editorMode: 'visual', - isGeneralSidebarDismissed: true, - panels: { - 'post-status': { - opened: true, - }, - }, - features: { - fixedToolbar: true, - }, - pinnedPluginItems: {}, - hiddenBlockTypes: [], -}; diff --git a/packages/edit-post/src/store/index.js b/packages/edit-post/src/store/index.js index 4560fd12d46bbb..de84aaf3062ab0 100644 --- a/packages/edit-post/src/store/index.js +++ b/packages/edit-post/src/store/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { registerStore } from '@wordpress/data'; +import { controls as dataControls } from '@wordpress/data-controls'; /** * Internal dependencies @@ -17,7 +18,10 @@ const store = registerStore( STORE_KEY, { reducer, actions, selectors, - controls, + controls: { + ...dataControls, + ...controls, + }, persist: [ 'preferences' ], } ); diff --git a/packages/edit-post/src/store/reducer.js b/packages/edit-post/src/store/reducer.js index 27e5c29493976a..de17f27eedde01 100644 --- a/packages/edit-post/src/store/reducer.js +++ b/packages/edit-post/src/store/reducer.js @@ -55,15 +55,6 @@ export const preferences = flow( [ combineReducers, createWithInitialState( PREFERENCES_DEFAULTS ), ] )( { - isGeneralSidebarDismissed( state, action ) { - switch ( action.type ) { - case 'OPEN_GENERAL_SIDEBAR': - case 'CLOSE_GENERAL_SIDEBAR': - return action.type === 'CLOSE_GENERAL_SIDEBAR'; - } - - return state; - }, panels( state, action ) { switch ( action.type ) { case 'TOGGLE_PANEL_ENABLED': { @@ -111,19 +102,6 @@ export const preferences = flow( [ return state; }, - pinnedPluginItems( state, action ) { - if ( action.type === 'TOGGLE_PINNED_PLUGIN_ITEM' ) { - return { - ...state, - [ action.pluginName ]: ! get( - state, - [ action.pluginName ], - true - ), - }; - } - return state; - }, hiddenBlockTypes( state, action ) { switch ( action.type ) { case 'SHOW_BLOCK_TYPES': @@ -181,27 +159,6 @@ export function removedPanels( state = [], action ) { return state; } -/** - * Reducer returning the next active general sidebar state. The active general - * sidebar is a unique name to identify either an editor or plugin sidebar. - * - * @param {?string} state Current state. - * @param {Object} action Action object. - * - * @return {?string} Updated state. - */ -export function activeGeneralSidebar( - state = DEFAULT_ACTIVE_GENERAL_SIDEBAR, - action -) { - switch ( action.type ) { - case 'OPEN_GENERAL_SIDEBAR': - return action.name; - } - - return state; -} - /** * Reducer for storing the name of the open modal, or null if no modal is open. * @@ -294,7 +251,6 @@ const metaBoxes = combineReducers( { } ); export default combineReducers( { - activeGeneralSidebar, activeModal, metaBoxes, preferences, diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index d2742fb3fe181c..fd99d43279462c 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -4,6 +4,11 @@ import createSelector from 'rememo'; import { get, includes, some, flatten, values } from 'lodash'; +/** + * WordPress dependencies + */ +import { createRegistrySelector } from '@wordpress/data'; + /** * Returns the current editing mode. * @@ -22,14 +27,17 @@ export function getEditorMode( state ) { * * @return {boolean} Whether the editor sidebar is opened. */ -export function isEditorSidebarOpened( state ) { - const activeGeneralSidebar = getActiveGeneralSidebarName( state ); - - return includes( - [ 'edit-post/document', 'edit-post/block' ], - activeGeneralSidebar - ); -} +export const isEditorSidebarOpened = createRegistrySelector( + ( select ) => () => { + const activeGeneralSidebar = select( + 'core/interface' + ).getActiveComplementaryArea( 'core/edit-post' ); + return includes( + [ 'edit-post/document', 'edit-post/block' ], + activeGeneralSidebar + ); + } +); /** * Returns true if the plugin sidebar is opened. @@ -37,10 +45,20 @@ export function isEditorSidebarOpened( state ) { * @param {Object} state Global application state * @return {boolean} Whether the plugin sidebar is opened. */ -export function isPluginSidebarOpened( state ) { - const activeGeneralSidebar = getActiveGeneralSidebarName( state ); - return !! activeGeneralSidebar && ! isEditorSidebarOpened( state ); -} +export const isPluginSidebarOpened = createRegistrySelector( + ( select ) => () => { + const activeGeneralSidebar = select( + 'core/interface' + ).getActiveComplementaryArea( 'core/edit-post' ); + return ( + !! activeGeneralSidebar && + ! includes( + [ 'edit-post/document', 'edit-post/block' ], + activeGeneralSidebar + ) + ); + } +); /** * Returns the current active general sidebar name, or null if there is no @@ -56,19 +74,13 @@ export function isPluginSidebarOpened( state ) { * * @return {?string} Active general sidebar name. */ -export function getActiveGeneralSidebarName( state ) { - // Dismissal takes precedent. - const isDismissed = getPreference( - state, - 'isGeneralSidebarDismissed', - false - ); - if ( isDismissed ) { - return null; +export const getActiveGeneralSidebarName = createRegistrySelector( + ( select ) => () => { + return select( 'core/interface' ).getActiveComplementaryArea( + 'core/edit-post' + ); } - - return state.activeGeneralSidebar; -} +); /** * Returns the preferences (these preferences are persisted locally). @@ -187,11 +199,14 @@ export function isFeatureActive( state, feature ) { * * @return {boolean} Whether the plugin item is pinned. */ -export function isPluginItemPinned( state, pluginName ) { - const pinnedPluginItems = getPreference( state, 'pinnedPluginItems', {} ); - - return get( pinnedPluginItems, [ pluginName ], true ); -} +export const isPluginItemPinned = createRegistrySelector( + ( select ) => ( pluginName ) => { + return select( 'core/interface' ).isItemPinned( + 'core/edit-post', + pluginName + ); + } +); /** * Returns an array of active meta box locations. diff --git a/packages/edit-post/src/store/test/actions.js b/packages/edit-post/src/store/test/actions.js index 07dc4b81ece682..31877f378bb286 100644 --- a/packages/edit-post/src/store/test/actions.js +++ b/packages/edit-post/src/store/test/actions.js @@ -5,37 +5,16 @@ import { toggleEditorPanelEnabled, toggleEditorPanelOpened, removeEditorPanel, - openGeneralSidebar, - closeGeneralSidebar, openPublishSidebar, closePublishSidebar, togglePublishSidebar, openModal, closeModal, toggleFeature, - togglePinnedPluginItem, requestMetaBoxUpdates, } from '../actions'; describe( 'actions', () => { - describe( 'openGeneralSidebar', () => { - it( 'should return OPEN_GENERAL_SIDEBAR action', () => { - const name = 'plugin/my-name'; - expect( openGeneralSidebar( name ) ).toEqual( { - type: 'OPEN_GENERAL_SIDEBAR', - name, - } ); - } ); - } ); - - describe( 'closeGeneralSidebar', () => { - it( 'should return CLOSE_GENERAL_SIDEBAR action', () => { - expect( closeGeneralSidebar() ).toEqual( { - type: 'CLOSE_GENERAL_SIDEBAR', - } ); - } ); - } ); - describe( 'openPublishSidebar', () => { it( 'should return an OPEN_PUBLISH_SIDEBAR action', () => { expect( openPublishSidebar() ).toEqual( { @@ -115,17 +94,6 @@ describe( 'actions', () => { } ); } ); - describe( 'togglePinnedPluginItem', () => { - it( 'should return TOGGLE_PINNED_PLUGIN_ITEM action', () => { - const pluginName = 'foo/bar'; - - expect( togglePinnedPluginItem( pluginName ) ).toEqual( { - type: 'TOGGLE_PINNED_PLUGIN_ITEM', - pluginName, - } ); - } ); - } ); - describe( 'requestMetaBoxUpdates', () => { it( 'should return the REQUEST_META_BOX_UPDATES action', () => { expect( requestMetaBoxUpdates() ).toEqual( { diff --git a/packages/edit-post/src/store/test/reducer.js b/packages/edit-post/src/store/test/reducer.js index b21be5ff26d9ba..59a966024bf920 100644 --- a/packages/edit-post/src/store/test/reducer.js +++ b/packages/edit-post/src/store/test/reducer.js @@ -7,9 +7,7 @@ import deepFreeze from 'deep-freeze'; * Internal dependencies */ import { - DEFAULT_ACTIVE_GENERAL_SIDEBAR, preferences, - activeGeneralSidebar, activeModal, isSavingMetaBoxes, metaBoxLocations, @@ -25,30 +23,6 @@ describe( 'state', () => { expect( state ).toEqual( PREFERENCES_DEFAULTS ); } ); - it( 'should set the general sidebar dismissed', () => { - const original = deepFreeze( preferences( undefined, {} ) ); - const state = preferences( original, { - type: 'OPEN_GENERAL_SIDEBAR', - name: 'edit-post/document', - } ); - - expect( state.isGeneralSidebarDismissed ).toBe( false ); - } ); - - it( 'should set the general sidebar undismissed', () => { - const original = deepFreeze( - preferences( undefined, { - type: 'OPEN_GENERAL_SIDEBAR', - name: 'edit-post/document', - } ) - ); - const state = preferences( original, { - type: 'CLOSE_GENERAL_SIDEBAR', - } ); - - expect( state.isGeneralSidebarDismissed ).toBe( true ); - } ); - it( 'should disable panels by default', () => { const original = deepFreeze( { panels: {}, @@ -186,48 +160,6 @@ describe( 'state', () => { expect( state.features ).toEqual( { chicken: false } ); } ); - describe( 'pinnedPluginItems', () => { - const initialState = deepFreeze( { - pinnedPluginItems: { - 'foo/enabled': true, - 'foo/disabled': false, - }, - } ); - - it( 'should disable a pinned plugin flag when the value does not exist', () => { - const state = preferences( initialState, { - type: 'TOGGLE_PINNED_PLUGIN_ITEM', - pluginName: 'foo/does-not-exist', - } ); - - expect( state.pinnedPluginItems[ 'foo/does-not-exist' ] ).toBe( - false - ); - } ); - - it( 'should disable a pinned plugin flag when it is enabled', () => { - const state = preferences( initialState, { - type: 'TOGGLE_PINNED_PLUGIN_ITEM', - pluginName: 'foo/enabled', - } ); - - expect( state.pinnedPluginItems[ 'foo/enabled' ] ).toBe( - false - ); - } ); - - it( 'should enable a pinned plugin flag when it is disabled', () => { - const state = preferences( initialState, { - type: 'TOGGLE_PINNED_PLUGIN_ITEM', - pluginName: 'foo/disabled', - } ); - - expect( state.pinnedPluginItems[ 'foo/disabled' ] ).toBe( - true - ); - } ); - } ); - describe( 'hiddenBlockTypes', () => { it( 'concatenates unique names on disable', () => { const original = deepFreeze( { @@ -257,24 +189,6 @@ describe( 'state', () => { } ); } ); - describe( 'activeGeneralSidebar', () => { - it( 'should default to the default active sidebar', () => { - const state = activeGeneralSidebar( undefined, {} ); - - expect( state ).toBe( DEFAULT_ACTIVE_GENERAL_SIDEBAR ); - } ); - - it( 'should set the general sidebar', () => { - const original = activeGeneralSidebar( undefined, {} ); - const state = activeGeneralSidebar( original, { - type: 'OPEN_GENERAL_SIDEBAR', - name: 'edit-post/document', - } ); - - expect( state ).toBe( 'edit-post/document' ); - } ); - } ); - describe( 'activeModal', () => { it( 'should default to null', () => { const state = activeModal( undefined, {} ); diff --git a/packages/edit-post/src/store/test/selectors.js b/packages/edit-post/src/store/test/selectors.js index 4da4686fc0379e..f2b349890602ae 100644 --- a/packages/edit-post/src/store/test/selectors.js +++ b/packages/edit-post/src/store/test/selectors.js @@ -9,13 +9,9 @@ import deepFreeze from 'deep-freeze'; import { getEditorMode, getPreference, - isEditorSidebarOpened, isEditorPanelOpened, isModalActive, isFeatureActive, - isPluginSidebarOpened, - getActiveGeneralSidebarName, - isPluginItemPinned, hasMetaBoxes, isSavingMetaBoxes, getActiveMetaBoxLocations, @@ -71,114 +67,6 @@ describe( 'selectors', () => { } ); } ); - describe( 'isEditorSidebarOpened', () => { - it( 'should return false when the editor sidebar is not opened', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: true, - }, - activeGeneralSidebar: null, - }; - - expect( isEditorSidebarOpened( state ) ).toBe( false ); - } ); - - it( 'should return false when the editor sidebar is assigned but not opened', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: true, - }, - activeGeneralSidebar: 'edit-post/document', - }; - - expect( isEditorSidebarOpened( state ) ).toBe( false ); - } ); - - it( 'should return false when the plugin sidebar is opened', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: false, - }, - activeGeneralSidebar: 'my-plugin/my-sidebar', - }; - - expect( isEditorSidebarOpened( state ) ).toBe( false ); - } ); - - it( 'should return true when the editor sidebar is opened', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: false, - }, - activeGeneralSidebar: 'edit-post/document', - }; - - expect( isEditorSidebarOpened( state ) ).toBe( true ); - } ); - } ); - - describe( 'isPluginSidebarOpened', () => { - it( 'should return false when the plugin sidebar is not opened', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: true, - }, - activeGeneralSidebar: null, - }; - - expect( isPluginSidebarOpened( state ) ).toBe( false ); - } ); - - it( 'should return false when the editor sidebar is opened', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: false, - }, - activeGeneralSidebar: 'edit-post/document', - }; - - expect( isPluginSidebarOpened( state ) ).toBe( false ); - } ); - - it( 'should return true when the plugin sidebar is opened', () => { - const name = 'plugin-sidebar/my-plugin/my-sidebar'; - const state = { - preferences: { - isGeneralSidebarDismissed: false, - }, - activeGeneralSidebar: name, - }; - - expect( isPluginSidebarOpened( state ) ).toBe( true ); - } ); - } ); - - describe( 'getActiveGeneralSidebarName', () => { - it( 'returns null if dismissed', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: true, - }, - activeGeneralSidebar: 'edit-post/block', - }; - - expect( getActiveGeneralSidebarName( state ) ).toBe( null ); - } ); - - it( 'returns active general sidebar', () => { - const state = { - preferences: { - isGeneralSidebarDismissed: false, - }, - activeGeneralSidebar: 'edit-post/block', - }; - - expect( getActiveGeneralSidebarName( state ) ).toBe( - 'edit-post/block' - ); - } ); - } ); - describe( 'isModalActive', () => { it( 'returns true if the provided name matches the value in the preferences activeModal property', () => { const state = { @@ -394,29 +282,6 @@ describe( 'selectors', () => { } ); } ); - describe( 'isPluginItemPinned', () => { - const state = { - preferences: { - pinnedPluginItems: { - 'foo/pinned': true, - 'foo/unpinned': false, - }, - }, - }; - - it( 'should return true if the flag is not set for the plugin item', () => { - expect( isPluginItemPinned( state, 'foo/unknown' ) ).toBe( true ); - } ); - - it( 'should return true if plugin item is not pinned', () => { - expect( isPluginItemPinned( state, 'foo/pinned' ) ).toBe( true ); - } ); - - it( 'should return false if plugin item item is unpinned', () => { - expect( isPluginItemPinned( state, 'foo/unpinned' ) ).toBe( false ); - } ); - } ); - describe( 'hasMetaBoxes', () => { it( 'should return true if there are active meta boxes', () => { const state = { diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index e9a85641e28a29..4e6fea9f88bee4 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -1,10 +1,11 @@ $footer-height: $button-size-small; +@import "../../interface/src/style.scss"; + @import "./components/header/style.scss"; @import "./components/header/fullscreen-mode-close/style.scss"; @import "./components/header/header-toolbar/style.scss"; @import "./components/header/more-menu/style.scss"; -@import "./components/header/pinned-plugins/style.scss"; @import "./components/keyboard-shortcut-help-modal/style.scss"; @import "./components/layout/style.scss"; @import "./components/manage-blocks-modal/style.scss"; @@ -19,7 +20,6 @@ $footer-height: $button-size-small; @import "./components/sidebar/post-status/style.scss"; @import "./components/sidebar/post-visibility/style.scss"; @import "./components/sidebar/settings-header/style.scss"; -@import "./components/sidebar/sidebar-header/style.scss"; @import "./components/text-editor/style.scss"; @import "./components/visual-editor/style.scss"; @import "./components/options-modal/style.scss"; diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 1a3f8f86066295..793d3a821c6797 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -20,7 +20,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/block-editor": "file:../block-editor", "@wordpress/block-library": "file:../block-library", "@wordpress/blocks": "file:../blocks", @@ -33,8 +33,10 @@ "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/interface": "file:../interface", "@wordpress/media-utils": "file:../media-utils", "@wordpress/notices": "file:../notices", + "@wordpress/plugins": "file:../plugins", "@wordpress/primitives": "file:../primitives", "@wordpress/url": "file:../url", "file-saver": "^2.0.2", diff --git a/packages/edit-site/src/components/block-editor/style.scss b/packages/edit-site/src/components/block-editor/style.scss index c0e285bc77546d..a1872f964f952d 100644 --- a/packages/edit-site/src/components/block-editor/style.scss +++ b/packages/edit-site/src/components/block-editor/style.scss @@ -1,4 +1,14 @@ .edit-site-block-editor__block-list { padding-bottom: $grid-unit-30; padding-top: $grid-unit-30 + 5; + + padding-left: $block-padding; + padding-right: $block-padding; + + // Full-wide. (to account for the padddings added above) + .block-editor-block-list__block[data-align="full"], + .block-editor-block-list__block.alignfull { + margin-left: -$block-padding; + margin-right: -$block-padding; + } } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index ea1b3bbf782c8f..66640b22f41e6f 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -16,10 +16,11 @@ import { } from '@wordpress/components'; import { EntityProvider } from '@wordpress/core-data'; import { - __experimentalEditorSkeleton as EditorSkeleton, - __experimentalFullscreenMode as FullscreenMode, + BlockBreadcrumb, + __unstableEditorStyles as EditorStyles, } from '@wordpress/block-editor'; import { useViewportMatch } from '@wordpress/compose'; +import { FullscreenMode, InterfaceSkeleton } from '@wordpress/interface'; /** * Internal dependencies @@ -61,6 +62,7 @@ function Editor( { settings: _settings } ) { return template ? ( <> + <EditorStyles styles={ settings.styles } /> <FullscreenMode isActive={ isFullscreenActive } /> <SlotFillProvider> <DropZoneProvider> @@ -72,7 +74,7 @@ function Editor( { settings: _settings } ) { > <Context.Provider value={ context }> <FocusReturnProvider> - <EditorSkeleton + <InterfaceSkeleton sidebar={ ! isMobile && <Sidebar /> } header={ <Header /> } content={ @@ -82,6 +84,7 @@ function Editor( { settings: _settings } ) { <BlockEditor /> </> } + footer={ <BlockBreadcrumb /> } /> <Popover.Slot /> </FocusReturnProvider> diff --git a/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss b/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss index a8ae5d8e446266..e8b4eb7b781ccd 100644 --- a/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss +++ b/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss @@ -23,7 +23,7 @@ } &:focus { - box-shadow: inset 0 0 0 2px color($theme-color), inset 0 0 0 3px $white; + box-shadow: inset 0 0 0 $border-width-focus $theme-color, inset 0 0 0 3px $white; } } } diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index a69b8508ee8cca..867dc74ed1d15e 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -2,7 +2,12 @@ * WordPress dependencies */ import { useCallback } from '@wordpress/element'; -import { BlockNavigationDropdown, ToolSelector } from '@wordpress/block-editor'; +import { + BlockNavigationDropdown, + ToolSelector, + Inserter, +} from '@wordpress/block-editor'; +import { PinnedItems } from '@wordpress/interface'; /** * Internal dependencies @@ -13,6 +18,8 @@ import MoreMenu from './more-menu'; import TemplateSwitcher from '../template-switcher'; import SaveButton from '../save-button'; +const inserterToggleProps = { isPrimary: true }; + export default function Header() { const { settings, setSettings } = useEditorContext(); const setActiveTemplateId = useCallback( @@ -46,6 +53,11 @@ export default function Header() { <div className="edit-site-header"> <FullscreenModeClose /> <div className="edit-site-header__toolbar"> + <Inserter + position="bottom right" + showInserterHelpPanel + toggleProps={ inserterToggleProps } + /> <TemplateSwitcher ids={ settings.templateIds } templatePartIds={ settings.templatePartIds } @@ -62,6 +74,7 @@ export default function Header() { </div> <div className="edit-site-header__actions"> <SaveButton /> + <PinnedItems.Slot scope="core/edit-site" /> <MoreMenu /> </div> </div> diff --git a/packages/edit-site/src/components/header/style.scss b/packages/edit-site/src/components/header/style.scss index 37312b6e619ed7..80c91d2880b8ec 100644 --- a/packages/edit-site/src/components/header/style.scss +++ b/packages/edit-site/src/components/header/style.scss @@ -9,6 +9,7 @@ .edit-site-header__toolbar { display: flex; flex-grow: 1; + padding-left: $grid-unit-10; & > * { margin-left: 5px; diff --git a/packages/edit-site/src/components/save-button/index.js b/packages/edit-site/src/components/save-button/index.js index 410f8d5970d399..28af9be05d723b 100644 --- a/packages/edit-site/src/components/save-button/index.js +++ b/packages/edit-site/src/components/save-button/index.js @@ -53,12 +53,13 @@ export default function SaveButton() { const disabled = ! isDirty || isSaving; const [ isOpen, setIsOpen ] = useState( false ); - const open = useCallback( setIsOpen.bind( null, true ), [] ); - const close = useCallback( setIsOpen.bind( null, false ), [] ); + const open = useCallback( () => setIsOpen( true ), [] ); + const close = useCallback( () => setIsOpen( false ), [] ); return ( <> <Button isPrimary + className="edit-site-save-button__button" aria-disabled={ disabled } disabled={ disabled } isBusy={ isSaving } diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js index 060c2ddce1a510..f5ee7eda2d9a23 100644 --- a/packages/edit-site/src/components/sidebar/index.js +++ b/packages/edit-site/src/components/sidebar/index.js @@ -1,20 +1,35 @@ /** * WordPress dependencies */ -import { createSlotFill, Panel } from '@wordpress/components'; +import { createSlotFill } from '@wordpress/components'; +import { ComplementaryArea } from '@wordpress/interface'; import { __ } from '@wordpress/i18n'; +import { cog, pencil } from '@wordpress/icons'; const { Slot: InspectorSlot, Fill: InspectorFill } = createSlotFill( 'EditSiteSidebarInspector' ); - function Sidebar() { return ( - <div className="edit-site-sidebar"> - <Panel header={ __( 'Inspector' ) }> + <> + <ComplementaryArea.Slot scope="core/edit-site" /> + <ComplementaryArea + scope="core/edit-site" + complementaryAreaIdentifier="edit-site/block-inspector" + title={ __( 'Block Inspector' ) } + icon={ cog } + > <InspectorSlot bubblesVirtually /> - </Panel> - </div> + </ComplementaryArea> + <ComplementaryArea + scope="core/edit-site" + complementaryAreaIdentifier="edit-site/global-styles" + title={ __( 'Global Styles' ) } + icon={ pencil } + > + <p>Global Styles area</p> + </ComplementaryArea> + </> ); } diff --git a/packages/edit-site/src/components/template-switcher/index.js b/packages/edit-site/src/components/template-switcher/index.js index d3192ac9a718dd..d3397089c1bfd4 100644 --- a/packages/edit-site/src/components/template-switcher/index.js +++ b/packages/edit-site/src/components/template-switcher/index.js @@ -6,13 +6,12 @@ import { useSelect } from '@wordpress/data'; import { useState, useCallback } from '@wordpress/element'; import { Tooltip, - Icon, DropdownMenu, MenuGroup, MenuItemsChoice, MenuItem, } from '@wordpress/components'; -import { layout, plus } from '@wordpress/icons'; +import { plus } from '@wordpress/icons'; /** * Internal dependencies @@ -22,19 +21,14 @@ import TemplatePreview from './preview'; function TemplateLabel( { template } ) { return ( - <div className="edit-site-template-switcher__label"> + <> { template.slug }{ ' ' } { template.status !== 'auto-draft' && ( <Tooltip text={ __( 'Customized' ) }> - <div className="edit-site-template-switcher__label-customized-icon-container"> - <Icon - icon="marker" - className="edit-site-template-switcher__label-customized-icon-icon" - /> - </div> + <span className="edit-site-template-switcher__label-customized-dot" /> </Tooltip> ) } - </div> + </> ); } @@ -68,10 +62,10 @@ export default function TemplateSwitcher( { label: template ? ( <TemplateLabel template={ template } /> ) : ( - __( 'loading…' ) + __( 'Loading…' ) ), value: id, - slug: template ? template.slug : __( 'loading…' ), + slug: template ? template.slug : __( 'Loading…' ), }; } ), templateParts: templatePartIds.map( ( id ) => { @@ -84,10 +78,10 @@ export default function TemplateSwitcher( { label: template ? ( <TemplateLabel template={ template } /> ) : ( - __( 'loading…' ) + __( 'Loading…' ) ), value: id, - slug: template ? template.slug : __( 'loading…' ), + slug: template ? template.slug : __( 'Loading…' ), }; } ), }; @@ -102,7 +96,7 @@ export default function TemplateSwitcher( { className: 'edit-site-template-switcher__popover', position: 'bottom right', } } - icon={ layout } + icon={ null } label={ __( 'Switch Template' ) } toggleProps={ { children: ( isTemplatePart @@ -143,6 +137,7 @@ export default function TemplateSwitcher( { { !! hoveredTemplate?.id && ( <TemplatePreview item={ hoveredTemplate } /> ) } + <div className="edit-site-template-switcher__footer" /> </> ) } </DropdownMenu> diff --git a/packages/edit-site/src/components/template-switcher/preview.js b/packages/edit-site/src/components/template-switcher/preview.js index 03cf6399e8d916..b1761f7b502b81 100644 --- a/packages/edit-site/src/components/template-switcher/preview.js +++ b/packages/edit-site/src/components/template-switcher/preview.js @@ -23,7 +23,9 @@ function TemplatePreview( { item } ) { ); return ( <div className="edit-site-template-switcher__preview"> - { !! blocks && <BlockPreview blocks={ blocks } autoHeight /> } + { !! blocks && ( + <BlockPreview blocks={ blocks } viewportWidth={ 1200 } /> + ) } </div> ); } diff --git a/packages/edit-site/src/components/template-switcher/style.scss b/packages/edit-site/src/components/template-switcher/style.scss index a7a410472fd961..592bb25c84bf4f 100644 --- a/packages/edit-site/src/components/template-switcher/style.scss +++ b/packages/edit-site/src/components/template-switcher/style.scss @@ -2,22 +2,34 @@ overflow: visible; } -.edit-site-template-switcher__label { +.edit-site-template-switcher__popover .components-menu-item__button { position: relative; - width: 100%; } -.edit-site-template-switcher__label-customized-icon-container { +.edit-site-template-switcher__label-customized-dot { position: absolute; - right: 5px; - top: 0; - width: 10px; + right: 4px; + top: 50%; + margin-top: -4px; + width: 8px; + height: 8px; + display: block; + background: $theme-color; + border-radius: 50%; } .edit-site-template-switcher__label-customized-icon-icon { width: 100%; } +/* + * This doesn't contain anything but it's needed because of dropdown jumpiness + * when there's a div after the last menu group. + */ +.edit-site-template-switcher__footer { + margin-bottom: -$grid-unit-15; +} + .edit-site-template-switcher__preview { display: none; border: $border-width solid $light-gray-secondary; @@ -30,7 +42,6 @@ top: -$border-width; left: calc(100% + #{$grid-unit-15}); - @include break-medium { display: block; } diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index d4145ab69a71ad..a2a4c6023f3403 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,3 +1,5 @@ +@import "../../interface/src/style.scss"; + @import "./components/block-editor/style.scss"; @import "./components/header/style.scss"; @import "./components/header/fullscreen-mode-close/style.scss"; @@ -12,7 +14,6 @@ html.wp-toolbar { background: $white; } -body.gutenberg_page_gutenberg-edit-site, body.toplevel_page_gutenberg-edit-site { @include wp-admin-reset(".edit-site"); } @@ -43,6 +44,12 @@ body.toplevel_page_gutenberg-edit-site { > .components-navigate-regions { height: 100%; } + + // Todo: Remove this rule when edit site gets support + // for opening unpinned sidebar items. + .interface-complementary-area__pin-unpin-item.components-button { + display: none; + } } /** diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index 09aa2bfa870708..2b174d082495ac 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/block-editor": "file:../block-editor", "@wordpress/block-library": "file:../block-library", "@wordpress/blocks": "file:../blocks", @@ -32,6 +32,7 @@ "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", "@wordpress/i18n": "file:../i18n", + "@wordpress/interface": "file:../interface", "@wordpress/media-utils": "file:../media-utils", "@wordpress/notices": "file:../notices", "lodash": "^4.17.15", diff --git a/packages/edit-widgets/src/components/layout/index.js b/packages/edit-widgets/src/components/layout/index.js index 5f5c4424b3909c..97b6c6b2ea9d8a 100644 --- a/packages/edit-widgets/src/components/layout/index.js +++ b/packages/edit-widgets/src/components/layout/index.js @@ -8,11 +8,9 @@ import { FocusReturnProvider, } from '@wordpress/components'; import { useState } from '@wordpress/element'; -import { - BlockEditorKeyboardShortcuts, - __experimentalEditorSkeleton as EditorSkeleton, -} from '@wordpress/block-editor'; +import { BlockEditorKeyboardShortcuts } from '@wordpress/block-editor'; import { useViewportMatch } from '@wordpress/compose'; +import { InterfaceSkeleton } from '@wordpress/interface'; /** * Internal dependencies @@ -32,7 +30,7 @@ function Layout( { blockEditorSettings } ) { <SlotFillProvider> <DropZoneProvider> <FocusReturnProvider> - <EditorSkeleton + <InterfaceSkeleton header={ <Header /> } sidebar={ ! isMobile && <Sidebar /> } content={ diff --git a/packages/edit-widgets/src/components/widget-area/style.scss b/packages/edit-widgets/src/components/widget-area/style.scss index 2f1160bd17c77b..248f5d4e4ff856 100644 --- a/packages/edit-widgets/src/components/widget-area/style.scss +++ b/packages/edit-widgets/src/components/widget-area/style.scss @@ -2,11 +2,6 @@ max-width: $widget-area-width; margin: 0 auto 30px; - // Reduce padding inside widget areas - .block-editor-block-list__layout { - padding-left: $block-side-ui-width + $block-padding; - padding-right: $block-side-ui-width + $block-padding; - } // By default the default block appender inserter has a negative position, // but given that on the widget screen we have 0 padding we need to remove the negative position. .block-editor-default-block-appender .block-editor-inserter, diff --git a/packages/edit-widgets/src/style.scss b/packages/edit-widgets/src/style.scss index 86ee2bd54c3c69..41cc5979e9dd6e 100644 --- a/packages/edit-widgets/src/style.scss +++ b/packages/edit-widgets/src/style.scss @@ -1,3 +1,5 @@ +@import "../../interface/src/style.scss"; + @import "./components/customizer-edit-widgets-initializer/style.scss"; @import "./components/header/style.scss"; @import "./components/layout/style.scss"; @@ -49,7 +51,7 @@ body.gutenberg_page_gutenberg-widgets { } - .block-editor-editor-skeleton__content { + .interface-interface-skeleton__content { background-color: #f1f1f1; } } diff --git a/packages/editor/package.json b/packages/editor/package.json index 6cf93f036cd482..0ed0e3e81f9cf8 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/autop": "file:../autop", "@wordpress/blob": "file:../blob", @@ -52,7 +52,7 @@ "@wordpress/wordcount": "file:../wordcount", "classnames": "^2.2.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "react-autosize-textarea": "^3.0.2", "redux-optimist": "^1.0.0", "refx": "^3.0.0", diff --git a/packages/editor/src/components/document-outline/style.scss b/packages/editor/src/components/document-outline/style.scss index c02f815eb6f09a..52e1a9e5b91fbd 100644 --- a/packages/editor/src/components/document-outline/style.scss +++ b/packages/editor/src/components/document-outline/style.scss @@ -51,13 +51,17 @@ padding: 2px 5px 2px 1px; color: $dark-gray-800; text-align: left; + border-radius: $radius-block-ui; &:disabled { cursor: default; } &:focus { - @include button-style__focus-active; + box-shadow: 0 0 0 $border-width-focus $theme-color; + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; } } diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index be2d8a804eb7fe..460823f3bcf856 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { some } from 'lodash'; +import { some, groupBy } from 'lodash'; /** * WordPress dependencies @@ -12,48 +12,69 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { useState } from '@wordpress/element'; function EntityRecordState( { record, checked, onChange } ) { - const entity = useSelect( - ( select ) => select( 'core' ).getEntity( record.kind, record.name ), - [ record.kind, record.name ] - ); - return ( <CheckboxControl - label={ - <> - { entity.label } - { !! record.title && ( - <> - { ': ' } - <strong> - { record.title || __( 'Untitled' ) } - </strong> - </> - ) } - </> - } - checked={ ! checked } + label={ <strong>{ record.title || __( 'Untitled' ) }</strong> } + checked={ checked } onChange={ onChange } /> ); } -export default function EntitiesSavedStates( { - isOpen, - onRequestClose, - ignoredForSave = [], -} ) { +function EntityTypeList( { list, unselectedEntities, setUnselectedEntities } ) { + const firstRecord = list[ 0 ]; + const entity = useSelect( + ( select ) => + select( 'core' ).getEntity( firstRecord.kind, firstRecord.name ), + [ firstRecord.kind, firstRecord.name ] + ); + + return ( + <div className="editor-entities-saved-states__entity-type-list"> + <h2>{ entity.label }</h2> + { list.map( ( record ) => { + return ( + <EntityRecordState + key={ record.key || 'site' } + record={ record } + checked={ + ! some( + unselectedEntities, + ( elt ) => + elt.kind === record.kind && + elt.name === record.name && + elt.key === record.key + ) + } + onChange={ ( value ) => + setUnselectedEntities( record, value ) + } + /> + ); + } ) } + </div> + ); +} + +export default function EntitiesSavedStates( { isOpen, onRequestClose } ) { const dirtyEntityRecords = useSelect( ( select ) => select( 'core' ).__experimentalGetDirtyEntityRecords(), [] ); const { saveEditedEntityRecord } = useDispatch( 'core' ); - const [ unsavedEntityRecords, _setUnsavedEntityRecords ] = useState( [] ); - const setUnsavedEntityRecords = ( { kind, name, key }, checked ) => { + // To group entities by type. + const partitionedSavables = Object.values( + groupBy( dirtyEntityRecords, 'name' ) + ); + + // Unchecked entities to be ignored by save function. + const [ unselectedEntities, _setUnselectedEntities ] = useState( [] ); + + const setUnselectedEntities = ( { kind, name, key }, checked ) => { if ( checked ) { - _setUnsavedEntityRecords( - unsavedEntityRecords.filter( + _setUnselectedEntities( + unselectedEntities.filter( ( elt ) => elt.kind !== kind || elt.name !== name || @@ -61,17 +82,18 @@ export default function EntitiesSavedStates( { ) ); } else { - _setUnsavedEntityRecords( [ - ...unsavedEntityRecords, + _setUnselectedEntities( [ + ...unselectedEntities, { kind, name, key }, ] ); } }; + const saveCheckedEntities = () => { const entitiesToSave = dirtyEntityRecords.filter( ( { kind, name, key } ) => { return ! some( - ignoredForSave.concat( unsavedEntityRecords ), + unselectedEntities, ( elt ) => elt.kind === kind && elt.name === name && @@ -86,6 +108,7 @@ export default function EntitiesSavedStates( { onRequestClose( entitiesToSave ); }; + return ( isOpen && ( <Modal @@ -93,23 +116,13 @@ export default function EntitiesSavedStates( { onRequestClose={ () => onRequestClose() } contentLabel={ __( 'Select items to save.' ) } > - { dirtyEntityRecords.map( ( record ) => { + { partitionedSavables.map( ( list ) => { return ( - <EntityRecordState - key={ record.key } - record={ record } - checked={ - ! some( - unsavedEntityRecords, - ( elt ) => - elt.kind === record.kind && - elt.name === record.name && - elt.key === record.key - ) - } - onChange={ ( value ) => - setUnsavedEntityRecords( record, value ) - } + <EntityTypeList + key={ list[ 0 ].name } + list={ list } + unselectedEntities={ unselectedEntities } + setUnselectedEntities={ setUnselectedEntities } /> ); } ) } @@ -118,7 +131,7 @@ export default function EntitiesSavedStates( { isPrimary disabled={ dirtyEntityRecords.length - - unsavedEntityRecords.length === + unselectedEntities.length === 0 } onClick={ saveCheckedEntities } diff --git a/packages/editor/src/components/entities-saved-states/style.scss b/packages/editor/src/components/entities-saved-states/style.scss index 6751b3ef2673b8..6a04c3db879c89 100644 --- a/packages/editor/src/components/entities-saved-states/style.scss +++ b/packages/editor/src/components/entities-saved-states/style.scss @@ -3,3 +3,9 @@ margin-left: auto; margin-right: 0; } +.editor-entities-saved-states__entity-type-list { + h2 { + font-size: 18px; + margin: 20px 0 10px; + } +} diff --git a/packages/editor/src/components/post-last-revision/index.js b/packages/editor/src/components/post-last-revision/index.js index b24f0f3ac0c1cc..643b6c1a4700a6 100644 --- a/packages/editor/src/components/post-last-revision/index.js +++ b/packages/editor/src/components/post-last-revision/index.js @@ -24,6 +24,7 @@ function LastRevision( { lastRevisionId, revisionsCount } ) { icon={ backup } > { sprintf( + /* translators: %d: number of revisions */ _n( '%d Revision', '%d Revisions', revisionsCount ), revisionsCount ) } diff --git a/packages/editor/src/components/post-last-revision/style.scss b/packages/editor/src/components/post-last-revision/style.scss index 1976ec65496006..d9fd35f16edb5c 100644 --- a/packages/editor/src/components/post-last-revision/style.scss +++ b/packages/editor/src/components/post-last-revision/style.scss @@ -7,19 +7,17 @@ } } -// Needs specificity -.components-button:not(:disabled):not([aria-disabled="true"]).editor-post-last-revision__title { +.components-button.editor-post-last-revision__title { height: auto; &:hover, &:active { // Override the default button hover style - background: $light-gray-200 !important; - border: none !important; - box-shadow: none !important; + background: $light-gray-200; } &:focus { - @include menu-style__focus; + box-shadow: inset 0 0 0 $border-width-focus $theme-color; + border-radius: 0; } } diff --git a/packages/editor/src/components/post-permalink/editor.js b/packages/editor/src/components/post-permalink/editor.js deleted file mode 100644 index a09ee66ed984a8..00000000000000 --- a/packages/editor/src/components/post-permalink/editor.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * WordPress dependencies - */ -import { withDispatch, withSelect } from '@wordpress/data'; -import { Component } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import { Button } from '@wordpress/components'; -import { compose } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import { cleanForSlug } from '../../utils/url'; - -class PostPermalinkEditor extends Component { - constructor( { permalinkParts, slug } ) { - super( ...arguments ); - - this.state = { - editedPostName: slug || permalinkParts.postName, - }; - - this.onSavePermalink = this.onSavePermalink.bind( this ); - } - - onSavePermalink( event ) { - const postName = cleanForSlug( this.state.editedPostName ); - - event.preventDefault(); - - this.props.onSave(); - - if ( postName === this.props.postName ) { - return; - } - - this.props.editPost( { - slug: postName, - } ); - - this.setState( { - editedPostName: postName, - } ); - } - - render() { - const { prefix, suffix } = this.props.permalinkParts; - const { editedPostName } = this.state; - - /* eslint-disable jsx-a11y/no-autofocus */ - // Autofocus is allowed here, as this mini-UI is only loaded when the user clicks to open it. - return ( - <form - className="editor-post-permalink-editor" - onSubmit={ this.onSavePermalink } - > - <span className="editor-post-permalink__editor-container"> - <span className="editor-post-permalink-editor__prefix"> - { prefix } - </span> - <input - className="editor-post-permalink-editor__edit" - aria-label={ __( 'Edit post permalink' ) } - value={ editedPostName } - onChange={ ( event ) => - this.setState( { - editedPostName: event.target.value, - } ) - } - type="text" - autoFocus - /> - <span className="editor-post-permalink-editor__suffix"> - { suffix } - </span> - &lrm; - </span> - <Button - className="editor-post-permalink-editor__save" - isSecondary - onClick={ this.onSavePermalink } - > - { __( 'Save' ) } - </Button> - </form> - ); - /* eslint-enable jsx-a11y/no-autofocus */ - } -} - -export default compose( [ - withSelect( ( select ) => { - const { getPermalinkParts } = select( 'core/editor' ); - return { - permalinkParts: getPermalinkParts(), - }; - } ), - withDispatch( ( dispatch ) => { - const { editPost } = dispatch( 'core/editor' ); - return { editPost }; - } ), -] )( PostPermalinkEditor ); diff --git a/packages/editor/src/components/post-permalink/index.js b/packages/editor/src/components/post-permalink/index.js deleted file mode 100644 index 1facb8432f41a6..00000000000000 --- a/packages/editor/src/components/post-permalink/index.js +++ /dev/null @@ -1,176 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; -import { get } from 'lodash'; - -/** - * WordPress dependencies - */ -import { withDispatch, withSelect } from '@wordpress/data'; -import { Component } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import { compose } from '@wordpress/compose'; -import { ClipboardButton, Button, ExternalLink } from '@wordpress/components'; -import { safeDecodeURI, safeDecodeURIComponent } from '@wordpress/url'; -import { link as linkIcon } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import PostPermalinkEditor from './editor.js'; - -class PostPermalink extends Component { - constructor() { - super( ...arguments ); - - this.addVisibilityCheck = this.addVisibilityCheck.bind( this ); - this.onVisibilityChange = this.onVisibilityChange.bind( this ); - - this.state = { - isCopied: false, - isEditingPermalink: false, - }; - } - - addVisibilityCheck() { - window.addEventListener( 'visibilitychange', this.onVisibilityChange ); - } - - onVisibilityChange() { - const { isEditable, refreshPost } = this.props; - // If the user just returned after having clicked the "Change Permalinks" button, - // fetch a new copy of the post from the server, just in case they enabled permalinks. - if ( ! isEditable && 'visible' === document.visibilityState ) { - refreshPost(); - } - } - - componentDidUpdate( prevProps, prevState ) { - // If we've just stopped editing the permalink, focus on the new permalink. - if ( prevState.isEditingPermalink && ! this.state.isEditingPermalink ) { - this.linkElement.focus(); - } - } - - componentWillUnmount() { - window.removeEventListener( - 'visibilitychange', - this.addVisibilityCheck - ); - } - - render() { - const { - isEditable, - isNew, - isPublished, - isViewable, - permalinkParts, - postLink, - postSlug, - } = this.props; - - if ( isNew || ! isViewable || ! permalinkParts || ! postLink ) { - return null; - } - - const { isCopied, isEditingPermalink } = this.state; - const ariaLabel = isCopied - ? __( 'Permalink copied' ) - : __( 'Copy the permalink' ); - - const { prefix, suffix } = permalinkParts; - const samplePermalink = isEditable - ? prefix + postSlug + suffix - : prefix; - - return ( - <div className="editor-post-permalink"> - <ClipboardButton - className={ classnames( 'editor-post-permalink__copy', { - 'is-copied': isCopied, - } ) } - text={ samplePermalink } - label={ ariaLabel } - onCopy={ () => this.setState( { isCopied: true } ) } - aria-disabled={ isCopied } - icon={ linkIcon } - /> - - <span className="editor-post-permalink__label"> - { __( 'Permalink:' ) } - </span> - - { ! isEditingPermalink && ( - <ExternalLink - className="editor-post-permalink__link" - href={ ! isPublished ? postLink : samplePermalink } - target="_blank" - ref={ ( linkElement ) => - ( this.linkElement = linkElement ) - } - > - { safeDecodeURI( samplePermalink ) } - &lrm; - </ExternalLink> - ) } - - { isEditingPermalink && ( - <PostPermalinkEditor - slug={ postSlug } - onSave={ () => - this.setState( { isEditingPermalink: false } ) - } - /> - ) } - - { isEditable && ! isEditingPermalink && ( - <Button - className="editor-post-permalink__edit" - isSecondary - onClick={ () => - this.setState( { isEditingPermalink: true } ) - } - > - { __( 'Edit' ) } - </Button> - ) } - </div> - ); - } -} - -export default compose( [ - withSelect( ( select ) => { - const { - isEditedPostNew, - isPermalinkEditable, - getCurrentPost, - getPermalinkParts, - getEditedPostAttribute, - isCurrentPostPublished, - getEditedPostSlug, - } = select( 'core/editor' ); - const { getPostType } = select( 'core' ); - - const { link } = getCurrentPost(); - - const postTypeName = getEditedPostAttribute( 'type' ); - const postType = getPostType( postTypeName ); - - return { - isNew: isEditedPostNew(), - postLink: link, - permalinkParts: getPermalinkParts(), - postSlug: safeDecodeURIComponent( getEditedPostSlug() ), - isEditable: isPermalinkEditable(), - isPublished: isCurrentPostPublished(), - isViewable: get( postType, [ 'viewable' ], false ), - }; - } ), - withDispatch( ( dispatch ) => { - const { refreshPost } = dispatch( 'core/editor' ); - return { refreshPost }; - } ), -] )( PostPermalink ); diff --git a/packages/editor/src/components/post-permalink/style.scss b/packages/editor/src/components/post-permalink/style.scss deleted file mode 100644 index 241250696123cf..00000000000000 --- a/packages/editor/src/components/post-permalink/style.scss +++ /dev/null @@ -1,140 +0,0 @@ -.editor-post-permalink { - display: inline-flex; - align-items: center; - flex-wrap: wrap; - padding: $grid-unit-10 $grid-unit-10 0; - font-family: $default-font; - font-size: $default-font-size; - white-space: nowrap; - background-clip: padding-box; - - // Block UI appearance. - border: $border-width solid $dark-gray-primary; - border-radius: $radius-block-ui; - background-color: $white; - - // Put toolbar snugly to edge on mobile. - margin-left: -$block-padding - $border-width; // This hides the border off the edge of the screen. - margin-right: -$block-padding - $border-width; - @include break-mobile() { - padding: $grid-unit-05; - } - @include break-small() { - margin-left: -$border-width; - margin-right: -$border-width; - } - - // Increase specificity to override margins set on label element. - &.editor-post-permalink > * { - margin-bottom: $grid-unit-10; - - @include break-mobile() { - margin-bottom: 0; - } - } - - // Prevent button shrinking in IE11 when other items have a 100% flex basis. - // This should be safe to apply in all browsers because we don't want these - // buttons to shrink anyway. - button { - flex-shrink: 0; - } -} - -.editor-post-permalink__copy { - border-radius: 4px; - padding: 6px; -} - -.editor-post-permalink__copy.is-copied { - opacity: 0.3; -} - -.editor-post-permalink__label { - margin: 0 10px 0 5px; - font-weight: 600; -} - -.editor-post-permalink__link { - color: $dark-gray-200; - text-decoration: underline; - margin-right: 10px; - flex-grow: 1; - overflow: hidden; - position: relative; - white-space: nowrap; - text-align: left; -} - -.editor-post-permalink-editor { - width: 100%; - min-width: 20%; - display: inline-flex; - align-items: center; - - .editor-post-permalink__editor-container { - flex: 0 1 100%; - display: flex; - overflow: hidden; // This enables serious flex shrinking. - padding: $border-width 0; // Necessary for the overflow to not crop the focus style. - - .editor-post-permalink-editor__prefix { - flex: 1 1 auto; - - @include break-small { - flex: 1 0 auto; - } - } - - .editor-post-permalink-editor__edit { - flex: 1 1 100%; - } - } - - // Higher specificity required to override core margin styles. - .editor-post-permalink-editor__save { - margin-left: auto; - } -} - -.editor-post-permalink-editor__prefix { - color: $dark-gray-300; - min-width: 20%; - overflow: hidden; - position: relative; - white-space: nowrap; - text-overflow: ellipsis; -} - -.editor-post-permalink input[type="text"].editor-post-permalink-editor__edit { - // Input fields are created with inherent widths. - // By supplying both a (any) width and a min-width, we allow it to scale in a flex container. - min-width: 10%; - width: 100%; - margin: 0 3px; - padding: 2px 4px; -} - -.editor-post-permalink-editor__suffix { - color: $dark-gray-300; - margin-right: 6px; - flex: 0 0 0%; -} - -.editor-post-permalink-editor__prefix { - text-align: left; -} - -/* rtl:begin:ignore */ -.editor-post-permalink__link { - text-align: left; -} -.editor-post-permalink__editor-container, -.editor-post-permalink__link { - direction: ltr; -} -.editor-post-permalink__link::after { - @include long-content-fade($direction:right, $size: 20%, $edge: 0); -} -/* rtl:end:ignore */ - diff --git a/packages/editor/src/components/post-publish-button/index.js b/packages/editor/src/components/post-publish-button/index.js index 6405ae571a3db8..c2383f52c19afb 100644 --- a/packages/editor/src/components/post-publish-button/index.js +++ b/packages/editor/src/components/post-publish-button/index.js @@ -3,7 +3,6 @@ */ import { noop, get, some } from 'lodash'; import classnames from 'classnames'; -import memoize from 'memize'; /** * WordPress dependencies @@ -33,12 +32,6 @@ export class PostPublishButton extends Component { this.state = { entitiesSavedStatesCallback: false, }; - this.createIgnoredForSave = memoize( - ( postType, postId ) => [ - { kind: 'postType', name: postType, key: postId }, - ], - { maxSize: 1 } - ); } componentDidMount() { if ( this.props.focusOnMount ) { @@ -102,8 +95,6 @@ export class PostPublishButton extends Component { onToggle, visibility, hasNonPostEntityChanges, - postType, - postId, } = this.props; const { entitiesSavedStatesCallback } = this.state; @@ -182,10 +173,6 @@ export class PostPublishButton extends Component { <EntitiesSavedStates isOpen={ Boolean( entitiesSavedStatesCallback ) } onRequestClose={ this.closeEntitiesSavedStates } - ignoredForSave={ this.createIgnoredForSave( - postType, - postId - ) } /> <Button ref={ this.buttonNode } diff --git a/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js b/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js index fede6a0a33186d..5d173e4f3c6807 100644 --- a/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js +++ b/packages/editor/src/components/post-publish-panel/maybe-post-format-panel.js @@ -46,6 +46,7 @@ const PostFormatPanel = ( { suggestion, onUpdatePostFormat } ) => { onUpdatePostFormat={ onUpdatePostFormat } suggestedPostFormat={ suggestion.id } suggestionText={ sprintf( + /* translators: %s: post format */ __( 'Apply the "%1$s" format.' ), suggestion.caption ) } diff --git a/packages/editor/src/components/post-taxonomies/flat-term-selector.js b/packages/editor/src/components/post-taxonomies/flat-term-selector.js index 299245a5e45aad..c6dd5af6db8530 100644 --- a/packages/editor/src/components/post-taxonomies/flat-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/flat-term-selector.js @@ -245,14 +245,17 @@ class FlatTermSelector extends Component { slug === 'post_tag' ? __( 'Tag' ) : __( 'Term' ) ); const termAddedLabel = sprintf( + /* translators: %s: term name. */ _x( '%s added', 'term' ), singularName ); const termRemovedLabel = sprintf( + /* translators: %s: term name. */ _x( '%s removed', 'term' ), singularName ); const removeTermLabel = sprintf( + /* translators: %s: term name. */ _x( 'Remove %s', 'term' ), singularName ); diff --git a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js index c8897753492f13..234b5f25e8f6ac 100644 --- a/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js +++ b/packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js @@ -171,6 +171,7 @@ class HierarchicalTermSelector extends Component { ? this.state.availableTerms : [ term, ...this.state.availableTerms ]; const termAddedMessage = sprintf( + /* translators: %s: taxonomy name */ _x( '%s added', 'term' ), get( this.props.taxonomy, @@ -319,6 +320,7 @@ class HierarchicalTermSelector extends Component { const resultCount = getResultCount( filteredTermsTree ); const resultsFoundMessage = sprintf( + /* translators: %d: number of results */ _n( '%d result found.', '%d results found.', resultCount ), resultCount ); diff --git a/packages/editor/src/components/post-title/index.js b/packages/editor/src/components/post-title/index.js index 3a5f17a8f68536..306e9e7c99113d 100644 --- a/packages/editor/src/components/post-title/index.js +++ b/packages/editor/src/components/post-title/index.js @@ -3,7 +3,6 @@ */ import Textarea from 'react-autosize-textarea'; import classnames from 'classnames'; -import { get } from 'lodash'; /** * WordPress dependencies @@ -13,13 +12,12 @@ import { Component } from '@wordpress/element'; import { decodeEntities } from '@wordpress/html-entities'; import { ENTER } from '@wordpress/keycodes'; import { withSelect, withDispatch } from '@wordpress/data'; -import { withFocusOutside, VisuallyHidden } from '@wordpress/components'; +import { VisuallyHidden } from '@wordpress/components'; import { withInstanceId, compose } from '@wordpress/compose'; /** * Internal dependencies */ -import PostPermalink from '../post-permalink'; import PostTypeSupportCheck from '../post-type-support-check'; /** @@ -41,10 +39,6 @@ class PostTitle extends Component { }; } - handleFocusOutside() { - this.onUnselect(); - } - onSelect() { this.setState( { isSelected: true } ); this.props.clearSelectedBlock(); @@ -71,7 +65,6 @@ class PostTitle extends Component { hasFixedToolbar, isCleanNewPost, isFocusMode, - isPostTypeViewable, instanceId, placeholder, title, @@ -79,53 +72,48 @@ class PostTitle extends Component { const { isSelected } = this.state; // The wp-block className is important for editor styles. - const className = classnames( 'wp-block editor-post-title__block', { - 'is-selected': isSelected, - 'is-focus-mode': isFocusMode, - 'has-fixed-toolbar': hasFixedToolbar, - } ); + const className = classnames( + 'wp-block editor-post-title editor-post-title__block', + { + 'is-selected': isSelected, + 'is-focus-mode': isFocusMode, + 'has-fixed-toolbar': hasFixedToolbar, + } + ); const decodedPlaceholder = decodeEntities( placeholder ); return ( <PostTypeSupportCheck supportKeys="title"> - <div className="editor-post-title"> - <div className={ className }> - <div> - <VisuallyHidden - as="label" - htmlFor={ `post-title-${ instanceId }` } - > - { decodedPlaceholder || __( 'Add title' ) } - </VisuallyHidden> - <Textarea - id={ `post-title-${ instanceId }` } - className="editor-post-title__input" - value={ title } - onChange={ this.onChange } - placeholder={ - decodedPlaceholder || __( 'Add title' ) - } - onFocus={ this.onSelect } - onKeyDown={ this.onKeyDown } - onKeyPress={ this.onUnselect } - /* - Only autofocus the title when the post is entirely empty. - This should only happen for a new post, which means we - focus the title on new post so the author can start typing - right away, without needing to click anything. - */ - /* eslint-disable jsx-a11y/no-autofocus */ - autoFocus={ - document.body === document.activeElement && - isCleanNewPost - } - /* eslint-enable jsx-a11y/no-autofocus */ - /> - </div> - { isSelected && isPostTypeViewable && ( - <PostPermalink /> - ) } - </div> + <div className={ className }> + <VisuallyHidden + as="label" + htmlFor={ `post-title-${ instanceId }` } + > + { decodedPlaceholder || __( 'Add title' ) } + </VisuallyHidden> + <Textarea + id={ `post-title-${ instanceId }` } + className="editor-post-title__input" + value={ title } + onChange={ this.onChange } + placeholder={ decodedPlaceholder || __( 'Add title' ) } + onFocus={ this.onSelect } + onBlur={ this.onUnselect } + onKeyDown={ this.onKeyDown } + onKeyPress={ this.onUnselect } + /* + Only autofocus the title when the post is entirely empty. + This should only happen for a new post, which means we + focus the title on new post so the author can start typing + right away, without needing to click anything. + */ + /* eslint-disable jsx-a11y/no-autofocus */ + autoFocus={ + document.body === document.activeElement && + isCleanNewPost + } + /* eslint-enable jsx-a11y/no-autofocus */ + /> </div> </PostTypeSupportCheck> ); @@ -135,14 +123,11 @@ class PostTitle extends Component { const applyWithSelect = withSelect( ( select ) => { const { getEditedPostAttribute, isCleanNewPost } = select( 'core/editor' ); const { getSettings } = select( 'core/block-editor' ); - const { getPostType } = select( 'core' ); - const postType = getPostType( getEditedPostAttribute( 'type' ) ); const { titlePlaceholder, focusMode, hasFixedToolbar } = getSettings(); return { isCleanNewPost: isCleanNewPost(), title: getEditedPostAttribute( 'title' ), - isPostTypeViewable: get( postType, [ 'viewable' ], false ), placeholder: titlePlaceholder, isFocusMode: focusMode, hasFixedToolbar, @@ -169,6 +154,5 @@ const applyWithDispatch = withDispatch( ( dispatch ) => { export default compose( applyWithSelect, applyWithDispatch, - withInstanceId, - withFocusOutside + withInstanceId )( PostTitle ); diff --git a/packages/editor/src/components/post-title/style.scss b/packages/editor/src/components/post-title/style.scss index 8760c20f196ace..351423d657b235 100644 --- a/packages/editor/src/components/post-title/style.scss +++ b/packages/editor/src/components/post-title/style.scss @@ -1,12 +1,7 @@ -.editor-post-title__block { +.editor-post-title { position: relative; - padding: 5px 0; font-size: $editor-font-size; - @include break-small() { - padding: 5px $block-side-ui-clearance; - } - .editor-post-title__input { display: block; width: 100%; @@ -18,7 +13,7 @@ color: $dark-gray-900; transition: border 0.1s ease-out, box-shadow 0.1s linear; @include reduce-motion("transition"); - padding: #{ $block-padding + 5px } $block-padding; + padding: #{ $block-padding + 5px } 0; word-break: keep-all; // Stack borders on mobile. @@ -68,24 +63,3 @@ } } } - -.editor-post-title .editor-post-permalink { - font-size: $default-font-size; - color: $dark-gray-900; - height: auto; - position: relative; - top: -2px; - width: 100%; - - @include break-mobile() { - position: absolute; - top: -$button-size + $border-width + $border-width + 1px; // Shift this element upward the same height as the block toolbar, minus the border size - right: 0; - flex-wrap: nowrap; - width: auto; - } - @include break-small() { - left: $block-side-ui-clearance; - right: $block-side-ui-clearance; - } -} diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 69a2dbbd958892..74c7b2f67cf72d 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -12,7 +12,10 @@ import { Component } from '@wordpress/element'; import { withDispatch, withSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { EntityProvider } from '@wordpress/core-data'; -import { BlockEditorProvider, transformStyles } from '@wordpress/block-editor'; +import { + BlockEditorProvider, + __unstableEditorStyles as EditorStyles, +} from '@wordpress/block-editor'; import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; @@ -114,12 +117,14 @@ class EditorProvider extends Component { 'templateLock', 'titlePlaceholder', 'onUpdateDefaultBlockStyles', + '__experimentalDisableCustomUnits', '__experimentalEnableLegacyWidgetBlock', '__experimentalBlockDirectory', '__experimentalEnableFullSiteEditing', '__experimentalEnableFullSiteEditingDemo', '__experimentalGlobalStylesUserEntityId', '__experimentalGlobalStylesBase', + '__experimentalDisableCustomLineHeight', 'gradients', ] ), mediaUpload: hasUploadPermissions ? mediaUpload : undefined, @@ -134,23 +139,6 @@ class EditorProvider extends Component { componentDidMount() { this.props.updateEditorSettings( this.props.settings ); - - if ( ! this.props.settings.styles ) { - return; - } - - const updatedStyles = transformStyles( - this.props.settings.styles, - '.editor-styles-wrapper' - ); - - map( updatedStyles, ( updatedCSS ) => { - if ( updatedCSS ) { - const node = document.createElement( 'style' ); - node.innerHTML = updatedCSS; - document.body.appendChild( node ); - } - } ); } componentDidUpdate( prevProps ) { @@ -197,27 +185,30 @@ class EditorProvider extends Component { ); return ( - <EntityProvider kind="root" type="site"> - <EntityProvider - kind="postType" - type={ post.type } - id={ post.id } - > - <BlockEditorProvider - value={ blocks } - onInput={ resetEditorBlocksWithoutUndoLevel } - onChange={ resetEditorBlocks } - selectionStart={ selectionStart } - selectionEnd={ selectionEnd } - settings={ editorSettings } - useSubRegistry={ false } + <> + <EditorStyles styles={ settings.styles } /> + <EntityProvider kind="root" type="site"> + <EntityProvider + kind="postType" + type={ post.type } + id={ post.id } > - { children } - <ReusableBlocksButtons /> - <ConvertToGroupButtons /> - </BlockEditorProvider> + <BlockEditorProvider + value={ blocks } + onInput={ resetEditorBlocksWithoutUndoLevel } + onChange={ resetEditorBlocks } + selectionStart={ selectionStart } + selectionEnd={ selectionEnd } + settings={ editorSettings } + useSubRegistry={ false } + > + { children } + <ReusableBlocksButtons /> + <ConvertToGroupButtons /> + </BlockEditorProvider> + </EntityProvider> </EntityProvider> - </EntityProvider> + </> ); } } diff --git a/packages/editor/src/components/reusable-blocks-buttons/reusable-block-delete-button.js b/packages/editor/src/components/reusable-blocks-buttons/reusable-block-delete-button.js index f2a9664c640800..7f5e29f009d3f5 100644 --- a/packages/editor/src/components/reusable-blocks-buttons/reusable-block-delete-button.js +++ b/packages/editor/src/components/reusable-blocks-buttons/reusable-block-delete-button.js @@ -69,6 +69,7 @@ export default compose( [ // TODO: Make this a <Confirm /> component or similar // eslint-disable-next-line no-alert const hasConfirmed = window.confirm( + // eslint-disable-next-line @wordpress/i18n-no-collapsible-whitespace __( 'Are you sure you want to delete this Reusable Block?\n\n' + 'It will be permanently removed from all posts and pages that use it.' diff --git a/packages/editor/src/components/table-of-contents/style.scss b/packages/editor/src/components/table-of-contents/style.scss index b7a20dc2a3c3e1..968f69a653764b 100644 --- a/packages/editor/src/components/table-of-contents/style.scss +++ b/packages/editor/src/components/table-of-contents/style.scss @@ -21,9 +21,15 @@ } } -.table-of-contents__wrapper:focus { - @include square-style__focus(); - outline-offset: $grid-unit-10; +.table-of-contents__wrapper:focus::before { + content: ""; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + box-shadow: inset 0 0 0 $border-width-focus $theme-color; } .table-of-contents__counts { diff --git a/packages/editor/src/editor-styles.scss b/packages/editor/src/editor-styles.scss index d7316552288953..f8eee44a116938 100644 --- a/packages/editor/src/editor-styles.scss +++ b/packages/editor/src/editor-styles.scss @@ -144,3 +144,17 @@ ol ul { max-width: 1100px; } } + +a { + color: inherit; + transition: none; +} + +code, +kbd { + padding: 0; + margin: 0; + background: inherit; + font-size: inherit; + font-family: monospace; +} diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 83a75edd9013ac..88ed59125a939b 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -9,7 +9,6 @@ @import "./components/post-format/style.scss"; @import "./components/post-last-revision/style.scss"; @import "./components/post-locked-modal/style.scss"; -@import "./components/post-permalink/style.scss"; @import "./components/post-publish-button/style.scss"; @import "./components/post-publish-panel/style.scss"; @import "./components/post-saved-state/style.scss"; diff --git a/packages/element/CHANGELOG.md b/packages/element/CHANGELOG.md index 6fa9e71bbb9593..2db200bde4fb93 100644 --- a/packages/element/CHANGELOG.md +++ b/packages/element/CHANGELOG.md @@ -1,5 +1,6 @@ ## Master +- Include TypeScript type declarations ([#21248](https://github.com/WordPress/gutenberg/pull/21248)) - Graduated `__experimentalCreateInterpolateElement` function to stable api: `createInterpolateElement` (see [20699](https://github.com/WordPress/gutenberg/pull/20699)) ## 2.10.0 (2019-12-19) diff --git a/packages/element/README.md b/packages/element/README.md index 1a51dea4046de9..c1f819f6116f5f 100755 --- a/packages/element/README.md +++ b/packages/element/README.md @@ -180,7 +180,7 @@ _Related_ _Parameters_ -- _child_ `WPElement`: Any renderable child, such as an element, string, or fragment. +- _child_ (unknown type): Any renderable child, such as an element, string, or fragment. - _container_ `HTMLElement`: DOM node into which element should be rendered. <a name="createRef" href="#createRef">#</a> **createRef** @@ -199,7 +199,7 @@ Finds the dom node of a React component. _Parameters_ -- _component_ `WPComponent`: Component's instance. +- _component_ (unknown type): Component's instance. <a name="forwardRef" href="#forwardRef">#</a> **forwardRef** @@ -289,13 +289,11 @@ aside from `children` are passed. _Parameters_ -- _props_ `Object`: -- _props.children_ `string`: HTML to render. -- _props.props_ `Object`: Any additonal props to be set on the containing div. +- _props_ `RawHTMLProps`: Children should be a string of HTML. Other props will be passed through to div wrapper. _Returns_ -- `WPComponent`: Dangerously-rendering component. +- `JSX.Element`: Dangerously-rendering component. <a name="render" href="#render">#</a> **render** @@ -303,7 +301,7 @@ Renders a given element into the target DOM node. _Parameters_ -- _element_ `WPElement`: Element to render. +- _element_ (unknown type): Element to render. - _target_ `HTMLElement`: DOM node into which element should be rendered. <a name="renderToString" href="#renderToString">#</a> **renderToString** @@ -312,9 +310,9 @@ Serializes a React element to string. _Parameters_ -- _element_ `WPElement`: Element to serialize. -- _context_ `?Object`: Context object. -- _legacyContext_ `?Object`: Legacy context object. +- _element_ (unknown type): Element to serialize. +- _context_ `[Object]`: Context object. +- _legacyContext_ `[Object]`: Legacy context object. _Returns_ diff --git a/packages/element/package.json b/packages/element/package.json index 0b54d5538af078..e1a2e68e7b7716 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -21,9 +21,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/escape-html": "file:../escape-html", "lodash": "^4.17.15", "react": "^16.9.0", diff --git a/packages/element/src/create-interpolate-element.js b/packages/element/src/create-interpolate-element.js index e6d0eefdd3bfa3..d3da32354bb119 100644 --- a/packages/element/src/create-interpolate-element.js +++ b/packages/element/src/create-interpolate-element.js @@ -3,6 +3,8 @@ */ import { createElement, cloneElement, Fragment, isValidElement } from 'react'; +/** @typedef {import('./react').WPElement} WPElement */ + let indoc, offset, output, stack; /** @@ -22,6 +24,24 @@ let indoc, offset, output, stack; */ const tokenizer = /<(\/)?(\w+)\s*(\/)?>/g; +/** + * The stack frame tracking parse progress. + * + * @typedef Frame + * + * @property {WPElement} element A parent element which may still have + * @property {number} tokenStart Offset at which parent element first + * appears. + * @property {number} tokenLength Length of string marking start of parent + * element. + * @property {number} [prevOffset] Running offset at which parsing should + * continue. + * @property {number} [leadingTextStart] Offset at which last closing element + * finished, used for finding text between + * elements. + * @property {WPElement[]} children Children. + */ + /** * Tracks recursive-descent parse state. * @@ -29,21 +49,21 @@ const tokenizer = /<(\/)?(\w+)\s*(\/)?>/g; * parsed. * * @private - * @param {WPElement} element A parent element which may still have - * nested children not yet parsed. - * @param {number} tokenStart Offset at which parent element first - * appears. - * @param {number} tokenLength Length of string marking start of parent - * element. - * @param {number} prevOffset Running offset at which parsing should - * continue. - * @param {number} leadingTextStart Offset at which last closing element - * finished, used for finding text between - * elements + * @param {WPElement} element A parent element which may still have + * nested children not yet parsed. + * @param {number} tokenStart Offset at which parent element first + * appears. + * @param {number} tokenLength Length of string marking start of parent + * element. + * @param {number} [prevOffset] Running offset at which parsing should + * continue. + * @param {number} [leadingTextStart] Offset at which last closing element + * finished, used for finding text between + * elements. * * @return {Frame} The stack frame tracking parse progress. */ -function Frame( +function createFrame( element, tokenStart, tokenLength, @@ -175,14 +195,14 @@ function proceed( conversionMap ) { // otherwise we found an inner element addChild( - new Frame( conversionMap[ name ], startOffset, tokenLength ) + createFrame( conversionMap[ name ], startOffset, tokenLength ) ); offset = startOffset + tokenLength; return true; case 'opener': stack.push( - new Frame( + createFrame( conversionMap[ name ], startOffset, tokenLength, @@ -210,7 +230,7 @@ function proceed( conversionMap ) { ); stackTop.children.push( text ); stackTop.prevOffset = startOffset + tokenLength; - const frame = new Frame( + const frame = createFrame( stackTop.element, stackTop.tokenStart, stackTop.tokenLength, diff --git a/packages/element/src/raw-html.js b/packages/element/src/raw-html.js index 0f56060e3057b6..f75a9ff66e4fca 100644 --- a/packages/element/src/raw-html.js +++ b/packages/element/src/raw-html.js @@ -3,17 +3,21 @@ */ import { createElement } from './react'; +// Disable reason: JSDoc linter doesn't seem to parse the union (`&`) correctly. +/* eslint-disable jsdoc/valid-types */ +/** @typedef {{children: string} & import('react').ComponentPropsWithoutRef<'div'>} RawHTMLProps */ +/* eslint-enable jsdoc/valid-types */ + /** * Component used as equivalent of Fragment with unescaped HTML, in cases where * it is desirable to render dangerous HTML without needing a wrapper element. * To preserve additional props, a `div` wrapper _will_ be created if any props * aside from `children` are passed. * - * @param {Object} props - * @param {string} props.children HTML to render. - * @param {Object} props.props Any additonal props to be set on the containing div. + * @param {RawHTMLProps} props Children should be a string of HTML. Other props + * will be passed through to div wrapper. * - * @return {WPComponent} Dangerously-rendering component. + * @return {JSX.Element} Dangerously-rendering component. */ export default function RawHTML( { children, ...props } ) { // The DIV wrapper will be stripped by serializer, unless there are diff --git a/packages/element/src/react-platform.js b/packages/element/src/react-platform.js index 44a3422ed79773..fe3d3e94a99941 100644 --- a/packages/element/src/react-platform.js +++ b/packages/element/src/react-platform.js @@ -13,7 +13,7 @@ import { * * @see https://github.com/facebook/react/issues/10309#issuecomment-318433235 * - * @param {WPElement} child Any renderable child, such as an element, + * @param {import('./react').WPElement} child Any renderable child, such as an element, * string, or fragment. * @param {HTMLElement} container DOM node into which element should be rendered. */ @@ -22,14 +22,14 @@ export { createPortal }; /** * Finds the dom node of a React component. * - * @param {WPComponent} component Component's instance. + * @param {import('./react').WPComponent} component Component's instance. */ export { findDOMNode }; /** * Renders a given element into the target DOM node. * - * @param {WPElement} element Element to render. + * @param {import('./react').WPElement} element Element to render. * @param {HTMLElement} target DOM node into which element should be rendered. */ export { render }; diff --git a/packages/element/src/react.js b/packages/element/src/react.js index 449b799ef74f89..78752a1b5a179a 100644 --- a/packages/element/src/react.js +++ b/packages/element/src/react.js @@ -37,7 +37,7 @@ import { isString } from 'lodash'; /** * Object containing a React component. * - * @typedef {import('react').Component} WPComponent + * @typedef {import('react').ComponentType} WPComponent */ /** diff --git a/packages/element/src/serialize.js b/packages/element/src/serialize.js index d5ef4e02a7758e..172657812533e4 100644 --- a/packages/element/src/serialize.js +++ b/packages/element/src/serialize.js @@ -52,7 +52,9 @@ import { import { createContext, Fragment, StrictMode, forwardRef } from './react'; import RawHTML from './raw-html'; -const { Provider, Consumer } = createContext(); +/** @typedef {import('./react').WPElement} WPElement */ + +const { Provider, Consumer } = createContext( undefined ); const ForwardRef = forwardRef( () => { return null; } ); @@ -60,14 +62,14 @@ const ForwardRef = forwardRef( () => { /** * Valid attribute types. * - * @type {Set} + * @type {Set<string>} */ const ATTRIBUTES_TYPES = new Set( [ 'string', 'boolean', 'number' ] ); /** * Element tags which can be self-closing. * - * @type {Set} + * @type {Set<string>} */ const SELF_CLOSING_TAGS = new Set( [ 'area', @@ -101,7 +103,7 @@ const SELF_CLOSING_TAGS = new Set( [ * [ tr.firstChild.textContent.trim() ]: true * } ), {} ) ).sort(); * - * @type {Set} + * @type {Set<string>} */ const BOOLEAN_ATTRIBUTES = new Set( [ 'allowfullscreen', @@ -152,7 +154,7 @@ const BOOLEAN_ATTRIBUTES = new Set( [ * * - `alt`: https://blog.whatwg.org/omit-alt * - * @type {Set} + * @type {Set<string>} */ const ENUMERATED_ATTRIBUTES = new Set( [ 'autocapitalize', @@ -195,7 +197,7 @@ const ENUMERATED_ATTRIBUTES = new Set( [ * .map( ( [ key ] ) => key ) * .sort(); * - * @type {Set} + * @type {Set<string>} */ const CSS_PROPERTIES_SUPPORTS_UNITLESS = new Set( [ 'animation', @@ -269,7 +271,7 @@ function isInternalAttribute( attribute ) { * @param {string} attribute Attribute name. * @param {*} value Non-normalized attribute value. * - * @return {string} Normalized attribute value. + * @return {*} Normalized attribute value. */ function getNormalAttributeValue( attribute, value ) { switch ( attribute ) { @@ -346,9 +348,9 @@ function getNormalStylePropertyValue( property, value ) { /** * Serializes a React element to string. * - * @param {WPElement} element Element to serialize. - * @param {?Object} context Context object. - * @param {?Object} legacyContext Legacy context object. + * @param {import('react').ReactNode} element Element to serialize. + * @param {Object} [context] Context object. + * @param {Object} [legacyContext] Legacy context object. * * @return {string} Serialized element. */ @@ -369,7 +371,10 @@ export function renderElement( element, context, legacyContext = {} ) { return element.toString(); } - const { type, props } = element; + const { + type, + props, + } = /** @type {{type?: any, props?: any}} */ ( element ); switch ( type ) { case StrictMode: @@ -434,11 +439,11 @@ export function renderElement( element, context, legacyContext = {} ) { /** * Serializes a native component type to string. * - * @param {?string} type Native component type to serialize, or null if - * rendering as fragment of children content. - * @param {Object} props Props object. - * @param {?Object} context Context object. - * @param {?Object} legacyContext Legacy context object. + * @param {?string} type Native component type to serialize, or null if + * rendering as fragment of children content. + * @param {Object} props Props object. + * @param {Object} [context] Context object. + * @param {Object} [legacyContext] Legacy context object. * * @return {string} Serialized element. */ @@ -478,13 +483,15 @@ export function renderNativeComponent( return '<' + type + attributes + '>' + content + '</' + type + '>'; } +/** @typedef {import('./react').WPComponent} WPComponent */ + /** * Serializes a non-native component type to string. * - * @param {Function} Component Component type to serialize. - * @param {Object} props Props object. - * @param {?Object} context Context object. - * @param {?Object} legacyContext Legacy context object. + * @param {WPComponent} Component Component type to serialize. + * @param {Object} props Props object. + * @param {Object} [context] Context object. + * @param {Object} [legacyContext] Legacy context object. * * @return {string} Serialized element */ @@ -494,10 +501,22 @@ export function renderComponent( context, legacyContext = {} ) { - const instance = new Component( props, legacyContext ); + const instance = new /** @type {import('react').ComponentClass} */ ( Component )( + props, + legacyContext + ); - if ( typeof instance.getChildContext === 'function' ) { - Object.assign( legacyContext, instance.getChildContext() ); + if ( + typeof ( + // Ignore reason: Current prettier reformats parens and mangles type assertion + // prettier-ignore + /** @type {{getChildContext?: () => unknown}} */ ( instance ).getChildContext + ) === 'function' + ) { + Object.assign( + legacyContext, + /** @type {{getChildContext?: () => unknown}} */ ( instance ).getChildContext() + ); } const html = renderElement( instance.render(), context, legacyContext ); @@ -508,9 +527,9 @@ export function renderComponent( /** * Serializes an array of children to string. * - * @param {Array} children Children to serialize. - * @param {?Object} context Context object. - * @param {?Object} legacyContext Legacy context object. + * @param {import('react').ReactNodeArray} children Children to serialize. + * @param {Object} [context] Context object. + * @param {Object} [legacyContext] Legacy context object. * * @return {string} Serialized children. */ diff --git a/packages/element/tsconfig.json b/packages/element/tsconfig.json new file mode 100644 index 00000000000000..1f90b9c762ae63 --- /dev/null +++ b/packages/element/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + + "noImplicitAny": false, + "strictNullChecks": false + }, + "references": [ { "path": "../escape-html" } ], + "include": [ "src/**/*" ] +} diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 5a67af6ef1d623..774afe9e90411e 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -1,7 +1,5 @@ ## Master -## 1.1.0 (2020-04-01) - ### New Feature - URLs for ZIP files are now supported as core, plugin, and theme sources. diff --git a/packages/env/README.md b/packages/env/README.md index 4b7eedc02c57fa..e27fba038c9aeb 100644 --- a/packages/env/README.md +++ b/packages/env/README.md @@ -201,6 +201,14 @@ ID user_login display_name user_email user_registered roles ✔ Ran `wp user list` in 'cli'. (in 2s 374ms) ``` +### `docker logs -f [container_id] >/dev/null` + +```sh +docker logs -f <container_id> >/dev/null + +Shows the error logs of the specified container in the terminal. The container_id is the one that is visible with `docker ps -a` +``` + ## .wp-env.json You can customize the WordPress installation, plugins and themes that the development environment will use by specifying a `.wp-env.json` file in the directory that you run `wp-env` from. @@ -209,7 +217,7 @@ You can customize the WordPress installation, plugins and themes that the develo | Field | Type | Default | Description | | ------------- | ------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | -| `"core"` | `string|null` | `null` | The WordPress installation to use. If `null` is specified, `wp-env` will use the latest production release of WordPress. | +| `"core"` | `string\|null` | `null` | The WordPress installation to use. If `null` is specified, `wp-env` will use the latest production release of WordPress. | | `"plugins"` | `string[]` | `[]` | A list of plugins to install and activate in the environment. | | `"themes"` | `string[]` | `[]` | A list of themes to install in the environment. The first theme in the list will be activated. | | `"port"` | `integer` | `8888` | The primary port number to use for the insallation. You'll access the instance through the port: 'http://localhost:8888'. | @@ -222,8 +230,8 @@ Several types of strings can be passed into the `core`, `plugins`, and `themes` | Type | Format | Example(s) | | ----------------- | ----------------------------- | -------------------------------------------------------- | -| Relative path | `.<path>|~<path>` | `"./a/directory"`, `"../a/directory"`, `"~/a/directory"` | -| Absolute path | `/<path>|<letter>:\<path>` | `"/a/directory"`, `"C:\\a\\directory"` | +| Relative path | `.<path>\|~<path>` | `"./a/directory"`, `"../a/directory"`, `"~/a/directory"` | +| Absolute path | `/<path>\|<letter>:\<path>` | `"/a/directory"`, `"C:\\a\\directory"` | | GitHub repository | `<owner>/<repo>[#<ref>]` | `"WordPress/WordPress"`, `"WordPress/gutenberg#master"` | | ZIP File | `http[s]://<host>/<path>.zip` | `"https://wordpress.org/wordpress-5.4-beta2.zip"` | diff --git a/packages/env/lib/build-docker-compose-config.js b/packages/env/lib/build-docker-compose-config.js index 8bc85da9f13262..c95cd875ba4e2e 100644 --- a/packages/env/lib/build-docker-compose-config.js +++ b/packages/env/lib/build-docker-compose-config.js @@ -43,13 +43,56 @@ module.exports = function buildDockerComposeConfig( config ) { ...themeMounts, ]; - const testsMounts = [ - `${ - config.coreSource ? config.coreSource.testsPath : 'tests-wordpress' - }:/var/www/html`, - ...pluginMounts, - ...themeMounts, - ]; + let testsMounts; + if ( config.coreSource ) { + testsMounts = [ + `${ config.coreSource.testsPath }:/var/www/html`, + + // When using a local source for "core" we want to ensure two things: + // + // 1. That changes the user makes within the "core" directory are + // served in both the development and tests environments. + // 2. That the development and tests environment use separate + // databases and `wp-content/uploads`. + // + // To do this we copy the local "core" files ($wordpress) to a tests + // directory ($tests-wordpress) and instruct the tests environment + // to source its files like so: + // + // - wp-config.php <- $tests-wordpress/wp-config.php + // - wp-config-sample.php <- $tests-wordpress/wp-config.php + // - wp-content <- $tests-wordpress/wp-content + // - * <- $wordpress/* + // + // https://github.com/WordPress/gutenberg/issues/21164 + ...( config.coreSource.type === 'local' + ? fs + .readdirSync( config.coreSource.path ) + .filter( + ( filename ) => + filename !== 'wp-config.php' && + filename !== 'wp-config-sample.php' && + filename !== 'wp-content' + ) + .map( + ( filename ) => + `${ path.join( + config.coreSource.path, + filename + ) }:/var/www/html/${ filename }` + ) + : [] ), + + ...pluginMounts, + ...themeMounts, + ]; + } else { + testsMounts = [ + 'tests-wordpress:/var/www/html', + ...pluginMounts, + ...themeMounts, + ]; + } // Set the default ports based on the config values. const developmentPorts = `\${WP_ENV_PORT:-${ config.port }}:80`; diff --git a/packages/env/lib/commands/clean.js b/packages/env/lib/commands/clean.js new file mode 100644 index 00000000000000..1a24adca8cadbc --- /dev/null +++ b/packages/env/lib/commands/clean.js @@ -0,0 +1,44 @@ +/** + * Internal dependencies + */ +const initConfig = require( '../init-config' ); +const { configureWordPress, resetDatabase } = require( '../wordpress' ); + +/** + * Wipes the development server's database, the tests server's database, or both. + * + * @param {Object} options + * @param {string} options.environment The environment to clean. Either 'development', 'tests', or 'all'. + * @param {Object} options.spinner A CLI spinner which indicates progress. + * @param {boolean} options.debug True if debug mode is enabled. + */ +module.exports = async function clean( { environment, spinner, debug } ) { + const config = await initConfig( { spinner, debug } ); + + const description = `${ environment } environment${ + environment === 'all' ? 's' : '' + }`; + spinner.text = `Cleaning ${ description }.`; + + const tasks = []; + + if ( environment === 'all' || environment === 'development' ) { + tasks.push( + resetDatabase( 'development', config ) + .then( () => configureWordPress( 'development', config ) ) + .catch( () => {} ) + ); + } + + if ( environment === 'all' || environment === 'tests' ) { + tasks.push( + resetDatabase( 'tests', config ) + .then( () => configureWordPress( 'tests', config ) ) + .catch( () => {} ) + ); + } + + await Promise.all( tasks ); + + spinner.text = `Cleaned ${ description }.`; +}; diff --git a/packages/env/lib/commands/index.js b/packages/env/lib/commands/index.js new file mode 100644 index 00000000000000..d301eab7ae3c2a --- /dev/null +++ b/packages/env/lib/commands/index.js @@ -0,0 +1,14 @@ +/** + * Internal dependencies + */ +const start = require( './start' ); +const stop = require( './stop' ); +const clean = require( './clean' ); +const run = require( './run' ); + +module.exports = { + start, + stop, + clean, + run, +}; diff --git a/packages/env/lib/commands/run.js b/packages/env/lib/commands/run.js new file mode 100644 index 00000000000000..02aad1407a9e5e --- /dev/null +++ b/packages/env/lib/commands/run.js @@ -0,0 +1,47 @@ +/** + * External dependencies + */ +const dockerCompose = require( 'docker-compose' ); + +/** + * Internal dependencies + */ +const initConfig = require( '../init-config' ); + +/** + * Runs an arbitrary command on the given Docker container. + * + * @param {Object} options + * @param {Object} options.container The Docker container to run the command on. + * @param {Object} options.command The command to run. + * @param {Object} options.spinner A CLI spinner which indicates progress. + * @param {boolean} options.debug True if debug mode is enabled. + */ +module.exports = async function run( { container, command, spinner, debug } ) { + const config = await initConfig( { spinner, debug } ); + + command = command.join( ' ' ); + + spinner.text = `Running \`${ command }\` in '${ container }'.`; + + const result = await dockerCompose.run( container, command, { + config: config.dockerComposeConfigPath, + commandOptions: [ '--rm' ], + log: config.debug, + } ); + + if ( result.out ) { + // eslint-disable-next-line no-console + console.log( + process.stdout.isTTY ? `\n\n${ result.out }\n\n` : result.out + ); + } else if ( result.err ) { + // eslint-disable-next-line no-console + console.error( + process.stdout.isTTY ? `\n\n${ result.err }\n\n` : result.err + ); + throw result.err; + } + + spinner.text = `Ran \`${ command }\` in '${ container }'.`; +}; diff --git a/packages/env/lib/commands/start.js b/packages/env/lib/commands/start.js new file mode 100644 index 00000000000000..16aa48d40302e7 --- /dev/null +++ b/packages/env/lib/commands/start.js @@ -0,0 +1,191 @@ +/** + * External dependencies + */ +const dockerCompose = require( 'docker-compose' ); +const util = require( 'util' ); +const path = require( 'path' ); +const fs = require( 'fs' ).promises; +const inquirer = require( 'inquirer' ); + +/** + * Promisified dependencies + */ +const sleep = util.promisify( setTimeout ); +const rimraf = util.promisify( require( 'rimraf' ) ); + +/** + * Internal dependencies + */ +const retry = require( '../retry' ); +const stop = require( './stop' ); +const initConfig = require( '../init-config' ); +const downloadSource = require( '../download-source' ); +const { + checkDatabaseConnection, + makeContentDirectoriesWritable, + configureWordPress, + copyCoreFiles, +} = require( '../wordpress' ); + +/** + * Starts the development server. + * + * @param {Object} options + * @param {Object} options.spinner A CLI spinner which indicates progress. + * @param {boolean} options.debug True if debug mode is enabled. + */ +module.exports = async function start( { spinner, debug } ) { + /** + * If the Docker image is already running and the `wp-env` files have been + * deleted, the start command will not complete successfully. Stopping + * the container before continuing allows the docker entrypoint script, + * which restores the files, to run again when we start the containers. + * + * Additionally, this serves as a way to restart the container entirely + * should the need arise. + * + * @see https://github.com/WordPress/gutenberg/pull/20253#issuecomment-587228440 + */ + await stop( { spinner, debug } ); + + await checkForLegacyInstall( spinner ); + + const config = await initConfig( { spinner, debug } ); + + spinner.text = 'Downloading WordPress.'; + + const progresses = {}; + const getProgressSetter = ( id ) => ( progress ) => { + progresses[ id ] = progress; + spinner.text = + 'Downloading WordPress.\n' + + Object.entries( progresses ) + .map( + ( [ key, value ] ) => + ` - ${ key }: ${ ( value * 100 ).toFixed( 0 ) }/100%` + ) + .join( '\n' ); + }; + + await Promise.all( [ + // Preemptively start the database while we wait for sources to download. + dockerCompose.upOne( 'mysql', { + config: config.dockerComposeConfigPath, + log: config.debug, + } ), + + ( async () => { + if ( config.coreSource ) { + await downloadSource( config.coreSource, { + onProgress: getProgressSetter( 'core' ), + spinner, + debug: config.debug, + } ); + await copyCoreFiles( + config.coreSource.path, + config.coreSource.testsPath + ); + } + } )(), + + ...config.pluginSources.map( ( source ) => + downloadSource( source, { + onProgress: getProgressSetter( source.basename ), + spinner, + debug: config.debug, + } ) + ), + + ...config.themeSources.map( ( source ) => + downloadSource( source, { + onProgress: getProgressSetter( source.basename ), + spinner, + debug: config.debug, + } ) + ), + ] ); + + spinner.text = 'Starting WordPress.'; + + await dockerCompose.upMany( [ 'wordpress', 'tests-wordpress' ], { + config: config.dockerComposeConfigPath, + log: config.debug, + } ); + + if ( config.coreSource === null ) { + // Don't chown wp-content when it exists on the user's local filesystem. + await Promise.all( [ + makeContentDirectoriesWritable( 'development', config ), + makeContentDirectoriesWritable( 'tests', config ), + ] ); + } + + try { + await checkDatabaseConnection( config ); + } catch ( error ) { + // Wait 30 seconds for MySQL to accept connections. + await retry( () => checkDatabaseConnection( config ), { + times: 30, + delay: 1000, + } ); + + // It takes 3-4 seconds for MySQL to be ready after it starts accepting connections. + await sleep( 4000 ); + } + + // Retry WordPress installation in case MySQL *still* wasn't ready. + await Promise.all( [ + retry( () => configureWordPress( 'development', config ), { + times: 2, + } ), + retry( () => configureWordPress( 'tests', config ), { times: 2 } ), + ] ); + + spinner.text = 'WordPress started.'; +}; + +/** + * Checks for legacy installs and provides + * the user the option to delete them. + * + * @param {Object} spinner A CLI spinner which indicates progress. + */ +async function checkForLegacyInstall( spinner ) { + const basename = path.basename( process.cwd() ); + const installs = [ + `../${ basename }-wordpress`, + `../${ basename }-tests-wordpress`, + ]; + await Promise.all( + installs.map( ( install ) => + fs + .access( install ) + .catch( () => + installs.splice( installs.indexOf( install ), 1 ) + ) + ) + ); + if ( ! installs.length ) { + return; + } + + spinner.info( + `It appears that you have used a previous version of this tool where installs were kept in ${ installs.join( + ' and ' + ) }. Installs are now in your home folder.\n` + ); + const { yesDelete } = await inquirer.prompt( [ + { + type: 'confirm', + name: 'yesDelete', + message: + 'Do you wish to delete these old installs to reclaim disk space?', + default: true, + }, + ] ); + if ( yesDelete ) { + await Promise.all( installs.map( ( install ) => rimraf( install ) ) ); + spinner.info( 'Old installs deleted successfully.' ); + } + spinner.start(); +} diff --git a/packages/env/lib/commands/stop.js b/packages/env/lib/commands/stop.js new file mode 100644 index 00000000000000..4f6688003ebb9d --- /dev/null +++ b/packages/env/lib/commands/stop.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +const dockerCompose = require( 'docker-compose' ); + +/** + * Internal dependencies + */ +const initConfig = require( '../init-config' ); + +/** + * Stops the development server. + * + * @param {Object} options + * @param {Object} options.spinner A CLI spinner which indicates progress. + * @param {boolean} options.debug True if debug mode is enabled. + */ +module.exports = async function stop( { spinner, debug } ) { + const { dockerComposeConfigPath } = await initConfig( { + spinner, + debug, + } ); + + spinner.text = 'Stopping WordPress.'; + + await dockerCompose.down( { + config: dockerComposeConfigPath, + log: debug, + } ); + + spinner.text = 'Stopped WordPress.'; +}; diff --git a/packages/env/lib/download-source.js b/packages/env/lib/download-source.js index 74bf5f1c4fb563..0e594312f37273 100644 --- a/packages/env/lib/download-source.js +++ b/packages/env/lib/download-source.js @@ -5,14 +5,13 @@ const util = require( 'util' ); const NodeGit = require( 'nodegit' ); const fs = require( 'fs' ); -const requestProgress = require( 'request-progress' ); -const request = require( 'request' ); +const got = require( 'got' ); const path = require( 'path' ); /** * Promisified dependencies */ -const finished = util.promisify( require( 'stream' ).finished ); +const pipeline = util.promisify( require( 'stream' ).pipeline ); const extractZip = util.promisify( require( 'extract-zip' ) ); const rimraf = util.promisify( require( 'rimraf' ) ); const copyDir = util.promisify( require( 'copy-dir' ) ); @@ -132,11 +131,12 @@ async function downloadZipSource( source, { onProgress, spinner, debug } ) { log( 'Downloading zip file.' ); const zipName = `${ source.path }.zip`; const zipFile = fs.createWriteStream( zipName ); - await finished( - requestProgress( request( source.url ) ) - .on( 'progress', ( { percent } ) => onProgress( percent ) ) - .pipe( zipFile ) + + const responseStream = got.stream( source.url ); + responseStream.on( 'downloadProgress', ( { percent } ) => + onProgress( percent ) ); + await pipeline( responseStream, zipFile ); log( 'Extracting to temporary folder.' ); const dirName = `${ source.path }.temp`; diff --git a/packages/env/lib/env.js b/packages/env/lib/env.js index 02070c2b07672f..3942a307109377 100644 --- a/packages/env/lib/env.js +++ b/packages/env/lib/env.js @@ -1,528 +1,11 @@ 'use strict'; -/** - * External dependencies - */ -const util = require( 'util' ); -const path = require( 'path' ); -const fs = require( 'fs' ).promises; -const dockerCompose = require( 'docker-compose' ); -const yaml = require( 'js-yaml' ); -const inquirer = require( 'inquirer' ); - -/** - * Promisified dependencies - */ -const copyDir = util.promisify( require( 'copy-dir' ) ); -const sleep = util.promisify( setTimeout ); -const rimraf = util.promisify( require( 'rimraf' ) ); - /** * Internal dependencies */ -const { ValidationError, readConfig } = require( './config' ); -const downloadSource = require( './download-source' ); -const buildDockerComposeConfig = require( './build-docker-compose-config' ); - -/** - * @typedef {import('./config').Config} Config - */ +const { ValidationError } = require( './config' ); +const commands = require( './commands' ); module.exports = { - /** - * Starts the development server. - * - * @param {Object} options - * @param {Object} options.spinner A CLI spinner which indicates progress. - * @param {boolean} options.debug True if debug mode is enabled. - */ - async start( { spinner, debug } ) { - /** - * If the Docker image is already running and the `wp-env` files have been - * deleted, the start command will not complete successfully. Stopping - * the container before continuing allows the docker entrypoint script, - * which restores the files, to run again when we start the containers. - * - * Additionally, this serves as a way to restart the container entirely - * should the need arise. - * - * @see https://github.com/WordPress/gutenberg/pull/20253#issuecomment-587228440 - */ - await module.exports.stop( { spinner, debug } ); - - await checkForLegacyInstall( spinner ); - - const config = await initConfig( { spinner, debug } ); - - spinner.text = 'Downloading WordPress.'; - - const progresses = {}; - const getProgressSetter = ( id ) => ( progress ) => { - progresses[ id ] = progress; - spinner.text = - 'Downloading WordPress.\n' + - Object.entries( progresses ) - .map( - ( [ key, value ] ) => - ` - ${ key }: ${ ( value * 100 ).toFixed( - 0 - ) }/100%` - ) - .join( '\n' ); - }; - - await Promise.all( [ - // Preemptively start the database while we wait for sources to download. - dockerCompose.upOne( 'mysql', { - config: config.dockerComposeConfigPath, - log: config.debug, - } ), - - ( async () => { - if ( config.coreSource ) { - await downloadSource( config.coreSource, { - onProgress: getProgressSetter( 'core' ), - spinner, - debug: config.debug, - } ); - await copyCoreFiles( - config.coreSource.path, - config.coreSource.testsPath - ); - } - } )(), - - ...config.pluginSources.map( ( source ) => - downloadSource( source, { - onProgress: getProgressSetter( source.basename ), - spinner, - debug: config.debug, - } ) - ), - - ...config.themeSources.map( ( source ) => - downloadSource( source, { - onProgress: getProgressSetter( source.basename ), - spinner, - debug: config.debug, - } ) - ), - ] ); - - spinner.text = 'Starting WordPress.'; - - await dockerCompose.upMany( [ 'wordpress', 'tests-wordpress' ], { - config: config.dockerComposeConfigPath, - log: config.debug, - } ); - - if ( config.coreSource === null ) { - // Don't chown wp-content when it exists on the user's local filesystem. - await Promise.all( [ - makeContentDirectoriesWritable( 'development', config ), - makeContentDirectoriesWritable( 'tests', config ), - ] ); - } - - try { - await checkDatabaseConnection( config ); - } catch ( error ) { - // Wait 30 seconds for MySQL to accept connections. - await retry( () => checkDatabaseConnection( config ), { - times: 30, - delay: 1000, - } ); - - // It takes 3-4 seconds for MySQL to be ready after it starts accepting connections. - await sleep( 4000 ); - } - - // Retry WordPress installation in case MySQL *still* wasn't ready. - await Promise.all( [ - retry( () => configureWordPress( 'development', config ), { - times: 2, - } ), - retry( () => configureWordPress( 'tests', config ), { times: 2 } ), - ] ); - - spinner.text = 'WordPress started.'; - }, - - /** - * Stops the development server. - * - * @param {Object} options - * @param {Object} options.spinner A CLI spinner which indicates progress. - * @param {boolean} options.debug True if debug mode is enabled. - */ - async stop( { spinner, debug } ) { - const { dockerComposeConfigPath } = await initConfig( { - spinner, - debug, - } ); - - spinner.text = 'Stopping WordPress.'; - - await dockerCompose.down( { - config: dockerComposeConfigPath, - log: debug, - } ); - - spinner.text = 'Stopped WordPress.'; - }, - - /** - * Wipes the development server's database, the tests server's database, or both. - * - * @param {Object} options - * @param {string} options.environment The environment to clean. Either 'development', 'tests', or 'all'. - * @param {Object} options.spinner A CLI spinner which indicates progress. - * @param {boolean} options.debug True if debug mode is enabled. - */ - async clean( { environment, spinner, debug } ) { - const config = await initConfig( { spinner, debug } ); - - const description = `${ environment } environment${ - environment === 'all' ? 's' : '' - }`; - spinner.text = `Cleaning ${ description }.`; - - const tasks = []; - - if ( environment === 'all' || environment === 'development' ) { - tasks.push( - resetDatabase( 'development', config ) - .then( () => configureWordPress( 'development', config ) ) - .catch( () => {} ) - ); - } - - if ( environment === 'all' || environment === 'tests' ) { - tasks.push( - resetDatabase( 'tests', config ) - .then( () => configureWordPress( 'tests', config ) ) - .catch( () => {} ) - ); - } - - await Promise.all( tasks ); - - spinner.text = `Cleaned ${ description }.`; - }, - - /** - * Runs an arbitrary command on the given Docker container. - * - * @param {Object} options - * @param {Object} options.container The Docker container to run the command on. - * @param {Object} options.command The command to run. - * @param {Object} options.spinner A CLI spinner which indicates progress. - * @param {boolean} options.debug True if debug mode is enabled. - */ - async run( { container, command, spinner, debug } ) { - const config = await initConfig( { spinner, debug } ); - - command = command.join( ' ' ); - - spinner.text = `Running \`${ command }\` in '${ container }'.`; - - const result = await dockerCompose.run( container, command, { - config: config.dockerComposeConfigPath, - commandOptions: [ '--rm' ], - log: config.debug, - } ); - - if ( result.out ) { - // eslint-disable-next-line no-console - console.log( - process.stdout.isTTY ? `\n\n${ result.out }\n\n` : result.out - ); - } else if ( result.err ) { - // eslint-disable-next-line no-console - console.error( - process.stdout.isTTY ? `\n\n${ result.err }\n\n` : result.err - ); - throw result.err; - } - - spinner.text = `Ran \`${ command }\` in '${ container }'.`; - }, - + ...commands, ValidationError, }; - -/** - * Checks for legacy installs and provides - * the user the option to delete them. - * - * @param {Object} spinner A CLI spinner which indicates progress. - */ -async function checkForLegacyInstall( spinner ) { - const basename = path.basename( process.cwd() ); - const installs = [ - `../${ basename }-wordpress`, - `../${ basename }-tests-wordpress`, - ]; - await Promise.all( - installs.map( ( install ) => - fs - .access( install ) - .catch( () => - installs.splice( installs.indexOf( install ), 1 ) - ) - ) - ); - if ( ! installs.length ) { - return; - } - - spinner.info( - `It appears that you have used a previous version of this tool where installs were kept in ${ installs.join( - ' and ' - ) }. Installs are now in your home folder.\n` - ); - const { yesDelete } = await inquirer.prompt( [ - { - type: 'confirm', - name: 'yesDelete', - message: - 'Do you wish to delete these old installs to reclaim disk space?', - default: true, - }, - ] ); - if ( yesDelete ) { - await Promise.all( installs.map( ( install ) => rimraf( install ) ) ); - spinner.info( 'Old installs deleted successfully.' ); - } - spinner.start(); -} - -/** - * Initializes the local environment so that Docker commands can be run. Reads - * ./.wp-env.json, creates ~/.wp-env, and creates ~/.wp-env/docker-compose.yml. - * - * @param {Object} options - * @param {Object} options.spinner A CLI spinner which indicates progress. - * @param {boolean} options.debug True if debug mode is enabled. - * - * @return {Config} The-env config object. - */ -async function initConfig( { spinner, debug } ) { - const configPath = path.resolve( '.wp-env.json' ); - const config = await readConfig( configPath ); - config.debug = debug; - - await fs.mkdir( config.workDirectoryPath, { recursive: true } ); - - const dockerComposeConfig = buildDockerComposeConfig( config ); - await fs.writeFile( - config.dockerComposeConfigPath, - yaml.dump( dockerComposeConfig ) - ); - - if ( config.debug ) { - spinner.info( - `Config:\n${ JSON.stringify( - config, - null, - 4 - ) }\n\nDocker Compose Config:\n${ JSON.stringify( - dockerComposeConfig, - null, - 4 - ) }` - ); - spinner.start(); - } - - return config; -} - -/** - * Copies a WordPress installation, taking care to ignore large directories - * (.git, node_modules) and configuration files (wp-config.php). - * - * @param {string} fromPath Path to the WordPress directory to copy. - * @param {string} toPath Destination path. - */ -async function copyCoreFiles( fromPath, toPath ) { - await copyDir( fromPath, toPath, { - filter( stat, filepath, filename ) { - if ( stat === 'symbolicLink' ) { - return false; - } - if ( stat === 'directory' && filename === '.git' ) { - return false; - } - if ( stat === 'directory' && filename === 'node_modules' ) { - return false; - } - if ( stat === 'file' && filename === 'wp-config.php' ) { - return false; - } - return true; - }, - } ); -} - -/** - * Makes the WordPress content directories (wp-content, wp-content/plugins, - * wp-content/themes) owned by the www-data user. This ensures that WordPress - * can write to these directories. - * - * This is necessary when running wp-env with `"core": null` because Docker - * will automatically create these directories as the root user when binding - * volumes during `docker-compose up`, and `docker-compose up` doesn't support - * the `-u` option. - * - * See https://github.com/docker-library/wordpress/issues/436. - * - * @param {string} environment The environment to check. Either 'development' or 'tests'. - * @param {Config} config The wp-env config object. - */ -async function makeContentDirectoriesWritable( - environment, - { dockerComposeConfigPath, debug } -) { - await dockerCompose.exec( - environment === 'development' ? 'wordpress' : 'tests-wordpress', - 'chown www-data:www-data wp-content wp-content/plugins wp-content/themes', - { - config: dockerComposeConfigPath, - log: debug, - } - ); -} - -/** - * Performs the given action again and again until it does not throw an error. - * - * @param {Function} action The action to perform. - * @param {Object} options - * @param {number} options.times How many times to try before giving up. - * @param {number} [options.delay=5000] How long, in milliseconds, to wait between each try. - */ -async function retry( action, { times, delay = 5000 } ) { - let tries = 0; - while ( true ) { - try { - return await action(); - } catch ( error ) { - if ( ++tries >= times ) { - throw error; - } - await sleep( delay ); - } - } -} - -/** - * Checks a WordPress database connection. An error is thrown if the test is - * unsuccessful. - * - * @param {Config} config The wp-env config object. - */ -async function checkDatabaseConnection( { dockerComposeConfigPath, debug } ) { - await dockerCompose.run( 'cli', 'wp db check', { - config: dockerComposeConfigPath, - commandOptions: [ '--rm' ], - log: debug, - } ); -} - -/** - * Configures WordPress for the given environment by installing WordPress, - * activating all plugins, and activating the first theme. These steps are - * performed sequentially so as to not overload the WordPress instance. - * - * @param {string} environment The environment to configure. Either 'development' or 'tests'. - * @param {Config} config The wp-env config object. - */ -async function configureWordPress( environment, config ) { - const options = { - config: config.dockerComposeConfigPath, - commandOptions: [ '--rm' ], - log: config.debug, - }; - - const port = environment === 'development' ? config.port : config.testsPort; - - // Install WordPress. - await dockerCompose.run( - environment === 'development' ? 'cli' : 'tests-cli', - [ - 'wp', - 'core', - 'install', - `--url=localhost:${ port }`, - `--title=${ config.name }`, - '--admin_user=admin', - '--admin_password=password', - '--admin_email=wordpress@example.com', - '--skip-email', - ], - options - ); - - // Set wp-config.php values. - for ( const [ key, value ] of Object.entries( config.config ) ) { - const command = [ 'wp', 'config', 'set', key, value ]; - if ( typeof value !== 'string' ) { - command.push( '--raw' ); - } - await dockerCompose.run( - environment === 'development' ? 'cli' : 'tests-cli', - command, - options - ); - } - - // Activate all plugins. - for ( const pluginSource of config.pluginSources ) { - await dockerCompose.run( - environment === 'development' ? 'cli' : 'tests-cli', - `wp plugin activate ${ pluginSource.basename }`, - options - ); - } - - // Activate the first theme. - const [ themeSource ] = config.themeSources; - if ( themeSource ) { - await dockerCompose.run( - environment === 'development' ? 'cli' : 'tests-cli', - `wp theme activate ${ themeSource.basename }`, - options - ); - } -} - -/** - * Resets the development server's database, the tests server's database, or both. - * - * @param {string} environment The environment to clean. Either 'development', 'tests', or 'all'. - * @param {Config} config The wp-env config object. - */ -async function resetDatabase( - environment, - { dockerComposeConfigPath, debug } -) { - const options = { - config: dockerComposeConfigPath, - commandOptions: [ '--rm' ], - log: debug, - }; - - const tasks = []; - - if ( environment === 'all' || environment === 'development' ) { - tasks.push( dockerCompose.run( 'cli', 'wp db reset --yes', options ) ); - } - - if ( environment === 'all' || environment === 'tests' ) { - tasks.push( - dockerCompose.run( 'tests-cli', 'wp db reset --yes', options ) - ); - } - - await Promise.all( tasks ); -} diff --git a/packages/env/lib/init-config.js b/packages/env/lib/init-config.js new file mode 100644 index 00000000000000..6d417954428375 --- /dev/null +++ b/packages/env/lib/init-config.js @@ -0,0 +1,57 @@ +/** + * External dependencies + */ +const path = require( 'path' ); +const fs = require( 'fs' ).promises; +const yaml = require( 'js-yaml' ); + +/** + * Internal dependencies + */ +const { readConfig } = require( './config' ); +const buildDockerComposeConfig = require( './build-docker-compose-config' ); + +/** + * @typedef {import('./config').Config} Config + */ + +/** + * Initializes the local environment so that Docker commands can be run. Reads + * ./.wp-env.json, creates ~/.wp-env, and creates ~/.wp-env/docker-compose.yml. + * + * @param {Object} options + * @param {Object} options.spinner initConfigA CLI spinner which indicates progress. + * @param {boolean} options.debug True if debug mode is enabled. + * + * @return {Config} The-env config object. + */ +module.exports = async function initConfig( { spinner, debug } ) { + const configPath = path.resolve( '.wp-env.json' ); + const config = await readConfig( configPath ); + config.debug = debug; + + await fs.mkdir( config.workDirectoryPath, { recursive: true } ); + + const dockerComposeConfig = buildDockerComposeConfig( config ); + await fs.writeFile( + config.dockerComposeConfigPath, + yaml.dump( dockerComposeConfig ) + ); + + if ( config.debug ) { + spinner.info( + `Config:\n${ JSON.stringify( + config, + null, + 4 + ) }\n\nDocker Compose Config:\n${ JSON.stringify( + dockerComposeConfig, + null, + 4 + ) }` + ); + spinner.start(); + } + + return config; +}; diff --git a/packages/env/lib/retry.js b/packages/env/lib/retry.js new file mode 100644 index 00000000000000..b23705ee2cc06d --- /dev/null +++ b/packages/env/lib/retry.js @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +const util = require( 'util' ); + +/** + * Promisified dependencies + */ +const sleep = util.promisify( setTimeout ); + +/** + * Performs the given action again and again until it does not throw an error. + * + * @param {Function} action The action to perform. + * @param {Object} options + * @param {number} options.times How many times to try before giving up. + * @param {number} [options.delay=5000] How long, in milliseconds, to wait between each try. + */ +module.exports = async function retry( action, { times, delay = 5000 } ) { + let tries = 0; + while ( true ) { + try { + return await action(); + } catch ( error ) { + if ( ++tries >= times ) { + throw error; + } + await sleep( delay ); + } + } +}; diff --git a/packages/env/lib/wordpress.js b/packages/env/lib/wordpress.js new file mode 100644 index 00000000000000..48910b49d38cf1 --- /dev/null +++ b/packages/env/lib/wordpress.js @@ -0,0 +1,190 @@ +/** + * External dependencies + */ +const dockerCompose = require( 'docker-compose' ); +const util = require( 'util' ); + +/** + * Promisified dependencies + */ +const copyDir = util.promisify( require( 'copy-dir' ) ); + +/** + * @typedef {import('./config').Config} Config + */ + +/** + * Makes the WordPress content directories (wp-content, wp-content/plugins, + * wp-content/themes) owned by the www-data user. This ensures that WordPress + * can write to these directories. + * + * This is necessary when running wp-env with `"core": null` because Docker + * will automatically create these directories as the root user when binding + * volumes during `docker-compose up`, and `docker-compose up` doesn't support + * the `-u` option. + * + * See https://github.com/docker-library/wordpress/issues/436. + * + * @param {string} environment The environment to check. Either 'development' or 'tests'. + * @param {Config} config The wp-env config object. + */ +async function makeContentDirectoriesWritable( + environment, + { dockerComposeConfigPath, debug } +) { + await dockerCompose.exec( + environment === 'development' ? 'wordpress' : 'tests-wordpress', + 'chown www-data:www-data wp-content wp-content/plugins wp-content/themes', + { + config: dockerComposeConfigPath, + log: debug, + } + ); +} + +/** + * Checks a WordPress database connection. An error is thrown if the test is + * unsuccessful. + * + * @param {Config} config The wp-env config object. + */ +async function checkDatabaseConnection( { dockerComposeConfigPath, debug } ) { + await dockerCompose.run( 'cli', 'wp db check', { + config: dockerComposeConfigPath, + commandOptions: [ '--rm' ], + log: debug, + } ); +} + +/** + * Configures WordPress for the given environment by installing WordPress, + * activating all plugins, and activating the first theme. These steps are + * performed sequentially so as to not overload the WordPress instance. + * + * @param {string} environment The environment to configure. Either 'development' or 'tests'. + * @param {Config} config The wp-env config object. + */ +async function configureWordPress( environment, config ) { + const options = { + config: config.dockerComposeConfigPath, + commandOptions: [ '--rm' ], + log: config.debug, + }; + + const port = environment === 'development' ? config.port : config.testsPort; + + // Install WordPress. + await dockerCompose.run( + environment === 'development' ? 'cli' : 'tests-cli', + [ + 'wp', + 'core', + 'install', + `--url=localhost:${ port }`, + `--title=${ config.name }`, + '--admin_user=admin', + '--admin_password=password', + '--admin_email=wordpress@example.com', + '--skip-email', + ], + options + ); + + // Set wp-config.php values. + for ( const [ key, value ] of Object.entries( config.config ) ) { + const command = [ 'wp', 'config', 'set', key, value ]; + if ( typeof value !== 'string' ) { + command.push( '--raw' ); + } + await dockerCompose.run( + environment === 'development' ? 'cli' : 'tests-cli', + command, + options + ); + } + + // Activate all plugins. + for ( const pluginSource of config.pluginSources ) { + await dockerCompose.run( + environment === 'development' ? 'cli' : 'tests-cli', + `wp plugin activate ${ pluginSource.basename }`, + options + ); + } + + // Activate the first theme. + const [ themeSource ] = config.themeSources; + if ( themeSource ) { + await dockerCompose.run( + environment === 'development' ? 'cli' : 'tests-cli', + `wp theme activate ${ themeSource.basename }`, + options + ); + } +} + +/** + * Resets the development server's database, the tests server's database, or both. + * + * @param {string} environment The environment to clean. Either 'development', 'tests', or 'all'. + * @param {Config} config The wp-env config object. + */ +async function resetDatabase( + environment, + { dockerComposeConfigPath, debug } +) { + const options = { + config: dockerComposeConfigPath, + commandOptions: [ '--rm' ], + log: debug, + }; + + const tasks = []; + + if ( environment === 'all' || environment === 'development' ) { + tasks.push( dockerCompose.run( 'cli', 'wp db reset --yes', options ) ); + } + + if ( environment === 'all' || environment === 'tests' ) { + tasks.push( + dockerCompose.run( 'tests-cli', 'wp db reset --yes', options ) + ); + } + + await Promise.all( tasks ); +} + +/** + * Copies a WordPress installation, taking care to ignore large directories + * (.git, node_modules) and configuration files (wp-config.php). + * + * @param {string} fromPath Path to the WordPress directory to copy. + * @param {string} toPath Destination path. + */ +async function copyCoreFiles( fromPath, toPath ) { + await copyDir( fromPath, toPath, { + filter( stat, filepath, filename ) { + if ( stat === 'symbolicLink' ) { + return false; + } + if ( stat === 'directory' && filename === '.git' ) { + return false; + } + if ( stat === 'directory' && filename === 'node_modules' ) { + return false; + } + if ( stat === 'file' && filename === 'wp-config.php' ) { + return false; + } + return true; + }, + } ); +} + +module.exports = { + makeContentDirectoriesWritable, + checkDatabaseConnection, + configureWordPress, + resetDatabase, + copyCoreFiles, +}; diff --git a/packages/env/package.json b/packages/env/package.json index 15b1f15fcf3892..199f1011112ce5 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -32,16 +32,15 @@ "wp-env": "bin/wp-env" }, "dependencies": { - "chalk": "^2.4.2", + "chalk": "^4.0.0", "copy-dir": "^1.2.0", "docker-compose": "^0.22.2", "extract-zip": "^1.6.7", - "inquirer": "^7.0.4", + "got": "^10.7.0", + "inquirer": "^7.1.0", "js-yaml": "^3.13.1", "nodegit": "^0.26.2", "ora": "^4.0.2", - "request": "^2.88.2", - "request-progress": "^3.0.0", "rimraf": "^3.0.2", "terminal-link": "^2.0.0", "yargs": "^14.0.0" diff --git a/packages/env/test/config.js b/packages/env/test/config.js index 181a5a3baec23e..34384e95b43d91 100644 --- a/packages/env/test/config.js +++ b/packages/env/test/config.js @@ -1,4 +1,4 @@ -'use strict'; +/* eslint-disable jest/no-try-expect */ /** * External dependencies */ @@ -221,11 +221,11 @@ describe( 'readConfig', () => { it( 'should throw a validaton error if the ports are not numbers', async () => { expect.assertions( 10 ); - testPortNumberValidation( 'port', 'string' ); - testPortNumberValidation( 'testsPort', [] ); - testPortNumberValidation( 'port', {} ); - testPortNumberValidation( 'testsPort', false ); - testPortNumberValidation( 'port', null ); + await testPortNumberValidation( 'port', 'string' ); + await testPortNumberValidation( 'testsPort', [] ); + await testPortNumberValidation( 'port', {} ); + await testPortNumberValidation( 'testsPort', false ); + await testPortNumberValidation( 'port', null ); } ); it( 'should throw a validaton error if the ports are the same', async () => { @@ -415,3 +415,4 @@ async function testPortNumberValidation( portName, value ) { } jest.clearAllMocks(); } +/* eslint-enable jest/no-try-expect */ diff --git a/packages/escape-html/CHANGELOG.md b/packages/escape-html/CHANGELOG.md index 9f38d3c2bb14ef..ab18f8a217b329 100644 --- a/packages/escape-html/CHANGELOG.md +++ b/packages/escape-html/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#20669](https://github.com/WordPress/gutenberg/pull/20669)) + ## 1.2.0 (2019-03-20) - Add fix for WordPress wptexturize greater-than tokenize bug (see https://core.trac.wordpress.org/ticket/45387) diff --git a/packages/escape-html/package.json b/packages/escape-html/package.json index fab30cccc0bece..f989477dd161da 100644 --- a/packages/escape-html/package.json +++ b/packages/escape-html/package.json @@ -19,9 +19,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/escape-html/tsconfig.json b/packages/escape-html/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/escape-html/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index c8818e75c3940a..3a240b667c6786 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -1,10 +1,29 @@ ## Master -## 4.1.0 (2020-04-01) +### Breaking Changes + +- There is a new `i18n` ruleset that includes all i18n-related rules and is included in the `recommended` ruleset. +- The `@wordpress/valid-sprintf` rule has been moved from the `custom` ruleset to the `i18n` ruleset. +- The `@wordpress/valid-sprintf` rule now recognizes mix of ordered and non-ordered placeholders. +- The bundled `eslint-plugin-jest` dependency has been updated from requiring `^22.15.1` to requiring `^23.8.2` ([#21424](https://github.com/WordPress/gutenberg/pull/21424)). +- The bundled `eslint-plugin-jsdoc` dependency has been updated from requiring `^21.0.0` to requiring `^22.1.0` ([#21424](https://github.com/WordPress/gutenberg/pull/21424)). +- The bundled `eslint-plugin-react-hooks` dependency has been updated from requiring `^1.6.1` to requiring `^3.0.0` ([#21424](https://github.com/WordPress/gutenberg/pull/21424)). ### New Features - The `prefer-const` rule included in the `recommended` and `esnext` rulesets has been relaxed to allow a `let` assignment if any of a [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) are reassigned. +- New Rule: [`@wordpress/i18n-text-domain`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/i18n-text-domain.md) +- New Rule: [`@wordpress/i18n-translator-comments`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/i18n-translator-comments.md) +- New Rule: [`@wordpress/i18n-no-variables`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/i18n-no-variables.md) +- New Rule: [`@wordpress/i18n-no-placeholders-only`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/i18n-no-placeholders-only.md) +- New Rule: [`@wordpress/i18n-no-collapsible-whitespace`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/i18n-no-collapsible-whitespace.md) +- New Rule: [`@wordpress/i18n-ellipsis`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/i18n-ellipsis.md) +- The bundled `eslint-plugin-react` dependency has been updated from requiring `^7.14.3` to requiring `^7.19.0` ([#21424](https://github.com/WordPress/gutenberg/pull/21424)). + +### Bug Fix + +- The `@wordpress/valid-sprintf` rule now detects usage of `sprintf` via `i18n.sprintf` (e.g. when using `import * as i18n from '@wordpress/i18n'`). +- `@wordpress/no-unused-vars-before-return` will correctly consider other unused variables after encountering an instance of an `excludePattern` option exception. ## 4.0.0 (2020-02-10) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 31979f983b52f9..e6bf980d326a3f 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -36,6 +36,7 @@ Alternatively, you can opt-in to only the more granular rulesets offered by the - `jsdoc` - `jsx-a11y` - `react` +- `i18n` - `test-e2e` - `test-unit` diff --git a/packages/eslint-plugin/configs/custom.js b/packages/eslint-plugin/configs/custom.js index 8949b63f94d8dc..276d1f15a2584a 100644 --- a/packages/eslint-plugin/configs/custom.js +++ b/packages/eslint-plugin/configs/custom.js @@ -2,30 +2,8 @@ module.exports = { plugins: [ '@wordpress' ], rules: { '@wordpress/no-unused-vars-before-return': 'error', - '@wordpress/valid-sprintf': 'error', '@wordpress/no-base-control-with-label-without-id': 'error', '@wordpress/no-unguarded-get-range-at': 'error', - 'no-restricted-syntax': [ - 'error', - { - selector: - 'CallExpression[callee.name=/^(__|_n|_nx|_x)$/]:not([arguments.0.type=/^Literal|BinaryExpression$/])', - message: - 'Translate function arguments must be string literals.', - }, - { - selector: - 'CallExpression[callee.name=/^(_n|_nx|_x)$/]:not([arguments.1.type=/^Literal|BinaryExpression$/])', - message: - 'Translate function arguments must be string literals.', - }, - { - selector: - 'CallExpression[callee.name=_nx]:not([arguments.3.type=/^Literal|BinaryExpression$/])', - message: - 'Translate function arguments must be string literals.', - }, - ], }, overrides: [ { diff --git a/packages/eslint-plugin/configs/i18n.js b/packages/eslint-plugin/configs/i18n.js new file mode 100644 index 00000000000000..c3271214e3ef5c --- /dev/null +++ b/packages/eslint-plugin/configs/i18n.js @@ -0,0 +1,12 @@ +module.exports = { + plugins: [ '@wordpress' ], + rules: { + '@wordpress/valid-sprintf': 'error', + '@wordpress/i18n-translator-comments': 'error', + '@wordpress/i18n-text-domain': 'error', + '@wordpress/i18n-no-collapsible-whitespace': 'error', + '@wordpress/i18n-no-placeholders-only': 'error', + '@wordpress/i18n-no-variables': 'error', + '@wordpress/i18n-ellipsis': 'error', + }, +}; diff --git a/packages/eslint-plugin/configs/jsdoc.js b/packages/eslint-plugin/configs/jsdoc.js index ce2414a31add63..bf5e245ec90009 100644 --- a/packages/eslint-plugin/configs/jsdoc.js +++ b/packages/eslint-plugin/configs/jsdoc.js @@ -47,6 +47,7 @@ const typescriptUtilityTypes = [ 'IterableIterator', 'NonNullable', 'Omit', + 'Parameters', 'Partial', 'Pick', 'PromiseLike', @@ -58,6 +59,9 @@ const typescriptUtilityTypes = [ 'Required', 'ReturnType', 'ThisType', + 'unknown', + 'never', + 'NodeJS', ]; module.exports = { @@ -94,5 +98,26 @@ module.exports = { 'jsdoc/require-jsdoc': 'off', 'jsdoc/require-param-description': 'off', 'jsdoc/require-returns': 'off', + 'jsdoc/check-access': 'error', + 'jsdoc/check-alignment': 'error', + 'jsdoc/check-param-names': 'error', + 'jsdoc/check-property-names': 'error', + 'jsdoc/check-tag-names': 'error', + 'jsdoc/check-types': 'error', + 'jsdoc/check-values': 'off', + 'jsdoc/empty-tags': 'error', + 'jsdoc/implements-on-classes': 'error', + 'jsdoc/newline-after-description': 'error', + 'jsdoc/require-param': 'error', + 'jsdoc/require-param-name': 'error', + 'jsdoc/require-param-type': 'error', + 'jsdoc/require-property': 'error', + 'jsdoc/require-property-description': 'error', + 'jsdoc/require-property-name': 'error', + 'jsdoc/require-property-type': 'error', + 'jsdoc/require-returns-check': 'error', + 'jsdoc/require-returns-description': 'error', + 'jsdoc/require-returns-type': 'error', + 'jsdoc/valid-types': 'error', }, }; diff --git a/packages/eslint-plugin/configs/recommended-with-formatting.js b/packages/eslint-plugin/configs/recommended-with-formatting.js index 61e08359128075..d6e51149a928e9 100644 --- a/packages/eslint-plugin/configs/recommended-with-formatting.js +++ b/packages/eslint-plugin/configs/recommended-with-formatting.js @@ -5,6 +5,7 @@ module.exports = { require.resolve( './custom.js' ), require.resolve( './react.js' ), require.resolve( './esnext.js' ), + require.resolve( './i18n.js' ), ], env: { node: true, diff --git a/packages/eslint-plugin/docs/rules/i18n-ellipsis.md b/packages/eslint-plugin/docs/rules/i18n-ellipsis.md new file mode 100644 index 00000000000000..f08a43bc56af4a --- /dev/null +++ b/packages/eslint-plugin/docs/rules/i18n-ellipsis.md @@ -0,0 +1,18 @@ +# Disallow using three dots in translatable strings (i18n-ellipsis) + +Three dots for indicating an ellipsis should be replaced with the UTF-8 character … (Horizontal Ellipsis, U+2026) as it has a more semantic meaning. + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +__( 'Continue...' ); + +``` + +Examples of **correct** code for this rule: + +```js +__( 'Continue…' ); +``` diff --git a/packages/eslint-plugin/docs/rules/i18n-no-collapsible-whitespace.md b/packages/eslint-plugin/docs/rules/i18n-no-collapsible-whitespace.md new file mode 100644 index 00000000000000..d9564698535a96 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/i18n-no-collapsible-whitespace.md @@ -0,0 +1,26 @@ +# Disallow collapsible whitespace in translatable strings. (i18n-no-collapsible-whitespace) + +Using complex whitespace in translatable strings and relying on HTML to collapse it can make translation more difficult and lead to unnecessary retranslation. + +Whitespace can be appropriate in longer translatable content, for example a whole blog post. These cases are unlikely to occur in the code scanned by eslint but if they do, [disable the rule with inline comments](http://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments. ( e.g. `// eslint-disable-line i18n-no-collapsible-whitespace` ). + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +__( "A string\non two lines" ); +__( 'A string\non two lines' ); +__( `A string +on two lines` ); +__( `A string with tabs` ); +__( "Multiple spaces. Even after a full stop. (We're going there)" ); +``` + +Examples of **correct** code for this rule: + +```js +__( `A long string ` + + `spread over ` + + `multiple lines.` ); +``` diff --git a/packages/eslint-plugin/docs/rules/i18n-no-placeholders-only.md b/packages/eslint-plugin/docs/rules/i18n-no-placeholders-only.md new file mode 100644 index 00000000000000..286690a79e70c0 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/i18n-no-placeholders-only.md @@ -0,0 +1,17 @@ +# Prevent using only placeholders in translatable strings (i18n-no-placeholders-only) + +Translatable strings that consist of nothing but a placeholder cannot be translated. + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +__( '%s' ); +``` + +Examples of **correct** code for this rule: + +```js +__( 'Hello %s' ); +``` diff --git a/packages/eslint-plugin/docs/rules/i18n-no-variables.md b/packages/eslint-plugin/docs/rules/i18n-no-variables.md new file mode 100644 index 00000000000000..3478f02acf755d --- /dev/null +++ b/packages/eslint-plugin/docs/rules/i18n-no-variables.md @@ -0,0 +1,24 @@ +# Enforce string literals as translation function arguments (i18n-no-variables) + +[Translation functions](https://github.com/WordPress/gutenberg/blob/master/packages/i18n/README.md#api) must be called with valid string literals as arguments. + +They cannot be variables or functions due to the way these strings are extracted through static analysis of the code. The exception to this rule is string concatenation within the argument itself. + +This limitation applies to both singular and plural strings, as well as the `context` argument if present. + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +__( `Hello ${foo}` ); +__( foo ); +_x( 'Hello World', bar ); +``` + +Examples of **correct** code for this rule: + +```js +__( 'Hello World' ); +_x( 'Hello' + ' World', 'context', 'foo' ); +``` diff --git a/packages/eslint-plugin/docs/rules/i18n-text-domain.md b/packages/eslint-plugin/docs/rules/i18n-text-domain.md new file mode 100644 index 00000000000000..7a637fc43aaeb1 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/i18n-text-domain.md @@ -0,0 +1,26 @@ +# Enforce passing valid text domains (i18n-text-domain) + +[Translation functions](https://github.com/WordPress/gutenberg/blob/master/packages/i18n/README.md#api) must be called with a valid string literal as the text domain. + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +__( 'Hello World' ); // unless allowedTextDomain contains 'default' +__( 'Hello World', 'default' ); // with allowedTextDomain = [ 'default' ] +__( 'Hello World', foo ); +``` + +Examples of **correct** code for this rule: + +```js +__( 'Hello World' ); // with allowedTextDomain = [ 'default' ] +__( 'Hello World', 'foo-bar' ); // with allowedTextDomain = [ 'foo-bar' ] +``` + +## Options + +This rule accepts a single options argument: + +- Set `allowedTextDomain` to specify the list of allowed text domains, e.g. `[ 'foo', 'bar' ]`. The default is `[ 'default' ]`. diff --git a/packages/eslint-plugin/docs/rules/i18n-translator-comments.md b/packages/eslint-plugin/docs/rules/i18n-translator-comments.md new file mode 100644 index 00000000000000..59a9453e46ec01 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/i18n-translator-comments.md @@ -0,0 +1,38 @@ +# Enforce adding translator comments (i18n-translator-comments) + +If using [translation functions](https://github.com/WordPress/gutenberg/blob/master/packages/i18n/README.md#api) with placeholders in them, +they need accompanying translator comments. + +## Rule details + +Examples of **incorrect** code for this rule: + +```js +var color = ''; +sprintf( __( 'Color: %s' ), color ); + +var address = ''; +sprintf( + __( 'Address: %s' ), + address +); + +// translators: %s: Name +var name = ''; +sprintf( __( 'Name: %s' ), name ); +``` + +Examples of **correct** code for this rule: + +```js +var color = ''; +// translators: %s: Color +sprintf( __( 'Color: %s' ), color ); + +var address = ''; +sprintf( + // translators: %s: Address. + __( 'Address: %s' ), + address, +); +``` diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 12eda9f0c23813..f910c5d6e1b835 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -24,14 +24,14 @@ ], "main": "index.js", "dependencies": { - "babel-eslint": "^10.0.3", - "eslint-config-prettier": "^6.10.0", - "eslint-plugin-jest": "^22.15.1", - "eslint-plugin-jsdoc": "^15.8.0", + "babel-eslint": "^10.1.0", + "eslint-config-prettier": "^6.10.1", + "eslint-plugin-jest": "^23.8.2", + "eslint-plugin-jsdoc": "^22.1.0", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-prettier": "^3.1.2", - "eslint-plugin-react": "^7.14.3", - "eslint-plugin-react-hooks": "^1.6.1", + "eslint-plugin-react": "^7.19.0", + "eslint-plugin-react-hooks": "^3.0.0", "globals": "^12.0.0", "prettier": "npm:wp-prettier@1.19.1", "requireindex": "^1.2.0" diff --git a/packages/eslint-plugin/rules/__tests__/i18n-ellipsis.js b/packages/eslint-plugin/rules/__tests__/i18n-ellipsis.js new file mode 100644 index 00000000000000..2bc487e92d42bd --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/i18n-ellipsis.js @@ -0,0 +1,65 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../i18n-ellipsis'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'i18n-ellipsis', rule, { + valid: [ + { + code: `__( 'Hello World…' )`, + }, + { + code: `__( 'Hello' + 'World…' )`, + }, + { + code: `_x( 'Hello World…', 'context' )`, + }, + { + code: `_n( 'Singular…', 'Plural…', number)`, + }, + { + code: `i18n.__( 'Hello World…' )`, + }, + ], + invalid: [ + { + code: `__( 'Hello World...' )`, + output: `__( 'Hello World…' )`, + errors: [ { messageId: 'foundThreeDots' } ], + }, + { + code: `__( 'Hello' + 'World...' )`, + output: `__( 'Hello' + 'World…' )`, + errors: [ { messageId: 'foundThreeDots' } ], + }, + { + code: `_x( 'Hello World...', 'context' )`, + output: `_x( 'Hello World…', 'context' )`, + errors: [ { messageId: 'foundThreeDots' } ], + }, + { + code: `_n( 'Singular...', 'Plural...', number)`, + output: `_n( 'Singular…', 'Plural…', number)`, + errors: [ + { messageId: 'foundThreeDots' }, + { messageId: 'foundThreeDots' }, + ], + }, + { + code: `i18n.__( 'Hello World...' )`, + output: `i18n.__( 'Hello World…' )`, + errors: [ { messageId: 'foundThreeDots' } ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/__tests__/i18n-no-collapsible-whitespace.js b/packages/eslint-plugin/rules/__tests__/i18n-no-collapsible-whitespace.js new file mode 100644 index 00000000000000..35e4e47301d7aa --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/i18n-no-collapsible-whitespace.js @@ -0,0 +1,62 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../i18n-no-collapsible-whitespace'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'i18n-no-collapsible-whitespace', rule, { + valid: [ + { + code: `__( 'Hello World…' )`, + }, + { + code: + '__( `A long string ` +\n `spread over ` +\n `multiple lines.` );', + }, + ], + invalid: [ + { + code: '__( "My double-quoted string\\nwith a newline" );', + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: "__( 'My single quoted string\\nwith a newline' );", + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: '__( `My template literal\non two lines` );', + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: "__( ' My tab-indented string.' );", + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: "__( '\tMy string with a tab escape sequence.' );", + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: "__( '\u0009My string with a unicode tab.' );", + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: '__( `A string with \r a carriage return.` );', + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + { + code: + "__( 'A string with consecutive spaces. These two are after a full stop.' );", + errors: [ { messageId: 'noCollapsibleWhitespace' } ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/__tests__/i18n-no-placeholders-only.js b/packages/eslint-plugin/rules/__tests__/i18n-no-placeholders-only.js new file mode 100644 index 00000000000000..7743798805267c --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/i18n-no-placeholders-only.js @@ -0,0 +1,50 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../i18n-no-placeholders-only'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'i18n-no-placeholders-only', rule, { + valid: [ + { + code: `__( 'Hello %s' )`, + }, + { + code: `i18n.__( 'Hello %s' )`, + }, + { + code: `__( '%d%%' )`, + }, + ], + invalid: [ + { + code: `__( '%s' )`, + errors: [ { messageId: 'noPlaceholdersOnly' } ], + }, + { + code: `__( '%s%s' )`, + errors: [ { messageId: 'noPlaceholdersOnly' } ], + }, + { + code: `_x( '%1$s' )`, + errors: [ { messageId: 'noPlaceholdersOnly' } ], + }, + { + code: `_n( '%s', '%s', number)`, + errors: [ + { messageId: 'noPlaceholdersOnly' }, + { messageId: 'noPlaceholdersOnly' }, + ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/__tests__/i18n-no-variables.js b/packages/eslint-plugin/rules/__tests__/i18n-no-variables.js new file mode 100644 index 00000000000000..1ee322944ef9fd --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/i18n-no-variables.js @@ -0,0 +1,92 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../i18n-no-variables'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'i18n-no-variables', rule, { + valid: [ + { + code: `__( 'Hello World' )`, + }, + { + code: `__( 'Hello' + 'World' )`, + }, + { + code: `_x( 'Hello World', 'context' )`, + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number)`, + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context' )`, + }, + { + code: `__( 'Hello World', 'foo' )`, + }, + { + code: `_x( 'Hello World', 'context', 'foo' )`, + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number, 'foo' )`, + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context', 'foo' )`, + }, + { + code: `i18n.__( 'Hello World' )`, + }, + ], + invalid: [ + { + code: `__(foo)`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: '__(`Hello ${foo}`)', + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `_x(foo, 'context' )`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `_x( 'Hello World', bar)`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `var number = ''; _n(foo,'Plural', number)`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `var number = ''; _n( 'Singular', bar, number)`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `var number = ''; _nx(foo, 'Plural', number, 'context' )`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `var number = ''; _nx( 'Singular', bar, number, 'context' )`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, baz)`, + errors: [ { messageId: 'invalidArgument' } ], + }, + { + code: `i18n.__(foo)`, + errors: [ { messageId: 'invalidArgument' } ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/__tests__/i18n-text-domain.js b/packages/eslint-plugin/rules/__tests__/i18n-text-domain.js new file mode 100644 index 00000000000000..1212c90d998ed7 --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/i18n-text-domain.js @@ -0,0 +1,170 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../i18n-text-domain'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'i18n-text-domain', rule, { + valid: [ + { + code: `__( 'Hello World' )`, + options: [ { allowedTextDomain: 'default' } ], + }, + { + code: `_x( 'Hello World', 'context' )`, + options: [ { allowedTextDomain: 'default' } ], + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number )`, + options: [ { allowedTextDomain: 'default' } ], + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context' )`, + options: [ { allowedTextDomain: 'default' } ], + }, + { + code: `__( 'Hello World', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + }, + { + code: `_x( 'Hello World', 'context', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number, 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + }, + { + code: `i18n.__( 'Hello World' )`, + options: [ { allowedTextDomain: 'default' } ], + }, + ], + invalid: [ + { + code: `__( 'Hello World' )`, + output: `__( 'Hello World', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'missing' } ], + }, + { + code: `_x( 'Hello World', 'context' )`, + output: `_x( 'Hello World', 'context', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'missing' } ], + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number )`, + output: `var number = ''; _n( 'Singular', 'Plural', number, 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'missing' } ], + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context' )`, + output: `var number = ''; _nx( 'Singular', 'Plural', number, 'context', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'missing' } ], + }, + { + code: `__( 'Hello World', 'bar' )`, + output: `__( 'Hello World', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'invalidValue' } ], + }, + { + code: `_x( 'Hello World', 'context', 'bar' )`, + output: `_x( 'Hello World', 'context', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'invalidValue' } ], + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number, 'bar' )`, + output: `var number = ''; _n( 'Singular', 'Plural', number, 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'invalidValue' } ], + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context', 'bar' )`, + output: `var number = ''; _nx( 'Singular', 'Plural', number, 'context', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'invalidValue' } ], + }, + { + code: `var value = ''; __( 'Hello World', value )`, + errors: [ { messageId: 'invalidType' } ], + }, + { + code: `var value = ''; _x( 'Hello World', 'context', value )`, + errors: [ { messageId: 'invalidType' } ], + }, + { + code: `var value = ''; var number = ''; _n( 'Singular', 'Plural', number, value )`, + errors: [ { messageId: 'invalidType' } ], + }, + { + code: `var value = ''; var number = ''; _nx( 'Singular', 'Plural', number, 'context', value )`, + errors: [ { messageId: 'invalidType' } ], + }, + { + code: `__( 'Hello World', 'default' )`, + output: `__( 'Hello World' )`, + options: [ { allowedTextDomain: 'default' } ], + errors: [ { messageId: 'unnecessaryDefault' } ], + }, + { + code: `__( 'default', 'default' )`, + output: `__( 'default' )`, + options: [ { allowedTextDomain: 'default' } ], + errors: [ { messageId: 'unnecessaryDefault' } ], + }, + { + code: `_x( 'Hello World', 'context', 'default' )`, + output: `_x( 'Hello World', 'context' )`, + options: [ { allowedTextDomain: 'default' } ], + errors: [ { messageId: 'unnecessaryDefault' } ], + }, + { + code: `var number = ''; _n( 'Singular', 'Plural', number, 'default' )`, + output: `var number = ''; _n( 'Singular', 'Plural', number )`, + options: [ { allowedTextDomain: 'default' } ], + errors: [ { messageId: 'unnecessaryDefault' } ], + }, + { + code: `var number = ''; _nx( 'Singular', 'Plural', number, 'context', 'default' )`, + output: `var number = ''; _nx( 'Singular', 'Plural', number, 'context' )`, + options: [ { allowedTextDomain: 'default' } ], + errors: [ { messageId: 'unnecessaryDefault' } ], + }, + { + code: `i18n.__( 'Hello World' )`, + output: `i18n.__( 'Hello World', 'foo' )`, + options: [ { allowedTextDomain: 'foo' } ], + errors: [ { messageId: 'missing' } ], + }, + { + code: `__( 'Hello World' )`, + output: `__( 'Hello World', 'foo' )`, + options: [ { allowedTextDomain: [ 'foo' ] } ], + errors: [ { messageId: 'missing' } ], + }, + { + code: `__( 'Hello World' )`, + output: `__( 'Hello World' )`, + options: [ { allowedTextDomain: [ 'foo', 'bar' ] } ], + errors: [ { messageId: 'missing' } ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/__tests__/i18n-translator-comments.js b/packages/eslint-plugin/rules/__tests__/i18n-translator-comments.js new file mode 100644 index 00000000000000..df59a9bbe07083 --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/i18n-translator-comments.js @@ -0,0 +1,84 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../i18n-translator-comments'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'i18n-translator-comments', rule, { + valid: [ + { + code: ` +// translators: %s: Color +sprintf( __( 'Color: %s' ), color );`, + }, + { + code: ` +sprintf( + // translators: %s: Address. + __( 'Address: %s' ), + address +);`, + }, + { + code: ` +// translators: %s: Color +i18n.sprintf( i18n.__( 'Color: %s' ), color );`, + }, + ], + invalid: [ + { + code: ` +sprintf( __( 'Color: %s' ), color );`, + errors: [ { messageId: 'missing' } ], + }, + { + code: ` +sprintf( + __( 'Address: %s' ), + address +);`, + errors: [ { messageId: 'missing' } ], + }, + { + code: ` +// translators: %s: Name +var name = ''; +sprintf( __( 'Name: %s' ), name );`, + errors: [ { messageId: 'missing' } ], + }, + { + code: ` +// translators: %s: Surname +console.log( + sprintf( __( 'Surname: %s' ), name ) +);`, + errors: [ { messageId: 'missing' } ], + }, + { + code: ` +// translators: %s: Preference +console.log( + sprintf( + __( 'Preference: %s' ), + preference + ) +);`, + errors: [ { messageId: 'missing' } ], + }, + { + code: ` +i18n.sprintf( i18n.__( 'Color: %s' ), color );`, + errors: [ { messageId: 'missing' } ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/__tests__/no-unused-vars-before-return.js b/packages/eslint-plugin/rules/__tests__/no-unused-vars-before-return.js index 291559e956f3ec..036ed7712bf583 100644 --- a/packages/eslint-plugin/rules/__tests__/no-unused-vars-before-return.js +++ b/packages/eslint-plugin/rules/__tests__/no-unused-vars-before-return.js @@ -104,5 +104,24 @@ function example() { }, ], }, + { + code: ` +function example() { + const foo = doSomeCostlyOperation(); + const bar = anotherCostlyOperation( foo ); + if ( number > 10 ) { + return number + 1; + } + + return number + foo + bar; +}`, + options: [ { excludePattern: '^do' } ], + errors: [ + { + message: + 'Variables should not be assigned until just prior its first reference. An early return statement may leave this variable unused.', + }, + ], + }, ], } ); diff --git a/packages/eslint-plugin/rules/__tests__/valid-sprintf.js b/packages/eslint-plugin/rules/__tests__/valid-sprintf.js index 119653220b3c0a..9b2b7de255d47b 100644 --- a/packages/eslint-plugin/rules/__tests__/valid-sprintf.js +++ b/packages/eslint-plugin/rules/__tests__/valid-sprintf.js @@ -19,6 +19,9 @@ ruleTester.run( 'valid-sprintf', rule, { { code: `sprintf( '%s', 'substitute' )`, }, + { + code: `sprintf( '%1$d%%', 500 )`, + }, { code: `sprintf( __( '%s' ), 'substitute' )`, }, @@ -37,76 +40,92 @@ ruleTester.run( 'valid-sprintf', rule, { { code: `var value = ''; sprintf( value, 'substitute' )`, }, + { + code: ` +sprintf( + /* translators: 1: number of blocks. 2: average rating. */ + _n( + 'This author has %1$d block, with an average rating of %2$d.', + 'This author has %1$d blocks, with an average rating of %2$d.', + authorBlockCount + ), + authorBlockCount, + authorBlockRating +);`, + }, + { + code: `i18n.sprintf( '%s', 'substitute' )`, + }, + { + code: `i18n.sprintf( i18n.__( '%s' ), 'substitute' )`, + }, + { + code: `sprintf( ...args )`, + }, + { + code: `sprintf( '%1$s %2$s', 'foo', 'bar' )`, + }, + { + code: `sprintf( '%(greeting)s', 'Hello' )`, + }, + { + code: `sprintf( '%(greeting)s %(toWhom)s', 'Hello', 'World' )`, + }, ], invalid: [ { code: `sprintf()`, - errors: [ - { message: 'sprintf must be called with a format string' }, - ], + errors: [ { messageId: 'noFormatString' } ], }, { code: `sprintf( '%s' )`, - errors: [ - { - message: - 'sprintf must be called with placeholder value argument(s)', - }, - ], + errors: [ { messageId: 'noPlaceholderArgs' } ], }, { code: `sprintf( 1, 'substitute' )`, - errors: [ - { - message: - 'sprintf must be called with a valid format string', - }, - ], + errors: [ { messageId: 'invalidFormatString' } ], }, { code: `sprintf( [], 'substitute' )`, - errors: [ - { - message: - 'sprintf must be called with a valid format string', - }, - ], + errors: [ { messageId: 'invalidFormatString' } ], }, { code: `sprintf( '%%', 'substitute' )`, - errors: [ - { - message: - 'sprintf format string must contain at least one placeholder', - }, - ], + errors: [ { messageId: 'noPlaceholders' } ], }, { code: `sprintf( __( '%%' ), 'substitute' )`, - errors: [ - { - message: - 'sprintf format string must contain at least one placeholder', - }, - ], + errors: [ { messageId: 'noPlaceholders' } ], }, { code: `sprintf( _n( '%s', '' ), 'substitute' )`, - errors: [ - { - message: - 'sprintf format string options must have the same number of placeholders', - }, - ], + errors: [ { messageId: 'placeholderMismatch' } ], }, { code: `sprintf( _n( '%s', '%s %s' ), 'substitute' )`, - errors: [ - { - message: - 'sprintf format string options must have the same number of placeholders', - }, - ], + errors: [ { messageId: 'placeholderMismatch' } ], + }, + { + code: ` +sprintf( + /* translators: 1: number of blocks. 2: average rating. */ + _n( + 'This author has %d block, with an average rating of %d.', + 'This author has %d blocks, with an average rating of %d.', + authorBlockCount + ), + authorBlockCount, + authorBlockRating +);`, + errors: [ { messageId: 'noOrderedPlaceholders' } ], + }, + { + code: `i18n.sprintf()`, + errors: [ { messageId: 'noFormatString' } ], + }, + { + code: `i18n.sprintf( i18n.__( '%%' ), 'substitute' )`, + errors: [ { messageId: 'noPlaceholders' } ], }, ], } ); diff --git a/packages/eslint-plugin/rules/i18n-ellipsis.js b/packages/eslint-plugin/rules/i18n-ellipsis.js new file mode 100644 index 00000000000000..8e1b5eabf9b5e5 --- /dev/null +++ b/packages/eslint-plugin/rules/i18n-ellipsis.js @@ -0,0 +1,98 @@ +/** + * Internal dependencies + */ +const { + TRANSLATION_FUNCTIONS, + getTextContentFromNode, + getTranslateFunctionName, + getTranslateFunctionArgs, +} = require( '../utils' ); + +const THREE_DOTS = '...'; +const ELLIPSIS = '…'; + +function replaceThreeDotsWithEllipsis( string ) { + return string.replace( /\.\.\./g, ELLIPSIS ); +} + +// see eslint-plugin-wpcalypso. +function makeFixerFunction( arg ) { + return ( fixer ) => { + switch ( arg.type ) { + case 'TemplateLiteral': + return arg.quasis.reduce( ( fixes, quasi ) => { + if ( + 'TemplateElement' === quasi.type && + quasi.value.raw.includes( THREE_DOTS ) + ) { + fixes.push( + fixer.replaceTextRange( + [ quasi.start, quasi.end ], + replaceThreeDotsWithEllipsis( quasi.value.raw ) + ) + ); + } + return fixes; + }, [] ); + + case 'Literal': + return [ + fixer.replaceText( + arg, + replaceThreeDotsWithEllipsis( arg.raw ) + ), + ]; + + case 'BinaryExpression': + return [ + ...makeFixerFunction( arg.left )( fixer ), + ...makeFixerFunction( arg.right )( fixer ), + ]; + } + }; +} + +module.exports = { + meta: { + type: 'problem', + schema: [], + messages: { + foundThreeDots: 'Use ellipsis character (…) in place of three dots', + }, + fixable: 'code', + }, + create( context ) { + return { + CallExpression( node ) { + const { callee, arguments: args } = node; + + const functionName = getTranslateFunctionName( callee ); + + if ( ! TRANSLATION_FUNCTIONS.has( functionName ) ) { + return; + } + + const candidates = getTranslateFunctionArgs( + functionName, + args + ); + + for ( const arg of candidates ) { + const argumentString = getTextContentFromNode( arg ); + if ( + ! argumentString || + ! argumentString.includes( THREE_DOTS ) + ) { + continue; + } + + context.report( { + node, + messageId: 'foundThreeDots', + fix: makeFixerFunction( arg ), + } ); + } + }, + }; + }, +}; diff --git a/packages/eslint-plugin/rules/i18n-no-collapsible-whitespace.js b/packages/eslint-plugin/rules/i18n-no-collapsible-whitespace.js new file mode 100644 index 00000000000000..1d34472bc7b4a7 --- /dev/null +++ b/packages/eslint-plugin/rules/i18n-no-collapsible-whitespace.js @@ -0,0 +1,74 @@ +/** + * Internal dependencies + */ +const { + TRANSLATION_FUNCTIONS, + getTextContentFromNode, + getTranslateFunctionName, + getTranslateFunctionArgs, +} = require( '../utils' ); + +const PROBLEMS_BY_CHAR_CODE = { + 9: '\\t', + 10: '\\n', + 13: '\\r', + 32: 'consecutive spaces', +}; + +module.exports = { + meta: { + type: 'problem', + schema: [], + messages: { + noCollapsibleWhitespace: + 'Translations should not contain collapsible whitespace{{problem}}', + }, + }, + create( context ) { + return { + CallExpression( node ) { + const { callee, arguments: args } = node; + + const functionName = getTranslateFunctionName( callee ); + + if ( ! TRANSLATION_FUNCTIONS.has( functionName ) ) { + return; + } + + const candidates = getTranslateFunctionArgs( + functionName, + args + ); + + for ( const arg of candidates ) { + const argumentString = getTextContentFromNode( arg ); + if ( ! argumentString ) { + continue; + } + + const collapsibleWhitespace = argumentString.match( + /(\n|\t|\r| {2})/ + ); + + if ( ! collapsibleWhitespace ) { + continue; + } + + const problem = + PROBLEMS_BY_CHAR_CODE[ + collapsibleWhitespace[ 0 ].charCodeAt( 0 ) + ]; + const problemString = problem ? ` (${ problem })` : ''; + + context.report( { + node, + messageId: 'noCollapsibleWhitespace', + data: { + problem: problemString, + }, + } ); + } + }, + }; + }, +}; diff --git a/packages/eslint-plugin/rules/i18n-no-placeholders-only.js b/packages/eslint-plugin/rules/i18n-no-placeholders-only.js new file mode 100644 index 00000000000000..3cc2b3dc34fb0f --- /dev/null +++ b/packages/eslint-plugin/rules/i18n-no-placeholders-only.js @@ -0,0 +1,59 @@ +/** + * Internal dependencies + */ +const { + TRANSLATION_FUNCTIONS, + REGEXP_SPRINTF_PLACEHOLDER, + getTextContentFromNode, + getTranslateFunctionName, + getTranslateFunctionArgs, +} = require( '../utils' ); + +module.exports = { + meta: { + type: 'problem', + schema: [], + messages: { + noPlaceholdersOnly: + 'Translatable strings should not contain nothing but placeholders', + }, + }, + create( context ) { + return { + CallExpression( node ) { + const { callee, arguments: args } = node; + + const functionName = getTranslateFunctionName( callee ); + + if ( ! TRANSLATION_FUNCTIONS.has( functionName ) ) { + return; + } + + const candidates = getTranslateFunctionArgs( + functionName, + args + ); + + for ( const arg of candidates ) { + const argumentString = getTextContentFromNode( arg ); + if ( ! argumentString ) { + continue; + } + + const modifiedString = argumentString + .replace( /%%/g, 'VALID_ESCAPED_PERCENTAGE_SIGN' ) + .replace( REGEXP_SPRINTF_PLACEHOLDER, '' ); + + if ( modifiedString.length > 0 ) { + continue; + } + + context.report( { + node, + messageId: 'noPlaceholdersOnly', + } ); + } + }, + }; + }, +}; diff --git a/packages/eslint-plugin/rules/i18n-no-variables.js b/packages/eslint-plugin/rules/i18n-no-variables.js new file mode 100644 index 00000000000000..c942ba440a7676 --- /dev/null +++ b/packages/eslint-plugin/rules/i18n-no-variables.js @@ -0,0 +1,66 @@ +/** + * Internal dependencies + */ +const { + TRANSLATION_FUNCTIONS, + getTranslateFunctionName, + getTranslateFunctionArgs, +} = require( '../utils' ); + +function isAcceptableLiteralNode( node ) { + if ( 'BinaryExpression' === node.type ) { + return ( + '+' === node.operator && + isAcceptableLiteralNode( node.left ) && + isAcceptableLiteralNode( node.right ) + ); + } + + if ( 'TemplateLiteral' === node.type ) { + // Backticks are fine, but if there's any interpolation in it, + // that's a problem + return node.expressions.length === 0; + } + + return 'Literal' === node.type; +} + +module.exports = { + meta: { + type: 'problem', + schema: [], + messages: { + invalidArgument: + 'Translate function arguments must be string literals.', + }, + }, + create( context ) { + return { + CallExpression( node ) { + const { callee, arguments: args } = node; + + const functionName = getTranslateFunctionName( callee ); + + if ( ! TRANSLATION_FUNCTIONS.has( functionName ) ) { + return; + } + + const candidates = getTranslateFunctionArgs( + functionName, + args + ); + + for ( const arg of candidates ) { + if ( isAcceptableLiteralNode( arg ) ) { + continue; + } + + context.report( { + node, + messageId: 'invalidArgument', + } ); + } + }, + }; + }, +}; diff --git a/packages/eslint-plugin/rules/i18n-text-domain.js b/packages/eslint-plugin/rules/i18n-text-domain.js new file mode 100644 index 00000000000000..94b0619372d547 --- /dev/null +++ b/packages/eslint-plugin/rules/i18n-text-domain.js @@ -0,0 +1,158 @@ +/** + * Internal dependencies + */ +const { + TRANSLATION_FUNCTIONS, + getTranslateFunctionName, +} = require( '../utils' ); + +/** + * Returns the text domain passed to the given translation function. + * + * @param {string} functionName Translation function name. + * @param {Array} args Function arguments. + * @return {undefined|*} Text domain argument. + */ +function getTextDomain( functionName, args ) { + switch ( functionName ) { + case '__': + return args[ 1 ]; + case '_x': + return args[ 2 ]; + case '_n': + return args[ 3 ]; + case '_nx': + return args[ 4 ]; + default: + return undefined; + } +} + +module.exports = { + meta: { + type: 'problem', + schema: [ + { + type: 'object', + properties: { + // Supports a single string as the majority use case, + // but also an array of text domains. + allowedTextDomain: { + anyOf: [ + { + type: 'array', + items: { + type: 'string', + }, + uniqueItems: true, + }, + { + type: 'string', + default: 'default', + }, + ], + }, + }, + additionalProperties: false, + }, + ], + messages: { + invalidValue: "Invalid text domain '{{ textDomain }}'", + invalidType: 'Text domain is not a string literal', + unnecessaryDefault: 'Unnecessary default text domain', + missing: 'Missing text domain', + useAllowedValue: + 'Use one of the whitelisted text domains: {{ textDomains }}', + }, + fixable: 'code', + }, + create( context ) { + const options = context.options[ 0 ] || {}; + const { allowedTextDomain = 'default' } = options; + const allowedTextDomains = Array.isArray( allowedTextDomain ) + ? allowedTextDomain + : [ allowedTextDomain ]; + const canFixTextDomain = allowedTextDomains.length === 1; + const allowDefault = allowedTextDomains.includes( 'default' ); + + return { + CallExpression( node ) { + const { callee, arguments: args } = node; + + const functionName = getTranslateFunctionName( callee ); + + if ( ! TRANSLATION_FUNCTIONS.has( functionName ) ) { + return; + } + + const textDomain = getTextDomain( functionName, args ); + + if ( textDomain === undefined ) { + if ( ! allowDefault ) { + const addMissingTextDomain = ( fixer ) => { + const lastArg = args[ args.length - 1 ]; + return fixer.insertTextAfter( + lastArg, + `, '${ allowedTextDomains[ 0 ] }'` + ); + }; + + context.report( { + node, + messageId: 'missing', + fix: canFixTextDomain ? addMissingTextDomain : null, + } ); + } + return; + } + + const { type, value, range } = textDomain; + + if ( type !== 'Literal' ) { + context.report( { + node, + messageId: 'invalidType', + } ); + return; + } + + if ( 'default' === value && allowDefault ) { + const removeDefaultTextDomain = ( fixer ) => { + const previousArgIndex = args.indexOf( textDomain ) - 1; + const previousArg = args[ previousArgIndex ]; + return fixer.removeRange( [ + previousArg.range[ 1 ], + range[ 1 ], + ] ); + }; + + context.report( { + node, + messageId: 'unnecessaryDefault', + fix: removeDefaultTextDomain, + } ); + return; + } + + if ( ! allowedTextDomains.includes( value ) ) { + const replaceTextDomain = ( fixer ) => { + return fixer.replaceTextRange( + // account for quotes. + [ range[ 0 ] + 1, range[ 1 ] - 1 ], + allowedTextDomains[ 0 ] + ); + }; + + context.report( { + node, + messageId: 'invalidValue', + data: { + textDomain: value, + }, + fix: canFixTextDomain ? replaceTextDomain : null, + } ); + } + }, + }; + }, +}; diff --git a/packages/eslint-plugin/rules/i18n-translator-comments.js b/packages/eslint-plugin/rules/i18n-translator-comments.js new file mode 100644 index 00000000000000..86d57449dc0547 --- /dev/null +++ b/packages/eslint-plugin/rules/i18n-translator-comments.js @@ -0,0 +1,112 @@ +/** + * Internal dependencies + */ +const { + TRANSLATION_FUNCTIONS, + REGEXP_SPRINTF_PLACEHOLDER, + getTranslateFunctionName, + getTranslateFunctionArgs, + getTextContentFromNode, +} = require( '../utils' ); + +module.exports = { + meta: { + type: 'problem', + messages: { + missing: + 'Translation function with placeholders is missing preceding translator comment', + }, + }, + create( context ) { + return { + CallExpression( node ) { + const { + callee, + loc: { + start: { line: currentLine }, + }, + parent, + arguments: args, + } = node; + + const functionName = getTranslateFunctionName( callee ); + + if ( ! TRANSLATION_FUNCTIONS.has( functionName ) ) { + return; + } + + const candidates = getTranslateFunctionArgs( + functionName, + args + ).map( getTextContentFromNode ); + + if ( candidates.filter( Boolean ).length === 0 ) { + return; + } + + const hasPlaceholders = candidates.some( ( candidate ) => + REGEXP_SPRINTF_PLACEHOLDER.test( candidate ) + ); + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#Using_test()_on_a_regex_with_the_global_flag. + REGEXP_SPRINTF_PLACEHOLDER.lastIndex = 0; + + if ( ! hasPlaceholders ) { + return; + } + + const comments = context.getCommentsBefore( node ).slice(); + + let parentNode = parent; + + /** + * Loop through all parent nodes and get their preceding comments as well. + * + * This way we can gather comments that are not directly preceding the translation + * function call, but are just on the line above it. This case is commonly supported + * by string extraction tools like WP-CLI's i18n command. + */ + while ( + parentNode && + parentNode.type !== 'Program' && + Math.abs( parentNode.loc.start.line - currentLine ) <= 1 + ) { + comments.push( ...context.getCommentsBefore( parentNode ) ); + parentNode = parentNode.parent; + } + + for ( const comment of comments ) { + const { + value: commentText, + loc: { + start: { line: commentLine }, + }, + } = comment; + + /* + Skip cases like this: + + // translators: %s: Preference + console.log( + sprintf( + __( 'Preference: %s' ), + preference + ) + ); + */ + if ( Math.abs( commentLine - currentLine ) > 1 ) { + break; + } + + if ( /translators:\s*\S+/i.test( commentText ) ) { + return; + } + } + + context.report( { + node, + messageId: 'missing', + } ); + }, + }; + }, +}; diff --git a/packages/eslint-plugin/rules/no-unused-vars-before-return.js b/packages/eslint-plugin/rules/no-unused-vars-before-return.js index 1a4cbb7d91c151..489b0beb86ad0e 100644 --- a/packages/eslint-plugin/rules/no-unused-vars-before-return.js +++ b/packages/eslint-plugin/rules/no-unused-vars-before-return.js @@ -74,7 +74,7 @@ module.exports = { declaratorCandidate.node.init.callee.name ) ) { - return; + continue; } // The first entry in `references` is the declaration diff --git a/packages/eslint-plugin/rules/valid-sprintf.js b/packages/eslint-plugin/rules/valid-sprintf.js index 73101d12b7d676..593ea11b564a02 100644 --- a/packages/eslint-plugin/rules/valid-sprintf.js +++ b/packages/eslint-plugin/rules/valid-sprintf.js @@ -1,68 +1,63 @@ /** - * Regular expression matching the presence of a printf format string - * placeholder. This naive pattern which does not validate the format. - * - * @type {RegExp} + * Internal dependencies */ -const REGEXP_PLACEHOLDER = /%[^%]/g; - -/** - * Given a function name and array of argument Node values, returns all - * possible string results from the corresponding translate function, or - * undefined if the function is not a translate function. - * - * @param {string} functionName Function name. - * @param {espree.Node[]} args Espree argument Node objects. - * - * @return {?Array<string>} All possible translate function string results. - */ -function getTranslateStrings( functionName, args ) { - switch ( functionName ) { - case '__': - case '_x': - args = args.slice( 0, 1 ); - break; - - case '_n': - case '_nx': - args = args.slice( 0, 2 ); - break; - - default: - return; - } - - return args - .filter( ( arg ) => arg.type === 'Literal' ) - .map( ( arg ) => arg.value ); -} +const { + REGEXP_SPRINTF_PLACEHOLDER, + REGEXP_SPRINTF_PLACEHOLDER_UNORDERED, + getTranslateFunctionName, + getTranslateFunctionArgs, + getTextContentFromNode, +} = require( '../utils' ); module.exports = { meta: { type: 'problem', schema: [], + messages: { + noFormatString: 'sprintf must be called with a format string', + invalidFormatString: + 'sprintf must be called with a valid format string', + noPlaceholderArgs: + 'sprintf must be called with placeholder value argument(s)', + noPlaceholders: + 'sprintf format string must contain at least one placeholder', + placeholderMismatch: + 'sprintf format string options must have the same number of placeholders', + noOrderedPlaceholders: + 'Multiple sprintf placeholders should be ordered. Mix of ordered and non-ordered placeholders found.', + }, }, create( context ) { return { CallExpression( node ) { const { callee, arguments: args } = node; - if ( callee.name !== 'sprintf' ) { + + const functionName = + callee.property && callee.property.name + ? callee.property.name + : callee.name; + + if ( functionName !== 'sprintf' ) { return; } if ( ! args.length ) { - context.report( + context.report( { node, - 'sprintf must be called with a format string' - ); + messageId: 'noFormatString', + } ); return; } if ( args.length < 2 ) { - context.report( + if ( args[ 0 ].type === 'SpreadElement' ) { + return; + } + + context.report( { node, - 'sprintf must be called with placeholder value argument(s)' - ); + messageId: 'noPlaceholderArgs', + } ); return; } @@ -77,17 +72,22 @@ module.exports = { break; case 'CallExpression': + const argFunctionName = getTranslateFunctionName( + args[ 0 ].callee + ); + // All possible options (arguments) from a translate // function must be valid. - candidates = getTranslateStrings( - args[ 0 ].callee.name, - args[ 0 ].arguments - ); + candidates = getTranslateFunctionArgs( + argFunctionName, + args[ 0 ].arguments, + false + ).map( getTextContentFromNode ); // An unknown function call may produce a valid string // value. Ideally its result is verified, but this is // not straight-forward to implement. Thus, bail. - if ( candidates === undefined ) { + if ( candidates.filter( Boolean ).length === 0 ) { return; } @@ -104,36 +104,61 @@ module.exports = { } if ( ! candidates.length ) { - context.report( + context.report( { node, - 'sprintf must be called with a valid format string' - ); + messageId: 'invalidFormatString', + } ); return; } let numPlaceholders; - for ( let i = 0; i < candidates.length; i++ ) { - const match = candidates[ i ].match( REGEXP_PLACEHOLDER ); + for ( const candidate of candidates ) { + const allMatches = candidate.match( + REGEXP_SPRINTF_PLACEHOLDER + ); // Prioritize placeholder number consistency over matching // placeholder, since it's a more common error to omit a // placeholder from the singular form of pluralization. if ( numPlaceholders !== undefined && - ( ! match || numPlaceholders !== match.length ) + ( ! allMatches || + numPlaceholders !== allMatches.length ) ) { - context.report( + context.report( { node, - 'sprintf format string options must have the same number of placeholders' - ); + messageId: 'placeholderMismatch', + } ); return; } - if ( ! match ) { - context.report( + const unorderedMatches = candidate.match( + REGEXP_SPRINTF_PLACEHOLDER_UNORDERED + ); + + if ( + unorderedMatches && + allMatches && + unorderedMatches.length > 0 && + allMatches.length > 1 && + unorderedMatches.length !== allMatches.length + ) { + context.report( { node, - 'sprintf format string must contain at least one placeholder' - ); + messageId: 'noOrderedPlaceholders', + } ); + return; + } + + // Catch cases where a string only contains %% (escaped percentage sign). + if ( + ! allMatches || + ( allMatches.length === 1 && allMatches[ 0 ] === '%%' ) + ) { + context.report( { + node, + messageId: 'noPlaceholders', + } ); return; } @@ -141,7 +166,7 @@ module.exports = { // Track the number of placeholders discovered in the // string to verify that all other candidate options // have the same number. - numPlaceholders = match.length; + numPlaceholders = allMatches.length; } } }, diff --git a/packages/eslint-plugin/utils/constants.js b/packages/eslint-plugin/utils/constants.js new file mode 100644 index 00000000000000..66ba5b52b63a5b --- /dev/null +++ b/packages/eslint-plugin/utils/constants.js @@ -0,0 +1,60 @@ +/** + * List of translation functions exposed by the `@wordpress/i18n` package. + * + * @type {Set<string>} Translation functions. + */ +const TRANSLATION_FUNCTIONS = new Set( [ '__', '_x', '_n', '_nx' ] ); + +/** + * Regular expression matching format placeholder syntax. + * + * The pattern for matching named arguments is a naive and incomplete matcher + * against valid JavaScript identifier names. + * + * via Mathias Bynens: + * + * >An identifier must start with $, _, or any character in the Unicode + * >categories “Uppercase letter (Lu)”, “Lowercase letter (Ll)”, “Titlecase + * >letter (Lt)”, “Modifier letter (Lm)”, “Other letter (Lo)”, or “Letter + * >number (Nl)”. + * > + * >The rest of the string can contain the same characters, plus any U+200C zero + * >width non-joiner characters, U+200D zero width joiner characters, and + * >characters in the Unicode categories “Non-spacing mark (Mn)”, “Spacing + * >combining mark (Mc)”, “Decimal digit number (Nd)”, or “Connector + * >punctuation (Pc)”. + * + * If browser support is constrained to those supporting ES2015, this could be + * made more accurate using the `u` flag: + * + * ``` + * /^[$_\p{L}\p{Nl}][$_\p{L}\p{Nl}\u200C\u200D\p{Mn}\p{Mc}\p{Nd}\p{Pc}]*$/u; + * ``` + * + * @see http://www.pixelbeat.org/programming/gcc/format_specs.html + * @see https://mathiasbynens.be/notes/javascript-identifiers#valid-identifier-names + * + * @type {RegExp} + */ +const REGEXP_SPRINTF_PLACEHOLDER = /%(((\d+)\$)|(\(([$_a-zA-Z][$_a-zA-Z0-9]*)\)))?[ +0#-]*\d*(\.(\d+|\*))?(ll|[lhqL])?([cduxXefgsp%])/g; +// ▲ ▲ ▲ ▲ ▲ ▲ ▲ type +// │ │ │ │ │ └ Length (unsupported) +// │ │ │ │ └ Precision / max width +// │ │ │ └ Min width (unsupported) +// │ │ └ Flags (unsupported) +// └ Index └ Name (for named arguments) + +/** + * "Unordered" means there's no position specifier: '%s', not '%2$s'. + * + * @see https://github.com/WordPress/WordPress-Coding-Standards/blob/2f927b0ba2bfcbffaa8f3251c086e109302d6622/WordPress/Sniffs/WP/I18nSniff.php#L62-L81 + * + * @type {RegExp} + */ +const REGEXP_SPRINTF_PLACEHOLDER_UNORDERED = /(?:(?<!%)%[+-]?(?:(?:0|'.)?-?[0-9]*(?:\.(?:[ 0]|'.)?[0-9]+)?|(?:[ ])?-?[0-9]+(?:\.(?:[ 0]|'.)?[0-9]+)?)[bcdeEfFgGosuxX])/; + +module.exports = { + TRANSLATION_FUNCTIONS, + REGEXP_SPRINTF_PLACEHOLDER, + REGEXP_SPRINTF_PLACEHOLDER_UNORDERED, +}; diff --git a/packages/eslint-plugin/utils/get-text-content-from-node.js b/packages/eslint-plugin/utils/get-text-content-from-node.js new file mode 100644 index 00000000000000..672f4f1aee7d4f --- /dev/null +++ b/packages/eslint-plugin/utils/get-text-content-from-node.js @@ -0,0 +1,34 @@ +/** + * Returns the actual text content from an argument passed to a translation function. + * + * @see eslint-plugin-wpcalypso + * + * @param {Object} node A Literal, TemplateLiteral or BinaryExpression (+) node + * @return {string|boolean} The concatenated string or false. + */ +function getTextContentFromNode( node ) { + if ( 'Literal' === node.type ) { + return node.value; + } + + if ( 'BinaryExpression' === node.type && '+' === node.operator ) { + const left = getTextContentFromNode( node.left ); + const right = getTextContentFromNode( node.right ); + + if ( left === false || right === false ) { + return false; + } + + return left + right; + } + + if ( node.type === 'TemplateLiteral' ) { + return node.quasis.map( ( quasis ) => quasis.value.raw ).join( '' ); + } + + return false; +} + +module.exports = { + getTextContentFromNode, +}; diff --git a/packages/eslint-plugin/utils/get-translate-function-args.js b/packages/eslint-plugin/utils/get-translate-function-args.js new file mode 100644 index 00000000000000..2ae5a611bb1b80 --- /dev/null +++ b/packages/eslint-plugin/utils/get-translate-function-args.js @@ -0,0 +1,40 @@ +/** + * Given a function name and array of argument Node values, + * returns all arguments except for text domain and number arguments. + * + * @param {string} functionName Function name. + * @param {espree.Node[]} args Espree argument Node objects. + * @param {boolean} includeContext Whether to include the context argument or not. + * + * @return {espree.Node[]} Translate function arguments. + */ +function getTranslateFunctionArgs( functionName, args, includeContext = true ) { + switch ( functionName ) { + case '__': + // __( text, domain ) -> [ text ]. + return args.slice( 0, 1 ); + + case '_x': + // _x( text, context, domain ) -> [ text, context ]. + return includeContext ? args.slice( 0, 2 ) : args.slice( 0, 1 ); + + case '_n': + // _n( single, plural, number, domain ) -> [ single, plural ]. + return args.slice( 0, 2 ); + + case '_nx': + // _nx( single, plural, number, context, domain ) -> [ single, plural, context ]. + const result = args.slice( 0, 2 ); + if ( includeContext ) { + result.push( args[ 3 ] ); + } + return result; + + default: + return []; + } +} + +module.exports = { + getTranslateFunctionArgs, +}; diff --git a/packages/eslint-plugin/utils/get-translate-function-name.js b/packages/eslint-plugin/utils/get-translate-function-name.js new file mode 100644 index 00000000000000..f62143572c62e6 --- /dev/null +++ b/packages/eslint-plugin/utils/get-translate-function-name.js @@ -0,0 +1,17 @@ +/** + * Get the actual translation function name from a CallExpression callee. + * + * Returns the "__" part from __ or i18n.__. + * + * @param {Object} callee + * @return {string} Function name. + */ +function getTranslateFunctionName( callee ) { + return callee.property && callee.property.name + ? callee.property.name + : callee.name; +} + +module.exports = { + getTranslateFunctionName, +}; diff --git a/packages/eslint-plugin/utils/index.js b/packages/eslint-plugin/utils/index.js new file mode 100644 index 00000000000000..97daaaa3208dd3 --- /dev/null +++ b/packages/eslint-plugin/utils/index.js @@ -0,0 +1,17 @@ +const { + TRANSLATION_FUNCTIONS, + REGEXP_SPRINTF_PLACEHOLDER, + REGEXP_SPRINTF_PLACEHOLDER_UNORDERED, +} = require( './constants' ); +const { getTranslateFunctionArgs } = require( './get-translate-function-args' ); +const { getTextContentFromNode } = require( './get-text-content-from-node' ); +const { getTranslateFunctionName } = require( './get-translate-function-name' ); + +module.exports = { + TRANSLATION_FUNCTIONS, + REGEXP_SPRINTF_PLACEHOLDER, + REGEXP_SPRINTF_PLACEHOLDER_UNORDERED, + getTranslateFunctionArgs, + getTextContentFromNode, + getTranslateFunctionName, +}; diff --git a/packages/format-library/package.json b/packages/format-library/package.json index 60b370ef14ad51..40a1110ea53efe 100644 --- a/packages/format-library/package.json +++ b/packages/format-library/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/block-editor": "file:../block-editor", "@wordpress/components": "file:../components", "@wordpress/data": "file:../data", diff --git a/packages/format-library/src/link/inline.js b/packages/format-library/src/link/inline.js index 827e6652e4025a..00bdadb1068e4a 100644 --- a/packages/format-library/src/link/inline.js +++ b/packages/format-library/src/link/inline.js @@ -119,11 +119,12 @@ function InlineLinkUI( { } ); if ( isCollapsed( value ) && ! isActive ) { + const newText = nextValue.title || newUrl; const toInsert = applyFormat( - create( { text: newUrl } ), + create( { text: newText } ), format, 0, - newUrl.length + newText.length ); onChange( insert( value, toInsert ) ); } else { diff --git a/packages/format-library/src/link/modal.native.js b/packages/format-library/src/link/modal.native.js index 79072fbd65cc11..d288b69262a591 100644 --- a/packages/format-library/src/link/modal.native.js +++ b/packages/format-library/src/link/modal.native.js @@ -169,6 +169,7 @@ class ModalLinkUI extends Component { autoCorrect={ false } keyboardType="url" onChangeValue={ this.onChangeInputValue } + onSubmit={ this.onDismiss } autoFocus={ Platform.OS === 'ios' } /> /* eslint-enable jsx-a11y/no-autofocus */ @@ -179,6 +180,7 @@ class ModalLinkUI extends Component { value={ text } placeholder={ __( 'Add link text' ) } onChangeValue={ this.onChangeText } + onSubmit={ this.onDismiss } /> <BottomSheet.SwitchCell icon={ external } diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 260515652d5b3d..fdb7db5cee570d 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/html-entities/CHANGELOG.md b/packages/html-entities/CHANGELOG.md index f9355f9f968653..5d0ba8e3277ef0 100644 --- a/packages/html-entities/CHANGELOG.md +++ b/packages/html-entities/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#20669](https://github.com/WordPress/gutenberg/pull/20669)) + ## 2.0.2 (2018-12-12) ## 2.0.1 (2018-11-21) diff --git a/packages/html-entities/package.json b/packages/html-entities/package.json index 5e0cb8c0f1d047..29fe920ad7cb1c 100644 --- a/packages/html-entities/package.json +++ b/packages/html-entities/package.json @@ -21,8 +21,9 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/html-entities/src/index.js b/packages/html-entities/src/index.js index 615087f992e78d..25e440748765cf 100644 --- a/packages/html-entities/src/index.js +++ b/packages/html-entities/src/index.js @@ -1,3 +1,4 @@ +/** @type {HTMLTextAreaElement} */ let _decodeTextArea; /** @@ -36,5 +37,23 @@ export function decodeEntities( html ) { _decodeTextArea.innerHTML = html; const decoded = _decodeTextArea.textContent; _decodeTextArea.innerHTML = ''; - return decoded; + + /** + * Cast to string, HTMLTextAreaElement should always have `string` textContent. + * + * > The `textContent` property of the `Node` interface represents the text content of the + * > node and its descendants. + * > + * > Value: A string or `null` + * > + * > * If the node is a `document` or a Doctype, `textContent` returns `null`. + * > * If the node is a CDATA section, comment, processing instruction, or text node, + * > textContent returns the text inside the node, i.e., the `Node.nodeValue`. + * > * For other node types, `textContent returns the concatenation of the textContent of + * > every child node, excluding comments and processing instructions. (This is an empty + * > string if the node has no children.) + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent + */ + return /** @type {string} */ ( decoded ); } diff --git a/packages/html-entities/tsconfig.json b/packages/html-entities/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/html-entities/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 485f3bc676e2ab..cf038c0a4fef9c 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,10 +1,10 @@ ## Master -## 3.10.0 (2020-04-01) - ### New Feature -- Add `isRTL` function (#20298) +- Add `isRTL` function ([#20298](https://github.com/WordPress/gutenberg/pull/20298)) +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) +- Add `createI18n` method to allow creation of multiple i18n instances ([#21182](https://github.com/WordPress/gutenberg/pull/21182)) ## 3.1.0 (2018-11-15) diff --git a/packages/i18n/README.md b/packages/i18n/README.md index 21847b5f3f0172..f57ce4124c191b 100644 --- a/packages/i18n/README.md +++ b/packages/i18n/README.md @@ -27,6 +27,19 @@ For a complete example, see the [Internationalization section of the Block Edito <!-- START TOKEN(Autogenerated API docs) --> +<a name="createI18n" href="#createI18n">#</a> **createI18n** + +Create an i18n instance + +_Parameters_ + +- _initialData_ `[LocaleData]`: Locale data configuration. +- _initialDomain_ `[string]`: Domain for which configuration applies. + +_Returns_ + +- `I18n`: I18n instance + <a name="isRTL" href="#isRTL">#</a> **isRTL** Check if current locale is RTL. diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 107ac2e964daf5..3c441692050f92 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -20,16 +20,17 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "bin": { "pot-to-php": "./tools/pot-to-php.js" }, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "gettext-parser": "^1.3.1", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "sprintf-js": "^1.1.1", - "tannin": "^1.1.0" + "tannin": "^1.2.0" }, "publishConfig": { "access": "public" diff --git a/packages/i18n/src/create-i18n.js b/packages/i18n/src/create-i18n.js new file mode 100644 index 00000000000000..0b0b4cd1826d14 --- /dev/null +++ b/packages/i18n/src/create-i18n.js @@ -0,0 +1,200 @@ +/** + * External dependencies + */ +import Tannin from 'tannin'; + +/** + * @typedef {Record<string,any>} LocaleData + */ + +/** + * Default locale data to use for Tannin domain when not otherwise provided. + * Assumes an English plural forms expression. + * + * @type {LocaleData} + */ +const DEFAULT_LOCALE_DATA = { + '': { + /** @param {number} n */ + plural_forms( n ) { + return n === 1 ? 0 : 1; + }, + }, +}; + +/** + * An i18n instance + * + * @typedef {Object} I18n + * @property {Function} setLocaleData Merges locale data into the Tannin instance by domain. Accepts data in a + * Jed-formatted JSON object shape. + * @property {Function} __ Retrieve the translation of text. + * @property {Function} _x Retrieve translated string with gettext context. + * @property {Function} _n Translates and retrieves the singular or plural form based on the supplied + * number. + * @property {Function} _nx Translates and retrieves the singular or plural form based on the supplied + * number, with gettext context. + * @property {Function} isRTL Check if current locale is RTL. + */ + +/** + * Create an i18n instance + * + * @param {LocaleData} [initialData] Locale data configuration. + * @param {string} [initialDomain] Domain for which configuration applies. + * @return {I18n} I18n instance + */ +export const createI18n = ( initialData, initialDomain ) => { + /** + * The underlying instance of Tannin to which exported functions interface. + * + * @type {Tannin} + */ + const tannin = new Tannin( {} ); + + /** + * Merges locale data into the Tannin instance by domain. Accepts data in a + * Jed-formatted JSON object shape. + * + * @see http://messageformat.github.io/Jed/ + * + * @param {LocaleData} [data] Locale data configuration. + * @param {string} [domain] Domain for which configuration applies. + */ + const setLocaleData = ( data, domain = 'default' ) => { + tannin.data[ domain ] = { + ...DEFAULT_LOCALE_DATA, + ...tannin.data[ domain ], + ...data, + }; + + // Populate default domain configuration (supported locale date which omits + // a plural forms expression). + tannin.data[ domain ][ '' ] = { + ...DEFAULT_LOCALE_DATA[ '' ], + ...tannin.data[ domain ][ '' ], + }; + }; + + /** + * Wrapper for Tannin's `dcnpgettext`. Populates default locale data if not + * otherwise previously assigned. + * + * @param {string|undefined} domain Domain to retrieve the translated text. + * @param {string|undefined} context Context information for the translators. + * @param {string} single Text to translate if non-plural. Used as + * fallback return value on a caught error. + * @param {string} [plural] The text to be used if the number is + * plural. + * @param {number} [number] The number to compare against to use + * either the singular or plural form. + * + * @return {string} The translated string. + */ + const dcnpgettext = ( + domain = 'default', + context, + single, + plural, + number + ) => { + if ( ! tannin.data[ domain ] ) { + setLocaleData( undefined, domain ); + } + + return tannin.dcnpgettext( domain, context, single, plural, number ); + }; + + /** + * Retrieve the translation of text. + * + * @see https://developer.wordpress.org/reference/functions/__/ + * + * @param {string} text Text to translate. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} Translated text. + */ + const __ = ( text, domain ) => { + return dcnpgettext( domain, undefined, text ); + }; + + /** + * Retrieve translated string with gettext context. + * + * @see https://developer.wordpress.org/reference/functions/_x/ + * + * @param {string} text Text to translate. + * @param {string} context Context information for the translators. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} Translated context string without pipe. + */ + const _x = ( text, context, domain ) => { + return dcnpgettext( domain, context, text ); + }; + + /** + * Translates and retrieves the singular or plural form based on the supplied + * number. + * + * @see https://developer.wordpress.org/reference/functions/_n/ + * + * @param {string} single The text to be used if the number is singular. + * @param {string} plural The text to be used if the number is plural. + * @param {number} number The number to compare against to use either the + * singular or plural form. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} The translated singular or plural form. + */ + const _n = ( single, plural, number, domain ) => { + return dcnpgettext( domain, undefined, single, plural, number ); + }; + + /** + * Translates and retrieves the singular or plural form based on the supplied + * number, with gettext context. + * + * @see https://developer.wordpress.org/reference/functions/_nx/ + * + * @param {string} single The text to be used if the number is singular. + * @param {string} plural The text to be used if the number is plural. + * @param {number} number The number to compare against to use either the + * singular or plural form. + * @param {string} context Context information for the translators. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} The translated singular or plural form. + */ + const _nx = ( single, plural, number, context, domain ) => { + return dcnpgettext( domain, context, single, plural, number ); + }; + + /** + * Check if current locale is RTL. + * + * **RTL (Right To Left)** is a locale property indicating that text is written from right to left. + * For example, the `he` locale (for Hebrew) specifies right-to-left. Arabic (ar) is another common + * language written RTL. The opposite of RTL, LTR (Left To Right) is used in other languages, + * including English (`en`, `en-US`, `en-GB`, etc.), Spanish (`es`), and French (`fr`). + * + * @return {boolean} Whether locale is RTL. + */ + const isRTL = () => { + return 'rtl' === _x( 'ltr', 'text direction' ); + }; + + if ( initialData ) { + setLocaleData( initialData, initialDomain ); + } + + return { + setLocaleData, + __, + _x, + _n, + _nx, + isRTL, + }; +}; diff --git a/packages/i18n/src/default-i18n.js b/packages/i18n/src/default-i18n.js new file mode 100644 index 00000000000000..c5fdc8c06548be --- /dev/null +++ b/packages/i18n/src/default-i18n.js @@ -0,0 +1,96 @@ +/** + * Internal dependencies + */ +import { createI18n } from './create-i18n'; + +const i18n = createI18n(); + +/* + * Comments in this file are duplicated from ./i18n due to + * https://github.com/WordPress/gutenberg/pull/20318#issuecomment-590837722 + */ + +/** + * @typedef {import('./create-i18n').LocaleData} LocaleData + */ + +/** + * Merges locale data into the Tannin instance by domain. Accepts data in a + * Jed-formatted JSON object shape. + * + * @see http://messageformat.github.io/Jed/ + * + * @param {LocaleData} [data] Locale data configuration. + * @param {string} [domain] Domain for which configuration applies. + */ +export const setLocaleData = i18n.setLocaleData.bind( i18n ); + +/** + * Retrieve the translation of text. + * + * @see https://developer.wordpress.org/reference/functions/__/ + * + * @param {string} text Text to translate. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} Translated text. + */ +export const __ = i18n.__.bind( i18n ); + +/** + * Retrieve translated string with gettext context. + * + * @see https://developer.wordpress.org/reference/functions/_x/ + * + * @param {string} text Text to translate. + * @param {string} context Context information for the translators. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} Translated context string without pipe. + */ +export const _x = i18n._x.bind( i18n ); + +/** + * Translates and retrieves the singular or plural form based on the supplied + * number. + * + * @see https://developer.wordpress.org/reference/functions/_n/ + * + * @param {string} single The text to be used if the number is singular. + * @param {string} plural The text to be used if the number is plural. + * @param {number} number The number to compare against to use either the + * singular or plural form. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} The translated singular or plural form. + */ +export const _n = i18n._n.bind( i18n ); + +/** + * Translates and retrieves the singular or plural form based on the supplied + * number, with gettext context. + * + * @see https://developer.wordpress.org/reference/functions/_nx/ + * + * @param {string} single The text to be used if the number is singular. + * @param {string} plural The text to be used if the number is plural. + * @param {number} number The number to compare against to use either the + * singular or plural form. + * @param {string} context Context information for the translators. + * @param {string} [domain] Domain to retrieve the translated text. + * + * @return {string} The translated singular or plural form. + */ +export const _nx = i18n._nx.bind( i18n ); + +/** + * Check if current locale is RTL. + * + * **RTL (Right To Left)** is a locale property indicating that text is written from right to left. + * For example, the `he` locale (for Hebrew) specifies right-to-left. Arabic (ar) is another common + * language written RTL. The opposite of RTL, LTR (Left To Right) is used in other languages, + * including English (`en`, `en-US`, `en-GB`, etc.), Spanish (`es`), and French (`fr`). + * + * @return {boolean} Whether locale is RTL. + */ +export const isRTL = i18n.isRTL.bind( i18n ); diff --git a/packages/i18n/src/index.js b/packages/i18n/src/index.js index 2b4286819c9cad..e5e04852a3c227 100644 --- a/packages/i18n/src/index.js +++ b/packages/i18n/src/index.js @@ -1,186 +1,3 @@ -/** - * External dependencies - */ -import Tannin from 'tannin'; -import memoize from 'memize'; -import sprintfjs from 'sprintf-js'; - -/** - * @typedef {{[key: string]: any}} LocaleData - */ - -/** - * Default locale data to use for Tannin domain when not otherwise provided. - * Assumes an English plural forms expression. - * - * @type {LocaleData} - */ -const DEFAULT_LOCALE_DATA = { - '': { - plural_forms: ( n ) => ( n === 1 ? 0 : 1 ), - }, -}; - -/** - * Log to console, once per message; or more precisely, per referentially equal - * argument set. Because Jed throws errors, we log these to the console instead - * to avoid crashing the application. - * - * @param {...*} args Arguments to pass to `console.error` - */ -const logErrorOnce = memoize( console.error ); // eslint-disable-line no-console - -/** - * The underlying instance of Tannin to which exported functions interface. - * - * @type {Tannin} - */ -const i18n = new Tannin( {} ); - -/** - * Merges locale data into the Tannin instance by domain. Accepts data in a - * Jed-formatted JSON object shape. - * - * @see http://messageformat.github.io/Jed/ - * - * @param {LocaleData} [data] Locale data configuration. - * @param {string} [domain] Domain for which configuration applies. - */ -export function setLocaleData( data, domain = 'default' ) { - i18n.data[ domain ] = { - ...DEFAULT_LOCALE_DATA, - ...i18n.data[ domain ], - ...data, - }; - - // Populate default domain configuration (supported locale date which omits - // a plural forms expression). - i18n.data[ domain ][ '' ] = { - ...DEFAULT_LOCALE_DATA[ '' ], - ...i18n.data[ domain ][ '' ], - }; -} - -/** - * Wrapper for Tannin's `dcnpgettext`. Populates default locale data if not - * otherwise previously assigned. - * - * @param {string|undefined} domain Domain to retrieve the translated text. - * @param {string|undefined} context Context information for the translators. - * @param {string} single Text to translate if non-plural. Used as - * fallback return value on a caught error. - * @param {string} [plural] The text to be used if the number is - * plural. - * @param {number} [number] The number to compare against to use - * either the singular or plural form. - * - * @return {string} The translated string. - */ -function dcnpgettext( domain = 'default', context, single, plural, number ) { - if ( ! i18n.data[ domain ] ) { - setLocaleData( undefined, domain ); - } - - return i18n.dcnpgettext( domain, context, single, plural, number ); -} - -/** - * Retrieve the translation of text. - * - * @see https://developer.wordpress.org/reference/functions/__/ - * - * @param {string} text Text to translate. - * @param {string} [domain] Domain to retrieve the translated text. - * - * @return {string} Translated text. - */ -export function __( text, domain ) { - return dcnpgettext( domain, undefined, text ); -} - -/** - * Retrieve translated string with gettext context. - * - * @see https://developer.wordpress.org/reference/functions/_x/ - * - * @param {string} text Text to translate. - * @param {string} context Context information for the translators. - * @param {string} [domain] Domain to retrieve the translated text. - * - * @return {string} Translated context string without pipe. - */ -export function _x( text, context, domain ) { - return dcnpgettext( domain, context, text ); -} - -/** - * Translates and retrieves the singular or plural form based on the supplied - * number. - * - * @see https://developer.wordpress.org/reference/functions/_n/ - * - * @param {string} single The text to be used if the number is singular. - * @param {string} plural The text to be used if the number is plural. - * @param {number} number The number to compare against to use either the - * singular or plural form. - * @param {string} [domain] Domain to retrieve the translated text. - * - * @return {string} The translated singular or plural form. - */ -export function _n( single, plural, number, domain ) { - return dcnpgettext( domain, undefined, single, plural, number ); -} - -/** - * Translates and retrieves the singular or plural form based on the supplied - * number, with gettext context. - * - * @see https://developer.wordpress.org/reference/functions/_nx/ - * - * @param {string} single The text to be used if the number is singular. - * @param {string} plural The text to be used if the number is plural. - * @param {number} number The number to compare against to use either the - * singular or plural form. - * @param {string} context Context information for the translators. - * @param {string} [domain] Domain to retrieve the translated text. - * - * @return {string} The translated singular or plural form. - */ -export function _nx( single, plural, number, context, domain ) { - return dcnpgettext( domain, context, single, plural, number ); -} - -/** - * Check if current locale is RTL. - * - * **RTL (Right To Left)** is a locale property indicating that text is written from right to left. - * For example, the `he` locale (for Hebrew) specifies right-to-left. Arabic (ar) is another common - * language written RTL. The opposite of RTL, LTR (Left To Right) is used in other languages, - * including English (`en`, `en-US`, `en-GB`, etc.), Spanish (`es`), and French (`fr`). - * - * @return {boolean} Whether locale is RTL. - */ -export function isRTL() { - return 'rtl' === _x( 'ltr', 'text direction' ); -} - -/** - * Returns a formatted string. If an error occurs in applying the format, the - * original format string is returned. - * - * @param {string} format The format of the string to generate. - * @param {...string} args Arguments to apply to the format. - * - * @see http://www.diveintojavascript.com/projects/javascript-sprintf - * - * @return {string} The formatted string. - */ -export function sprintf( format, ...args ) { - try { - return sprintfjs.sprintf( format, ...args ); - } catch ( error ) { - logErrorOnce( 'sprintf error: \n\n' + error.toString() ); - - return format; - } -} +export { sprintf } from './sprintf'; +export * from './create-i18n'; +export { setLocaleData, __, _x, _n, _nx, isRTL } from './default-i18n'; diff --git a/packages/i18n/src/sprintf.js b/packages/i18n/src/sprintf.js new file mode 100644 index 00000000000000..397fe7abe4e40f --- /dev/null +++ b/packages/i18n/src/sprintf.js @@ -0,0 +1,35 @@ +/** + * External dependencies + */ +import memoize from 'memize'; +import sprintfjs from 'sprintf-js'; + +/** + * Log to console, once per message; or more precisely, per referentially equal + * argument set. Because Jed throws errors, we log these to the console instead + * to avoid crashing the application. + * + * @param {...*} args Arguments to pass to `console.error` + */ +const logErrorOnce = memoize( console.error ); // eslint-disable-line no-console + +/** + * Returns a formatted string. If an error occurs in applying the format, the + * original format string is returned. + * + * @param {string} format The format of the string to generate. + * @param {...string} args Arguments to apply to the format. + * + * @see http://www.diveintojavascript.com/projects/javascript-sprintf + * + * @return {string} The formatted string. + */ +export function sprintf( format, ...args ) { + try { + return sprintfjs.sprintf( format, ...args ); + } catch ( error ) { + logErrorOnce( 'sprintf error: \n\n' + error.toString() ); + + return format; + } +} diff --git a/packages/i18n/src/test/create-i18n.js b/packages/i18n/src/test/create-i18n.js new file mode 100644 index 00000000000000..ef21d468a33721 --- /dev/null +++ b/packages/i18n/src/test/create-i18n.js @@ -0,0 +1,194 @@ +/* eslint-disable @wordpress/i18n-text-domain, @wordpress/i18n-translator-comments */ + +/** + * Internal dependencies + */ +import { createI18n } from '..'; + +const strayaLocale = { + hello: [ 'gday' ], +}; + +const frenchLocale = { + hello: [ 'bonjour' ], +}; + +const localeData = { + '': { + // Domain name + domain: 'test_domain', + lang: 'fr', + // Plural form function for language + plural_forms: 'nplurals=2; plural=(n != 1);', + }, + + hello: [ 'bonjour' ], + + 'verb\u0004feed': [ 'nourrir' ], + + 'hello %s': [ 'bonjour %s' ], + + '%d banana': [ '%d banane', '%d bananes' ], + + 'fruit\u0004%d apple': [ '%d pomme', '%d pommes' ], +}; + +const additionalLocaleData = { + cheeseburger: [ 'hamburger au fromage' ], + '%d cat': [ '%d chat', '%d chats' ], +}; + +const createTestLocale = () => createI18n( localeData, 'test_domain' ); +const createTestLocaleWithAdditionalData = () => { + const locale = createI18n( localeData, 'test_domain' ); + locale.setLocaleData( additionalLocaleData, 'test_domain' ); + return locale; +}; + +describe( 'createI18n', () => { + test( 'instantiated with locale data', () => { + const straya = createI18n( strayaLocale ); + expect( straya.__( 'hello' ) ).toEqual( 'gday' ); + } ); + + test( 'multiple instances maintain their own distinct locale data', () => { + const straya = createI18n(); + const french = createI18n(); + + straya.setLocaleData( strayaLocale ); + french.setLocaleData( frenchLocale ); + + expect( straya.__( 'hello' ) ).toEqual( 'gday' ); + expect( french.__( 'hello' ) ).toEqual( 'bonjour' ); + } ); + + describe( '__', () => { + it( 'use the translation', () => { + const locale = createTestLocale(); + expect( locale.__( 'hello', 'test_domain' ) ).toBe( 'bonjour' ); + } ); + } ); + + describe( '_x', () => { + it( 'use the translation with context', () => { + const locale = createTestLocale(); + expect( locale._x( 'feed', 'verb', 'test_domain' ) ).toBe( + 'nourrir' + ); + } ); + } ); + + describe( '_n', () => { + it( 'use the plural form', () => { + const locale = createTestLocale(); + expect( + locale._n( '%d banana', '%d bananas', 3, 'test_domain' ) + ).toBe( '%d bananes' ); + } ); + + it( 'use the singular form', () => { + const locale = createTestLocale(); + expect( + locale._n( '%d banana', '%d bananas', 1, 'test_domain' ) + ).toBe( '%d banane' ); + } ); + } ); + + describe( '_nx', () => { + it( 'use the plural form', () => { + const locale = createTestLocale(); + expect( + locale._nx( '%d apple', '%d apples', 3, 'fruit', 'test_domain' ) + ).toBe( '%d pommes' ); + } ); + + it( 'use the singular form', () => { + const locale = createTestLocale(); + expect( + locale._nx( '%d apple', '%d apples', 1, 'fruit', 'test_domain' ) + ).toBe( '%d pomme' ); + } ); + } ); + + describe( 'isRTL', () => { + const ARLocaleData = { + '': { + plural_forms: + 'nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;', + language: 'ar', + localeSlug: 'ar', + }, + 'text direction\u0004ltr': [ 'rtl' ], + Back: [ 'رجوع' ], + }; + + it( 'is false for non-rtl', () => { + const locale = createI18n(); + expect( locale.isRTL() ).toBe( false ); + } ); + + it( 'is true for rtl', () => { + const locale = createI18n( ARLocaleData ); + expect( locale.isRTL() ).toBe( true ); + } ); + } ); + + describe( 'setLocaleData', () => { + it( 'supports omitted plural forms expression', () => { + const locale = createTestLocaleWithAdditionalData(); + locale.setLocaleData( + { + '': { + domain: 'test_domain2', + lang: 'fr', + }, + + '%d banana': [ '%d banane', '%d bananes' ], + }, + 'test_domain2' + ); + expect( + locale._n( '%d banana', '%d bananes', 2, 'test_domain2' ) + ).toBe( '%d bananes' ); + } ); + + describe( '__', () => { + it( 'existing translation still available', () => { + const locale = createTestLocaleWithAdditionalData(); + expect( locale.__( 'hello', 'test_domain' ) ).toBe( 'bonjour' ); + } ); + + it( 'new translation available.', () => { + const locale = createTestLocaleWithAdditionalData(); + expect( locale.__( 'cheeseburger', 'test_domain' ) ).toBe( + 'hamburger au fromage' + ); + } ); + } ); + + describe( '_n', () => { + it( 'existing plural form still works', () => { + const locale = createTestLocaleWithAdditionalData(); + expect( + locale._n( '%d banana', '%d bananas', 3, 'test_domain' ) + ).toBe( '%d bananes' ); + } ); + + it( 'new singular form was added', () => { + const locale = createTestLocaleWithAdditionalData(); + expect( + locale._n( '%d cat', '%d cats', 1, 'test_domain' ) + ).toBe( '%d chat' ); + } ); + + it( 'new plural form was added', () => { + const locale = createTestLocaleWithAdditionalData(); + expect( + locale._n( '%d cat', '%d cats', 3, 'test_domain' ) + ).toBe( '%d chats' ); + } ); + } ); + } ); +} ); + +/* eslint-enable @wordpress/i18n-text-domain, @wordpress/i18n-translator-comments */ diff --git a/packages/i18n/src/test/index.js b/packages/i18n/src/test/index.js deleted file mode 100644 index 5246bc8f3659b1..00000000000000 --- a/packages/i18n/src/test/index.js +++ /dev/null @@ -1,187 +0,0 @@ -// Mock memoization as identity function. Inline since Jest errors on out-of- -// scope references in a mock callback. -jest.mock( 'memize', () => ( fn ) => fn ); - -const localeData = { - '': { - // Domain name - domain: 'test_domain', - lang: 'fr', - // Plural form function for language - plural_forms: 'nplurals=2; plural=(n != 1);', - }, - - hello: [ 'bonjour' ], - - 'verb\u0004feed': [ 'nourrir' ], - - 'hello %s': [ 'bonjour %s' ], - - '%d banana': [ '%d banane', '%d bananes' ], - - 'fruit\u0004%d apple': [ '%d pomme', '%d pommes' ], -}; -const additionalLocaleData = { - cheeseburger: [ 'hamburger au fromage' ], - '%d cat': [ '%d chat', '%d chats' ], -}; - -// Get clean locale data -let sprintf, __, _x, _n, _nx, isRTL, setLocaleData; -beforeEach( () => { - const module = require.resolve( '..' ); - delete require.cache[ module ]; - ( { sprintf, __, _x, _n, _nx, isRTL, setLocaleData } = require( '..' ) ); -} ); - -describe( 'i18n', () => { - describe( '__', () => { - beforeEach( setDefaultLocalData ); - - it( 'use the translation', () => { - expect( __( 'hello', 'test_domain' ) ).toBe( 'bonjour' ); - } ); - } ); - - describe( '_x', () => { - beforeEach( setDefaultLocalData ); - - it( 'use the translation with context', () => { - expect( _x( 'feed', 'verb', 'test_domain' ) ).toBe( 'nourrir' ); - } ); - } ); - - describe( '_n', () => { - beforeEach( setDefaultLocalData ); - - it( 'use the plural form', () => { - expect( _n( '%d banana', '%d bananas', 3, 'test_domain' ) ).toBe( - '%d bananes' - ); - } ); - - it( 'use the singular form', () => { - expect( _n( '%d banana', '%d bananas', 1, 'test_domain' ) ).toBe( - '%d banane' - ); - } ); - } ); - - describe( '_nx', () => { - beforeEach( setDefaultLocalData ); - - it( 'use the plural form', () => { - expect( - _nx( '%d apple', '%d apples', 3, 'fruit', 'test_domain' ) - ).toBe( '%d pommes' ); - } ); - - it( 'use the singular form', () => { - expect( - _nx( '%d apple', '%d apples', 1, 'fruit', 'test_domain' ) - ).toBe( '%d pomme' ); - } ); - } ); - - describe( 'isRTL', () => { - const ARLocaleData = { - '': { - plural_forms: - 'nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;', - language: 'ar', - localeSlug: 'ar', - }, - 'text direction\u0004ltr': [ 'rtl' ], - Back: [ 'رجوع' ], - }; - - it( 'is false for non-rtl', () => { - expect( isRTL() ).toBe( false ); - } ); - - it( 'is true for rtl', () => { - setLocaleData( ARLocaleData ); - expect( isRTL() ).toBe( true ); - } ); - } ); - - describe( 'sprintf', () => { - beforeEach( setDefaultLocalData ); - - it( 'absorbs errors', () => { - // Disable reason: Failing case is the purpose of the test. - // eslint-disable-next-line @wordpress/valid-sprintf - const result = sprintf( 'Hello %(placeholder-not-provided)s' ); - - expect( console ).toHaveErrored(); - expect( result ).toBe( 'Hello %(placeholder-not-provided)s' ); - } ); - - it( 'replaces placeholders', () => { - const result = sprintf( __( 'hello %s', 'test_domain' ), 'Riad' ); - - expect( result ).toBe( 'bonjour Riad' ); - } ); - } ); - - describe( 'setLocaleData', () => { - beforeAll( () => { - setDefaultLocalData(); - setLocaleData( additionalLocaleData, 'test_domain' ); - } ); - - it( 'supports omitted plural forms expression', () => { - setLocaleData( - { - '': { - domain: 'test_domain2', - lang: 'fr', - }, - - '%d banana': [ '%d banane', '%d bananes' ], - }, - 'test_domain2' - ); - - expect( _n( '%d banana', '%d bananes', 2, 'test_domain2' ) ).toBe( - '%d bananes' - ); - } ); - - describe( '__', () => { - it( 'existing translation still available', () => { - expect( __( 'hello', 'test_domain' ) ).toBe( 'bonjour' ); - } ); - - it( 'new translation available.', () => { - expect( __( 'cheeseburger', 'test_domain' ) ).toBe( - 'hamburger au fromage' - ); - } ); - } ); - - describe( '_n', () => { - it( 'existing plural form still works', () => { - expect( - _n( '%d banana', '%d bananas', 3, 'test_domain' ) - ).toBe( '%d bananes' ); - } ); - - it( 'new singular form was added', () => { - expect( _n( '%d cat', '%d cats', 1, 'test_domain' ) ).toBe( - '%d chat' - ); - } ); - - it( 'new plural form was added', () => { - expect( _n( '%d cat', '%d cats', 3, 'test_domain' ) ).toBe( - '%d chats' - ); - } ); - } ); - } ); -} ); - -function setDefaultLocalData() { - setLocaleData( localeData, 'test_domain' ); -} diff --git a/packages/i18n/src/test/sprintf.js b/packages/i18n/src/test/sprintf.js new file mode 100644 index 00000000000000..035d3b3a4b3d41 --- /dev/null +++ b/packages/i18n/src/test/sprintf.js @@ -0,0 +1,27 @@ +// Mock memoization as identity function. Inline since Jest errors on +// out-of-scope references in a mock callback. +jest.mock( 'memize', () => ( fn ) => fn ); + +/** + * Internal dependencies + */ +import { sprintf } from '../sprintf'; + +describe( 'i18n', () => { + describe( 'sprintf', () => { + it( 'absorbs errors', () => { + // Disable reason: Failing case is the purpose of the test. + // eslint-disable-next-line @wordpress/valid-sprintf + const result = sprintf( 'Hello %(placeholder-not-provided)s' ); + + expect( console ).toHaveErrored(); + expect( result ).toBe( 'Hello %(placeholder-not-provided)s' ); + } ); + + it( 'replaces placeholders', () => { + const result = sprintf( 'bonjour %s', 'Riad' ); + + expect( result ).toBe( 'bonjour Riad' ); + } ); + } ); +} ); diff --git a/packages/i18n/tsconfig.json b/packages/i18n/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/i18n/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 15517d8f1ce7c7..e89ce48f536520 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -1,5 +1,7 @@ ## Master +Include TypeScript type declarations ([#21487](https://github.com/WordPress/gutenberg/pull/21487)) + ## 1.0.0 (2020-02-04) Initial release. diff --git a/packages/icons/package.json b/packages/icons/package.json index 088f8b51236a3e..c7e81e1f133b1a 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -22,8 +22,9 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/element": "../element", "@wordpress/primitives": "../primitives" }, diff --git a/packages/icons/src/icon/index.js b/packages/icons/src/icon/index.js index eb196b9d05b6dc..d80acbd952c30a 100644 --- a/packages/icons/src/icon/index.js +++ b/packages/icons/src/icon/index.js @@ -3,6 +3,20 @@ */ import { cloneElement } from '@wordpress/element'; +// Disable reason: JSDoc linter doesn't seem to parse the union (`&`) correctly. +/* eslint-disable jsdoc/valid-types */ +/** @typedef {{icon: JSX.Element, size?: number} & import('react').ComponentPropsWithoutRef<'SVG'>} IconProps */ +/* eslint-enable jsdoc/valid-types */ + +/** + * Return an SVG icon. + * + * @param {IconProps} props icon is the SVG component to render + * size is a number specifiying the icon size in pixels + * Other props will be passed to wrapped SVG component + * + * @return {JSX.Element} Icon component + */ function Icon( { icon, size = 24, ...props } ) { return cloneElement( icon, { width: size, diff --git a/packages/icons/src/icon/stories/index.js b/packages/icons/src/icon/stories/index.js index ff184207af8568..9d1b2d427809c8 100644 --- a/packages/icons/src/icon/stories/index.js +++ b/packages/icons/src/icon/stories/index.js @@ -42,7 +42,7 @@ export const _default = () => { const LibraryExample = () => { const [ filter, setFilter ] = useState( '' ); - const filteredIcons = omitBy( availableIcons, ( icon, name ) => { + const filteredIcons = omitBy( availableIcons, ( _icon, name ) => { return name.indexOf( filter ) === -1; } ); return ( diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index c57f714ef3860e..ec4be6602653d5 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -38,6 +38,8 @@ export { default as columns } from './library/columns'; export { default as comment } from './library/comment'; export { default as controlsRepeat } from './library/controls-repeat'; export { default as cover } from './library/cover'; +export { default as create } from './library/create'; +export { default as desktop } from './library/desktop'; export { default as external } from './library/external'; export { default as file } from './library/file'; export { default as formatBold } from './library/format-bold'; @@ -50,6 +52,7 @@ export { default as formatOutdent } from './library/format-outdent'; export { default as formatRtl } from './library/format-rtl'; export { default as formatStrikethrough } from './library/format-strikethrough'; export { default as gallery } from './library/gallery'; +export { default as globe } from './library/globe'; export { default as grid } from './library/grid'; export { default as group } from './library/group'; export { default as heading } from './library/heading'; @@ -70,6 +73,7 @@ export { default as media } from './library/media'; export { default as mediaAndText } from './library/media-and-text'; export { default as menu } from './library/menu'; export { default as minus } from './library/minus'; +export { default as mobile } from './library/mobile'; export { default as more } from './library/more'; export { default as moreHorizontal } from './library/more-horizontal'; export { default as moreVertical } from './library/more-vertical'; @@ -98,8 +102,8 @@ export { default as resizeCornerNE } from './library/resize-corner-n-e'; export { default as rss } from './library/rss'; export { default as search } from './library/search'; export { default as separator } from './library/separator'; +export { default as share } from './library/share'; export { default as shortcode } from './library/shortcode'; -export { default as globe } from './library/globe'; export { default as starEmpty } from './library/star-empty'; export { default as starFilled } from './library/star-filled'; export { default as starHalf } from './library/star-half'; @@ -114,8 +118,10 @@ export { default as tableRowDelete } from './library/table-row-delete'; export { default as table } from './library/table'; export { default as tag } from './library/tag'; export { default as textColor } from './library/text-color'; +export { default as tablet } from './library/tablet'; export { default as title } from './library/title'; export { default as trash } from './library/trash'; +export { default as typography } from './library/typography'; export { default as undo } from './library/undo'; export { default as update } from './library/update'; export { default as upload } from './library/upload'; diff --git a/packages/icons/src/library/button.js b/packages/icons/src/library/button.js index 4bbe3dd8a6bc78..0e9071bc29fb48 100644 --- a/packages/icons/src/library/button.js +++ b/packages/icons/src/library/button.js @@ -5,7 +5,7 @@ import { Path, SVG } from '@wordpress/primitives'; const button = ( <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> - <Path d="M19 7H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5V9c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13.5h8V12H8v1.5z" /> + <Path d="M19 6.5H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5v-7c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13h8v-1.5H8V13z" /> </SVG> ); diff --git a/packages/icons/src/library/create.js b/packages/icons/src/library/create.js new file mode 100644 index 00000000000000..09019e6ef8d924 --- /dev/null +++ b/packages/icons/src/library/create.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const create = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M16 11.2h-3.2V8h-1.6v3.2H8v1.6h3.2V16h1.6v-3.2H16z" /> + </SVG> +); + +export default create; diff --git a/packages/icons/src/library/desktop.js b/packages/icons/src/library/desktop.js new file mode 100644 index 00000000000000..f7423731a0bc0c --- /dev/null +++ b/packages/icons/src/library/desktop.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const desktop = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M20.5 16h-.7V8c0-1.1-.9-2-2-2H6.2c-1.1 0-2 .9-2 2v8h-.7c-.8 0-1.5.7-1.5 1.5h20c0-.8-.7-1.5-1.5-1.5zM5.7 8c0-.3.2-.5.5-.5h11.6c.3 0 .5.2.5.5v7.6H5.7V8z" /> + </SVG> +); + +export default desktop; diff --git a/packages/icons/src/library/html.js b/packages/icons/src/library/html.js index 12373851d46f26..5f1966166d9f28 100644 --- a/packages/icons/src/library/html.js +++ b/packages/icons/src/library/html.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const html = ( <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> - <Path d="M4.5,11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5V11z M7,10.5h1.5V15H10v-4.5h1.5V9H7V10.5z M14.5,10l-1-1H12v6h1.5v-3.9 l1,1l1-1V15H17V9h-1.5L14.5,10z M19.5,13.5V9H18v6h5v-1.5H19.5z" /> + <Path d="M4.8 11.4H2.1V9H1v6h1.1v-2.6h2.7V15h1.1V9H4.8v2.4zm1.9-1.3h1.7V15h1.1v-4.9h1.7V9H6.7v1.1zM16.2 9l-1.5 2.7L13.3 9h-.9l-.8 6h1.1l.5-4 1.5 2.8 1.5-2.8.5 4h1.1L17 9h-.8zm3.8 5V9h-1.1v6h3.6v-1H20z" /> </SVG> ); diff --git a/packages/icons/src/library/info.js b/packages/icons/src/library/info.js index 7499b180738b3b..f3425d9e950415 100644 --- a/packages/icons/src/library/info.js +++ b/packages/icons/src/library/info.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const info = ( <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> - <Path d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-5h-2v5zm0-7h2V8h-2v2z" /> + <Path d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z" /> </SVG> ); diff --git a/packages/icons/src/library/mobile.js b/packages/icons/src/library/mobile.js new file mode 100644 index 00000000000000..4f1f4055337343 --- /dev/null +++ b/packages/icons/src/library/mobile.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const desktop = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M15 4H9c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h6c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H9c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h6c.3 0 .5.2.5.5v12zm-4.5-.5h2V16h-2v1.5z" /> + </SVG> +); + +export default desktop; diff --git a/packages/icons/src/library/post-list.js b/packages/icons/src/library/post-list.js index 0c5fbdfa0c7e84..7656d492d17fd0 100644 --- a/packages/icons/src/library/post-list.js +++ b/packages/icons/src/library/post-list.js @@ -1,17 +1,11 @@ /** * WordPress dependencies */ -import { Path, Rect, SVG } from '@wordpress/primitives'; +import { Path, SVG } from '@wordpress/primitives'; const postList = ( <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> - <Rect x="11" y="7" width="6" height="2" /> - <Rect x="11" y="11" width="6" height="2" /> - <Rect x="11" y="15" width="6" height="2" /> - <Rect x="7" y="7" width="2" height="2" /> - <Rect x="7" y="11" width="2" height="2" /> - <Rect x="7" y="15" width="2" height="2" /> - <Path d="M20.1,3H3.9C3.4,3,3,3.4,3,3.9v16.2C3,20.5,3.4,21,3.9,21h16.2c0.4,0,0.9-0.5,0.9-0.9V3.9C21,3.4,20.5,3,20.1,3z M19,19H5V5h14V19z" /> + <Path d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H6c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h12c.3 0 .5.2.5.5v12zM7 11h2V9H7v2zm0 4h2v-2H7v2zm3-4h7V9h-7v2zm0 4h7v-2h-7v2z" /> </SVG> ); diff --git a/packages/icons/src/library/search.js b/packages/icons/src/library/search.js index 6ca14df2b2a7d7..a28abf5fce1706 100644 --- a/packages/icons/src/library/search.js +++ b/packages/icons/src/library/search.js @@ -4,8 +4,8 @@ import { SVG, Path } from '@wordpress/primitives'; const search = ( - <SVG xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24"> - <Path d="M12.14 4.18c1.87 1.87 2.11 4.75.72 6.89.12.1.22.21.36.31.2.16.47.36.81.59.34.24.56.39.66.47.42.31.73.57.94.78.32.32.6.65.84 1 .25.35.44.69.59 1.04.14.35.21.68.18 1-.02.32-.14.59-.36.81s-.49.34-.81.36c-.31.02-.65-.04-.99-.19-.35-.14-.7-.34-1.04-.59-.35-.24-.68-.52-1-.84-.21-.21-.47-.52-.77-.93-.1-.13-.25-.35-.47-.66-.22-.32-.4-.57-.56-.78-.16-.2-.29-.35-.44-.5-2.07 1.09-4.69.76-6.44-.98-2.14-2.15-2.14-5.64 0-7.78 2.15-2.15 5.63-2.15 7.78 0zm-1.41 6.36c1.36-1.37 1.36-3.58 0-4.95-1.37-1.37-3.59-1.37-4.95 0-1.37 1.37-1.37 3.58 0 4.95 1.36 1.37 3.58 1.37 4.95 0z" /> + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M13.5 6C10.5 6 8 8.5 8 11.5c0 1.1.3 2.1.9 3l-3.4 3 1 1.1 3.4-2.9c1 .9 2.2 1.4 3.6 1.4 3 0 5.5-2.5 5.5-5.5C19 8.5 16.5 6 13.5 6zm0 9.5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z" /> </SVG> ); diff --git a/packages/icons/src/library/share.js b/packages/icons/src/library/share.js new file mode 100644 index 00000000000000..72e186b99d8b31 --- /dev/null +++ b/packages/icons/src/library/share.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { Path, SVG } from '@wordpress/primitives'; + +const share = ( + <SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <Path d="M9 11.8l6.1-4.5c.1.4.4.7.9.7h2c.6 0 1-.4 1-1V5c0-.6-.4-1-1-1h-2c-.6 0-1 .4-1 1v.4l-6.4 4.8c-.2-.1-.4-.2-.6-.2H6c-.6 0-1 .4-1 1v2c0 .6.4 1 1 1h2c.2 0 .4-.1.6-.2l6.4 4.8v.4c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-2c0-.6-.4-1-1-1h-2c-.5 0-.8.3-.9.7L9 12.2v-.4z" /> + </SVG> +); + +export default share; diff --git a/packages/icons/src/library/tablet.js b/packages/icons/src/library/tablet.js new file mode 100644 index 00000000000000..791e14dd4798f6 --- /dev/null +++ b/packages/icons/src/library/tablet.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const tablet = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M17 4H7c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H7c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h10c.3 0 .5.2.5.5v12zm-7.5-.5h4V16h-4v1.5z" /> + </SVG> +); + +export default tablet; diff --git a/packages/icons/src/library/typography.js b/packages/icons/src/library/typography.js new file mode 100644 index 00000000000000..944a559207567f --- /dev/null +++ b/packages/icons/src/library/typography.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const typography = ( + <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <Path d="M6.9 7L3 17.8h1.7l1-2.8h4.1l1 2.8h1.7L8.6 7H6.9zm-.7 6.6l1.5-4.3 1.5 4.3h-3zM21.6 17c-.1.1-.2.2-.3.2-.1.1-.2.1-.4.1s-.3-.1-.4-.2c-.1-.1-.1-.3-.1-.6V12c0-.5 0-1-.1-1.4-.1-.4-.3-.7-.5-1-.2-.2-.5-.4-.9-.5-.4 0-.8-.1-1.3-.1s-1 .1-1.4.2c-.4.1-.7.3-1 .4-.2.2-.4.3-.6.5-.1.2-.2.4-.2.7 0 .3.1.5.2.8.2.2.4.3.8.3.3 0 .6-.1.8-.3.2-.2.3-.4.3-.7 0-.3-.1-.5-.2-.7-.2-.2-.4-.3-.6-.4.2-.2.4-.3.7-.4.3-.1.6-.1.8-.1.3 0 .6 0 .8.1.2.1.4.3.5.5.1.2.2.5.2.9v1.1c0 .3-.1.5-.3.6-.2.2-.5.3-.9.4-.3.1-.7.3-1.1.4-.4.1-.8.3-1.1.5-.3.2-.6.4-.8.7-.2.3-.3.7-.3 1.2 0 .6.2 1.1.5 1.4.3.4.9.5 1.6.5.5 0 1-.1 1.4-.3.4-.2.8-.6 1.1-1.1 0 .4.1.7.3 1 .2.3.6.4 1.2.4.4 0 .7-.1.9-.2.2-.1.5-.3.7-.4h-.3zm-3-.9c-.2.4-.5.7-.8.8-.3.2-.6.2-.8.2-.4 0-.6-.1-.9-.3-.2-.2-.3-.6-.3-1.1 0-.5.1-.9.3-1.2s.5-.5.8-.7c.3-.2.7-.3 1-.5.3-.1.6-.3.7-.6v3.4z" /> + </SVG> +); + +export default typography; diff --git a/packages/icons/tsconfig.json b/packages/icons/tsconfig.json new file mode 100644 index 00000000000000..a40438556d26fb --- /dev/null +++ b/packages/icons/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ], + "references": [ { "path": "../primitives" } ] +} diff --git a/packages/interface/.npmrc b/packages/interface/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/interface/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md new file mode 100644 index 00000000000000..e597eb0e1e333d --- /dev/null +++ b/packages/interface/CHANGELOG.md @@ -0,0 +1,3 @@ +## Master + +Initial release. diff --git a/packages/interface/README.md b/packages/interface/README.md new file mode 100644 index 00000000000000..21fc84ab45acf5 --- /dev/null +++ b/packages/interface/README.md @@ -0,0 +1,62 @@ +# (Experimental) Interface + +The Interface Package contains the basis the start a new WordPress screen as Edit Post or Edit Site. The package offers a data store and a set of components. The store is useful to contain common data required by a screen (e.g., active areas). The information is persisted across screen reloads. The components allow one to implement functionality like a sidebar or menu items. Third-party plugins by default, can extend them. + +## Installation + +Install the module + +```bash +npm install @wordpress/interface --save +``` + +_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as lower versions of IE then using [core-js](https://github.com/zloirock/core-js) or [@babel/polyfill](https://babeljs.io/docs/en/next/babel-polyfill) will add support for these methods. Learn more about it in [Babel docs](https://babeljs.io/docs/en/next/caveats)._ + + +## API Usage + +### Complementary Areas + +This component was named after a [complementatry landmark](https://www.w3.org/TR/wai-aria-practices/examples/landmarks/complementary.html) – a supporting section of the document, designed to be complementary to the main content at a similar level in the DOM hierarchy, but remains meaningful when separated from the main content. + +`ComplementaryArea` and `ComplementaryArea.Slot` form a slot fill pair to render complementary areas. Multiple `ComplementaryArea` components representing different complementary areas may be rendered at the same time, but only one appears on the slot depending on which complementary area is enabled. + +It is possible to control which complementary is enabled by using the store: + +Bellow are some examples of how to control the active complementary area using the store: +```js +wp.data.select( 'core/interface' ).getActiveComplementaryArea( 'core/edit-post' ); +// -> "edit-post/document" + +wp.data.dispatch( 'core/interface' ).enableComplementaryArea( 'core/edit-post', 'edit-post/block' ); + +wp.data.select( 'core/interface' ).getActiveComplementaryArea( 'core/edit-post' ); +// -> "edit-post/block" + +wp.data.dispatch( 'core/interface' ).disableComplementaryArea( 'core/edit-post' ); + +wp.data.select( 'core/interface' ).getActiveComplementaryArea( 'core/edit-post' ); +// -> null +``` + +### Pinned Items + +`PinnedItems` and `PinnedItems.Slot` form a slot fill pair to render pinned items (or areas) that act as a list of favorites similar to browser extensions listed in the Chrome Menu. + +Example usage: `ComplementaryArea` component makes use of `PinnedItems` and automatically adds a pinned item for the complementary areas marked as a favorite. + +```js +wp.data.select( 'core/interface' ).isItemPinned( 'core/edit-post', 'edit-post-block-patterns/block-patterns-sidebar' ); +// -> false + +wp.data.dispatch( 'core/interface' ).pinItem( 'core/edit-post', 'edit-post-block-patterns/block-patterns-sidebar' ); + +wp.data.select( 'core/interface' ).isItemPinned( 'core/edit-post', 'edit-post-block-patterns/block-patterns-sidebar' ); +// -> true + +wp.data.dispatch( 'core/interface' ).unpinItem( 'core/edit-post', 'edit-post-block-patterns/block-patterns-sidebar' ); + +wp.data.select( 'core/interface' ).isItemPinned( 'core/edit-post', 'edit-post-block-patterns/block-patterns-sidebar' ); -> false +``` + +<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> diff --git a/packages/interface/package.json b/packages/interface/package.json new file mode 100644 index 00000000000000..8d7a2e122fc589 --- /dev/null +++ b/packages/interface/package.json @@ -0,0 +1,38 @@ +{ + "name": "@wordpress/interface", + "version": "0.0.1", + "description": "Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "interface", + "components" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/interface/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/interface" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "react-native": "src/index", + "dependencies": { + "@babel/runtime": "^7.9.2", + "@wordpress/components": "file:../components", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/plugins": "file:../plugins", + "classnames": "^2.2.5", + "lodash": "^4.17.15" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/interface/src/components/complementary-area-header/index.js b/packages/interface/src/components/complementary-area-header/index.js new file mode 100644 index 00000000000000..8e284fb4f2808c --- /dev/null +++ b/packages/interface/src/components/complementary-area-header/index.js @@ -0,0 +1,54 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Button } from '@wordpress/components'; +import { close } from '@wordpress/icons'; + +const ComplementaryAreaHeader = ( { + smallScreenTitle, + toggleShortcut, + onClose, + children, + className, + closeLabel, +} ) => { + return ( + <> + <div className="components-panel__header interface-complementary-area-header__small"> + { smallScreenTitle && ( + <span className="interface-complementary-area-header__small-title"> + { smallScreenTitle } + </span> + ) } + <Button + onClick={ onClose } + icon={ close } + label={ closeLabel } + /> + </div> + <div + className={ classnames( + 'components-panel__header', + 'interface-complementary-area-header', + className + ) } + tabIndex={ -1 } + > + { children } + <Button + onClick={ onClose } + icon={ close } + label={ closeLabel } + shortcut={ toggleShortcut } + /> + </div> + </> + ); +}; + +export default ComplementaryAreaHeader; diff --git a/packages/edit-post/src/components/sidebar/sidebar-header/style.scss b/packages/interface/src/components/complementary-area-header/style.scss similarity index 71% rename from packages/edit-post/src/components/sidebar/sidebar-header/style.scss rename to packages/interface/src/components/complementary-area-header/style.scss index aac3b2630f9a73..7808bc904ad230 100644 --- a/packages/edit-post/src/components/sidebar/sidebar-header/style.scss +++ b/packages/interface/src/components/complementary-area-header/style.scss @@ -1,9 +1,8 @@ -/* Text Editor specific */ -.components-panel__header.edit-post-sidebar-header__small { +.components-panel__header.interface-complementary-area-header__small { background: $white; padding-right: $grid-unit-05; - .edit-post-sidebar__title { + .interface-complementary-area-header__small-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -15,7 +14,7 @@ } } -.components-panel__header.edit-post-sidebar-header { +.interface-complementary-area-header { padding-right: $grid-unit-05; background: $light-gray-200; diff --git a/packages/interface/src/components/complementary-area/README.md b/packages/interface/src/components/complementary-area/README.md new file mode 100644 index 00000000000000..e44aaccb6b71cd --- /dev/null +++ b/packages/interface/src/components/complementary-area/README.md @@ -0,0 +1,115 @@ +ComplementaryArea +============================= + +`ComplementaryArea` is a component to render complementary areas like sidebars. Its implementation is based on slot & fill. +Multiple areas may be added in a given time, but only one is visible; the component renders the required artifacts to control which area is visible. The component allows, for example, to have multiple plugins rendering their sidebars, the user only sees one of the sidebars, but can switch which sidebar is active. + +The contents passed to ComplementaryArea are rendered in the ComplementaryArea.Slot corresponding to their scope if the complementary area is enabled. + +Besides rendering the complimentary area, the component renders a button in `PinnedItems` that allows opening the complementary area. The button only appears if the complementary is marked as favorite. By default, the complementary area headers rendered contain a button to mark and unmark areas as favorites. + +## Props + +### children + +The content to be displayed within the complementary area. + +- Type: `Element` +- Required: Yes + +### closeLabel + +Label of the button that allows to close the complementary area. + +- Type: `String` +- Required: No +- Default: "Close plugin" + +### complementaryAreaIdentifier + +Identifier of the complementary area. The string is saved on the store and allows to identify which of the sidebars is active. + +- Type: `String` +- Required: No +- Default: Concatenation of `name` of the plugin extracted from the context (when available) with the "name" of the sidebar passed as a property. + +### header + +In cases where a custom header is desirable, the prop could be used. It can contain the contents that should be drawn on the header. + +- Type: `Element` +- Required: No + +### headerClassName + +A className passed to the header container. + +- Type: `String` +- Required: No + +### icon + +The icon to render. + +- Type: `Function|WPComponent|null` +- Required: No +- Default: `null` + +### name + +Name of the complementary area. The name of the complementarity area is concatenated with the name of the plugin to form the identifier of the complementary area. The name of the plugin is extracted from the plugin context where the sidebar is rendered. If there is no plugin context available or there is a need to specify a custom identifier, please use the `complementaryAreaIdentifier` property instead. + +- Type: `String` +- Required: No + +### panelClassName + +A className passed to the panel that contains the contents of the sidebar. + +- Type: `String` +- Required: No +- Default: `null` + +### scope + +The scope of the complementary area e.g: "core/edit-post", "core/edit-site", "myplugin/custom-screen-a", + +- Type: `String` +- Required: Yes + +### smallScreenTitle + +In small screens, the complementary area may take up the entire screen. +`smallScreenTitle` allows displaying a title above the complementary area, so the user is more aware of what the area refers to. + +- Type: `String` +- Required: No + +### title + +Human friendly title of the complementary area. + +- Type: `String` +- Required: Yes + +### toggleShortcut + +Keyboard shortcut that allows opening and closing the area. Passed to the button that allows the same action, so the user sees a visual indication that there is a keyboard shortcut. + +- Type: `String|Object` +- Required: No + +ComplementaryArea.Slot +============================= + +A slot that renders the currently active ComplementaryArea. + +## Props + +### scope + +The scope of the complementary area e.g: "core/edit-post", "core/edit-site", "myplugin/custom-screen-a", + +- Type: `String` +- Required: Yes + diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js new file mode 100644 index 00000000000000..54d34edc45eafc --- /dev/null +++ b/packages/interface/src/components/complementary-area/index.js @@ -0,0 +1,148 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Animate, Button, Panel, Slot, Fill } from '@wordpress/components'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { withPluginContext } from '@wordpress/plugins'; +import { starEmpty, starFilled } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import ComplementaryAreaHeader from '../complementary-area-header'; +import PinnedItems from '../pinned-items'; + +function ComplementaryAreaSlot( { scope, ...props } ) { + return <Slot name={ `ComplementaryArea/${ scope }` } { ...props } />; +} + +function ComplementaryAreaFill( { scope, children, className } ) { + return ( + <Fill name={ `ComplementaryArea/${ scope }` }> + <Animate type="slide-in" options={ { origin: 'left' } }> + { () => <div className={ className }>{ children }</div> } + </Animate> + </Fill> + ); +} + +function ComplementaryArea( { + children, + className, + closeLabel = __( 'Close plugin' ), + complementaryAreaIdentifier, + header, + headerClassName, + icon, + isPinnable = true, + panelClassName, + scope, + smallScreenTitle, + title, + toggleShortcut, +} ) { + const { isActive, isPinned } = useSelect( + ( select ) => { + const { getActiveComplementaryArea, isItemPinned } = select( + 'core/interface' + ); + return { + isActive: + getActiveComplementaryArea( scope ) === + complementaryAreaIdentifier, + isPinned: isItemPinned( scope, complementaryAreaIdentifier ), + }; + }, + [ complementaryAreaIdentifier, scope ] + ); + const { enableComplementaryArea, disableComplementaryArea } = useDispatch( + 'core/interface' + ); + const { pinItem, unpinItem } = useDispatch( 'core/interface' ); + return ( + <> + { isPinned && ( + <PinnedItems scope={ scope }> + <Button + icon={ icon } + label={ title } + onClick={ () => + isActive + ? disableComplementaryArea( scope ) + : enableComplementaryArea( + scope, + complementaryAreaIdentifier + ) + } + isPressed={ isActive } + aria-expanded={ isActive } + /> + </PinnedItems> + ) } + { isActive && ( + <ComplementaryAreaFill + className={ classnames( + 'interface-complementary-area', + className + ) } + scope={ scope } + > + <ComplementaryAreaHeader + className={ headerClassName } + closeLabel={ closeLabel } + onClose={ () => disableComplementaryArea( scope ) } + smallScreenTitle={ smallScreenTitle } + toggleShortcut={ toggleShortcut } + > + { header || ( + <> + <strong>{ title }</strong> + { isPinnable && ( + <Button + className="interface-complementary-area__pin-unpin-item" + icon={ + isPinned ? starFilled : starEmpty + } + label={ + isPinned + ? __( 'Unpin from toolbar' ) + : __( 'Pin to toolbar' ) + } + onClick={ () => + ( isPinned ? unpinItem : pinItem )( + scope, + complementaryAreaIdentifier + ) + } + isPressed={ isPinned } + aria-expanded={ isPinned } + /> + ) } + </> + ) } + </ComplementaryAreaHeader> + <Panel className={ panelClassName }>{ children }</Panel> + </ComplementaryAreaFill> + ) } + </> + ); +} + +const ComplementaryAreaWrapped = withPluginContext( ( context, ownProps ) => { + return { + icon: ownProps.icon || context.icon, + complementaryAreaIdentifier: + ownProps.complementaryAreaIdentifier || + `${ context.name }/${ ownProps.name }`, + }; +} )( ComplementaryArea ); + +ComplementaryAreaWrapped.Slot = ComplementaryAreaSlot; + +export default ComplementaryAreaWrapped; diff --git a/packages/interface/src/components/complementary-area/style.scss b/packages/interface/src/components/complementary-area/style.scss new file mode 100644 index 00000000000000..469e6605d13d5f --- /dev/null +++ b/packages/interface/src/components/complementary-area/style.scss @@ -0,0 +1,82 @@ +.interface-complementary-area { + background: $white; + color: $dark-gray-500; + overflow: visible; + + @include break-small() { + z-index: auto; + height: 100%; + overflow: auto; + -webkit-overflow-scrolling: touch; + } + + @include break-medium() { + width: $sidebar-width; + } + + > .components-panel { + border-left: none; + border-right: none; + overflow: auto; + -webkit-overflow-scrolling: touch; + height: auto; + max-height: calc(100vh - #{ $admin-bar-height-big + $panel-header-height + $panel-header-height }); + margin-top: -1px; + margin-bottom: -1px; + position: relative; + + @include break-small() { + overflow: visible; + height: auto; + max-height: none; + } + } + + > .components-panel .components-panel__header { + position: fixed; + z-index: z-index(".components-panel__header"); + top: 0; + left: 0; + right: 0; + height: $panel-header-height; + + @include break-small() { + position: inherit; + top: auto; + left: auto; + right: auto; + } + } + + p { + margin-top: 0; + } + + h2, + h3 { + font-size: $default-font-size; + color: $dark-gray-500; + margin-bottom: 1.5em; + } + + hr { + border-top: none; + border-bottom: 1px solid $light-gray-500; + margin: 1.5em 0; + } + + div.components-toolbar { + box-shadow: none; + margin-bottom: 1.5em; + &:last-child { + margin-bottom: 0; + } + } + + .block-editor-skip-to-selected-block:focus { + top: auto; + right: 10px; + bottom: 10px; + left: auto; + } +} diff --git a/packages/block-editor/src/components/fullscreen-mode/index.js b/packages/interface/src/components/fullscreen-mode/index.js similarity index 100% rename from packages/block-editor/src/components/fullscreen-mode/index.js rename to packages/interface/src/components/fullscreen-mode/index.js diff --git a/packages/block-editor/src/components/fullscreen-mode/style.scss b/packages/interface/src/components/fullscreen-mode/style.scss similarity index 62% rename from packages/block-editor/src/components/fullscreen-mode/style.scss rename to packages/interface/src/components/fullscreen-mode/style.scss index 141f75b2aea88d..a20d23bc4ac632 100644 --- a/packages/block-editor/src/components/fullscreen-mode/style.scss +++ b/packages/interface/src/components/fullscreen-mode/style.scss @@ -19,18 +19,5 @@ body.js.is-fullscreen-mode { #wpfooter { margin-left: 0; } - - // Animations. - .edit-post-header { - transform: translateY(-100%); - animation: edit-post-fullscreen-mode__slide-in-animation 0.1s forwards; - @include reduce-motion("animation"); - } - } -} - -@keyframes edit-post-fullscreen-mode__slide-in-animation { - 100% { - transform: translateY(0%); } } diff --git a/packages/block-editor/src/components/fullscreen-mode/test/index.js b/packages/interface/src/components/fullscreen-mode/test/index.js similarity index 100% rename from packages/block-editor/src/components/fullscreen-mode/test/index.js rename to packages/interface/src/components/fullscreen-mode/test/index.js diff --git a/packages/interface/src/components/index.js b/packages/interface/src/components/index.js new file mode 100644 index 00000000000000..9071a42c0ff944 --- /dev/null +++ b/packages/interface/src/components/index.js @@ -0,0 +1,4 @@ +export { default as ComplementaryArea } from './complementary-area'; +export { default as FullscreenMode } from './fullscreen-mode'; +export { default as InterfaceSkeleton } from './interface-skeleton'; +export { default as PinnedItems } from './pinned-items'; diff --git a/packages/interface/src/components/index.native.js b/packages/interface/src/components/index.native.js new file mode 100644 index 00000000000000..460408d4bf2f12 --- /dev/null +++ b/packages/interface/src/components/index.native.js @@ -0,0 +1,2 @@ +export { default as ComplementaryArea } from './complementary-area'; +export { default as PinnedItems } from './pinned-items'; diff --git a/packages/block-editor/src/components/editor-skeleton/index.js b/packages/interface/src/components/interface-skeleton/index.js similarity index 61% rename from packages/block-editor/src/components/editor-skeleton/index.js rename to packages/interface/src/components/interface-skeleton/index.js index ca4f3646f529c6..d1065602373608 100644 --- a/packages/block-editor/src/components/editor-skeleton/index.js +++ b/packages/interface/src/components/interface-skeleton/index.js @@ -24,72 +24,84 @@ function useHTMLClass( className ) { }, [ className ] ); } -function EditorSkeleton( { +function InterfaceSkeleton( { footer, header, sidebar, content, - publish, + actions, + labels, className, } ) { - useHTMLClass( 'block-editor-editor-skeleton__html-container' ); + useHTMLClass( 'interface-interface-skeleton__html-container' ); + + const defaultLabels = { + header: __( 'Header' ), + body: __( 'Content' ), + sidebar: __( 'Settings' ), + actions: __( 'Publish' ), + footer: __( 'Footer' ), + }; + + const mergedLabels = { ...defaultLabels, ...labels }; + return ( <div className={ classnames( className, - 'block-editor-editor-skeleton' + 'interface-interface-skeleton' ) } > { !! header && ( <div - className="block-editor-editor-skeleton__header" + className="interface-interface-skeleton__header" role="region" /* translators: accessibility text for the top bar landmark region. */ - aria-label={ __( 'Editor top bar' ) } + aria-label={ mergedLabels.header } tabIndex="-1" > { header } </div> ) } - <div className="block-editor-editor-skeleton__body"> + <div className="interface-interface-skeleton__body"> <div - className="block-editor-editor-skeleton__content" + className="interface-interface-skeleton__content" role="region" /* translators: accessibility text for the content landmark region. */ - aria-label={ __( 'Editor content' ) } + aria-label={ mergedLabels.body } tabIndex="-1" > { content } </div> { !! sidebar && ( <div - className="block-editor-editor-skeleton__sidebar" + className="interface-interface-skeleton__sidebar" role="region" /* translators: accessibility text for the settings landmark region. */ - aria-label={ __( 'Editor settings' ) } + aria-label={ mergedLabels.sidebar } tabIndex="-1" > { sidebar } </div> ) } - { !! publish && ( + { !! actions && ( <div - className="block-editor-editor-skeleton__publish" + className="interface-interface-skeleton__actions" role="region" /* translators: accessibility text for the publish landmark region. */ - aria-label={ __( 'Editor publish' ) } + aria-label={ mergedLabels.actions } tabIndex="-1" > - { publish } + { actions } </div> ) } </div> { !! footer && ( <div - className="block-editor-editor-skeleton__footer" + className="interface-interface-skeleton__footer" role="region" /* translators: accessibility text for the footer landmark region. */ - aria-label={ __( 'Editor footer' ) } + aria-label={ mergedLabels.footer } tabIndex="-1" > { footer } @@ -99,4 +111,4 @@ function EditorSkeleton( { ); } -export default navigateRegions( EditorSkeleton ); +export default navigateRegions( InterfaceSkeleton ); diff --git a/packages/block-editor/src/components/editor-skeleton/style.scss b/packages/interface/src/components/interface-skeleton/style.scss similarity index 82% rename from packages/block-editor/src/components/editor-skeleton/style.scss rename to packages/interface/src/components/interface-skeleton/style.scss index 0d70dc621b8f10..39b7b85493f20d 100644 --- a/packages/block-editor/src/components/editor-skeleton/style.scss +++ b/packages/interface/src/components/interface-skeleton/style.scss @@ -1,6 +1,6 @@ // On Mobile devices, swiping the HTML element should not scroll. // By making it fixed, we prevent that. -html.block-editor-editor-skeleton__html-container { +html.interface-interface-skeleton__html-container { position: fixed; width: 100%; @@ -10,7 +10,7 @@ html.block-editor-editor-skeleton__html-container { } } -.block-editor-editor-skeleton { +.interface-interface-skeleton { display: flex; flex-direction: column; height: auto; @@ -33,9 +33,9 @@ html.block-editor-editor-skeleton__html-container { } } -@include editor-left(".block-editor-editor-skeleton"); +@include editor-left(".interface-interface-skeleton"); -.block-editor-editor-skeleton__body { +.interface-interface-skeleton__body { flex-grow: 1; display: flex; @@ -57,7 +57,7 @@ html.block-editor-editor-skeleton__html-container { overscroll-behavior-y: none; } -.block-editor-editor-skeleton__content { +.interface-interface-skeleton__content { flex-grow: 1; // Treat as flex container to allow children to grow to occupy full @@ -73,12 +73,12 @@ html.block-editor-editor-skeleton__html-container { } -.block-editor-editor-skeleton__sidebar { +.interface-interface-skeleton__sidebar { display: block; width: auto; // Keep the sidebar width flexible. flex-shrink: 0; position: absolute; - z-index: z-index(".block-editor-editor-skeleton__sidebar"); + z-index: z-index(".interface-interface-skeleton__sidebar"); top: 0; right: 0; bottom: 0; @@ -91,15 +91,15 @@ html.block-editor-editor-skeleton__html-container { overflow: auto; border-left: $border-width solid $light-gray-500; position: relative !important; - z-index: z-index(".block-editor-editor-skeleton__sidebar {greater than small}"); + z-index: z-index(".interface-interface-skeleton__sidebar {greater than small}"); } } -.block-editor-editor-skeleton__header { +.interface-interface-skeleton__header { flex-shrink: 0; height: auto; // Keep the height flexible. border-bottom: $border-width solid $light-gray-500; - z-index: z-index(".block-editor-editor-skeleton__header"); + z-index: z-index(".interface-interface-skeleton__header"); color: $dark-gray-primary; // On Mobile the header is sticky. @@ -113,7 +113,7 @@ html.block-editor-editor-skeleton__html-container { } } -.block-editor-editor-skeleton__footer { +.interface-interface-skeleton__footer { height: auto; // Keep the height flexible. flex-shrink: 0; border-top: $border-width solid $light-gray-500; @@ -126,9 +126,9 @@ html.block-editor-editor-skeleton__html-container { } } -.block-editor-editor-skeleton__publish { - z-index: z-index(".block-editor-editor-skeleton__publish"); - position: fixed !important; // Need to override the default relative positionning +.interface-interface-skeleton__actions { + z-index: z-index(".interface-interface-skeleton__actions"); + position: fixed !important; // Need to override the default relative positioning top: -9999em; bottom: auto; left: auto; diff --git a/packages/interface/src/components/pinned-items/README.md b/packages/interface/src/components/pinned-items/README.md new file mode 100644 index 00000000000000..0bf15513480417 --- /dev/null +++ b/packages/interface/src/components/pinned-items/README.md @@ -0,0 +1,38 @@ +PinnedItems +============================= + +There are situations where a screen has an area for favorites or pinned items. +This Component allows adding items to that area. Most of the time, the Component should not be used directly as, for example, `ComplementaryArea` Component already renders PinnedItems that allow opening complementary areas marked as favorite. +When used directly, items should not unconditionally add items should only be added if they are marked as "favorite" or verify other conditions. + +## Props + +### children + +The content to be displayed for the pinned items. Most of the time, a button with an icon should be used. + +- Type: `Element` +- Required: Yes + +### scope + +The scope of the pinned items area e.g: "core/edit-post", "core/edit-site", "myplugin/custom-screen-a", + +- Type: `String` +- Required: Yes + +PinnedItems.Slot +============================= + +A slot that renders the pinned items. + +## Props + +### scope + +The scope of the pinned items area e.g: "core/edit-post", "core/edit-site", "myplugin/custom-screen-a", + +- Type: `String` +- Required: Yes + + diff --git a/packages/interface/src/components/pinned-items/index.js b/packages/interface/src/components/pinned-items/index.js new file mode 100644 index 00000000000000..59fc70003095bb --- /dev/null +++ b/packages/interface/src/components/pinned-items/index.js @@ -0,0 +1,37 @@ +/** + * External dependencies + */ +import { isEmpty } from 'lodash'; +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Slot, Fill } from '@wordpress/components'; + +function PinnedItems( { scope, ...props } ) { + return <Fill name={ `PinnedItems/${ scope }` } { ...props } />; +} + +function PinnedItemsSlot( { scope, className, ...props } ) { + return ( + <Slot name={ `PinnedItems/${ scope }` } { ...props }> + { ( fills ) => + ! isEmpty( fills ) && ( + <div + className={ classnames( + className, + 'interface-pinned-items' + ) } + > + { fills } + </div> + ) + } + </Slot> + ); +} + +PinnedItems.Slot = PinnedItemsSlot; + +export default PinnedItems; diff --git a/packages/interface/src/components/pinned-items/style.scss b/packages/interface/src/components/pinned-items/style.scss new file mode 100644 index 00000000000000..76f0fe87fa25a0 --- /dev/null +++ b/packages/interface/src/components/pinned-items/style.scss @@ -0,0 +1,20 @@ +.interface-pinned-items { + display: none; + + @include break-small() { + display: flex; + } + + .components-button { + margin-left: 4px; + + &.is-pressed { + margin-left: 5px; + } + + svg { + max-width: 24px; + max-height: 24px; + } + } +} diff --git a/packages/interface/src/index.js b/packages/interface/src/index.js new file mode 100644 index 00000000000000..7b5bd2101b7195 --- /dev/null +++ b/packages/interface/src/index.js @@ -0,0 +1,6 @@ +/** + * Internal dependencies + */ +import './store'; + +export * from './components'; diff --git a/packages/interface/src/store/actions.js b/packages/interface/src/store/actions.js new file mode 100644 index 00000000000000..ae01f9945e1487 --- /dev/null +++ b/packages/interface/src/store/actions.js @@ -0,0 +1,84 @@ +/** + * Returns an action object used in signalling that an active area should be changed. + * + * @param {string} itemType Type of item. + * @param {string} scope Item scope. + * @param {string} item Item identifier. + * + * @return {Object} Action object. + */ +function setSingleEnableItem( itemType, scope, item ) { + return { + type: 'SET_SINGLE_ENABLE_ITEM', + itemType, + scope, + item, + }; +} + +/** + * Returns an action object used in signalling that a complementary item should be enabled. + * + * @param {string} scope Complementary area scope. + * @param {string} area Area identifier. + * + * @return {Object} Action object. + */ +export function enableComplementaryArea( scope, area ) { + return setSingleEnableItem( 'complementaryArea', scope, area ); +} + +/** + * Returns an action object used in signalling that the complementary area of a given scope should be disabled. + * + * @param {string} scope Complementary area scope. + * + * @return {Object} Action object. + */ +export function disableComplementaryArea( scope ) { + return setSingleEnableItem( 'complementaryArea', scope, undefined ); +} + +/** + * Returns an action object to make an area enabled/disabled. + * + * @param {string} itemType Type of item. + * @param {string} scope Item scope. + * @param {string} item Item identifier. + * @param {boolean} isEnable Boolean indicating if an area should be pinned or not. + * + * @return {Object} Action object. + */ +function setMultipleEnableItem( itemType, scope, item, isEnable ) { + return { + type: 'SET_MULTIPLE_ENABLE_ITEM', + itemType, + scope, + item, + isEnable, + }; +} + +/** + * Returns an action object used in signalling that an item should be pinned. + * + * @param {string} scope Item scope. + * @param {string} itemId Item identifier. + * + * @return {Object} Action object. + */ +export function pinItem( scope, itemId ) { + return setMultipleEnableItem( 'pinnedItems', scope, itemId, true ); +} + +/** + * Returns an action object used in signalling that an item should be unpinned. + * + * @param {string} scope Item scope. + * @param {string} itemId Item identifier. + * + * @return {Object} Action object. + */ +export function unpinItem( scope, itemId ) { + return setMultipleEnableItem( 'pinnedItems', scope, itemId, false ); +} diff --git a/packages/interface/src/store/constants.js b/packages/interface/src/store/constants.js new file mode 100644 index 00000000000000..ad82e7c6a6d755 --- /dev/null +++ b/packages/interface/src/store/constants.js @@ -0,0 +1,6 @@ +/** + * The identifier for the data store. + * + * @type {string} + */ +export const STORE_KEY = 'core/interface'; diff --git a/packages/interface/src/store/defaults.js b/packages/interface/src/store/defaults.js new file mode 100644 index 00000000000000..9d5c172d262441 --- /dev/null +++ b/packages/interface/src/store/defaults.js @@ -0,0 +1,18 @@ +export const DEFAULTS = { + enableItems: { + singleEnableItems: { + complementaryArea: { + 'core/edit-site': 'edit-site/block-inspector', + 'core/edit-post': 'edit-post/document', + }, + }, + multipleEnableItems: { + pinnedItems: { + 'core/edit-site': { + 'edit-site/block-inspector': true, + 'edit-site/global-styles': true, + }, + }, + }, + }, +}; diff --git a/packages/interface/src/store/defaults.native.js b/packages/interface/src/store/defaults.native.js new file mode 100644 index 00000000000000..730ef449dde23c --- /dev/null +++ b/packages/interface/src/store/defaults.native.js @@ -0,0 +1,10 @@ +export const DEFAULTS = { + enableItems: { + singleEnableItems: { + complementaryArea: {}, + }, + multipleEnableItems: { + pinnedItems: {}, + }, + }, +}; diff --git a/packages/edit-post/src/store/index.native.js b/packages/interface/src/store/index.js similarity index 59% rename from packages/edit-post/src/store/index.native.js rename to packages/interface/src/store/index.js index 10355071bd454a..12c723cd51b04e 100644 --- a/packages/edit-post/src/store/index.native.js +++ b/packages/interface/src/store/index.js @@ -7,7 +7,6 @@ import { registerStore } from '@wordpress/data'; * Internal dependencies */ import reducer from './reducer'; -import applyMiddlewares from './middlewares'; import * as actions from './actions'; import * as selectors from './selectors'; import { STORE_KEY } from './constants'; @@ -16,11 +15,7 @@ const store = registerStore( STORE_KEY, { reducer, actions, selectors, - persist: [ 'preferences' ], + persist: [ 'enableItems' ], } ); -applyMiddlewares( store ); -// Do not dispatch INIT for mobile as its effect currently only deals with -// setting up the sidebar and we don't need/support it at the moment for mobile - export default store; diff --git a/packages/interface/src/store/reducer.js b/packages/interface/src/store/reducer.js new file mode 100644 index 00000000000000..f3540ec5c38513 --- /dev/null +++ b/packages/interface/src/store/reducer.js @@ -0,0 +1,132 @@ +/** + * External dependencies + */ +import { flow, get, isEmpty, omit } from 'lodash'; + +/** + * WordPress dependencies + */ +import { combineReducers } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { DEFAULTS } from './defaults'; + +/** + * Higher-order reducer creator which provides the given initial state for the + * original reducer. + * + * @param {*} initialState Initial state to provide to reducer. + * + * @return {Function} Higher-order reducer. + */ +const createWithInitialState = ( initialState ) => ( reducer ) => { + return ( state = initialState, action ) => reducer( state, action ); +}; + +/** + * Reducer to keep tract of the active area per scope. + * + * @param {boolean} state Previous state. + * @param {Object} action Action Object. + * + * @return {Object} Updated state. + */ +export function singleEnableItems( + state = {}, + { type, itemType, scope, item } +) { + if ( type !== 'SET_SINGLE_ENABLE_ITEM' || ! itemType || ! scope ) { + return state; + } + + if ( + ! item && + ! get( DEFAULTS.enableItems.singleEnableItems, [ itemType, scope ] ) + ) { + const newTypeState = omit( state[ itemType ], [ scope ] ); + return isEmpty( newTypeState ) + ? omit( state, [ itemType ] ) + : { + ...state, + [ itemType ]: newTypeState, + }; + } + return { + ...state, + [ itemType ]: { + ...state[ itemType ], + [ scope ]: item || null, + }, + }; +} + +/** + * Reducer keeping track of the "pinned" items per scope + * + * @param {boolean} state Previous state. + * @param {Object} action Action Object. + * + * @return {Object} Updated state. + */ +export function multipleEnableItems( + state = {}, + { type, itemType, scope, item, isEnable } +) { + if ( + type !== 'SET_MULTIPLE_ENABLE_ITEM' || + ! itemType || + ! scope || + ! item || + get( state, [ itemType, scope, item ] ) === isEnable + ) { + return state; + } + const currentTypeState = state[ itemType ] || {}; + const currentScopeState = currentTypeState[ scope ] || {}; + if ( + ! isEnable && + ! get( DEFAULTS.enableItems.multipleEnableItems, [ + itemType, + scope, + item, + ] ) + ) { + const newScopeState = omit( currentScopeState, [ item ] ); + const newTypeState = isEmpty( newScopeState ) + ? omit( currentTypeState, [ scope ] ) + : { + ...currentScopeState, + [ scope ]: newScopeState, + }; + return isEmpty( newTypeState ) + ? omit( state, [ itemType ] ) + : { + ...state, + [ itemType ]: newTypeState, + }; + } + + return { + ...state, + [ itemType ]: { + ...currentTypeState, + [ scope ]: { + ...currentScopeState, + [ item ]: isEnable || false, + }, + }, + }; +} + +const enableItems = combineReducers( { + singleEnableItems, + multipleEnableItems, +} ); + +export default flow( [ combineReducers, createWithInitialState( DEFAULTS ) ] )( + { + enableItems, + } +); diff --git a/packages/interface/src/store/selectors.js b/packages/interface/src/store/selectors.js new file mode 100644 index 00000000000000..08c7d787bdb8e9 --- /dev/null +++ b/packages/interface/src/store/selectors.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +import { get } from 'lodash'; + +/** + * Returns the item that is enabled in a given scope. + * + * @param {Object} state Global application state. + * @param {string} itemType Type of item. + * @param {string} scope Item scope. + * + * @return {string} The item that is enabled in the passed scope and type. + */ +function getSingleEnableItem( state, itemType, scope ) { + return get( + state.enableItems.singleEnableItems, + [ itemType, scope ], + null + ); +} + +/** + * Returns the complementary area that is active in a given scope. + * + * @param {Object} state Global application state. + * @param {string} scope Item scope. + * + * @return {string} The complementary area that is active in the given scope. + */ +export function getActiveComplementaryArea( state, scope ) { + return getSingleEnableItem( state, 'complementaryArea', scope ); +} + +/** + * Returns a boolean indicating if an item is enabled or not in a given scope. + * + * @param {Object} state Global application state. + * @param {string} itemType Type of item. + * @param {string} scope Scope. + * @param {string} item Item to check. + * + * @return {boolean} True if the item is enabled and false otherwise. + */ +function isMultipleEnabledItemEnabled( state, itemType, scope, item ) { + return ( + get( state.enableItems.multipleEnableItems, [ + itemType, + scope, + item, + ] ) === true + ); +} + +/** + * Returns a boolean indicating if an item is pinned or not. + * + * @param {Object} state Global application state. + * @param {string} scope Scope. + * @param {string} item Item to check. + * + * @return {boolean} True if the item is pinned and false otherwise. + */ +export function isItemPinned( state, scope, item ) { + return isMultipleEnabledItemEnabled( state, 'pinnedItems', scope, item ); +} diff --git a/packages/interface/src/style.scss b/packages/interface/src/style.scss new file mode 100644 index 00000000000000..d7f1e35e6e6616 --- /dev/null +++ b/packages/interface/src/style.scss @@ -0,0 +1,5 @@ +@import "./components/complementary-area-header/style.scss"; +@import "./components/complementary-area/style.scss"; +@import "./components/fullscreen-mode/style.scss"; +@import "./components/interface-skeleton/style.scss"; +@import "./components/pinned-items/style.scss"; diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 17019daee1ea6b..4eb1d049e00796 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -1,3 +1,15 @@ +## Master + +### Breaking change + +- Restructure package moving source files into `lib` directory. Direct imports of + `@wordpress/is-shallow-equal/arrays` and `@wordpress/is-shallow-equal/objects` were never + officially supported and have been removed. ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 1.5.0 (2019-08-05) ### Bug Fixes diff --git a/packages/is-shallow-equal/benchmark/index.js b/packages/is-shallow-equal/benchmark/index.js index 5506e53206e129..5779f87688eae3 100644 --- a/packages/is-shallow-equal/benchmark/index.js +++ b/packages/is-shallow-equal/benchmark/index.js @@ -16,10 +16,10 @@ const afterArrayUnequal = [ 1, 2, 3, 4, 5, 'Unequal', 7 ]; [ [ '@wordpress/is-shallow-equal (type specific)', - require( '../objects' ), - require( '../arrays' ), + require( '..' ).isShallowEqualObjects, + require( '..' ).isShallowEqualArrays, ], - [ '@wordpress/is-shallow-equal', require( '../' ) ], + [ '@wordpress/is-shallow-equal', require( '..' ) ], [ 'shallowequal', require( 'shallowequal' ) ], [ 'shallow-equal (type specific)', diff --git a/packages/is-shallow-equal/arrays.js b/packages/is-shallow-equal/lib/arrays.js similarity index 100% rename from packages/is-shallow-equal/arrays.js rename to packages/is-shallow-equal/lib/arrays.js diff --git a/packages/is-shallow-equal/index.js b/packages/is-shallow-equal/lib/index.js similarity index 94% rename from packages/is-shallow-equal/index.js rename to packages/is-shallow-equal/lib/index.js index dc9c074f8327e2..3469656d020376 100644 --- a/packages/is-shallow-equal/index.js +++ b/packages/is-shallow-equal/lib/index.js @@ -9,7 +9,7 @@ var isShallowEqualArrays = require( './arrays' ); var isArray = Array.isArray; /** - * @typedef {{[key: string]: any}} ComparableObject + * @typedef {Record<string, any>} ComparableObject */ /** diff --git a/packages/is-shallow-equal/objects.js b/packages/is-shallow-equal/lib/objects.js similarity index 100% rename from packages/is-shallow-equal/objects.js rename to packages/is-shallow-equal/lib/objects.js diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index 0800bdb4e75437..a0e784d1c571da 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -20,14 +20,15 @@ "url": "https://github.com/WordPress/gutenberg/issues" }, "files": [ - "arrays.js", - "index.js", - "objects.js" + "lib", + "build-types", + "*.md" ], - "main": "index.js", + "main": "lib/index.js", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/is-shallow-equal/test/index.js b/packages/is-shallow-equal/test/index.js index 3ec86ed3529287..66bf538552c645 100644 --- a/packages/is-shallow-equal/test/index.js +++ b/packages/is-shallow-equal/test/index.js @@ -1,9 +1,10 @@ /** * Internal dependencies */ -import isShallowEqual from '../'; -import isShallowEqualArrays from '../arrays'; -import isShallowEqualObjects from '../objects'; +import isShallowEqual, { + isShallowEqualArrays, + isShallowEqualObjects, +} from '..'; describe( 'isShallowEqual', () => { it( 'returns false if of different types', () => { diff --git a/packages/is-shallow-equal/tsconfig.json b/packages/is-shallow-equal/tsconfig.json new file mode 100644 index 00000000000000..426ab13d0aa8f6 --- /dev/null +++ b/packages/is-shallow-equal/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "lib", + "declarationDir": "build-types" + }, + "include": [ "lib/**/*" ] +} diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 1403c4b16d858c..db3ab01eba0114 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -29,8 +29,8 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.8.3", - "jest-matcher-utils": "^24.7.0", + "@babel/runtime": "^7.9.2", + "jest-matcher-utils": "^25.3.0", "lodash": "^4.17.15" }, "peerDependencies": { diff --git a/packages/jest-console/src/test/index.test.js b/packages/jest-console/src/test/index.test.js index 490e3242070c17..caebf6915ab5c8 100644 --- a/packages/jest-console/src/test/index.test.js +++ b/packages/jest-console/src/test/index.test.js @@ -71,15 +71,20 @@ describe( 'jest-console', () => { describe( 'lifecycle', () => { beforeAll( () => { + // Disable reason: // This is a difficult one to test, since the matcher's // own lifecycle is defined to run before ours. Infer // that we're being watched by testing the console // method as being a spy. + // eslint-disable-next-line jest/no-standalone-expect expect( console[ methodName ].assertionsNumber ).toBeGreaterThanOrEqual( 0 ); } ); + // Disable reason: + // See beforeAll implementation and explanation added there. + // eslint-disable-next-line jest/expect-expect it( 'captures logging in lifecycle', () => {} ); } ); } ); diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 6113ac0aba4d7c..19991645ab38f7 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -1,5 +1,10 @@ ## Master +### Breaking Changes + +- The peer `jest` dependency has been updated from requiring `>=24` to requiring `>=25` (see [Breaking Changes](https://jestjs.io/blog/2020/01/21/jest-25), [#20766](https://github.com/WordPress/gutenberg/pull/20766)). +- This package requires now `node` v10.0.0 or later ([#20766](https://github.com/WordPress/gutenberg/pull/20766)). + ## 5.4.0 (2020-02-04) ### Bug Fixes diff --git a/packages/jest-preset-default/package.json b/packages/jest-preset-default/package.json index 753f731573816e..67cda57c184b93 100644 --- a/packages/jest-preset-default/package.json +++ b/packages/jest-preset-default/package.json @@ -22,7 +22,7 @@ "url": "https://github.com/WordPress/gutenberg/issues" }, "engines": { - "node": ">=8" + "node": ">=10" }, "files": [ "scripts", @@ -31,15 +31,15 @@ ], "main": "index.js", "dependencies": { - "@jest/reporters": "^24.8.0", + "@jest/reporters": "^25.3.0", "@wordpress/jest-console": "file:../jest-console", - "babel-jest": "^24.9.0", - "enzyme": "^3.9.0", - "enzyme-adapter-react-16": "^1.10.0", - "enzyme-to-json": "^3.3.5" + "babel-jest": "^25.3.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-to-json": "^3.4.4" }, "peerDependencies": { - "jest": ">=24" + "jest": ">=25" }, "publishConfig": { "access": "public" diff --git a/packages/jest-puppeteer-axe/package.json b/packages/jest-puppeteer-axe/package.json index 03e84e46c75e0b..2a98a1380d95c5 100644 --- a/packages/jest-puppeteer-axe/package.json +++ b/packages/jest-puppeteer-axe/package.json @@ -30,7 +30,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "axe-puppeteer": "^1.0.0" }, "peerDependencies": { diff --git a/packages/keyboard-shortcuts/README.md b/packages/keyboard-shortcuts/README.md index 5bb9f1480a4481..bfb6cd62106fee 100644 --- a/packages/keyboard-shortcuts/README.md +++ b/packages/keyboard-shortcuts/README.md @@ -1,4 +1,4 @@ -# Keycodes +# Keyboard Shortcuts Keyboard shortcuts is a generic package that allow registering andd modifying shortcuts. diff --git a/packages/keyboard-shortcuts/package.json b/packages/keyboard-shortcuts/package.json index 77a5f26facca0d..f0f22dd7da2dbc 100644 --- a/packages/keyboard-shortcuts/package.json +++ b/packages/keyboard-shortcuts/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", "@wordpress/element": "file:../element", diff --git a/packages/keycodes/README.md b/packages/keycodes/README.md index 7d54480a89b4bd..bb7036ba95de74 100644 --- a/packages/keycodes/README.md +++ b/packages/keycodes/README.md @@ -162,6 +162,10 @@ Keycode for TAB key. Keycode for UP key. +<a name="ZERO" href="#ZERO">#</a> **ZERO** + +Keycode for ZERO key. + <!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/keycodes/package.json b/packages/keycodes/package.json index cd98091760929b..c74f2a7a1cf7da 100644 --- a/packages/keycodes/package.json +++ b/packages/keycodes/package.json @@ -22,7 +22,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/i18n": "file:../i18n", "lodash": "^4.17.15" }, diff --git a/packages/keycodes/src/index.js b/packages/keycodes/src/index.js index 998200bd21f31b..fc975909aa4e4d 100644 --- a/packages/keycodes/src/index.js +++ b/packages/keycodes/src/index.js @@ -32,7 +32,7 @@ import { isAppleOS } from './platform'; * An object of handler functions for each of the possible modifier * combinations. A handler will return a value for a given key. * - * @typedef {{[M in WPKeycodeModifier]:(key:string)=>any}} WPKeycodeHandlerByModifier + * @typedef {Record<WPKeycodeModifier, (key:string)=>any>} WPKeycodeHandlerByModifier */ /** @@ -95,6 +95,10 @@ export const COMMAND = 'meta'; * Keycode for SHIFT key. */ export const SHIFT = 'shift'; +/** + * Keycode for ZERO key. + */ +export const ZERO = 48; /** * Object that contains functions that return the available modifier diff --git a/packages/list-reusable-blocks/package.json b/packages/list-reusable-blocks/package.json index 163a050b0d5557..fccaf035c6c21a 100644 --- a/packages/list-reusable-blocks/package.json +++ b/packages/list-reusable-blocks/package.json @@ -20,7 +20,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", diff --git a/packages/media-utils/package.json b/packages/media-utils/package.json index 3eeed1865ba72e..1c2b025daca80a 100644 --- a/packages/media-utils/package.json +++ b/packages/media-utils/package.json @@ -22,7 +22,7 @@ "main": "build/index.js", "module": "build-module/index.js", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", "@wordpress/element": "file:../element", diff --git a/packages/notices/package.json b/packages/notices/package.json index af972bf4268aa0..c589640cbdaa41 100644 --- a/packages/notices/package.json +++ b/packages/notices/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/a11y": "file:../a11y", "@wordpress/data": "file:../data", "lodash": "^4.17.15" diff --git a/packages/npm-package-json-lint-config/CHANGELOG.md b/packages/npm-package-json-lint-config/CHANGELOG.md index 945e31866bbe8e..c00529998a1fff 100644 --- a/packages/npm-package-json-lint-config/CHANGELOG.md +++ b/packages/npm-package-json-lint-config/CHANGELOG.md @@ -1,6 +1,12 @@ +## Master + +### Breaking Change + +- Add `types` to the order of preferred properties. ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 2.0.0 (2019-06-12) -### Braking Change +### Breaking Change - Added `type` and `react-native` to the order of preferred properties. diff --git a/packages/npm-package-json-lint-config/index.js b/packages/npm-package-json-lint-config/index.js index e8fbd3eebdcec2..831970c59bf3a6 100644 --- a/packages/npm-package-json-lint-config/index.js +++ b/packages/npm-package-json-lint-config/index.js @@ -57,6 +57,7 @@ const defaultConfig = { 'main', 'module', 'react-native', + 'types', 'bin', 'dependencies', 'devDependencies', diff --git a/packages/nux/package.json b/packages/nux/package.json index 206e8d583b342b..04b5bc5c80d2ae 100644 --- a/packages/nux/package.json +++ b/packages/nux/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 92ab4b6718f748..52da1315c87dd0 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:../compose", "@wordpress/element": "file:../element", "@wordpress/hooks": "file:../hooks", diff --git a/packages/plugins/src/api/index.js b/packages/plugins/src/api/index.js index 8a3a0c0834c385..61c6e6695304ec 100644 --- a/packages/plugins/src/api/index.js +++ b/packages/plugins/src/api/index.js @@ -41,7 +41,8 @@ const plugins = {}; * unique across all registered plugins. * @param {WPPlugin} settings The settings for this plugin. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var el = wp.element.createElement; @@ -78,7 +79,8 @@ const plugins = {}; * } ); * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```js * // Using ESNext syntax * import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post'; @@ -153,7 +155,8 @@ export function registerPlugin( name, settings ) { * * @param {string} name Plugin name. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var unregisterPlugin = wp.plugins.unregisterPlugin; @@ -161,7 +164,8 @@ export function registerPlugin( name, settings ) { * unregisterPlugin( 'plugin-name' ); * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```js * // Using ESNext syntax * const { unregisterPlugin } = wp.plugins; diff --git a/packages/plugins/src/components/plugin-area/index.js b/packages/plugins/src/components/plugin-area/index.js index b60ddbfb875667..445ded2e68d9b2 100644 --- a/packages/plugins/src/components/plugin-area/index.js +++ b/packages/plugins/src/components/plugin-area/index.js @@ -18,7 +18,8 @@ import { getPlugins } from '../../api'; /** * A component that renders all plugin fills in a hidden div. * - * @example <caption>ES5</caption> + * @example + * <caption>ES5</caption> * ```js * // Using ES5 syntax * var el = wp.element.createElement; @@ -34,7 +35,8 @@ import { getPlugins } from '../../api'; * } * ``` * - * @example <caption>ESNext</caption> + * @example + * <caption>ESNext</caption> * ```js * // Using ESNext syntax * const { PluginArea } = wp.plugins; diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index 320942d34efb3a..6d73529eee2190 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -1,7 +1,5 @@ ## Master -## 0.1.0 (2020-04-01) - ### Initial Release - The config was extracted from `@wordpress/scripts` package ([#20026](https://github.com/WordPress/gutenberg/pull/20026)). diff --git a/packages/prettier-config/lib/index.js b/packages/prettier-config/lib/index.js index 17308856dce9d9..08854b5775981d 100644 --- a/packages/prettier-config/lib/index.js +++ b/packages/prettier-config/lib/index.js @@ -1,4 +1,18 @@ -module.exports = { +/** @typedef {import('prettier').Options} PrettierOptions */ + +/** + * @typedef WPPrettierOptions + * + * @property {boolean} [parenSpacing=true] Insert spaces inside parentheses. + */ + +// Disable reason: The current JSDoc tooling does not yet understand TypeScript +// union types. + +/* eslint-disable jsdoc/valid-types */ +/** @type {PrettierOptions & WPPrettierOptions} */ +/* eslint-enable jsdoc/valid-types */ +const config = { useTabs: true, tabWidth: 4, printWidth: 80, @@ -10,3 +24,5 @@ module.exports = { semi: true, arrowParens: 'always', }; + +module.exports = config; diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 987f03128a4f93..5c7fcce58aea1a 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -25,6 +25,7 @@ "lib/index.js" ], "main": "lib/index.js", + "types": "build-types", "publishConfig": { "access": "public" } diff --git a/packages/prettier-config/tsconfig.json b/packages/prettier-config/tsconfig.json new file mode 100644 index 00000000000000..426ab13d0aa8f6 --- /dev/null +++ b/packages/prettier-config/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "lib", + "declarationDir": "build-types" + }, + "include": [ "lib/**/*" ] +} diff --git a/packages/primitives/CHANGELOG.md b/packages/primitives/CHANGELOG.md index e597eb0e1e333d..480dc11051dadc 100644 --- a/packages/primitives/CHANGELOG.md +++ b/packages/primitives/CHANGELOG.md @@ -1,3 +1,7 @@ ## Master +Include TypeScript type declarations ([#21482](https://github.com/WordPress/gutenberg/pull/21482)) + +## 1.0.0 + Initial release. diff --git a/packages/primitives/package.json b/packages/primitives/package.json index 7ade2ebda5da2f..7c21406159fa68 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -22,8 +22,9 @@ "module": "build-module/index.js", "react-native": "src/index", "sideEffects": false, + "types": "build-types", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/element": "file:../element", "classnames": "^2.2.5" }, diff --git a/packages/primitives/src/svg/index.js b/packages/primitives/src/svg/index.js index 470ee1af88b86a..38f1c3e1b1ce94 100644 --- a/packages/primitives/src/svg/index.js +++ b/packages/primitives/src/svg/index.js @@ -8,26 +8,91 @@ import classnames from 'classnames'; */ import { createElement } from '@wordpress/element'; +// Disable reason: JSDoc linter doesn't seem to parse the union (`&`) correctly. +/* eslint-disable jsdoc/valid-types */ +/** @typedef {{isPressed?: boolean} & import('react').ComponentPropsWithoutRef<'svg'>} SVGProps */ +/* eslint-enable jsdoc/valid-types */ + +/** + * @param {import('react').ComponentPropsWithoutRef<'circle'>} props + * + * @return {JSX.Element} Circle component + */ export const Circle = ( props ) => createElement( 'circle', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'g'>} props + * + * @return {JSX.Element} G component + */ export const G = ( props ) => createElement( 'g', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'path'>} props + * + * @return {JSX.Element} Path component + */ export const Path = ( props ) => createElement( 'path', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'polygon'>} props + * + * @return {JSX.Element} Polygon component + */ export const Polygon = ( props ) => createElement( 'polygon', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'rect'>} props + * + * @return {JSX.Element} Rect component + */ export const Rect = ( props ) => createElement( 'rect', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'defs'>} props + * + * @return {JSX.Element} Defs component + */ export const Defs = ( props ) => createElement( 'defs', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'radialGradient'>} props + * + * @return {JSX.Element} RadialGradient component + */ export const RadialGradient = ( props ) => createElement( 'radialGradient', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'linearGradient'>} props + * + * @return {JSX.Element} LinearGradient component + */ export const LinearGradient = ( props ) => createElement( 'linearGradient', props ); + +/** + * @param {import('react').ComponentPropsWithoutRef<'stop'>} props + * + * @return {JSX.Element} Stop component + */ export const Stop = ( props ) => createElement( 'stop', props ); +/** + * + * @param {SVGProps} props isPressed indicates whether the SVG should appear as pressed. + * Other props will be passed through to svg component. + * + * @return {JSX.Element} Stop component + */ export const SVG = ( { className, isPressed, ...props } ) => { const appliedProps = { ...props, className: classnames( className, { 'is-pressed': isPressed } ) || undefined, role: 'img', - 'aria-hidden': 'true', - focusable: 'false', + 'aria-hidden': true, + focusable: false, }; // Disable reason: We need to have a way to render HTML tag for web. diff --git a/packages/primitives/tsconfig.json b/packages/primitives/tsconfig.json new file mode 100644 index 00000000000000..085d6fa752ab04 --- /dev/null +++ b/packages/primitives/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ], + "references": [ { "path": "../element" } ] +} diff --git a/packages/priority-queue/CHANGELOG.md b/packages/priority-queue/CHANGELOG.md index e4a76269c9ca8a..9232755f3aa4dc 100644 --- a/packages/priority-queue/CHANGELOG.md +++ b/packages/priority-queue/CHANGELOG.md @@ -1,5 +1,9 @@ ## Master +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 1.5.0 (2020-02-04) ### Bug Fixes diff --git a/packages/priority-queue/README.md b/packages/priority-queue/README.md index 3b6e43861bd2f8..600a82240cbb8e 100644 --- a/packages/priority-queue/README.md +++ b/packages/priority-queue/README.md @@ -40,7 +40,7 @@ queue.add( ctx2, () => console.log( 'This will be printed second' ) ); _Returns_ -- `WPPriorityQueue`: Queue object with `add` and `flush` methods. +- `WPPriorityQueue`: Queue object with `add`, `flush` and `reset` methods. <!-- END TOKEN(Autogenerated API docs) --> diff --git a/packages/priority-queue/package.json b/packages/priority-queue/package.json index 955bbbd161f18b..8d8dca22fb5c71 100644 --- a/packages/priority-queue/package.json +++ b/packages/priority-queue/package.json @@ -21,9 +21,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/priority-queue/src/index.js b/packages/priority-queue/src/index.js index e1933cbf11a47a..27f3abf81d09a8 100644 --- a/packages/priority-queue/src/index.js +++ b/packages/priority-queue/src/index.js @@ -27,6 +27,12 @@ import requestIdleCallback from './request-idle-callback'; * @typedef {(element:WPPriorityQueueContext)=>boolean} WPPriorityQueueFlush */ +/** + * Reset the queue. + * + * @typedef {()=>void} WPPriorityQueueReset + */ + /** * Priority queue instance. * @@ -34,6 +40,7 @@ import requestIdleCallback from './request-idle-callback'; * * @property {WPPriorityQueueAdd} add Add callback to queue for context. * @property {WPPriorityQueueFlush} flush Flush queue for context. + * @property {WPPriorityQueueReset} reset Reset queue. */ /** @@ -56,25 +63,25 @@ import requestIdleCallback from './request-idle-callback'; * queue.add( ctx2, () => console.log( 'This will be printed second' ) ); *``` * - * @return {WPPriorityQueue} Queue object with `add` and `flush` methods. + * @return {WPPriorityQueue} Queue object with `add`, `flush` and `reset` methods. */ export const createQueue = () => { /** @type {WPPriorityQueueContext[]} */ - const waitingList = []; + let waitingList = []; /** @type {WeakMap<WPPriorityQueueContext,WPPriorityQueueCallback>} */ - const elementsMap = new WeakMap(); + let elementsMap = new WeakMap(); let isRunning = false; + /* eslint-disable jsdoc/valid-types */ /** * Callback to process as much queue as time permits. * - * @type {IdleRequestCallback & FrameRequestCallback} - * * @param {IdleDeadline|number} deadline Idle callback deadline object, or * animation frame timestamp. */ + /* eslint-enable */ const runWaitingList = ( deadline ) => { const hasTimeRemaining = typeof deadline === 'number' @@ -143,8 +150,20 @@ export const createQueue = () => { return true; }; + /** + * Reset the queue without running the pending callbacks. + * + * @type {WPPriorityQueueReset} + */ + const reset = () => { + waitingList = []; + elementsMap = new WeakMap(); + isRunning = false; + }; + return { add, flush, + reset, }; }; diff --git a/packages/priority-queue/src/request-idle-callback.js b/packages/priority-queue/src/request-idle-callback.js index eee8044fe365e5..64b51e7d2b3364 100644 --- a/packages/priority-queue/src/request-idle-callback.js +++ b/packages/priority-queue/src/request-idle-callback.js @@ -1,5 +1,9 @@ /** - * @return {typeof window.requestIdleCallback|typeof window.requestAnimationFrame|((callback:(timestamp:number)=>void)=>void)} + * @typedef {( timeOrDeadline: IdleDeadline | number ) => void} Callback + */ + +/** + * @return {(callback: Callback) => void} RequestIdleCallback */ export function createRequestIdleCallback() { if ( typeof window === 'undefined' ) { diff --git a/packages/priority-queue/tsconfig.json b/packages/priority-queue/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/priority-queue/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/project-management-automation/CHANGELOG.md b/packages/project-management-automation/CHANGELOG.md index 2c2284ae8eebfc..0e2f5ad00a4104 100644 --- a/packages/project-management-automation/CHANGELOG.md +++ b/packages/project-management-automation/CHANGELOG.md @@ -1,3 +1,14 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) +- The "Add First Time Contributor Label" task now prompts the user to link their GitHub account to their WordPress.org profile if neccessary for props credit. The task has been renamed "First Time Contributor". + +### Improvements + +- The "Add First Time Contributor Label" task now runs retroactively on pushes to master, due to [permission constraints](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token) of GitHub Actions. + ## 1.0.0 (2019-08-29) - Initial release. diff --git a/packages/project-management-automation/README.md b/packages/project-management-automation/README.md index 40c85f70a67233..17726771d94e66 100644 --- a/packages/project-management-automation/README.md +++ b/packages/project-management-automation/README.md @@ -2,7 +2,7 @@ This is a [GitHub Action](https://help.github.com/en/categories/automating-your-workflow-with-github-actions) which contains various automation to assist with managing the Gutenberg GitHub repository: -- `add-first-time-contributor-label`: Adds the 'First Time Contributor' label to PRs opened by contributors that have not yet made a commit. +- `first-time-contributor`: Adds the 'First Time Contributor' label to PRs merged on behalf of contributors that have not previously made a contribution, and prompts the user to link their GitHub account to their WordPress.org profile if neccessary for props credit. - `add-milestone`: Assigns the correct milestone to PRs once merged. - `assign-fixed-issues`: Assigns any issues 'fixed' by a newly opened PR to the author of that PR. diff --git a/packages/project-management-automation/lib/add-first-time-contributor-label.js b/packages/project-management-automation/lib/add-first-time-contributor-label.js deleted file mode 100644 index 661a2412b03ac5..00000000000000 --- a/packages/project-management-automation/lib/add-first-time-contributor-label.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Internal dependencies - */ -const debug = require( './debug' ); - -/** @typedef {import('@actions/github').GitHub} GitHub */ -/** @typedef {import('@octokit/webhooks').WebhookPayloadPullRequest} WebhookPayloadPullRequest */ - -/** - * Adds the 'First Time Contributor' label to PRs opened by contributors that - * have not yet made a commit. - * - * @param {WebhookPayloadPullRequest} payload Pull request event payload. - * @param {GitHub} octokit Initialized Octokit REST client. - */ -async function addFirstTimeContributorLabel( payload, octokit ) { - const owner = payload.repository.owner.login; - const repo = payload.repository.name; - const author = payload.pull_request.user.login; - - debug( - `add-first-time-contributor-label: Searching for commits in ${ owner }/${ repo } by @${ author }` - ); - - const { - data: { total_count: totalCount }, - } = await octokit.search.commits( { - q: `repo:${ owner }/${ repo }+author:${ author }`, - } ); - - if ( totalCount !== 0 ) { - debug( - `add-first-time-contributor-label: ${ totalCount } commits found. Aborting` - ); - return; - } - - debug( - `add-first-time-contributor-label: Adding 'First Time Contributor' label to issue #${ payload.pull_request.number }` - ); - - await octokit.issues.addLabels( { - owner, - repo, - issue_number: payload.pull_request.number, - labels: [ 'First-time Contributor' ], - } ); -} - -module.exports = addFirstTimeContributorLabel; diff --git a/packages/project-management-automation/lib/add-milestone.js b/packages/project-management-automation/lib/add-milestone.js index e1e8ae39bc99f4..1716a8bea4f024 100644 --- a/packages/project-management-automation/lib/add-milestone.js +++ b/packages/project-management-automation/lib/add-milestone.js @@ -2,6 +2,7 @@ * Internal dependencies */ const debug = require( './debug' ); +const getAssociatedPullRequest = require( './get-associated-pull-request' ); /** @typedef {import('@octokit/rest').HookError} HookError */ /** @typedef {import('@actions/github').GitHub} GitHub */ @@ -45,8 +46,7 @@ async function addMilestone( payload, octokit ) { return; } - const match = payload.commits[ 0 ].message.match( /\(#(\d+)\)$/m ); - const prNumber = match && match[ 1 ]; + const prNumber = getAssociatedPullRequest( payload.commits[ 0 ] ); if ( ! prNumber ) { debug( 'add-milestone: Commit is not a squashed PR. Aborting' ); return; diff --git a/packages/project-management-automation/lib/first-time-contributor.js b/packages/project-management-automation/lib/first-time-contributor.js new file mode 100644 index 00000000000000..901b9df361e04f --- /dev/null +++ b/packages/project-management-automation/lib/first-time-contributor.js @@ -0,0 +1,124 @@ +/** + * Internal dependencies + */ +const debug = require( './debug' ); +const getAssociatedPullRequest = require( './get-associated-pull-request' ); +const hasWordPressProfile = require( './has-wordpress-profile' ); + +/** @typedef {import('@actions/github').GitHub} GitHub */ +/** @typedef {import('@octokit/webhooks').WebhookPayloadPush} WebhookPayloadPush */ +/** @typedef {import('./get-associated-pull-request').WebhookPayloadPushCommit} WebhookPayloadPushCommit */ + +/** + * Returns the message text to be used for the comment prompting contributor to + * link their GitHub account from their WordPress.org profile for props credit. + * + * @param {string} author GitHub username of author. + * + * @return {string} Message text. + */ +function getPromptMessageText( author ) { + return ( + 'Congratulations on your first merged pull request, @' + + author + + "! We'd like to credit you for your contribution in the post " + + "announcing the next WordPress release, but we can't find a " + + 'WordPress.org profile associated with your GitHub account. When you ' + + 'have a moment, visit the following URL and click "link your GitHub ' + + 'account" under "GitHub Username" to link your accounts:\n\n' + + "https://profiles.wordpress.org/me/profile/edit/\n\nAnd if you don't " + + 'have a WordPress.org account, you can create one on this page:\n\n' + + 'https://login.wordpress.org/register\n\nKudos!' + ); +} + +/** + * Adds the 'First Time Contributor' label to PRs merged on behalf of + * contributors that have not yet made a commit, and prompts the user to link + * their GitHub account to their WordPress.org profile if neccessary for props + * credit. + * + * @param {WebhookPayloadPush} payload Push event payload. + * @param {GitHub} octokit Initialized Octokit REST client. + */ +async function firstTimeContributor( payload, octokit ) { + if ( payload.ref !== 'refs/heads/master' ) { + debug( 'first-time-contributor: Commit is not to `master`. Aborting' ); + return; + } + + const commit = + /** @type {WebhookPayloadPushCommit} */ ( payload.commits[ 0 ] ); + const pullRequest = getAssociatedPullRequest( commit ); + if ( ! pullRequest ) { + debug( + 'first-time-contributor: Cannot determine pull request associated with commit. Aborting' + ); + return; + } + + const repo = payload.repository.name; + const owner = payload.repository.owner.login; + const author = commit.author.username; + debug( + `first-time-contributor: Searching for commits in ${ owner }/${ repo } by @${ author }` + ); + + const { data: commits } = await octokit.repos.listCommits( { + owner, + repo, + author, + } ); + + if ( commits.length > 1 ) { + debug( + `first-time-contributor: Not the first commit for author. Aborting` + ); + return; + } + + debug( + `first-time-contributor: Adding 'First Time Contributor' label to issue #${ pullRequest }` + ); + + await octokit.issues.addLabels( { + owner, + repo, + issue_number: pullRequest, + labels: [ 'First-time Contributor' ], + } ); + + debug( + `first-time-contributor: Checking for WordPress username associated with @${ author }` + ); + + let hasProfile; + try { + hasProfile = await hasWordPressProfile( author ); + } catch ( error ) { + debug( + `first-time-contributor: Error retrieving from profile API:\n\n${ error.toString() }` + ); + return; + } + + if ( hasProfile ) { + debug( + `first-time-contributor: User already known. No need to prompt for account link!` + ); + return; + } + + debug( + 'first-time-contributor: User not known. Adding comment to prompt for account link.' + ); + + await octokit.issues.createComment( { + owner, + repo, + issue_number: pullRequest, + body: getPromptMessageText( author ), + } ); +} + +module.exports = firstTimeContributor; diff --git a/packages/project-management-automation/lib/get-associated-pull-request.js b/packages/project-management-automation/lib/get-associated-pull-request.js new file mode 100644 index 00000000000000..6ec267a26a5b8e --- /dev/null +++ b/packages/project-management-automation/lib/get-associated-pull-request.js @@ -0,0 +1,39 @@ +/** + * @typedef WebhookPayloadPushCommitAuthor + * + * @property {string} name Author name. + * @property {string} email Author email. + * @property {string} username Author username. + */ + +/** + * Minimal type detail of GitHub Push webhook event payload, for lack of their + * own. + * + * TODO: If GitHub improves this on their own webhook payload types, this type + * should no longer be necessary. + * + * @typedef {Record<string,*>} WebhookPayloadPushCommit + * + * @property {string} message Commit message. + * @property {WebhookPayloadPushCommitAuthor} author Commit author. + * + * @see https://developer.github.com/v3/activity/events/types/#pushevent + */ + +/** + * Given a commit object, returns a promise resolving with the pull request + * number associated with the commit, or null if an associated pull request + * cannot be determined. + * + * @param {WebhookPayloadPushCommit} commit Commit object. + * + * @return {number?} Pull request number, or null if it cannot be + * determined. + */ +function getAssociatedPullRequest( commit ) { + const match = commit.message.match( /\(#(\d+)\)$/m ); + return match && Number( match[ 1 ] ); +} + +module.exports = getAssociatedPullRequest; diff --git a/packages/project-management-automation/lib/has-wordpress-profile.js b/packages/project-management-automation/lib/has-wordpress-profile.js new file mode 100644 index 00000000000000..cb2adfdba71e0b --- /dev/null +++ b/packages/project-management-automation/lib/has-wordpress-profile.js @@ -0,0 +1,46 @@ +/** + * External dependencies + */ +const { request } = require( 'https' ); + +/** + * Endpoint hostname for WordPress.org profile lookup by GitHub username. + * + * @type {string} + */ +const BASE_PROFILE_LOOKUP_API_HOSTNAME = 'profiles.wordpress.org'; + +/** + * Base path for WordPress.org profile lookup by GitHub username. + * + * @type {string} + */ +const BASE_PROFILE_LOOKUP_API_BASE_PATH = '/wp-json/wporg-github/v1/lookup/'; + +/** + * Returns a promise resolving to a boolean indicating if the given GitHub + * username can be associated with a WordPress.org profile. + * + * @param {string} githubUsername GitHub username. + * + * @return {Promise<boolean>} Promise resolving to whether WordPress profile is + * known. + */ +async function hasWordPressProfile( githubUsername ) { + return new Promise( ( resolve, reject ) => { + const options = { + hostname: BASE_PROFILE_LOOKUP_API_HOSTNAME, + path: BASE_PROFILE_LOOKUP_API_BASE_PATH + githubUsername, + method: 'HEAD', + headers: { + 'User-Agent': 'Gutenberg/project-management-automation', + }, + }; + + request( options, ( res ) => resolve( res.statusCode === 200 ) ) + .on( 'error', ( error ) => reject( error ) ) + .end(); + } ); +} + +module.exports = hasWordPressProfile; diff --git a/packages/project-management-automation/lib/if-not-fork.js b/packages/project-management-automation/lib/if-not-fork.js index 5c8e65adb4d9dd..7ab214026cf8bd 100644 --- a/packages/project-management-automation/lib/if-not-fork.js +++ b/packages/project-management-automation/lib/if-not-fork.js @@ -15,6 +15,7 @@ const debug = require( './debug' ); * @return {WPAutomationTask} Enhanced task. */ function ifNotFork( handler ) { + /** @type {WPAutomationTask} */ const newHandler = ( payload, octokit ) => { if ( payload.pull_request.head.repo.full_name === diff --git a/packages/project-management-automation/lib/index.js b/packages/project-management-automation/lib/index.js index 630bda89440e93..2b280d1d5d5248 100644 --- a/packages/project-management-automation/lib/index.js +++ b/packages/project-management-automation/lib/index.js @@ -8,7 +8,7 @@ const { context, GitHub } = require( '@actions/github' ); * Internal dependencies */ const assignFixedIssues = require( './assign-fixed-issues' ); -const addFirstTimeContributorLabel = require( './add-first-time-contributor-label' ); +const firstTimeContributor = require( './first-time-contributor' ); const addMilestone = require( './add-milestone' ); const debug = require( './debug' ); const ifNotFork = require( './if-not-fork' ); @@ -42,9 +42,8 @@ const automations = [ task: ifNotFork( assignFixedIssues ), }, { - event: 'pull_request', - action: 'opened', - task: ifNotFork( addFirstTimeContributorLabel ), + event: 'push', + task: firstTimeContributor, }, { event: 'push', diff --git a/packages/project-management-automation/lib/test/add-first-time-contributor-label.js b/packages/project-management-automation/lib/test/add-first-time-contributor-label.js deleted file mode 100644 index ac8e5d59f26a0c..00000000000000 --- a/packages/project-management-automation/lib/test/add-first-time-contributor-label.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Internal dependencies - */ -import addFirstTimeContributorLabel from '../add-first-time-contributor-label'; - -describe( 'addFirstTimeContributorLabel', () => { - const payload = { - pull_request: { - user: { - login: 'matt', - }, - number: 123, - }, - repository: { - owner: { - login: 'WordPress', - }, - name: 'gutenberg', - }, - }; - - it( 'does nothing if the user has commits', async () => { - const octokit = { - search: { - commits: jest.fn( () => - Promise.resolve( { - data: { - total_count: 100, - }, - } ) - ), - }, - issues: { - addLabels: jest.fn(), - }, - }; - - await addFirstTimeContributorLabel( payload, octokit ); - - expect( octokit.search.commits ).toHaveBeenCalledWith( { - q: 'repo:WordPress/gutenberg+author:matt', - } ); - expect( octokit.issues.addLabels ).not.toHaveBeenCalled(); - } ); - - it( 'adds the label if the user does not have commits', async () => { - const octokit = { - search: { - commits: jest.fn( () => - Promise.resolve( { - data: { - total_count: 0, - }, - } ) - ), - }, - issues: { - addLabels: jest.fn(), - }, - }; - - await addFirstTimeContributorLabel( payload, octokit ); - - expect( octokit.search.commits ).toHaveBeenCalledWith( { - q: 'repo:WordPress/gutenberg+author:matt', - } ); - expect( octokit.issues.addLabels ).toHaveBeenCalledWith( { - owner: 'WordPress', - repo: 'gutenberg', - issue_number: 123, - labels: [ 'First-time Contributor' ], - } ); - } ); -} ); diff --git a/packages/project-management-automation/lib/test/add-milestone.js b/packages/project-management-automation/lib/test/add-milestone.js index 63f49811f9692e..13ecd80aa9b0a2 100644 --- a/packages/project-management-automation/lib/test/add-milestone.js +++ b/packages/project-management-automation/lib/test/add-milestone.js @@ -63,7 +63,7 @@ describe( 'addMilestone', () => { expect( octokit.issues.get ).toHaveBeenCalledWith( { owner: 'WordPress', repo: 'gutenberg', - issue_number: '123', + issue_number: 123, } ); expect( octokit.issues.createMilestone ).not.toHaveBeenCalled(); expect( octokit.issues.listMilestonesForRepo ).not.toHaveBeenCalled(); @@ -124,7 +124,7 @@ describe( 'addMilestone', () => { expect( octokit.issues.get ).toHaveBeenCalledWith( { owner: 'WordPress', repo: 'gutenberg', - issue_number: '123', + issue_number: 123, } ); expect( octokit.repos.getContents ).toHaveBeenCalledWith( { owner: 'WordPress', @@ -144,7 +144,7 @@ describe( 'addMilestone', () => { expect( octokit.issues.update ).toHaveBeenCalledWith( { owner: 'WordPress', repo: 'gutenberg', - issue_number: '123', + issue_number: 123, milestone: 12, } ); } ); @@ -202,7 +202,7 @@ describe( 'addMilestone', () => { expect( octokit.issues.get ).toHaveBeenCalledWith( { owner: 'WordPress', repo: 'gutenberg', - issue_number: '123', + issue_number: 123, } ); expect( octokit.repos.getContents ).toHaveBeenCalledWith( { owner: 'WordPress', @@ -222,7 +222,7 @@ describe( 'addMilestone', () => { expect( octokit.issues.update ).toHaveBeenCalledWith( { owner: 'WordPress', repo: 'gutenberg', - issue_number: '123', + issue_number: 123, milestone: 12, } ); } ); diff --git a/packages/project-management-automation/lib/test/first-time-contributor.js b/packages/project-management-automation/lib/test/first-time-contributor.js new file mode 100644 index 00000000000000..27a328c2b5948e --- /dev/null +++ b/packages/project-management-automation/lib/test/first-time-contributor.js @@ -0,0 +1,216 @@ +/** + * Internal dependencies + */ +import firstTimeContributor from '../first-time-contributor'; +import hasWordPressProfile from '../has-wordpress-profile'; + +jest.mock( '../has-wordpress-profile', () => jest.fn() ); + +describe( 'firstTimeContributor', () => { + beforeEach( () => { + hasWordPressProfile.mockReset(); + } ); + + const payload = { + ref: 'refs/heads/master', + commits: [ + { + id: '4c535288a6a2b75ff23ee96c75f7d9877e919241', + message: 'Add a feature from pull request (#123)', + author: { + name: 'Ghost', + email: 'ghost@example.invalid', + username: 'ghost', + }, + }, + ], + repository: { + owner: { + login: 'WordPress', + }, + name: 'gutenberg', + }, + }; + + it( 'does nothing if not a commit to master', async () => { + const payloadForBranchPush = { + ...payload, + ref: 'refs/heads/update/chicken-branch', + }; + + const octokit = { + repos: { + listCommits: jest.fn(), + }, + }; + + await firstTimeContributor( payloadForBranchPush, octokit ); + + expect( octokit.repos.listCommits ).not.toHaveBeenCalled(); + } ); + + it( 'does nothing if commit pull request undeterminable', async () => { + const payloadDirectToMaster = { + ...payload, + commits: [ + { + message: 'Add a feature direct to master', + author: { + name: 'Ghost', + email: 'ghost@example.invalid', + username: 'ghost', + }, + }, + ], + }; + + const octokit = { + repos: { + listCommits: jest.fn(), + }, + }; + + await firstTimeContributor( payloadDirectToMaster, octokit ); + + expect( octokit.repos.listCommits ).not.toHaveBeenCalled(); + } ); + + it( 'does nothing if the user has multiple commits', async () => { + const octokit = { + repos: { + listCommits: jest.fn( () => + Promise.resolve( { + data: [ + { sha: '4c535288a6a2b75ff23ee96c75f7d9877e919241' }, + { sha: '59b07cc57adff90630fc9d5cf2317269a0f4f158' }, + ], + } ) + ), + }, + issues: { + addLabels: jest.fn(), + }, + }; + + await firstTimeContributor( payload, octokit ); + + expect( octokit.repos.listCommits ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + author: 'ghost', + } ); + expect( octokit.issues.addLabels ).not.toHaveBeenCalled(); + } ); + + it( 'adds the label if this was the first commit for the user', async () => { + const octokit = { + repos: { + listCommits: jest.fn( () => + Promise.resolve( { + data: [ + { sha: '4c535288a6a2b75ff23ee96c75f7d9877e919241' }, + ], + } ) + ), + }, + issues: { + addLabels: jest.fn(), + createComment: jest.fn(), + }, + }; + + hasWordPressProfile.mockReturnValue( Promise.resolve( true ) ); + + await firstTimeContributor( payload, octokit ); + + expect( octokit.repos.listCommits ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + author: 'ghost', + } ); + expect( octokit.issues.addLabels ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + issue_number: 123, + labels: [ 'First-time Contributor' ], + } ); + expect( octokit.issues.createComment ).not.toHaveBeenCalled(); + } ); + + it( 'aborts if the request to retrieve WordPress.org user profile fails', async () => { + const octokit = { + repos: { + listCommits: jest.fn( () => + Promise.resolve( { + data: [ + { sha: '4c535288a6a2b75ff23ee96c75f7d9877e919241' }, + ], + } ) + ), + }, + issues: { + addLabels: jest.fn(), + createComment: jest.fn(), + }, + }; + + hasWordPressProfile.mockImplementation( () => { + return Promise.reject( new Error( 'Whoops!' ) ); + } ); + + await firstTimeContributor( payload, octokit ); + + expect( octokit.repos.listCommits ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + author: 'ghost', + } ); + expect( octokit.issues.addLabels ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + issue_number: 123, + labels: [ 'First-time Contributor' ], + } ); + expect( octokit.issues.createComment ).not.toHaveBeenCalled(); + } ); + + it( 'prompts the user to link their GitHub account to their WordPress.org profile', async () => { + const octokit = { + repos: { + listCommits: jest.fn( () => + Promise.resolve( { + data: [ + { sha: '4c535288a6a2b75ff23ee96c75f7d9877e919241' }, + ], + } ) + ), + }, + issues: { + addLabels: jest.fn(), + createComment: jest.fn(), + }, + }; + + hasWordPressProfile.mockReturnValue( Promise.resolve( false ) ); + + await firstTimeContributor( payload, octokit ); + + expect( octokit.repos.listCommits ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + author: 'ghost', + } ); + expect( octokit.issues.addLabels ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + issue_number: 123, + labels: [ 'First-time Contributor' ], + } ); + expect( octokit.issues.createComment ).toHaveBeenCalledWith( { + owner: 'WordPress', + repo: 'gutenberg', + issue_number: 123, + body: expect.stringMatching( /^Congratulations/ ), + } ); + } ); +} ); diff --git a/packages/project-management-automation/lib/test/get-associated-pull-request.js b/packages/project-management-automation/lib/test/get-associated-pull-request.js new file mode 100644 index 00000000000000..1e00d636e94e2a --- /dev/null +++ b/packages/project-management-automation/lib/test/get-associated-pull-request.js @@ -0,0 +1,37 @@ +/** + * Internal dependencies + */ +import getAssociatedPullRequest from '../get-associated-pull-request'; + +/** @typedef {import('../get-associated-pull-request').WebhookPayloadPushCommit} WebhookPayloadPushCommit */ + +/** + * An example commit which can be associated with a pull request, e.g. a pull + * request merge commit. + * + * @type {WebhookPayloadPushCommit} + */ +const VALID_COMMIT = { + message: + 'Components: SlotFill: Guard property access to possibly-undefined slot (#21205)', +}; + +/** + * An example commit which cannot be associated with a pull request, e.g. when + * someone commits directly to master. + * + * @type {WebhookPayloadPushCommit} + */ +const INVALID_COMMIT = { + message: 'Add basic placeholder content to post title, content, and date.', +}; + +describe( 'getAssociatedPullRequest', () => { + it( 'should return the pull request number associated with a commit', () => { + expect( getAssociatedPullRequest( VALID_COMMIT ) ).toBe( 21205 ); + } ); + + it( 'should return null if a pull request cannot be determined', () => { + expect( getAssociatedPullRequest( INVALID_COMMIT ) ).toBeNull(); + } ); +} ); diff --git a/packages/project-management-automation/lib/test/has-wordpress-profile.js b/packages/project-management-automation/lib/test/has-wordpress-profile.js new file mode 100644 index 00000000000000..9cb13544a245a1 --- /dev/null +++ b/packages/project-management-automation/lib/test/has-wordpress-profile.js @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import nock from 'nock'; + +/** + * Internal dependencies + */ +import hasWordPressProfile from '../has-wordpress-profile'; + +describe( 'hasWordPressProfile', () => { + it( 'resolves as false for missing profile', async () => { + nock( 'https://profiles.wordpress.org' ) + .intercept( '/wp-json/wporg-github/v1/lookup/ghost', 'HEAD' ) + .reply( 404 ); + + const result = await hasWordPressProfile( 'ghost' ); + + expect( result ).toBe( false ); + } ); + + it( 'resolves as true for known profile', async () => { + nock( 'https://profiles.wordpress.org' ) + .intercept( '/wp-json/wporg-github/v1/lookup/m', 'HEAD' ) + .reply( 200 ); + + const result = await hasWordPressProfile( 'm' ); + + expect( result ).toBe( true ); + } ); +} ); diff --git a/packages/project-management-automation/package.json b/packages/project-management-automation/package.json index 02875d0cfd0ca9..9274e83e5e832f 100644 --- a/packages/project-management-automation/package.json +++ b/packages/project-management-automation/package.json @@ -17,10 +17,11 @@ "url": "https://github.com/WordPress/gutenberg/issues" }, "main": "lib/index.js", + "types": "build-types", "dependencies": { "@actions/core": "^1.0.0", "@actions/github": "^1.0.0", - "@babel/runtime": "^7.8.3" + "@babel/runtime": "^7.9.2" }, "publishConfig": { "access": "public" diff --git a/packages/project-management-automation/tsconfig.json b/packages/project-management-automation/tsconfig.json new file mode 100644 index 00000000000000..395281ecb0e72d --- /dev/null +++ b/packages/project-management-automation/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "lib", + "declarationDir": "build-types", + + // This is required due to a type error coming from missing types in @actions/github + "noImplicitAny": false + }, + "include": [ "lib/**/*" ] +} diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 89db00b09fff9f..103b02fb9b8b1d 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -24,7 +24,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "is-promise": "^2.1.0", "lodash": "^4.17.15", "rungen": "^0.3.2" diff --git a/packages/redux-routine/src/test/index.js b/packages/redux-routine/src/test/index.js index 6c2888e00a7514..b240f8740894f2 100644 --- a/packages/redux-routine/src/test/index.js +++ b/packages/redux-routine/src/test/index.js @@ -60,6 +60,7 @@ describe( 'createMiddleware', () => { try { yield { type: 'WAIT_FAIL' }; } catch ( error ) { + // eslint-disable-next-line jest/no-try-expect expect( error ).toBe( 'Message' ); } } @@ -80,6 +81,7 @@ describe( 'createMiddleware', () => { try { yield { type: 'WAIT_FAIL' }; } catch ( error ) { + // eslint-disable-next-line jest/no-try-expect expect( error.message ).toBe( 'Message' ); } } @@ -106,6 +108,7 @@ describe( 'createMiddleware', () => { try { yield { type: 'WAIT_FAIL' }; } catch ( error ) { + // eslint-disable-next-line jest/no-try-expect expect( error.message ).toBe( 'Message' ); return null; } diff --git a/packages/rich-text/package.json b/packages/rich-text/package.json index 7f904de015969c..9076445f681566 100644 --- a/packages/rich-text/package.json +++ b/packages/rich-text/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", "@wordpress/deprecated": "file:../deprecated", @@ -31,7 +31,7 @@ "@wordpress/keycodes": "file:../keycodes", "classnames": "^2.2.5", "lodash": "^4.17.15", - "memize": "^1.0.5", + "memize": "^1.1.0", "rememo": "^3.0.0" }, "publishConfig": { diff --git a/packages/rich-text/src/component/boundary-style.js b/packages/rich-text/src/component/boundary-style.js index cba9eeaf6b5a3f..3c17da53697041 100644 --- a/packages/rich-text/src/component/boundary-style.js +++ b/packages/rich-text/src/component/boundary-style.js @@ -3,15 +3,6 @@ */ import { useEffect } from '@wordpress/element'; -/** - * Global stylesheet shared by all RichText instances. - */ -const globalStyle = document.createElement( 'style' ); - -const boundarySelector = '*[data-rich-text-format-boundary]'; - -document.head.appendChild( globalStyle ); - /** * Calculates and renders the format boundary style when the active formats * change. @@ -24,19 +15,31 @@ export function BoundaryStyle( { activeFormats, forwardedRef } ) { return; } + const boundarySelector = '*[data-rich-text-format-boundary]'; const element = forwardedRef.current.querySelector( boundarySelector ); if ( ! element ) { return; } - const computedStyle = window.getComputedStyle( element ); + const { ownerDocument } = element; + const { defaultView } = ownerDocument; + const computedStyle = defaultView.getComputedStyle( element ); const newColor = computedStyle.color .replace( ')', ', 0.2)' ) .replace( 'rgb', 'rgba' ); const selector = `.rich-text:focus ${ boundarySelector }`; const rule = `background-color: ${ newColor }`; const style = `${ selector } {${ rule }}`; + const globalStyleId = 'rich-text-boundary-style'; + + let globalStyle = ownerDocument.getElementById( globalStyleId ); + + if ( ! globalStyle ) { + globalStyle = ownerDocument.createElement( 'style' ); + globalStyle.id = globalStyleId; + ownerDocument.head.appendChild( globalStyle ); + } if ( globalStyle.innerHTML !== style ) { globalStyle.innerHTML = style; diff --git a/packages/rich-text/src/component/index.js b/packages/rich-text/src/component/index.js index baa8826f12879e..cd174b2baaabba 100644 --- a/packages/rich-text/src/component/index.js +++ b/packages/rich-text/src/component/index.js @@ -40,12 +40,7 @@ import { isEmptyLine } from '../is-empty'; import withFormatTypes from './with-format-types'; import { BoundaryStyle } from './boundary-style'; import { InlineWarning } from './inline-warning'; - -/** - * Browser dependencies - */ - -const { getSelection, getComputedStyle } = window; +import { insert } from '../insert'; /** @typedef {import('@wordpress/element').WPSyntheticEvent} WPSyntheticEvent */ @@ -113,9 +108,11 @@ function createPrepareEditableTree( props, prefix ) { /** * If the selection is set on the placeholder element, collapse the selection to * the start (before the placeholder). + * + * @param {Window} defaultView */ -function fixPlaceholderSelection() { - const selection = window.getSelection(); +function fixPlaceholderSelection( defaultView ) { + const selection = defaultView.getSelection(); const { anchorNode, anchorOffset } = selection; if ( anchorNode.nodeType !== anchorNode.ELEMENT_NODE ) { @@ -142,6 +139,8 @@ class RichText extends Component { constructor( { value, selectionStart, selectionEnd } ) { super( ...arguments ); + this.getDocument = this.getDocument.bind( this ); + this.getWindow = this.getWindow.bind( this ); this.onFocus = this.onFocus.bind( this ); this.onBlur = this.onBlur.bind( this ); this.onChange = this.onChange.bind( this ); @@ -186,24 +185,32 @@ class RichText extends Component { } componentWillUnmount() { - document.removeEventListener( + this.getDocument().removeEventListener( 'selectionchange', this.onSelectionChange ); - window.cancelAnimationFrame( this.rafId ); + this.getWindow().cancelAnimationFrame( this.rafId ); } componentDidMount() { this.applyRecord( this.record, { domOnly: true } ); } + getDocument() { + return this.props.forwardedRef.current.ownerDocument; + } + + getWindow() { + return this.getDocument().defaultView; + } + createRecord() { const { __unstableMultilineTag: multilineTag, forwardedRef, preserveWhiteSpace, } = this.props; - const selection = getSelection(); + const selection = this.getWindow().getSelection(); const range = selection.rangeCount > 0 ? selection.getRangeAt( 0 ) : null; @@ -251,6 +258,7 @@ class RichText extends Component { formatTypes, onPaste, __unstableIsSelected: isSelected, + __unstableDisableFormats, } = this.props; const { activeFormats = [] } = this.state; @@ -293,6 +301,11 @@ class RichText extends Component { window.console.log( 'Received HTML:\n\n', html ); window.console.log( 'Received plain text:\n\n', plainText ); + if ( __unstableDisableFormats ) { + this.onChange( insert( this.record, plainText ) ); + return; + } + const record = this.record; const transformed = formatTypes.reduce( ( accumlator, { __unstablePasteRule } ) => { @@ -401,9 +414,14 @@ class RichText extends Component { // frame. The event listener for selection changes may be added too late // at this point, but this focus event is still too early to calculate // the selection. - this.rafId = window.requestAnimationFrame( this.onSelectionChange ); + this.rafId = this.getWindow().requestAnimationFrame( + this.onSelectionChange + ); - document.addEventListener( 'selectionchange', this.onSelectionChange ); + this.getDocument().addEventListener( + 'selectionchange', + this.onSelectionChange + ); if ( this.props.setFocusedElement ) { deprecated( 'wp.blockEditor.RichText setFocusedElement prop', { @@ -414,7 +432,7 @@ class RichText extends Component { } onBlur() { - document.removeEventListener( + this.getDocument().removeEventListener( 'selectionchange', this.onSelectionChange ); @@ -514,7 +532,7 @@ class RichText extends Component { // Do not update the selection when characters are being composed as // this rerenders the component and might distroy internal browser // editing state. - document.removeEventListener( + this.getDocument().removeEventListener( 'selectionchange', this.onSelectionChange ); @@ -526,7 +544,10 @@ class RichText extends Component { // input event after composition. this.onInput( { inputType: 'insertText' } ); // Tracking selection changes can be resumed. - document.addEventListener( 'selectionchange', this.onSelectionChange ); + this.getDocument().addEventListener( + 'selectionchange', + this.onSelectionChange + ); } /** @@ -569,7 +590,7 @@ class RichText extends Component { // element, in which case the caret is not visible. We need to set // the caret before the placeholder if that's the case. if ( value.text.length === 0 && start === 0 ) { - fixPlaceholderSelection(); + fixPlaceholderSelection( this.getWindow() ); } return; @@ -830,7 +851,7 @@ class RichText extends Component { const { text, formats, start, end, activeFormats = [] } = value; const collapsed = isCollapsed( value ); // To do: ideally, we should look at visual position instead. - const { direction } = getComputedStyle( + const { direction } = this.getWindow().getComputedStyle( this.props.forwardedRef.current ); const reverseKey = direction === 'rtl' ? RIGHT : LEFT; @@ -933,8 +954,8 @@ class RichText extends Component { const { parentNode } = target; const index = Array.from( parentNode.childNodes ).indexOf( target ); - const range = target.ownerDocument.createRange(); - const selection = getSelection(); + const range = this.getDocument().createRange(); + const selection = this.getWindow().getSelection(); range.setStart( target.parentNode, index ); range.setEnd( target.parentNode, index + 1 ); diff --git a/packages/rich-text/src/component/inline-warning.js b/packages/rich-text/src/component/inline-warning.js index d74858dd912b66..00598b4d7c544d 100644 --- a/packages/rich-text/src/component/inline-warning.js +++ b/packages/rich-text/src/component/inline-warning.js @@ -6,9 +6,9 @@ import { useEffect } from '@wordpress/element'; export function InlineWarning( { forwardedRef } ) { useEffect( () => { if ( process.env.NODE_ENV === 'development' ) { - const computedStyle = window.getComputedStyle( - forwardedRef.current - ); + const target = forwardedRef.current; + const { defaultView } = target.ownerDocument; + const computedStyle = defaultView.getComputedStyle( target ); if ( computedStyle.display === 'inline' ) { // eslint-disable-next-line no-console diff --git a/packages/rich-text/src/create.js b/packages/rich-text/src/create.js index ca25ef8e09be10..89c8d298da6865 100644 --- a/packages/rich-text/src/create.js +++ b/packages/rich-text/src/create.js @@ -16,12 +16,6 @@ import { ZWNBSP, } from './special-characters'; -/** - * Browser dependencies - */ - -const { TEXT_NODE, ELEMENT_NODE } = window.Node; - function createEmptyValue() { return { formats: [], @@ -160,6 +154,8 @@ export function create( { } if ( typeof html === 'string' && html.length > 0 ) { + // It does not matter which document this is, we're just using it to + // parse. element = createElement( document, html ); } @@ -208,7 +204,7 @@ function accumulateSelection( accumulator, node, range, value ) { if ( value.start !== undefined ) { accumulator.start = currentLength + value.start; // Range indicates that the current node has selection. - } else if ( node === startContainer && node.nodeType === TEXT_NODE ) { + } else if ( node === startContainer && node.nodeType === node.TEXT_NODE ) { accumulator.start = currentLength + startOffset; // Range indicates that the current node is selected. } else if ( @@ -231,7 +227,7 @@ function accumulateSelection( accumulator, node, range, value ) { if ( value.end !== undefined ) { accumulator.end = currentLength + value.end; // Range indicates that the current node has selection. - } else if ( node === endContainer && node.nodeType === TEXT_NODE ) { + } else if ( node === endContainer && node.nodeType === node.TEXT_NODE ) { accumulator.end = currentLength + endOffset; // Range indicates that the current node is selected. } else if ( @@ -342,7 +338,7 @@ function createFromElement( { const node = element.childNodes[ index ]; const type = node.nodeName.toLowerCase(); - if ( node.nodeType === TEXT_NODE ) { + if ( node.nodeType === node.TEXT_NODE ) { let filter = removePadding; if ( ! preserveWhiteSpace ) { @@ -361,7 +357,7 @@ function createFromElement( { continue; } - if ( node.nodeType !== ELEMENT_NODE ) { + if ( node.nodeType !== node.ELEMENT_NODE ) { continue; } diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index 0a63e94a95e3ab..a0d57617a0d0b3 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -5,12 +5,6 @@ import { toTree } from './to-tree'; import { createElement } from './create-element'; -/** - * Browser dependencies - */ - -const { TEXT_NODE } = window.Node; - /** * Creates a path as an array of indices from the given root node to the given * node. @@ -59,18 +53,6 @@ function getNodeByPath( node, path ) { }; } -/** - * Returns a new instance of a DOM tree upon which RichText operations can be - * applied. - * - * Note: The current implementation will return a shared reference, reset on - * each call to `createEmpty`. Therefore, you should not hold a reference to - * the value to operate upon asynchronously, as it may have unexpected results. - * - * @return {Object} RichText tree. - */ -const createEmpty = () => createElement( document, '' ); - function append( element, child ) { if ( typeof child === 'string' ) { child = element.ownerDocument.createTextNode( child ); @@ -101,8 +83,8 @@ function getParent( { parentNode } ) { return parentNode; } -function isText( { nodeType } ) { - return nodeType === TEXT_NODE; +function isText( node ) { + return node.nodeType === node.TEXT_NODE; } function getText( { nodeValue } ) { @@ -119,6 +101,7 @@ export function toDom( { prepareEditableTree, isEditableTree = true, placeholder, + doc = document, } ) { let startPath = []; let endPath = []; @@ -130,6 +113,18 @@ export function toDom( { }; } + /** + * Returns a new instance of a DOM tree upon which RichText operations can be + * applied. + * + * Note: The current implementation will return a shared reference, reset on + * each call to `createEmpty`. Therefore, you should not hold a reference to + * the value to operate upon asynchronously, as it may have unexpected results. + * + * @return {Object} RichText tree. + */ + const createEmpty = () => createElement( doc, '' ); + const tree = toTree( { value, multilineTag, @@ -186,6 +181,7 @@ export function apply( { multilineTag, prepareEditableTree, placeholder, + doc: current.ownerDocument, } ); applyValue( body, current ); @@ -207,7 +203,7 @@ export function applyValue( future, current ) { } else if ( ! currentChild.isEqualNode( futureChild ) ) { if ( currentChild.nodeName !== futureChild.nodeName || - ( currentChild.nodeType === TEXT_NODE && + ( currentChild.nodeType === currentChild.TEXT_NODE && currentChild.data !== futureChild.data ) ) { current.replaceChild( futureChild, currentChild ); @@ -282,8 +278,9 @@ export function applySelection( { startPath, endPath }, current ) { current, endPath ); - const selection = window.getSelection(); const { ownerDocument } = current; + const { defaultView } = ownerDocument; + const selection = defaultView.getSelection(); const range = ownerDocument.createRange(); range.setStart( startContainer, startOffset ); @@ -305,21 +302,15 @@ export function applySelection( { startPath, endPath }, current ) { // This function is not intended to cause a shift in focus. Since the above // selection manipulations may shift focus, ensure that focus is restored to - // its previous state. `activeElement` can be `null` or the body element if - // there is no focus, which is accounted for here in the explicit `blur` to - // restore to a state of non-focus. - if ( activeElement !== document.activeElement ) { + // its previous state. + if ( activeElement !== ownerDocument.activeElement ) { // The `instanceof` checks protect against edge cases where the focused // element is not of the interface HTMLElement (does not have a `focus` // or `blur` property). // // See: https://github.com/Microsoft/TypeScript/issues/5901#issuecomment-431649653 - if ( activeElement ) { - if ( activeElement instanceof window.HTMLElement ) { - activeElement.focus(); - } - } else if ( document.activeElement instanceof window.HTMLElement ) { - document.activeElement.blur(); + if ( activeElement instanceof defaultView.HTMLElement ) { + activeElement.focus(); } } } diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 7e23dee6250e96..116fbd380b0b50 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -1,11 +1,14 @@ ## Master -## 7.2.0 (2020-04-01) +### Breaking Changes + +- The bundled `jest` dependency has been updated from requiring `^24.9.0` to requiring `^25.3.0` (see [Breaking Changes](https://jestjs.io/blog/2020/01/21/jest-25), [#20766](https://github.com/WordPress/gutenberg/pull/20766)). ### Enhancements - Incompatibility between `@svgr/webpack` in version `4.3.3` and `url-loader` in version `3.0.0` was fixed by bumping `@svgr/webpack` to `^5.2.0`. - All webpack dependencies got minor version update if applicable. +- The bundled `eslint` dependency has been updated from requiring `^6.1.0` to requiring `^6.8.0` ([#21424](https://github.com/WordPress/gutenberg/pull/21424)). ### Internal diff --git a/packages/scripts/README.md b/packages/scripts/README.md index 42df6dd14a78d8..3c49a764787ed6 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -50,7 +50,7 @@ It might also be a good idea to get familiar with the [JavaScript Build Setup tu To update an existing project to a new version of `@wordpress/scripts`, open the [changelog](https://github.com/WordPress/gutenberg/blob/master/packages/scripts/CHANGELOG.md), find the version you’re currently on (check `package.json` in the top-level directory of your project), and apply the migration instructions for the newer versions. -In most cases bumping the `@wordpress/scripts` version in `package.json` and running `npm install` in the root folder of your project should be enough, but it’s good to check the [changelog](https://github.com/WordPress/gutenberg/blob/master/packages/scripts/CHANGELOG.md) for potential breaking changes. There is also `update-packages` script included in this package that aims to automate the process of updating WordPress dependencies in your projects. +In most cases bumping the `@wordpress/scripts` version in `package.json` and running `npm install` in the root folder of your project should be enough, but it’s good to check the [changelog](https://github.com/WordPress/gutenberg/blob/master/packages/scripts/CHANGELOG.md) for potential breaking changes. There is also `packages-update` script included in this package that aims to automate the process of updating WordPress dependencies in your projects. We commit to keeping the breaking changes minimal so you can upgrade `@wordpress/scripts` as seamless as possible. diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 2c8de002300e87..5d96b7f93d079e 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -40,18 +40,19 @@ "@wordpress/jest-preset-default": "file:../jest-preset-default", "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", "@wordpress/prettier-config": "file:../prettier-config", - "babel-jest": "^24.9.0", - "babel-loader": "^8.0.6", - "chalk": "^2.4.2", + "babel-jest": "^25.3.0", + "babel-loader": "^8.1.0", + "chalk": "^4.0.0", "check-node-version": "^3.1.1", "command-exists": "^1.2.8", "cross-spawn": "^5.1.0", "decompress-zip": "^0.2.2", "dir-glob": "^3.0.1", - "eslint": "^6.1.0", - "eslint-plugin-markdown": "1.0.1", - "jest": "^24.9.0", - "jest-puppeteer": "^4.3.0", + "eslint": "^6.8.0", + "eslint-plugin-markdown": "^1.0.2", + "got": "^10.7.0", + "jest": "^25.3.0", + "jest-puppeteer": "^4.4.0", "js-yaml": "^3.13.1", "lodash": "^4.17.15", "markdownlint": "^0.18.0", @@ -61,7 +62,6 @@ "prettier": "npm:wp-prettier@1.19.1", "puppeteer": "^2.0.0", "read-pkg-up": "^1.0.1", - "request": "^2.88.0", "resolve-bin": "^0.4.0", "source-map-loader": "^0.2.4", "sprintf-js": "^1.1.1", diff --git a/packages/scripts/scripts/format-js.js b/packages/scripts/scripts/format-js.js index 5210d114b26a75..29b2a78ab1fb9f 100644 --- a/packages/scripts/scripts/format-js.js +++ b/packages/scripts/scripts/format-js.js @@ -101,7 +101,7 @@ if ( fileArgs.length === 0 ) { } // Converts `foo/bar` directory to `foo/bar/**/*.js` -const globArgs = dirGlob( fileArgs, { extensions: [ 'js' ] } ); +const globArgs = dirGlob( fileArgs, { extensions: [ 'js', 'jsx' ] } ); const result = spawn( resolveBin( 'prettier' ), diff --git a/packages/scripts/utils/env.js b/packages/scripts/utils/env.js index 372ef3479192dc..41fc7fc9932859 100644 --- a/packages/scripts/utils/env.js +++ b/packages/scripts/utils/env.js @@ -2,7 +2,7 @@ * External dependencies */ const { isPlainObject } = require( 'lodash' ); -const request = require( 'request' ); +const got = require( 'got' ); const DecompressZip = require( 'decompress-zip' ); const chalk = require( 'chalk' ); const { sprintf } = require( 'sprintf-js' ); @@ -95,10 +95,9 @@ function downloadWordPressZip() { stdout.write( 'Downloading...\n' ); // Download the archive. - request - .get( - 'https://github.com/WordPress/wordpress-develop/archive/master.zip' - ) + got.stream( + 'https://github.com/WordPress/wordpress-develop/archive/master.zip' + ) .on( 'error', ( error ) => { stdout.write( "ERROR: The zip file couldn't be downloaded.\n" ); stdout.write( error.toString() ); @@ -176,7 +175,7 @@ function buildWordPress( newInstall, fastInstall ) { if ( env.npm_package_wp_env_welcome_build_command ) { const nextStep = sprintf( - '\nRun %s to build the latest version of %s, then open %s to get started!\n', + '\nRun %1$s to build the latest version of %2$s, then open %3$s to get started!\n', chalk.blue( env.npm_package_wp_env_welcome_build_command ), chalk.green( env.npm_package_wp_env_plugin_name ), chalk.blue( currentUrl ) @@ -191,7 +190,7 @@ function buildWordPress( newInstall, fastInstall ) { ); const access = sprintf( - 'Default username: %s, password: %s\n', + 'Default username: %1$s, password: %2$s\n', chalk.blue( 'admin' ), chalk.blue( 'password' ) ); diff --git a/packages/server-side-render/README.md b/packages/server-side-render/README.md index dcd3d6b2bc5906..b9baee0f813b0a 100644 --- a/packages/server-side-render/README.md +++ b/packages/server-side-render/README.md @@ -81,6 +81,21 @@ Render core/archives preview. ```jsx import ServerSideRender from '@wordpress/server-side-render'; +const MyServerSideRender = () => ( + <ServerSideRender + block="core/archives" + attributes={ { + showPostCounts: true, + displayAsDropdown: false, + } } + /> +); +``` +If imported from the `wp` global, an alias is required to work in JSX. + +```jsx +const { serverSideRender: ServerSideRender } = wp; + const MyServerSideRender = () => ( <ServerSideRender block="core/archives" diff --git a/packages/server-side-render/package.json b/packages/server-side-render/package.json index b877517aa5d853..fa303e97fe3723 100644 --- a/packages/server-side-render/package.json +++ b/packages/server-side-render/package.json @@ -22,7 +22,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/components": "file:../components", "@wordpress/data": "file:../data", diff --git a/packages/server-side-render/src/server-side-render.js b/packages/server-side-render/src/server-side-render.js index 8e2f93446095d4..f428adf8f4495b 100644 --- a/packages/server-side-render/src/server-side-render.js +++ b/packages/server-side-render/src/server-side-render.js @@ -131,8 +131,8 @@ ServerSideRender.defaultProps = { </Placeholder> ), ErrorResponsePlaceholder: ( { response, className } ) => { - // translators: %s: error message describing the problem const errorMessage = sprintf( + // translators: %s: error message describing the problem __( 'Error loading block: %s' ), response.errorMsg ); diff --git a/packages/shortcode/package.json b/packages/shortcode/package.json index ed8ce524c2f45a..1a02c9bcb59e57 100644 --- a/packages/shortcode/package.json +++ b/packages/shortcode/package.json @@ -21,9 +21,9 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15", - "memize": "^1.0.5" + "memize": "^1.1.0" }, "publishConfig": { "access": "public" diff --git a/packages/token-list/CHANGELOG.md b/packages/token-list/CHANGELOG.md index 4f09e8ebd8395f..48bb8d17224648 100644 --- a/packages/token-list/CHANGELOG.md +++ b/packages/token-list/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 1.1.0 (2018-11-20) ### Enhancements diff --git a/packages/token-list/package.json b/packages/token-list/package.json index 2e7947df9e8f59..7669e55cefa0ce 100644 --- a/packages/token-list/package.json +++ b/packages/token-list/package.json @@ -19,8 +19,9 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15" }, "publishConfig": { diff --git a/packages/token-list/src/index.js b/packages/token-list/src/index.js index 08f63abfa26128..41f84b47fcc926 100644 --- a/packages/token-list/src/index.js +++ b/packages/token-list/src/index.js @@ -17,11 +17,49 @@ export default class TokenList { constructor( initialValue = '' ) { this.value = initialValue; - [ 'entries', 'forEach', 'keys', 'values' ].forEach( ( fn ) => { - this[ fn ] = ( ...args ) => this._valueAsArray[ fn ]( ...args ); - } ); + // Disable reason: These are type hints on the class. + /* eslint-disable no-unused-expressions */ + /** @type {string} */ + this._currentValue; + + /** @type {string[]} */ + this._valueAsArray; + /* eslint-enable no-unused-expressions */ } + // Disable reason: JSDoc lint doesn't understand TypeScript types + /* eslint-disable jsdoc/valid-types */ + + /** + * @param {Parameters<Array<string>['entries']>} args + */ + entries( ...args ) { + return this._valueAsArray.entries( ...args ); + } + + /** + * @param {Parameters<Array<string>['forEach']>} args + */ + forEach( ...args ) { + return this._valueAsArray.forEach( ...args ); + } + + /** + * @param {Parameters<Array<string>['keys']>} args + */ + keys( ...args ) { + return this._valueAsArray.keys( ...args ); + } + + /** + * @param {Parameters<Array<string>['values']>} args + */ + values( ...args ) { + return this._valueAsArray.values( ...args ); + } + + /* eslint-enable jsdoc/valid-types */ + /** * Returns the associated set as string. * diff --git a/packages/token-list/tsconfig.json b/packages/token-list/tsconfig.json new file mode 100644 index 00000000000000..e22ff86abb6f2d --- /dev/null +++ b/packages/token-list/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index 2068d14751ba48..bf543a62422845 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -1,6 +1,8 @@ ## Master -## 2.12.0 (2020-04-01) +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) ### Bug Fixes diff --git a/packages/url/package.json b/packages/url/package.json index 5f626ec93cfe33..0c599ec4e63648 100644 --- a/packages/url/package.json +++ b/packages/url/package.json @@ -20,9 +20,10 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15", "qs": "^6.5.2", "react-native-url-polyfill": "^1.1.2" diff --git a/packages/url/src/get-query-arg.js b/packages/url/src/get-query-arg.js index 38330aed3ac458..f6e184f0798ce3 100644 --- a/packages/url/src/get-query-arg.js +++ b/packages/url/src/get-query-arg.js @@ -3,9 +3,11 @@ */ import { parse } from 'qs'; +/* eslint-disable jsdoc/valid-types */ /** * @typedef {{[key: string]: QueryArgParsed}} QueryArgObject */ +/* eslint-enable */ /** * @typedef {string|string[]|QueryArgObject} QueryArgParsed diff --git a/packages/url/src/is-url.native.js b/packages/url/src/is-url.native.js index 9a8048a00fa56e..d3b5cd5dd23d0d 100644 --- a/packages/url/src/is-url.native.js +++ b/packages/url/src/is-url.native.js @@ -3,9 +3,11 @@ */ import { URL } from 'react-native-url-polyfill'; +/* eslint-disable jsdoc/valid-types */ /** * @type {typeof import('./is-url').isURL} */ +/* eslint-enable */ export function isURL( url ) { // A URL can be considered value if the `URL` constructor is able to parse // it. The constructor throws an error for an invalid URL. diff --git a/packages/url/tsconfig.json b/packages/url/tsconfig.json new file mode 100644 index 00000000000000..70efdfe49990d5 --- /dev/null +++ b/packages/url/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + + // This is required because the `react-native-url-polyfill` dependency lacks types + "noImplicitAny": false + }, + "include": [ "src/**/*" ] +} diff --git a/packages/viewport/package.json b/packages/viewport/package.json index 4107750d51c6a9..6d96bcd385b3d1 100644 --- a/packages/viewport/package.json +++ b/packages/viewport/package.json @@ -21,7 +21,7 @@ "module": "build-module/index.js", "react-native": "src/index", "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", "lodash": "^4.17.15" diff --git a/packages/warning/CHANGELOG.md b/packages/warning/CHANGELOG.md index 15517d8f1ce7c7..e6a9454a3e0ff7 100644 --- a/packages/warning/CHANGELOG.md +++ b/packages/warning/CHANGELOG.md @@ -1,5 +1,9 @@ ## Master +### New feature + +- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942)) + ## 1.0.0 (2020-02-04) Initial release. diff --git a/packages/warning/package.json b/packages/warning/package.json index fd94779db9e83b..ebe83bb4221e6d 100644 --- a/packages/warning/package.json +++ b/packages/warning/package.json @@ -20,6 +20,7 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "publishConfig": { "access": "public" diff --git a/packages/warning/tsconfig.json b/packages/warning/tsconfig.json new file mode 100644 index 00000000000000..3c2c31f506f132 --- /dev/null +++ b/packages/warning/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types" + }, + "include": [ "src/**/*" ] +} diff --git a/packages/wordcount/package.json b/packages/wordcount/package.json index 1b7dbcbf5bcb46..352ca7fe023af0 100644 --- a/packages/wordcount/package.json +++ b/packages/wordcount/package.json @@ -22,7 +22,7 @@ "react-native": "src/index", "sideEffects": false, "dependencies": { - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.9.2", "lodash": "^4.17.15" }, "publishConfig": { diff --git a/phpunit/class-register-block-type-from-metadata-test.php b/phpunit/class-register-block-type-from-metadata-test.php new file mode 100644 index 00000000000000..e039c078d01640 --- /dev/null +++ b/phpunit/class-register-block-type-from-metadata-test.php @@ -0,0 +1,45 @@ +<?php +/** + * Test `register_block_type_from_metadata`. + * + * @package Gutenberg + */ + +class Register_Block_Type_From_Metadata_Test extends WP_UnitTestCase { + /** + * Tests that the function returns false when the `block.json` is not found + * in the WordPress core. + */ + function test_metadata_not_found_in_wordpress_core() { + $result = register_block_type_from_metadata( 'unknown' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that the function returns false when the `block.json` is not found + * in the current directory. + */ + function test_metadata_not_found_in_the_current_directory() { + $result = register_block_type_from_metadata( __DIR__ ); + + $this->assertFalse( $result ); + } + + /** + * Tests that the function returns the registered block when the `block.json` + * is found in the fixtures directory. + */ + function test_block_registers_with_metadata_fixture() { + $result = register_block_type_from_metadata( + __DIR__ . '/fixtures', + array( + 'foo' => 'bar', + ) + ); + + $this->assertInstanceOf( 'WP_Block_Type', $result ); + $this->assertEquals( 'test/block-name', $result->name ); + $this->assertEquals( 'bar', $result->foo ); + } +} diff --git a/phpunit/fixtures/block.json b/phpunit/fixtures/block.json new file mode 100644 index 00000000000000..3da9b88d722a27 --- /dev/null +++ b/phpunit/fixtures/block.json @@ -0,0 +1,4 @@ +{ + "name": "test/block-name", + "category": "widgets" +} diff --git a/readme.txt b/readme.txt index 44d97cf9af7f1e..4e327cd97efc46 100644 --- a/readme.txt +++ b/readme.txt @@ -1,7 +1,7 @@ === Gutenberg === Contributors: matveb, joen, karmatosed Requires at least: 5.3.0 -Tested up to: 5.3 +Tested up to: 5.4 Stable tag: V.V.V License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -52,4 +52,4 @@ The four phases of the project are Editing, Customization, Collaboration, and Mu == Changelog == -To read the changelog for Gutenberg 7.8.1, please navigate to the <a href="https://github.com/WordPress/gutenberg/releases/tag/v7.8.1">release page</a>. +To read the changelog for Gutenberg 7.9.0-rc.1, please navigate to the <a href="https://github.com/WordPress/gutenberg/releases/tag/v7.9.0-rc.1">release page</a>. diff --git a/storybook/test/__snapshots__/index.js.snap b/storybook/test/__snapshots__/index.js.snap index 8dd430f9d2f795..8b70d1608b401a 100644 --- a/storybook/test/__snapshots__/index.js.snap +++ b/storybook/test/__snapshots__/index.js.snap @@ -1,5 +1,44 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Storyshots Components/AnglePickerControl Default 1`] = ` +<div + className="components-base-control components-angle-picker-control" +> + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="components-angle-picker-control__input-0" + > + Angle + </label> + <div + aria-hidden="true" + className="components-angle-picker-control__angle-circle" + onMouseDown={[Function]} + > + <div + className="components-angle-picker-control__angle-circle-indicator-wrapper" + > + <span + className="components-angle-picker-control__angle-circle-indicator" + /> + </div> + </div> + <input + className="components-angle-picker-control__input-field" + id="components-angle-picker-control__input-0" + max={360} + min={0} + onChange={[Function]} + step="1" + type="number" + /> + </div> +</div> +`; + exports[`Storyshots Components/Animate Appear Bottom Left 1`] = ` <div className="components-animate__appear is-from-left is-from-bottom components-notice is-success is-dismissible" @@ -20,8 +59,8 @@ exports[`Storyshots Components/Animate Appear Bottom Left 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -56,8 +95,8 @@ exports[`Storyshots Components/Animate Appear Bottom Right 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -92,8 +131,8 @@ exports[`Storyshots Components/Animate Appear Top Left 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -128,8 +167,8 @@ exports[`Storyshots Components/Animate Appear Top Right 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -162,8 +201,8 @@ exports[`Storyshots Components/Animate Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -196,8 +235,8 @@ exports[`Storyshots Components/Animate Loading 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -230,8 +269,8 @@ exports[`Storyshots Components/Animate Slide In 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -315,8 +354,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -333,8 +372,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -351,8 +390,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -369,8 +408,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -387,8 +426,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -437,8 +476,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -455,8 +494,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -473,8 +512,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -491,8 +530,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -509,8 +548,8 @@ exports[`Storyshots Components/Button Buttons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -574,9 +613,9 @@ exports[`Storyshots Components/Button Disabled Focusable Icon 1`] = ` type="button" > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-ellipsis" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -620,8 +659,8 @@ exports[`Storyshots Components/Button Grouped Icons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -645,8 +684,8 @@ exports[`Storyshots Components/Button Grouped Icons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -670,8 +709,8 @@ exports[`Storyshots Components/Button Grouped Icons 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -699,9 +738,9 @@ exports[`Storyshots Components/Button Icon 1`] = ` type="button" > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-ellipsis" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -829,19 +868,19 @@ exports[`Storyshots Components/Card Default 1`] = ` } .emotion-0.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-0.is-borderless { @@ -857,15 +896,15 @@ exports[`Storyshots Components/Card Default 1`] = ` } .emotion-2.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-2.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-2.is-size-small { - padding: 12px; + padding: 16px; } .emotion-2.is-size-extraSmall { @@ -888,19 +927,19 @@ exports[`Storyshots Components/Card Default 1`] = ` } .emotion-4.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-4.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-4.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-4.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-4.is-borderless { @@ -958,15 +997,15 @@ exports[`Storyshots Components/Card/Body Default 1`] = ` } .emotion-0.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { @@ -1014,15 +1053,15 @@ exports[`Storyshots Components/Card/Divider Default 1`] = ` } .emotion-0.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { @@ -1095,19 +1134,19 @@ exports[`Storyshots Components/Card/Footer Default 1`] = ` } .emotion-0.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-0.is-borderless { @@ -1162,19 +1201,19 @@ exports[`Storyshots Components/Card/Header Default 1`] = ` } .emotion-0.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-0.is-borderless { @@ -1222,15 +1261,15 @@ exports[`Storyshots Components/Card/Media Default 1`] = ` } .emotion-2.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-2.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-2.is-size-small { - padding: 12px; + padding: 16px; } .emotion-2.is-size-extraSmall { @@ -1316,19 +1355,19 @@ exports[`Storyshots Components/Card/Media Header And Footer 1`] = ` } .emotion-0.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-0.is-borderless { @@ -1351,19 +1390,19 @@ exports[`Storyshots Components/Card/Media Header And Footer 1`] = ` } .emotion-4.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-4.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-4.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-4.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-4.is-borderless { @@ -1498,15 +1537,15 @@ Array [ } .emotion-4.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-4.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-4.is-size-small { - padding: 12px; + padding: 16px; } .emotion-4.is-size-extraSmall { @@ -1570,19 +1609,19 @@ exports[`Storyshots Components/Card/Media Iframe Embed 1`] = ` } .emotion-0.is-size-large { - padding: 20px 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 12px 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 8px 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { - padding: 4px 8px; + padding: 8px; } .emotion-0.is-borderless { @@ -1666,15 +1705,15 @@ exports[`Storyshots Components/Card/Media On Bottom 1`] = ` } .emotion-0.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-0.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-0.is-size-small { - padding: 12px; + padding: 16px; } .emotion-0.is-size-extraSmall { @@ -1753,15 +1792,15 @@ exports[`Storyshots Components/Card/Media On Top 1`] = ` } .emotion-2.is-size-large { - padding: 28px; + padding: 24px 32px; } .emotion-2.is-size-medium { - padding: 20px; + padding: 16px 24px; } .emotion-2.is-size-small { - padding: 12px; + padding: 16px; } .emotion-2.is-size-extraSmall { @@ -1847,9 +1886,9 @@ exports[`Storyshots Components/CheckboxControl All 1`] = ` value="1" /> <svg - aria-hidden="true" + aria-hidden={true} className="components-checkbox-control__checked" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -1896,9 +1935,9 @@ exports[`Storyshots Components/CheckboxControl Default 1`] = ` value="1" /> <svg - aria-hidden="true" + aria-hidden={true} className="components-checkbox-control__checked" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2330,8 +2369,8 @@ exports[`Storyshots Components/ColorPicker Alpha Enabled 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2504,8 +2543,8 @@ exports[`Storyshots Components/ColorPicker Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2545,9 +2584,9 @@ exports[`Storyshots Components/CustomSelectControl Default 1`] = ` type="button" > <svg - aria-hidden="true" + aria-hidden={true} className="components-custom-select-control__button-icon" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2574,10 +2613,10 @@ exports[`Storyshots Components/CustomSelectControl Default 1`] = ` exports[`Storyshots Components/Dashicon Default 1`] = ` <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-wordpress" color="#0079AA" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -2590,6 +2629,95 @@ exports[`Storyshots Components/Dashicon Default 1`] = ` </svg> `; +exports[`Storyshots Components/Disabled Default 1`] = ` +<div + className="components-disabled" +> + <div + className="components-base-control" + > + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="inspector-text-control-2" + > + Text Control + </label> + <input + className="components-text-control__input" + id="inspector-text-control-2" + onChange={[Function]} + type="text" + /> + </div> + </div> + <div + className="components-base-control" + > + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="inspector-textarea-control-0" + > + TextArea Control + </label> + <textarea + className="components-textarea-control__input" + id="inspector-textarea-control-0" + onChange={[Function]} + rows={4} + /> + </div> + </div> + <div + className="components-base-control" + > + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="inspector-select-control-0" + > + Select Control + </label> + <select + className="components-select-control__input" + id="inspector-select-control-0" + multiple={false} + onChange={[Function]} + > + <option + disabled={true} + value={null} + > + Select an option + </option> + <option + value="a" + > + Option A + </option> + <option + value="b" + > + Option B + </option> + <option + value="c" + > + Option C + </option> + </select> + </div> + </div> +</div> +`; + exports[`Storyshots Components/Draggable Default 1`] = ` <div> <p> @@ -2620,8 +2748,8 @@ exports[`Storyshots Components/Draggable Default 1`] = ` } > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2661,8 +2789,8 @@ Array [ type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2696,8 +2824,8 @@ Array [ type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -2714,350 +2842,47 @@ Array [ ] `; -exports[`Storyshots Components/Experimental/Text Body 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 16px; - line-height: 24px; -} - -<p - className="emotion-0 emotion-1" -> - Body -</p> -`; - -exports[`Storyshots Components/Experimental/Text Body Small 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 14px; - line-height: 20px; -} - -<p - className="emotion-0 emotion-1" -> - Body Small -</p> -`; - -exports[`Storyshots Components/Experimental/Text Button 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 20px; -} - -<p - className="emotion-0 emotion-1" -> - Button -</p> -`; - -exports[`Storyshots Components/Experimental/Text Caption 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 12px; - line-height: 16px; -} - -<p - className="emotion-0 emotion-1" +exports[`Storyshots Components/ExternalLink Default 1`] = ` +<a + className="components-external-link" + href="https://wordpress.org" + rel="external noreferrer noopener" + target="_blank" > - Caption -</p> -`; - -exports[`Storyshots Components/Experimental/Text Default 1`] = ` -Array [ - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 32px; - line-height: 40px; -} - -<h1 - className="emotion-0 emotion-1" + WordPress + <span + className="components-visually-hidden" > - Title Large - </h1>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 24px; - line-height: 32px; -} - -<h2 - className="emotion-0 emotion-1" + (opens in a new tab) + </span> + <svg + aria-hidden={true} + className="components-external-link__icon" + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" > - Title Medium - </h2>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 20px; - line-height: 28px; -} + <path + d="M18.2 17c0 .7-.6 1.2-1.2 1.2H7c-.7 0-1.2-.6-1.2-1.2V7c0-.7.6-1.2 1.2-1.2h3.2V4.2H7C5.5 4.2 4.2 5.5 4.2 7v10c0 1.5 1.2 2.8 2.8 2.8h10c1.5 0 2.8-1.2 2.8-2.8v-3.6h-1.5V17zM14.9 3v1.5h3.7l-6.4 6.4 1.1 1.1 6.4-6.4v3.7h1.5V3h-6.3z" + /> + </svg> +</a> +`; -<h3 - className="emotion-0 emotion-1" +exports[`Storyshots Components/FontSizePicker Default 1`] = ` +<fieldset + className="components-font-size-picker" +> + <legend + className="components-visually-hidden" > - Title Small - </h3>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 20px; - font-size: 16px; - line-height: 24px; -} - -<p - className="emotion-0 emotion-1" - > - Subtitle - </p>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 20px; - font-size: 14px; - line-height: 20px; -} - -<p - className="emotion-0 emotion-1" - > - Subtitle Small - </p>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 16px; - line-height: 24px; -} - -<p - className="emotion-0 emotion-1" - > - Body - </p>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 14px; - line-height: 20px; -} - -<p - className="emotion-0 emotion-1" - > - Body Small - </p>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 20px; -} - -<p - className="emotion-0 emotion-1" - > - Button - </p>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 12px; - line-height: 16px; -} - -<p - className="emotion-0 emotion-1" - > - Caption - </p>, - .emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 12px; - line-height: 16px; -} - -<p - className="emotion-0 emotion-1" - > - Label - </p>, -] -`; - -exports[`Storyshots Components/Experimental/Text Label 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 12px; - line-height: 16px; -} - -<p - className="emotion-0 emotion-1" -> - Label -</p> -`; - -exports[`Storyshots Components/Experimental/Text Subtitle 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 20px; - font-size: 16px; - line-height: 24px; -} - -<p - className="emotion-0 emotion-1" -> - Subtitle -</p> -`; - -exports[`Storyshots Components/Experimental/Text Subtitle Small 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 20px; - font-size: 14px; - line-height: 20px; -} - -<p - className="emotion-0 emotion-1" -> - Subtitle Small -</p> -`; - -exports[`Storyshots Components/Experimental/Text Title Large 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 32px; - line-height: 40px; -} - -<h1 - className="emotion-0 emotion-1" -> - Title Large -</h1> -`; - -exports[`Storyshots Components/Experimental/Text Title Medium 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 24px; - line-height: 32px; -} - -<h2 - className="emotion-0 emotion-1" -> - Title Medium -</h2> -`; - -exports[`Storyshots Components/Experimental/Text Title Small 1`] = ` -.emotion-0 { - margin: 0; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; - font-weight: 400; - font-size: 20px; - line-height: 28px; -} - -<h3 - className="emotion-0 emotion-1" -> - Title Small -</h3> -`; - -exports[`Storyshots Components/ExternalLink Default 1`] = ` -<a - className="components-external-link" - href="https://wordpress.org" - rel="external noreferrer noopener" - target="_blank" -> - WordPress - <span - className="components-visually-hidden" - > - (opens in a new tab) - </span> - <svg - aria-hidden="true" - className="components-external-link__icon" - focusable="false" - height={24} - role="img" - viewBox="0 0 24 24" - width={24} - xmlns="http://www.w3.org/2000/svg" - > - <path - d="M18.2 17c0 .7-.6 1.2-1.2 1.2H7c-.7 0-1.2-.6-1.2-1.2V7c0-.7.6-1.2 1.2-1.2h3.2V4.2H7C5.5 4.2 4.2 5.5 4.2 7v10c0 1.5 1.2 2.8 2.8 2.8h10c1.5 0 2.8-1.2 2.8-2.8v-3.6h-1.5V17zM14.9 3v1.5h3.7l-6.4 6.4 1.1 1.1 6.4-6.4v3.7h1.5V3h-6.3z" - /> - </svg> -</a> -`; - -exports[`Storyshots Components/FontSizePicker Default 1`] = ` -<fieldset - className="components-font-size-picker" -> - <legend - className="components-visually-hidden" - > - Font size - </legend> - <div - className="components-font-size-picker__controls" + Font size + </legend> + <div + className="components-font-size-picker__controls" > <div className="components-custom-select-control components-font-size-picker__select" @@ -3081,9 +2906,9 @@ exports[`Storyshots Components/FontSizePicker Default 1`] = ` > Normal <svg - aria-hidden="true" + aria-hidden={true} className="components-custom-select-control__button-icon" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -3372,9 +3197,9 @@ input[type='number'].emotion-18 { > Normal <svg - aria-hidden="true" + aria-hidden={true} className="components-custom-select-control__button-icon" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -3425,8 +3250,8 @@ input[type='number'].emotion-18 { className="emotion-0 emotion-1" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -3506,8 +3331,8 @@ input[type='number'].emotion-18 { className="emotion-16 emotion-17" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -3571,9 +3396,9 @@ exports[`Storyshots Components/FontSizePicker Without Custom Sizes 1`] = ` > Normal <svg - aria-hidden="true" + aria-hidden={true} className="components-custom-select-control__button-icon" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -3630,9 +3455,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -3664,9 +3489,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -3698,9 +3523,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -3728,9 +3553,9 @@ Array [ exports[`Storyshots Components/Icon Default 1`] = ` <div> <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height="24" role="img" viewBox="0 0 20 20" @@ -3765,9 +3590,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={14} role="img" viewBox="0 0 20 20" @@ -3798,9 +3623,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={16} role="img" viewBox="0 0 20 20" @@ -3831,9 +3656,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -3864,9 +3689,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 20 20" @@ -3897,9 +3722,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={28} role="img" viewBox="0 0 20 20" @@ -3930,9 +3755,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={32} role="img" viewBox="0 0 20 20" @@ -3963,9 +3788,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={40} role="img" viewBox="0 0 20 20" @@ -3996,9 +3821,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={48} role="img" viewBox="0 0 20 20" @@ -4029,9 +3854,9 @@ Array [ } > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-screenoptions" - focusable="false" + focusable={false} height={56} role="img" viewBox="0 0 20 20" @@ -4058,8 +3883,8 @@ Array [ exports[`Storyshots Components/Icon With A Component 1`] = ` <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} role="img" > <path @@ -4070,8 +3895,8 @@ exports[`Storyshots Components/Icon With A Component 1`] = ` exports[`Storyshots Components/Icon With A Function 1`] = ` <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} role="img" > <path @@ -4082,8 +3907,8 @@ exports[`Storyshots Components/Icon With A Function 1`] = ` exports[`Storyshots Components/Icon With An SVG 1`] = ` <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" width={24} @@ -4104,6 +3929,17 @@ exports[`Storyshots Components/Modal Default 1`] = ` </button> `; +exports[`Storyshots Components/NumberControl Default 1`] = ` +<input + className="component-number-control" + inputMode="numeric" + onChange={[Function]} + onKeyDown={[Function]} + type="number" + value="" +/> +`; + exports[`Storyshots Components/Panel Default 1`] = ` <div className="components-panel" @@ -4131,9 +3967,9 @@ exports[`Storyshots Components/Panel Default 1`] = ` aria-hidden="true" > <svg - aria-hidden="true" + aria-hidden={true} className="components-panel__arrow" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -4184,9 +4020,9 @@ exports[`Storyshots Components/Panel Multiple Bodies 1`] = ` aria-hidden="true" > <svg - aria-hidden="true" + aria-hidden={true} className="components-panel__arrow" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -4223,9 +4059,9 @@ exports[`Storyshots Components/Panel Multiple Bodies 1`] = ` aria-hidden="true" > <svg - aria-hidden="true" + aria-hidden={true} className="components-panel__arrow" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -4271,9 +4107,9 @@ exports[`Storyshots Components/Panel With Icon 1`] = ` aria-hidden="true" > <svg - aria-hidden="true" + aria-hidden={true} className="components-panel__arrow" - focusable="false" + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -4287,9 +4123,9 @@ exports[`Storyshots Components/Panel With Icon 1`] = ` </span> My Block Settings <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-wordpress components-panel__icon" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -4319,9 +4155,9 @@ exports[`Storyshots Components/Placeholder Default 1`] = ` className="components-placeholder__label" > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-smiley" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -4351,13 +4187,13 @@ exports[`Storyshots Components/Placeholder Default 1`] = ` > <label className="components-base-control__label" - htmlFor="inspector-text-control-2" + htmlFor="inspector-text-control-3" > Sample Field </label> <input className="components-text-control__input" - id="inspector-text-control-2" + id="inspector-text-control-3" onChange={[Function]} placeholder="Enter something here" type="text" @@ -4533,6 +4369,55 @@ exports[`Storyshots Components/Popover Positioning 1`] = ` </div> `; +exports[`Storyshots Components/Radio Default 1`] = ` +<div + aria-label="options" + className="components-button-group" + id="default-radiogroup" + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + role="radiogroup" +> + <button + aria-checked={false} + checked={false} + className="components-button is-secondary" + id="default-radiogroup-1" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option1" + > + Option 1 + </button> + <button + aria-checked={false} + checked={false} + className="components-button is-secondary" + id="default-radiogroup-2" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option2" + > + Option 2 + </button> +</div> +`; + exports[`Storyshots Components/RadioControl Default 1`] = ` <div className="components-base-control components-radio-control" @@ -4684,14 +4569,233 @@ exports[`Storyshots Components/RadioControl With Help 1`] = ` </div> `; -exports[`Storyshots Components/RangeControl Custom Marks 1`] = ` -.emotion-36 { - -webkit-tap-highlight-color: transparent; - box-sizing: border-box; - cursor: pointer; - -webkit-align-items: flex-start; - -webkit-box-align: flex-start; - -ms-flex-align: flex-start; +exports[`Storyshots Components/RadioGroup Controlled 1`] = ` +<div + aria-label="options" + className="components-button-group" + id="controlled-radiogroup" + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + role="radiogroup" +> + <button + aria-checked={false} + checked={false} + className="components-button is-secondary" + id="controlled-radiogroup-1" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option1" + > + Option 1 + </button> + <button + aria-checked={true} + checked={true} + className="components-button is-primary" + id="controlled-radiogroup-2" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option2" + > + Option 2 + </button> + <button + aria-checked={false} + checked={false} + className="components-button is-secondary" + id="controlled-radiogroup-3" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option3" + > + Option 3 + </button> +</div> +`; + +exports[`Storyshots Components/RadioGroup Default 1`] = ` +<div + aria-label="options" + className="components-button-group" + id="default-radiogroup" + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + role="radiogroup" +> + <button + aria-checked={false} + checked={false} + className="components-button is-secondary" + id="default-radiogroup-1" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option1" + > + Option 1 + </button> + <button + aria-checked={true} + checked={true} + className="components-button is-primary" + id="default-radiogroup-2" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option2" + > + Option 2 + </button> + <button + aria-checked={false} + checked={false} + className="components-button is-secondary" + id="default-radiogroup-3" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + tabIndex={-1} + type="radio" + value="option3" + > + Option 3 + </button> +</div> +`; + +exports[`Storyshots Components/RadioGroup Disabled 1`] = ` +<div + aria-label="options" + className="components-button-group" + id="disabled-radiogroup" + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + role="radiogroup" +> + <button + aria-checked={false} + aria-disabled={true} + checked={false} + className="components-button is-secondary" + disabled={true} + id="disabled-radiogroup-1" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + style={ + Object { + "pointerEvents": "none", + } + } + type="radio" + value="option1" + > + Option 1 + </button> + <button + aria-checked={true} + aria-disabled={true} + checked={true} + className="components-button is-primary" + disabled={true} + id="disabled-radiogroup-2" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + style={ + Object { + "pointerEvents": "none", + } + } + type="radio" + value="option2" + > + Option 2 + </button> + <button + aria-checked={false} + aria-disabled={true} + checked={false} + className="components-button is-secondary" + disabled={true} + id="disabled-radiogroup-3" + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + role="radio" + style={ + Object { + "pointerEvents": "none", + } + } + type="radio" + value="option3" + > + Option 3 + </button> +</div> +`; + +exports[`Storyshots Components/RangeControl Custom Marks 1`] = ` +.emotion-36 { + -webkit-tap-highlight-color: transparent; + box-sizing: border-box; + cursor: pointer; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; align-items: flex-start; display: -webkit-inline-box; display: -webkit-inline-flex; @@ -5596,6 +5700,7 @@ input[type='number'].emotion-14 { onChange={[Function]} step={1} type="number" + value={0} /> </span> </div> @@ -6729,9 +6834,9 @@ input[type='number'].emotion-16 { className="emotion-14 emotion-15" > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-wordpress" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -6978,9 +7083,9 @@ input[type='number'].emotion-16 { className="emotion-0 emotion-1" > <svg - aria-hidden="true" + aria-hidden={true} className="dashicon dashicons-wordpress" - focusable="false" + focusable={false} height={20} role="img" viewBox="0 0 20 20" @@ -7835,14 +7940,14 @@ exports[`Storyshots Components/SelectControl Default 1`] = ` > <label className="components-base-control__label" - htmlFor="inspector-select-control-0" + htmlFor="inspector-select-control-1" > Label Text </label> <select - aria-describedby="inspector-select-control-0__help" + aria-describedby="inspector-select-control-1__help" className="components-select-control__input" - id="inspector-select-control-0" + id="inspector-select-control-1" multiple={false} onChange={[Function]} > @@ -7871,7 +7976,7 @@ exports[`Storyshots Components/SelectControl Default 1`] = ` </div> <p className="components-base-control__help" - id="inspector-select-control-0__help" + id="inspector-select-control-1__help" > Help text to explain the select control. </p> @@ -7974,127 +8079,274 @@ exports[`Storyshots Components/TabPanel Default 1`] = ` </div> `; -exports[`Storyshots Components/TextControl Default 1`] = ` -<div - className="components-base-control" -> - <div - className="components-base-control__field" - > - <label - className="components-base-control__label" - htmlFor="inspector-text-control-3" - > - Label Text - </label> - <input - aria-describedby="inspector-text-control-3__help" - className="components-text-control__input" - id="inspector-text-control-3" - onChange={[Function]} - type="text" - /> - </div> - <p - className="components-base-control__help" - id="inspector-text-control-3__help" - > - Help text to explain the input. - </p> -</div> -`; - -exports[`Storyshots Components/TextHighlight Default 1`] = ` +exports[`Storyshots Components/Text Default 1`] = ` Array [ - "We call the new editor ", - <mark> - Gutenberg - </mark>, - ". The entire editing experience has been rebuilt for media rich pages and posts.", -] -`; + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 400; + font-size: 32px; + line-height: 40px; +} -exports[`Storyshots Components/TextareaControl Default 1`] = ` -<div - className="components-base-control" -> - <div - className="components-base-control__field" - > - <label - className="components-base-control__label" - htmlFor="inspector-textarea-control-0" - > - Label Text - </label> - <textarea - aria-describedby="inspector-textarea-control-0__help" - className="components-textarea-control__input" - id="inspector-textarea-control-0" - onChange={[Function]} - rows={4} - /> - </div> - <p - className="components-base-control__help" - id="inspector-textarea-control-0__help" +<h1 + className="emotion-0 emotion-1" > - Help text to explain the textarea. - </p> -</div> -`; + Title Large + </h1>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 400; + font-size: 24px; + line-height: 32px; +} -exports[`Storyshots Components/Tip Default 1`] = ` -<div - className="components-tip" -> - <svg - aria-hidden="true" - focusable="false" - height="24" - role="img" - viewBox="0 0 24 24" - width="24" +<h2 + className="emotion-0 emotion-1" > - <path - d="M12 15.8c-3.7 0-6.8-3-6.8-6.8s3-6.8 6.8-6.8c3.7 0 6.8 3 6.8 6.8s-3.1 6.8-6.8 6.8zm0-12C9.1 3.8 6.8 6.1 6.8 9s2.4 5.2 5.2 5.2c2.9 0 5.2-2.4 5.2-5.2S14.9 3.8 12 3.8zM8 17.5h8V19H8zM10 20.5h4V22h-4z" - /> - </svg> - <p> - <p> - An example tip - </p> - </p> -</div> -`; + Title Medium + </h2>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 400; + font-size: 20px; + line-height: 28px; +} -exports[`Storyshots Components/ToggleControl Default 1`] = ` -<div - className="components-base-control components-toggle-control" -> - <div - className="components-base-control__field" +<h3 + className="emotion-0 emotion-1" > - <span - className="components-form-toggle is-checked" - > - <input - checked={true} - className="components-form-toggle__input" - id="inspector-toggle-control-0" - onChange={[Function]} - type="checkbox" - /> - <span - className="components-form-toggle__track" + Title Small + </h3>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 600; + font-size: 14px; + line-height: 20px; + font-size: 16px; + line-height: 24px; +} + +<p + className="emotion-0 emotion-1" + > + Subtitle + </p>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 600; + font-size: 14px; + line-height: 20px; + font-size: 14px; + line-height: 20px; +} + +<p + className="emotion-0 emotion-1" + > + Subtitle Small + </p>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 400; +} + +<p + className="emotion-0 emotion-1" + > + Body + </p>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 400; + font-size: 14px; + line-height: 20px; +} + +<p + className="emotion-0 emotion-1" + > + Body Small + </p>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 600; + font-size: 14px; + line-height: 20px; +} + +<p + className="emotion-0 emotion-1" + > + Button + </p>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 400; + font-size: 12px; + line-height: 16px; +} + +<p + className="emotion-0 emotion-1" + > + Caption + </p>, + .emotion-0 { + box-sizing: border-box; + margin: 0; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + font-weight: 600; + font-size: 12px; + line-height: 16px; +} + +<p + className="emotion-0 emotion-1" + > + Label + </p>, +] +`; + +exports[`Storyshots Components/TextControl Default 1`] = ` +<div + className="components-base-control" +> + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="inspector-text-control-4" + > + Label Text + </label> + <input + aria-describedby="inspector-text-control-4__help" + className="components-text-control__input" + id="inspector-text-control-4" + onChange={[Function]} + type="text" + /> + </div> + <p + className="components-base-control__help" + id="inspector-text-control-4__help" + > + Help text to explain the input. + </p> +</div> +`; + +exports[`Storyshots Components/TextHighlight Default 1`] = ` +Array [ + "We call the new editor ", + <mark> + Gutenberg + </mark>, + ". The entire editing experience has been rebuilt for media rich pages and posts.", +] +`; + +exports[`Storyshots Components/TextareaControl Default 1`] = ` +<div + className="components-base-control" +> + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="inspector-textarea-control-1" + > + Label Text + </label> + <textarea + aria-describedby="inspector-textarea-control-1__help" + className="components-textarea-control__input" + id="inspector-textarea-control-1" + onChange={[Function]} + rows={4} + /> + </div> + <p + className="components-base-control__help" + id="inspector-textarea-control-1__help" + > + Help text to explain the textarea. + </p> +</div> +`; + +exports[`Storyshots Components/Tip Default 1`] = ` +<div + className="components-tip" +> + <svg + aria-hidden={true} + focusable={false} + height="24" + role="img" + viewBox="0 0 24 24" + width="24" + > + <path + d="M12 15.8c-3.7 0-6.8-3-6.8-6.8s3-6.8 6.8-6.8c3.7 0 6.8 3 6.8 6.8s-3.1 6.8-6.8 6.8zm0-12C9.1 3.8 6.8 6.1 6.8 9s2.4 5.2 5.2 5.2c2.9 0 5.2-2.4 5.2-5.2S14.9 3.8 12 3.8zM8 17.5h8V19H8zM10 20.5h4V22h-4z" + /> + </svg> + <p> + <p> + An example tip + </p> + </p> +</div> +`; + +exports[`Storyshots Components/ToggleControl Default 1`] = ` +<div + className="components-base-control components-toggle-control" +> + <div + className="components-base-control__field" + > + <span + className="components-form-toggle is-checked" + > + <input + checked={true} + className="components-form-toggle__input" + id="inspector-toggle-control-0" + onChange={[Function]} + type="checkbox" + /> + <span + className="components-form-toggle__track" /> <span className="components-form-toggle__thumb" /> <svg - aria-hidden="true" + aria-hidden={true} className="components-form-toggle__on" - focusable="false" + focusable={false} height="6" role="img" viewBox="0 0 2 6" @@ -8141,9 +8393,9 @@ exports[`Storyshots Components/ToggleControl With Help Text 1`] = ` className="components-form-toggle__thumb" /> <svg - aria-hidden="true" + aria-hidden={true} className="components-form-toggle__on" - focusable="false" + focusable={false} height="6" role="img" viewBox="0 0 2 6" @@ -8199,6 +8451,9 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` aria-orientation="horizontal" className="components-accessible-toolbar" id="options-toolbar" + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} role="toolbar" > <div @@ -8212,6 +8467,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8219,8 +8475,8 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8249,6 +8505,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8256,8 +8513,8 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8280,6 +8537,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} tabIndex={-1} type="button" @@ -8295,6 +8553,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8302,8 +8561,8 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8323,6 +8582,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8330,8 +8590,8 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8351,6 +8611,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8358,8 +8619,8 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8384,6 +8645,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8405,6 +8667,7 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8412,8 +8675,8 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8429,51 +8692,391 @@ exports[`Storyshots Components/Toolbar Default 1`] = ` </div> `; -exports[`Storyshots Components/Toolbar Without Group 1`] = ` -<div - aria-label="Options" - aria-orientation="horizontal" - className="components-accessible-toolbar" - id="options-toolbar-without-group" - role="toolbar" -> - <button - aria-label="Bold" - aria-pressed={true} - className="components-button components-toolbar-button is-pressed has-icon" - id="options-toolbar-without-group-1" - onBlur={[Function]} - onClick={[Function]} - onFocus={[Function]} - onKeyDown={[Function]} - onMouseDown={[Function]} - onMouseEnter={[Function]} - onMouseLeave={[Function]} - tabIndex={-1} - type="button" +exports[`Storyshots Components/Toolbar Toolbars 1`] = ` +<div> + <div + style={ + Object { + "padding": "20px", + } + } > - <svg - aria-hidden="true" - focusable="false" - height={24} - role="img" - viewBox="0 0 24 24" - width={24} - xmlns="http://www.w3.org/2000/svg" + <h2> + Icon-only Toolbar + </h2> + <div + className="components-toolbar" > - <path - d="M14.7 11.3c1-.6 1.5-1.6 1.5-3 0-2.3-1.3-3.4-4-3.4H7v14h5.8c1.4 0 2.5-.3 3.3-1 .8-.7 1.2-1.7 1.2-2.9.1-1.9-.8-3.1-2.6-3.7zm-5.1-4h2.3c.6 0 1.1.1 1.4.4.3.3.5.7.5 1.2s-.2 1-.5 1.2c-.3.3-.8.4-1.4.4H9.6V7.3zm4.6 9c-.4.3-1 .4-1.7.4H9.6v-3.9h2.9c.7 0 1.3.2 1.7.5.4.3.6.8.6 1.5s-.2 1.2-.6 1.5z" - /> - </svg> - </button> - <button - aria-label="Italic" + <div> + <button + aria-label="Bold" + className="components-button components-toolbar__control has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M14.7 11.3c1-.6 1.5-1.6 1.5-3 0-2.3-1.3-3.4-4-3.4H7v14h5.8c1.4 0 2.5-.3 3.3-1 .8-.7 1.2-1.7 1.2-2.9.1-1.9-.8-3.1-2.6-3.7zm-5.1-4h2.3c.6 0 1.1.1 1.4.4.3.3.5.7.5 1.2s-.2 1-.5 1.2c-.3.3-.8.4-1.4.4H9.6V7.3zm4.6 9c-.4.3-1 .4-1.7.4H9.6v-3.9h2.9c.7 0 1.3.2 1.7.5.4.3.6.8.6 1.5s-.2 1.2-.6 1.5z" + /> + </svg> + </button> + </div> + <div> + <button + aria-label="Italic" + aria-pressed={true} + className="components-button components-toolbar__control is-pressed has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M12.5 5L10 19h1.9l2.5-14z" + /> + </svg> + </button> + </div> + <div> + <button + aria-label="Link" + className="components-button components-toolbar__control has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M15.6 7.2H14v1.5h1.6c2 0 3.7 1.7 3.7 3.7s-1.7 3.7-3.7 3.7H14v1.5h1.6c2.8 0 5.2-2.3 5.2-5.2 0-2.9-2.3-5.2-5.2-5.2zM4.7 12.4c0-2 1.7-3.7 3.7-3.7H10V7.2H8.4c-2.9 0-5.2 2.3-5.2 5.2 0 2.9 2.3 5.2 5.2 5.2H10v-1.5H8.4c-2 0-3.7-1.7-3.7-3.7zm4.6.9h5.3v-1.5H9.3v1.5z" + /> + </svg> + </button> + </div> + </div> + </div> + <div + style={ + Object { + "padding": "20px", + } + } + > + <h2> + Text-only Toolbar + </h2> + <div + className="components-toolbar" + > + <div> + <button + className="components-button components-toolbar__control" + onClick={[Function]} + type="button" + > + Bold Format + </button> + </div> + <div> + <button + aria-pressed={true} + className="components-button components-toolbar__control is-pressed" + onClick={[Function]} + type="button" + > + Italic Format + </button> + </div> + <div> + <button + className="components-button components-toolbar__control" + onClick={[Function]} + type="button" + > + Link Format + </button> + </div> + </div> + </div> + <div + style={ + Object { + "padding": "20px", + } + } + > + <h2> + Text and Icon Toolbar + </h2> + <div + className="components-toolbar" + > + <div> + <button + aria-label="Bold" + className="components-button components-toolbar__control has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M14.7 11.3c1-.6 1.5-1.6 1.5-3 0-2.3-1.3-3.4-4-3.4H7v14h5.8c1.4 0 2.5-.3 3.3-1 .8-.7 1.2-1.7 1.2-2.9.1-1.9-.8-3.1-2.6-3.7zm-5.1-4h2.3c.6 0 1.1.1 1.4.4.3.3.5.7.5 1.2s-.2 1-.5 1.2c-.3.3-.8.4-1.4.4H9.6V7.3zm4.6 9c-.4.3-1 .4-1.7.4H9.6v-3.9h2.9c.7 0 1.3.2 1.7.5.4.3.6.8.6 1.5s-.2 1.2-.6 1.5z" + /> + </svg> + </button> + </div> + <div> + <button + aria-pressed={true} + className="components-button components-toolbar__control is-pressed" + onClick={[Function]} + type="button" + > + Bold Format + </button> + </div> + <div> + <button + aria-label="Italic" + className="components-button components-toolbar__control has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M12.5 5L10 19h1.9l2.5-14z" + /> + </svg> + </button> + </div> + <div> + <button + className="components-button components-toolbar__control" + onClick={[Function]} + type="button" + > + Italic Format + </button> + </div> + <div> + <button + aria-label="Link" + className="components-button components-toolbar__control has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M15.6 7.2H14v1.5h1.6c2 0 3.7 1.7 3.7 3.7s-1.7 3.7-3.7 3.7H14v1.5h1.6c2.8 0 5.2-2.3 5.2-5.2 0-2.9-2.3-5.2-5.2-5.2zM4.7 12.4c0-2 1.7-3.7 3.7-3.7H10V7.2H8.4c-2.9 0-5.2 2.3-5.2 5.2 0 2.9 2.3 5.2 5.2 5.2H10v-1.5H8.4c-2 0-3.7-1.7-3.7-3.7zm4.6.9h5.3v-1.5H9.3v1.5z" + /> + </svg> + </button> + </div> + <div> + <button + className="components-button components-toolbar__control" + onClick={[Function]} + type="button" + > + Link Format + </button> + </div> + </div> + </div> + <div + style={ + Object { + "padding": "20px", + } + } + > + <h2> + Single Icon Button Toolbar + </h2> + <div + className="components-toolbar" + > + <div> + <button + aria-label="Bold" + className="components-button components-toolbar__control has-icon" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M14.7 11.3c1-.6 1.5-1.6 1.5-3 0-2.3-1.3-3.4-4-3.4H7v14h5.8c1.4 0 2.5-.3 3.3-1 .8-.7 1.2-1.7 1.2-2.9.1-1.9-.8-3.1-2.6-3.7zm-5.1-4h2.3c.6 0 1.1.1 1.4.4.3.3.5.7.5 1.2s-.2 1-.5 1.2c-.3.3-.8.4-1.4.4H9.6V7.3zm4.6 9c-.4.3-1 .4-1.7.4H9.6v-3.9h2.9c.7 0 1.3.2 1.7.5.4.3.6.8.6 1.5s-.2 1.2-.6 1.5z" + /> + </svg> + </button> + </div> + </div> + </div> + <div + style={ + Object { + "padding": "20px", + } + } + > + <h2> + Single Text Button toolbar + </h2> + <div + className="components-toolbar" + > + <div> + <button + className="components-button components-toolbar__control" + onClick={[Function]} + type="button" + > + Bold Toolbar + </button> + </div> + </div> + </div> +</div> +`; + +exports[`Storyshots Components/Toolbar Without Group 1`] = ` +<div + aria-label="Options" + aria-orientation="horizontal" + className="components-accessible-toolbar" + id="options-toolbar-without-group" + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + role="toolbar" +> + <button + aria-label="Bold" + aria-pressed={true} + className="components-button components-toolbar-button is-pressed has-icon" + id="options-toolbar-without-group-1" + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + tabIndex={-1} + type="button" + > + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M14.7 11.3c1-.6 1.5-1.6 1.5-3 0-2.3-1.3-3.4-4-3.4H7v14h5.8c1.4 0 2.5-.3 3.3-1 .8-.7 1.2-1.7 1.2-2.9.1-1.9-.8-3.1-2.6-3.7zm-5.1-4h2.3c.6 0 1.1.1 1.4.4.3.3.5.7.5 1.2s-.2 1-.5 1.2c-.3.3-.8.4-1.4.4H9.6V7.3zm4.6 9c-.4.3-1 .4-1.7.4H9.6v-3.9h2.9c.7 0 1.3.2 1.7.5.4.3.6.8.6 1.5s-.2 1.2-.6 1.5z" + /> + </svg> + </button> + <button + aria-label="Italic" className="components-button components-toolbar-button has-icon" id="options-toolbar-without-group-2" onBlur={[Function]} onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8481,8 +9084,8 @@ exports[`Storyshots Components/Toolbar Without Group 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8502,6 +9105,7 @@ exports[`Storyshots Components/Toolbar Without Group 1`] = ` onClick={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onKeyUp={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} @@ -8509,8 +9113,8 @@ exports[`Storyshots Components/Toolbar Without Group 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8543,8 +9147,8 @@ exports[`Storyshots Components/ToolbarGroup Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8570,8 +9174,8 @@ exports[`Storyshots Components/ToolbarGroup Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8597,8 +9201,8 @@ exports[`Storyshots Components/ToolbarGroup Default 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8634,8 +9238,8 @@ exports[`Storyshots Components/ToolbarGroup With Controls Prop 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8663,8 +9267,8 @@ exports[`Storyshots Components/ToolbarGroup With Controls Prop 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8692,8 +9296,8 @@ exports[`Storyshots Components/ToolbarGroup With Controls Prop 1`] = ` type="button" > <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8709,6 +9313,203 @@ exports[`Storyshots Components/ToolbarGroup With Controls Prop 1`] = ` </div> `; +exports[`Storyshots Components/TreeSelect Default 1`] = ` +<div + className="components-base-control" +> + <div + className="components-base-control__field" + > + <label + className="components-base-control__label" + htmlFor="inspector-select-control-2" + > + Label Text + </label> + <select + aria-describedby="inspector-select-control-2__help" + className="components-select-control__input" + id="inspector-select-control-2" + multiple={false} + onChange={[Function]} + > + <option + value="" + > + No parent page + </option> + <option + value="p1" + > + Page 1 + </option> + <option + value="p11" + > +    Descend 1 of page 1 + </option> + <option + value="p12" + > +    Descend 2 of page 1 + </option> + <option + value="p2" + > + Page 2 + </option> + <option + value="p21" + > +    Descend 1 of page 2 + </option> + <option + value="p211" + > +       Descend 1 of Descend 1 of page 2 + </option> + </select> + </div> + <p + className="components-base-control__help" + id="inspector-select-control-2__help" + > + Help text to explain the select control. + </p> +</div> +`; + +exports[`Storyshots Components/UnitControl Default 1`] = ` +.emotion-6 { + max-width: 80px; +} + +.emotion-4 { + box-sizing: border-box; + position: relative; +} + +.emotion-0.emotion-0.emotion-0 { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -moz-appearance: textfield; + box-sizing: border-box; + border: 1px solid #000; + border-radius: 2px; + padding: 3px 8px; + display: block; + width: 100%; + padding-right: 20px; + height: 30px; + line-height: 30; + min-height: 30px; +} + +.emotion-0.emotion-0.emotion-0::-webkit-outer-spin-button, +.emotion-0.emotion-0.emotion-0::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.emotion-2.emotion-2.emotion-2 { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: #fff; + border-radius: 2px; + border: none; + box-sizing: border-box; + color: #555d66; + display: block; + font-size: 8px; + line-height: 1; + -webkit-letter-spacing: -0.5px; + -moz-letter-spacing: -0.5px; + -ms-letter-spacing: -0.5px; + letter-spacing: -0.5px; + outline: none; + padding: 2px 2px; + position: absolute; + text-align-last: center; + text-transform: uppercase; + width: 22px; + z-index: 1; + right: 4px; + top: 5px; + height: 20px; + min-height: 20px; + cursor: pointer; + border: 1px solid transparent; +} + +.emotion-2.emotion-2.emotion-2:hover { + background-color: #edeff0; +} + +.emotion-2.emotion-2.emotion-2:focus { + border-color: #007cba; + outline: 2px solid transparent; + outline-offset: 0; +} + +<div + className="emotion-6 emotion-7" +> + <div + className="component-unit-control emotion-4 emotion-5" + > + <input + className="component-number-control component-unit-control__input emotion-0 emotion-1" + inputMode="numeric" + onChange={[Function]} + onKeyDown={[Function]} + size="default" + type="number" + value="" + /> + <select + className="component-unit-control__select component-unit-control__select emotion-2 emotion-3" + onChange={[Function]} + size="default" + tabIndex={null} + value="px" + > + <option + value="px" + > + px + </option> + <option + value="%" + > + % + </option> + <option + value="em" + > + em + </option> + <option + value="rem" + > + rem + </option> + <option + value="vw" + > + vw + </option> + <option + value="vh" + > + vh + </option> + </select> + </div> +</div> +`; + exports[`Storyshots Components/VisuallyHidden Default 1`] = ` Array [ <div @@ -8758,45 +9559,6 @@ Array [ ] `; -exports[`Storyshots Components|AnglePickerControl Default 1`] = ` -<div - className="components-base-control components-angle-picker-control" -> - <div - className="components-base-control__field" - > - <label - className="components-base-control__label" - htmlFor="components-angle-picker-control__input-0" - > - Angle - </label> - <div - aria-hidden="true" - className="components-angle-picker-control__angle-circle" - onMouseDown={[Function]} - > - <div - className="components-angle-picker-control__angle-circle-indicator-wrapper" - > - <span - className="components-angle-picker-control__angle-circle-indicator" - /> - </div> - </div> - <input - className="components-angle-picker-control__input-field" - id="components-angle-picker-control__input-0" - max={360} - min={0} - onChange={[Function]} - step="1" - type="number" - /> - </div> -</div> -`; - exports[`Storyshots Icons/Icon Default 1`] = ` Array [ <div> @@ -8804,8 +9566,8 @@ Array [ Dashicons (corrected viewport) </h2> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8817,8 +9579,8 @@ Array [ /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -8830,8 +9592,8 @@ Array [ /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -8848,8 +9610,8 @@ Array [ Material and Other </h2> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8861,8 +9623,8 @@ Array [ /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -8874,8 +9636,8 @@ Array [ /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -8933,8 +9695,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` alignCenter </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -8946,8 +9708,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -8959,8 +9721,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -8990,8 +9752,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` alignJustify </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9003,8 +9765,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9016,8 +9778,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9047,8 +9809,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` alignLeft </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9060,8 +9822,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9073,8 +9835,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9104,8 +9866,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` alignRight </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9117,8 +9879,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9130,8 +9892,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9161,8 +9923,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` archive </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9174,8 +9936,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9187,8 +9949,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9218,8 +9980,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` arrowDown </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9231,8 +9993,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9244,8 +10006,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9275,8 +10037,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` arrowLeft </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9288,8 +10050,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9301,8 +10063,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9332,8 +10094,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` arrowRight </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9345,8 +10107,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9358,8 +10120,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9389,8 +10151,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` arrowUp </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9402,8 +10164,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9415,8 +10177,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9446,8 +10208,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` audio </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9459,8 +10221,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9472,8 +10234,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9503,8 +10265,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` backup </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9516,8 +10278,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9529,8 +10291,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9560,8 +10322,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` blockDefault </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9573,8 +10335,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9586,8 +10348,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9617,8 +10379,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` blockTable </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9630,8 +10392,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9643,8 +10405,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9674,8 +10436,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` brush </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9687,8 +10449,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9700,8 +10462,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9731,8 +10493,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` button </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9740,12 +10502,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M19 7H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5V9c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13.5h8V12H8v1.5z" + d="M19 6.5H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5v-7c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13h8v-1.5H8V13z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9753,12 +10515,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M19 7H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5V9c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13.5h8V12H8v1.5z" + d="M19 6.5H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5v-7c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13h8v-1.5H8V13z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9766,7 +10528,7 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M19 7H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5V9c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13.5h8V12H8v1.5z" + d="M19 6.5H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7c0-1.1-.9-2-2-2zm.5 9c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5v-7c0-.3.2-.5.5-.5h14c.3 0 .5.2.5.5v7zM8 13h8v-1.5H8V13z" /> </svg> </div> @@ -9788,8 +10550,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` calendar </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9801,8 +10563,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9814,8 +10576,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9845,8 +10607,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` camera </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -9858,8 +10620,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -9871,8 +10633,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -9902,8 +10664,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` capturePhoto </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9915,8 +10677,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9928,8 +10690,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -9959,8 +10721,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` captureVideo </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -9972,8 +10734,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -9985,8 +10747,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10016,8 +10778,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` category </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10029,8 +10791,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10042,8 +10804,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10073,8 +10835,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` chartLine </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -10086,8 +10848,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -10099,8 +10861,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -10130,8 +10892,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` check </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10143,8 +10905,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10156,8 +10918,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10187,8 +10949,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` chevronDown </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10200,8 +10962,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10213,8 +10975,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10244,8 +11006,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` chevronLeft </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10257,8 +11019,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10270,8 +11032,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10301,8 +11063,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` chevronRight </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10314,8 +11076,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10327,8 +11089,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10358,8 +11120,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` chevronUp </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10371,8 +11133,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10384,8 +11146,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10415,8 +11177,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` classic </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10428,8 +11190,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10441,8 +11203,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10472,8 +11234,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` closeCircleFilled </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -10485,8 +11247,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -10498,8 +11260,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -10529,8 +11291,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` close </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10542,8 +11304,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10555,8 +11317,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10586,8 +11348,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` cloudUpload </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -10599,8 +11361,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -10612,8 +11374,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -10643,8 +11405,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` cloud </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -10656,8 +11418,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -10669,8 +11431,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -10700,8 +11462,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` code </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10713,8 +11475,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10726,8 +11488,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10757,8 +11519,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` cog </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10770,8 +11532,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10783,8 +11545,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10814,8 +11576,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` column </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10827,8 +11589,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10840,8 +11602,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10871,8 +11633,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` columns </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10884,8 +11646,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10897,8 +11659,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10928,8 +11690,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` comment </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -10941,8 +11703,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -10954,8 +11716,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -10985,8 +11747,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` controlsRepeat </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -10998,29 +11760,143 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} + height={36} + role="img" + viewBox="-2 -2 24 24" + width={36} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M5 7v3l-2 1.5V5h11V3l4 3.01L14 9V7H5zm10 6v-3l2-1.5V15H6v2l-4-3.01L6 11v2h9z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={48} + role="img" + viewBox="-2 -2 24 24" + width={48} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M5 7v3l-2 1.5V5h11V3l4 3.01L14 9V7H5zm10 6v-3l2-1.5V15H6v2l-4-3.01L6 11v2h9z" + /> + </svg> + </div> + <div + style={ + Object { + "alignItems": "center", + "display": "flex", + } + } + > + <strong + style={ + Object { + "width": "120px", + } + } + > + cover + </strong> + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M18.7 3H5.3C4 3 3 4 3 5.3v13.4C3 20 4 21 5.3 21h13.4c1.3 0 2.3-1 2.3-2.3V5.3C21 4 20 3 18.7 3zm.8 15.7c0 .4-.4.8-.8.8H5.3c-.4 0-.8-.4-.8-.8V5.3c0-.4.4-.8.8-.8h6.2v8.9l2.5-3.1 2.5 3.1V4.5h2.2c.4 0 .8.4.8.8v13.4z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={36} + role="img" + viewBox="0 0 24 24" + width={36} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M18.7 3H5.3C4 3 3 4 3 5.3v13.4C3 20 4 21 5.3 21h13.4c1.3 0 2.3-1 2.3-2.3V5.3C21 4 20 3 18.7 3zm.8 15.7c0 .4-.4.8-.8.8H5.3c-.4 0-.8-.4-.8-.8V5.3c0-.4.4-.8.8-.8h6.2v8.9l2.5-3.1 2.5 3.1V4.5h2.2c.4 0 .8.4.8.8v13.4z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={48} + role="img" + viewBox="0 0 24 24" + width={48} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M18.7 3H5.3C4 3 3 4 3 5.3v13.4C3 20 4 21 5.3 21h13.4c1.3 0 2.3-1 2.3-2.3V5.3C21 4 20 3 18.7 3zm.8 15.7c0 .4-.4.8-.8.8H5.3c-.4 0-.8-.4-.8-.8V5.3c0-.4.4-.8.8-.8h6.2v8.9l2.5-3.1 2.5 3.1V4.5h2.2c.4 0 .8.4.8.8v13.4z" + /> + </svg> + </div> + <div + style={ + Object { + "alignItems": "center", + "display": "flex", + } + } + > + <strong + style={ + Object { + "width": "120px", + } + } + > + create + </strong> + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M16 11.2h-3.2V8h-1.6v3.2H8v1.6h3.2V16h1.6v-3.2H16z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} height={36} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={36} xmlns="http://www.w3.org/2000/svg" > <path - d="M5 7v3l-2 1.5V5h11V3l4 3.01L14 9V7H5zm10 6v-3l2-1.5V15H6v2l-4-3.01L6 11v2h9z" + d="M16 11.2h-3.2V8h-1.6v3.2H8v1.6h3.2V16h1.6v-3.2H16z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={48} xmlns="http://www.w3.org/2000/svg" > <path - d="M5 7v3l-2 1.5V5h11V3l4 3.01L14 9V7H5zm10 6v-3l2-1.5V15H6v2l-4-3.01L6 11v2h9z" + d="M16 11.2h-3.2V8h-1.6v3.2H8v1.6h3.2V16h1.6v-3.2H16z" /> </svg> </div> @@ -11039,11 +11915,11 @@ exports[`Storyshots Icons/Icon Library 1`] = ` } } > - cover + desktop </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11051,12 +11927,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M18.7 3H5.3C4 3 3 4 3 5.3v13.4C3 20 4 21 5.3 21h13.4c1.3 0 2.3-1 2.3-2.3V5.3C21 4 20 3 18.7 3zm.8 15.7c0 .4-.4.8-.8.8H5.3c-.4 0-.8-.4-.8-.8V5.3c0-.4.4-.8.8-.8h6.2v8.9l2.5-3.1 2.5 3.1V4.5h2.2c.4 0 .8.4.8.8v13.4z" + d="M20.5 16h-.7V8c0-1.1-.9-2-2-2H6.2c-1.1 0-2 .9-2 2v8h-.7c-.8 0-1.5.7-1.5 1.5h20c0-.8-.7-1.5-1.5-1.5zM5.7 8c0-.3.2-.5.5-.5h11.6c.3 0 .5.2.5.5v7.6H5.7V8z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11064,12 +11940,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M18.7 3H5.3C4 3 3 4 3 5.3v13.4C3 20 4 21 5.3 21h13.4c1.3 0 2.3-1 2.3-2.3V5.3C21 4 20 3 18.7 3zm.8 15.7c0 .4-.4.8-.8.8H5.3c-.4 0-.8-.4-.8-.8V5.3c0-.4.4-.8.8-.8h6.2v8.9l2.5-3.1 2.5 3.1V4.5h2.2c.4 0 .8.4.8.8v13.4z" + d="M20.5 16h-.7V8c0-1.1-.9-2-2-2H6.2c-1.1 0-2 .9-2 2v8h-.7c-.8 0-1.5.7-1.5 1.5h20c0-.8-.7-1.5-1.5-1.5zM5.7 8c0-.3.2-.5.5-.5h11.6c.3 0 .5.2.5.5v7.6H5.7V8z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11077,7 +11953,7 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M18.7 3H5.3C4 3 3 4 3 5.3v13.4C3 20 4 21 5.3 21h13.4c1.3 0 2.3-1 2.3-2.3V5.3C21 4 20 3 18.7 3zm.8 15.7c0 .4-.4.8-.8.8H5.3c-.4 0-.8-.4-.8-.8V5.3c0-.4.4-.8.8-.8h6.2v8.9l2.5-3.1 2.5 3.1V4.5h2.2c.4 0 .8.4.8.8v13.4z" + d="M20.5 16h-.7V8c0-1.1-.9-2-2-2H6.2c-1.1 0-2 .9-2 2v8h-.7c-.8 0-1.5.7-1.5 1.5h20c0-.8-.7-1.5-1.5-1.5zM5.7 8c0-.3.2-.5.5-.5h11.6c.3 0 .5.2.5.5v7.6H5.7V8z" /> </svg> </div> @@ -11099,8 +11975,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` external </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11112,8 +11988,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11125,8 +12001,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11156,8 +12032,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` file </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11169,8 +12045,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11182,8 +12058,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11213,8 +12089,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatBold </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11226,8 +12102,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11239,8 +12115,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11270,8 +12146,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatIndent </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11283,8 +12159,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11296,8 +12172,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11327,8 +12203,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatItalic </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11340,8 +12216,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11353,8 +12229,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11384,8 +12260,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatListBullets </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11397,8 +12273,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11410,8 +12286,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11441,8 +12317,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatListNumbered </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11454,8 +12330,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11467,8 +12343,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11498,8 +12374,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatLtr </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -11511,8 +12387,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -11524,8 +12400,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -11555,8 +12431,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatOutdent </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11568,8 +12444,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11581,8 +12457,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11612,8 +12488,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatRtl </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -11625,8 +12501,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -11638,8 +12514,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -11669,8 +12545,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` formatStrikethrough </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11682,8 +12558,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11695,8 +12571,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11726,8 +12602,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` gallery </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11739,8 +12615,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11752,8 +12628,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11765,6 +12641,63 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> </div> + <div + style={ + Object { + "alignItems": "center", + "display": "flex", + } + } + > + <strong + style={ + Object { + "width": "120px", + } + } + > + globe + </strong> + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="-2 -2 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9 0C4.03 0 0 4.03 0 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zM1.11 9.68h2.51c.04.91.167 1.814.38 2.7H1.84c-.403-.85-.65-1.764-.73-2.7zm8.57-5.4V1.19c.964.366 1.756 1.08 2.22 2 .205.347.386.708.54 1.08l-2.76.01zm3.22 1.35c.232.883.37 1.788.41 2.7H9.68v-2.7h3.22zM8.32 1.19v3.09H5.56c.154-.372.335-.733.54-1.08.462-.924 1.255-1.64 2.22-2.01zm0 4.44v2.7H4.7c.04-.912.178-1.817.41-2.7h3.21zm-4.7 2.69H1.11c.08-.936.327-1.85.73-2.7H4c-.213.886-.34 1.79-.38 2.7zM4.7 9.68h3.62v2.7H5.11c-.232-.883-.37-1.788-.41-2.7zm3.63 4v3.09c-.964-.366-1.756-1.08-2.22-2-.205-.347-.386-.708-.54-1.08l2.76-.01zm1.35 3.09v-3.04h2.76c-.154.372-.335.733-.54 1.08-.464.92-1.256 1.634-2.22 2v-.04zm0-4.44v-2.7h3.62c-.04.912-.178 1.817-.41 2.7H9.68zm4.71-2.7h2.51c-.08.936-.327 1.85-.73 2.7H14c.21-.87.337-1.757.38-2.65l.01-.05zm0-1.35c-.046-.894-.176-1.78-.39-2.65h2.16c.403.85.65 1.764.73 2.7l-2.5-.05zm1-4H13.6c-.324-.91-.793-1.76-1.39-2.52 1.244.56 2.325 1.426 3.14 2.52h.04zm-9.6-2.52c-.597.76-1.066 1.61-1.39 2.52H2.65c.815-1.094 1.896-1.96 3.14-2.52zm-3.15 12H4.4c.324.91.793 1.76 1.39 2.52-1.248-.567-2.33-1.445-3.14-2.55l-.01.03zm9.56 2.52c.597-.76 1.066-1.61 1.39-2.52h1.76c-.82 1.08-1.9 1.933-3.14 2.48l-.01.04z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={36} + role="img" + viewBox="-2 -2 24 24" + width={36} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9 0C4.03 0 0 4.03 0 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zM1.11 9.68h2.51c.04.91.167 1.814.38 2.7H1.84c-.403-.85-.65-1.764-.73-2.7zm8.57-5.4V1.19c.964.366 1.756 1.08 2.22 2 .205.347.386.708.54 1.08l-2.76.01zm3.22 1.35c.232.883.37 1.788.41 2.7H9.68v-2.7h3.22zM8.32 1.19v3.09H5.56c.154-.372.335-.733.54-1.08.462-.924 1.255-1.64 2.22-2.01zm0 4.44v2.7H4.7c.04-.912.178-1.817.41-2.7h3.21zm-4.7 2.69H1.11c.08-.936.327-1.85.73-2.7H4c-.213.886-.34 1.79-.38 2.7zM4.7 9.68h3.62v2.7H5.11c-.232-.883-.37-1.788-.41-2.7zm3.63 4v3.09c-.964-.366-1.756-1.08-2.22-2-.205-.347-.386-.708-.54-1.08l2.76-.01zm1.35 3.09v-3.04h2.76c-.154.372-.335.733-.54 1.08-.464.92-1.256 1.634-2.22 2v-.04zm0-4.44v-2.7h3.62c-.04.912-.178 1.817-.41 2.7H9.68zm4.71-2.7h2.51c-.08.936-.327 1.85-.73 2.7H14c.21-.87.337-1.757.38-2.65l.01-.05zm0-1.35c-.046-.894-.176-1.78-.39-2.65h2.16c.403.85.65 1.764.73 2.7l-2.5-.05zm1-4H13.6c-.324-.91-.793-1.76-1.39-2.52 1.244.56 2.325 1.426 3.14 2.52h.04zm-9.6-2.52c-.597.76-1.066 1.61-1.39 2.52H2.65c.815-1.094 1.896-1.96 3.14-2.52zm-3.15 12H4.4c.324.91.793 1.76 1.39 2.52-1.248-.567-2.33-1.445-3.14-2.55l-.01.03zm9.56 2.52c.597-.76 1.066-1.61 1.39-2.52h1.76c-.82 1.08-1.9 1.933-3.14 2.48l-.01.04z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={48} + role="img" + viewBox="-2 -2 24 24" + width={48} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9 0C4.03 0 0 4.03 0 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zM1.11 9.68h2.51c.04.91.167 1.814.38 2.7H1.84c-.403-.85-.65-1.764-.73-2.7zm8.57-5.4V1.19c.964.366 1.756 1.08 2.22 2 .205.347.386.708.54 1.08l-2.76.01zm3.22 1.35c.232.883.37 1.788.41 2.7H9.68v-2.7h3.22zM8.32 1.19v3.09H5.56c.154-.372.335-.733.54-1.08.462-.924 1.255-1.64 2.22-2.01zm0 4.44v2.7H4.7c.04-.912.178-1.817.41-2.7h3.21zm-4.7 2.69H1.11c.08-.936.327-1.85.73-2.7H4c-.213.886-.34 1.79-.38 2.7zM4.7 9.68h3.62v2.7H5.11c-.232-.883-.37-1.788-.41-2.7zm3.63 4v3.09c-.964-.366-1.756-1.08-2.22-2-.205-.347-.386-.708-.54-1.08l2.76-.01zm1.35 3.09v-3.04h2.76c-.154.372-.335.733-.54 1.08-.464.92-1.256 1.634-2.22 2v-.04zm0-4.44v-2.7h3.62c-.04.912-.178 1.817-.41 2.7H9.68zm4.71-2.7h2.51c-.08.936-.327 1.85-.73 2.7H14c.21-.87.337-1.757.38-2.65l.01-.05zm0-1.35c-.046-.894-.176-1.78-.39-2.65h2.16c.403.85.65 1.764.73 2.7l-2.5-.05zm1-4H13.6c-.324-.91-.793-1.76-1.39-2.52 1.244.56 2.325 1.426 3.14 2.52h.04zm-9.6-2.52c-.597.76-1.066 1.61-1.39 2.52H2.65c.815-1.094 1.896-1.96 3.14-2.52zm-3.15 12H4.4c.324.91.793 1.76 1.39 2.52-1.248-.567-2.33-1.445-3.14-2.55l-.01.03zm9.56 2.52c.597-.76 1.066-1.61 1.39-2.52h1.76c-.82 1.08-1.9 1.933-3.14 2.48l-.01.04z" + /> + </svg> + </div> <div style={ Object { @@ -11783,8 +12716,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` grid </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -11796,8 +12729,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -11809,8 +12742,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -11840,8 +12773,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` group </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11853,8 +12786,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11866,8 +12799,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11897,8 +12830,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` heading </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -11910,8 +12843,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -11923,8 +12856,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -11954,8 +12887,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` help </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -11967,8 +12900,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -11980,8 +12913,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12011,8 +12944,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` html </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12020,12 +12953,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M4.5,11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5V11z M7,10.5h1.5V15H10v-4.5h1.5V9H7V10.5z M14.5,10l-1-1H12v6h1.5v-3.9 l1,1l1-1V15H17V9h-1.5L14.5,10z M19.5,13.5V9H18v6h5v-1.5H19.5z" + d="M4.8 11.4H2.1V9H1v6h1.1v-2.6h2.7V15h1.1V9H4.8v2.4zm1.9-1.3h1.7V15h1.1v-4.9h1.7V9H6.7v1.1zM16.2 9l-1.5 2.7L13.3 9h-.9l-.8 6h1.1l.5-4 1.5 2.8 1.5-2.8.5 4h1.1L17 9h-.8zm3.8 5V9h-1.1v6h3.6v-1H20z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12033,12 +12966,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M4.5,11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5V11z M7,10.5h1.5V15H10v-4.5h1.5V9H7V10.5z M14.5,10l-1-1H12v6h1.5v-3.9 l1,1l1-1V15H17V9h-1.5L14.5,10z M19.5,13.5V9H18v6h5v-1.5H19.5z" + d="M4.8 11.4H2.1V9H1v6h1.1v-2.6h2.7V15h1.1V9H4.8v2.4zm1.9-1.3h1.7V15h1.1v-4.9h1.7V9H6.7v1.1zM16.2 9l-1.5 2.7L13.3 9h-.9l-.8 6h1.1l.5-4 1.5 2.8 1.5-2.8.5 4h1.1L17 9h-.8zm3.8 5V9h-1.1v6h3.6v-1H20z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12046,7 +12979,7 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M4.5,11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5V11z M7,10.5h1.5V15H10v-4.5h1.5V9H7V10.5z M14.5,10l-1-1H12v6h1.5v-3.9 l1,1l1-1V15H17V9h-1.5L14.5,10z M19.5,13.5V9H18v6h5v-1.5H19.5z" + d="M4.8 11.4H2.1V9H1v6h1.1v-2.6h2.7V15h1.1V9H4.8v2.4zm1.9-1.3h1.7V15h1.1v-4.9h1.7V9H6.7v1.1zM16.2 9l-1.5 2.7L13.3 9h-.9l-.8 6h1.1l.5-4 1.5 2.8 1.5-2.8.5 4h1.1L17 9h-.8zm3.8 5V9h-1.1v6h3.6v-1H20z" /> </svg> </div> @@ -12068,8 +13001,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` image </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12081,8 +13014,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12094,8 +13027,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12125,8 +13058,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` info </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12134,12 +13067,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-5h-2v5zm0-7h2V8h-2v2z" + d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12147,12 +13080,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-5h-2v5zm0-7h2V8h-2v2z" + d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12160,7 +13093,7 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-5h-2v5zm0-7h2V8h-2v2z" + d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z" /> </svg> </div> @@ -12182,8 +13115,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` insertAfter </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12195,8 +13128,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12208,8 +13141,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12239,8 +13172,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` insertBefore </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12252,8 +13185,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12265,8 +13198,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12296,8 +13229,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` keyboardClose </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12309,8 +13242,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12322,8 +13255,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12353,8 +13286,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` keyboardReturn </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12366,8 +13299,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12379,8 +13312,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12410,8 +13343,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` layout </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12423,8 +13356,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12436,8 +13369,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12467,8 +13400,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` link </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12480,8 +13413,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12493,8 +13426,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12524,8 +13457,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` linkOff </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12537,8 +13470,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12550,8 +13483,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12581,8 +13514,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` list </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12594,8 +13527,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12607,8 +13540,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12638,8 +13571,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` mapMarker </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12651,8 +13584,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12664,8 +13597,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12695,8 +13628,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` media </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12708,8 +13641,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12721,8 +13654,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12752,8 +13685,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` mediaAndText </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12765,8 +13698,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12778,8 +13711,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12809,8 +13742,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` menu </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12822,8 +13755,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12835,8 +13768,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12866,8 +13799,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` minus </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -12879,8 +13812,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -12892,8 +13825,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -12905,6 +13838,63 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> </div> + <div + style={ + Object { + "alignItems": "center", + "display": "flex", + } + } + > + <strong + style={ + Object { + "width": "120px", + } + } + > + mobile + </strong> + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M15 4H9c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h6c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H9c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h6c.3 0 .5.2.5.5v12zm-4.5-.5h2V16h-2v1.5z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={36} + role="img" + viewBox="0 0 24 24" + width={36} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M15 4H9c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h6c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H9c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h6c.3 0 .5.2.5.5v12zm-4.5-.5h2V16h-2v1.5z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={48} + role="img" + viewBox="0 0 24 24" + width={48} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M15 4H9c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h6c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H9c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h6c.3 0 .5.2.5.5v12zm-4.5-.5h2V16h-2v1.5z" + /> + </svg> + </div> <div style={ Object { @@ -12923,8 +13913,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` more </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12936,8 +13926,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -12949,8 +13939,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -12980,8 +13970,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` moreHorizontal </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -12993,8 +13983,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13006,8 +13996,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13037,8 +14027,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` moreVertical </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13050,8 +14040,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13063,8 +14053,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13094,8 +14084,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` navigation </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13107,8 +14097,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13120,8 +14110,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13151,8 +14141,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` pageBreak </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13164,8 +14154,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13177,8 +14167,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13208,8 +14198,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` page </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -13221,8 +14211,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -13234,8 +14224,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -13265,8 +14255,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` paragraph </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13278,8 +14268,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13291,8 +14281,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13322,8 +14312,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` positionCenter </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13335,8 +14325,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13348,8 +14338,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13379,8 +14369,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` positionLeft </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13392,8 +14382,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13405,8 +14395,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13436,8 +14426,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` positionRight </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13449,8 +14439,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13462,8 +14452,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13493,8 +14483,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` pencil </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -13506,8 +14496,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -13519,8 +14509,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -13550,8 +14540,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` pin </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -13563,8 +14553,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -13576,8 +14566,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -13607,8 +14597,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` plugins </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -13620,8 +14610,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -13633,8 +14623,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -13664,8 +14654,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` plusCircleFilled </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13677,8 +14667,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13690,8 +14680,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13721,8 +14711,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` plusCircle </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -13734,8 +14724,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -13747,8 +14737,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -13778,8 +14768,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` plus </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -13791,8 +14781,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -13804,8 +14794,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -13835,150 +14825,42 @@ exports[`Storyshots Icons/Icon Library 1`] = ` postList </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" width={24} xmlns="http://www.w3.org/2000/svg" > - <rect - height="2" - width="6" - x="11" - y="7" - /> - <rect - height="2" - width="6" - x="11" - y="11" - /> - <rect - height="2" - width="6" - x="11" - y="15" - /> - <rect - height="2" - width="2" - x="7" - y="7" - /> - <rect - height="2" - width="2" - x="7" - y="11" - /> - <rect - height="2" - width="2" - x="7" - y="15" - /> <path - d="M20.1,3H3.9C3.4,3,3,3.4,3,3.9v16.2C3,20.5,3.4,21,3.9,21h16.2c0.4,0,0.9-0.5,0.9-0.9V3.9C21,3.4,20.5,3,20.1,3z M19,19H5V5h14V19z" + d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H6c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h12c.3 0 .5.2.5.5v12zM7 11h2V9H7v2zm0 4h2v-2H7v2zm3-4h7V9h-7v2zm0 4h7v-2h-7v2z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" width={36} xmlns="http://www.w3.org/2000/svg" > - <rect - height="2" - width="6" - x="11" - y="7" - /> - <rect - height="2" - width="6" - x="11" - y="11" - /> - <rect - height="2" - width="6" - x="11" - y="15" - /> - <rect - height="2" - width="2" - x="7" - y="7" - /> - <rect - height="2" - width="2" - x="7" - y="11" - /> - <rect - height="2" - width="2" - x="7" - y="15" - /> <path - d="M20.1,3H3.9C3.4,3,3,3.4,3,3.9v16.2C3,20.5,3.4,21,3.9,21h16.2c0.4,0,0.9-0.5,0.9-0.9V3.9C21,3.4,20.5,3,20.1,3z M19,19H5V5h14V19z" + d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H6c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h12c.3 0 .5.2.5.5v12zM7 11h2V9H7v2zm0 4h2v-2H7v2zm3-4h7V9h-7v2zm0 4h7v-2h-7v2z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" width={48} xmlns="http://www.w3.org/2000/svg" > - <rect - height="2" - width="6" - x="11" - y="7" - /> - <rect - height="2" - width="6" - x="11" - y="11" - /> - <rect - height="2" - width="6" - x="11" - y="15" - /> - <rect - height="2" - width="2" - x="7" - y="7" - /> - <rect - height="2" - width="2" - x="7" - y="11" - /> - <rect - height="2" - width="2" - x="7" - y="15" - /> <path - d="M20.1,3H3.9C3.4,3,3,3.4,3,3.9v16.2C3,20.5,3.4,21,3.9,21h16.2c0.4,0,0.9-0.5,0.9-0.9V3.9C21,3.4,20.5,3,20.1,3z M19,19H5V5h14V19z" + d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H6c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h12c.3 0 .5.2.5.5v12zM7 11h2V9H7v2zm0 4h2v-2H7v2zm3-4h7V9h-7v2zm0 4h7v-2h-7v2z" /> </svg> </div> @@ -14000,8 +14882,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` preformatted </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14013,8 +14895,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14026,8 +14908,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14057,8 +14939,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` pullLeft </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14070,8 +14952,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14083,8 +14965,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14114,8 +14996,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` pullRight </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14127,8 +15009,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14140,8 +15022,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14171,8 +15053,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` pullquote </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14184,8 +15066,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14197,8 +15079,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14228,8 +15110,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` quote </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14241,8 +15123,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14254,8 +15136,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14285,8 +15167,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` redo </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14298,8 +15180,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14311,8 +15193,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14342,8 +15224,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` replace </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14355,8 +15237,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14368,8 +15250,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14399,8 +15281,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` resizeCornerNE </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14412,8 +15294,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14425,8 +15307,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14456,8 +15338,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` rss </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14469,8 +15351,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14482,8 +15364,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14513,42 +15395,42 @@ exports[`Storyshots Icons/Icon Library 1`] = ` search </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={24} xmlns="http://www.w3.org/2000/svg" > <path - d="M12.14 4.18c1.87 1.87 2.11 4.75.72 6.89.12.1.22.21.36.31.2.16.47.36.81.59.34.24.56.39.66.47.42.31.73.57.94.78.32.32.6.65.84 1 .25.35.44.69.59 1.04.14.35.21.68.18 1-.02.32-.14.59-.36.81s-.49.34-.81.36c-.31.02-.65-.04-.99-.19-.35-.14-.7-.34-1.04-.59-.35-.24-.68-.52-1-.84-.21-.21-.47-.52-.77-.93-.1-.13-.25-.35-.47-.66-.22-.32-.4-.57-.56-.78-.16-.2-.29-.35-.44-.5-2.07 1.09-4.69.76-6.44-.98-2.14-2.15-2.14-5.64 0-7.78 2.15-2.15 5.63-2.15 7.78 0zm-1.41 6.36c1.36-1.37 1.36-3.58 0-4.95-1.37-1.37-3.59-1.37-4.95 0-1.37 1.37-1.37 3.58 0 4.95 1.36 1.37 3.58 1.37 4.95 0z" + d="M13.5 6C10.5 6 8 8.5 8 11.5c0 1.1.3 2.1.9 3l-3.4 3 1 1.1 3.4-2.9c1 .9 2.2 1.4 3.6 1.4 3 0 5.5-2.5 5.5-5.5C19 8.5 16.5 6 13.5 6zm0 9.5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={36} xmlns="http://www.w3.org/2000/svg" > <path - d="M12.14 4.18c1.87 1.87 2.11 4.75.72 6.89.12.1.22.21.36.31.2.16.47.36.81.59.34.24.56.39.66.47.42.31.73.57.94.78.32.32.6.65.84 1 .25.35.44.69.59 1.04.14.35.21.68.18 1-.02.32-.14.59-.36.81s-.49.34-.81.36c-.31.02-.65-.04-.99-.19-.35-.14-.7-.34-1.04-.59-.35-.24-.68-.52-1-.84-.21-.21-.47-.52-.77-.93-.1-.13-.25-.35-.47-.66-.22-.32-.4-.57-.56-.78-.16-.2-.29-.35-.44-.5-2.07 1.09-4.69.76-6.44-.98-2.14-2.15-2.14-5.64 0-7.78 2.15-2.15 5.63-2.15 7.78 0zm-1.41 6.36c1.36-1.37 1.36-3.58 0-4.95-1.37-1.37-3.59-1.37-4.95 0-1.37 1.37-1.37 3.58 0 4.95 1.36 1.37 3.58 1.37 4.95 0z" + d="M13.5 6C10.5 6 8 8.5 8 11.5c0 1.1.3 2.1.9 3l-3.4 3 1 1.1 3.4-2.9c1 .9 2.2 1.4 3.6 1.4 3 0 5.5-2.5 5.5-5.5C19 8.5 16.5 6 13.5 6zm0 9.5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={48} xmlns="http://www.w3.org/2000/svg" > <path - d="M12.14 4.18c1.87 1.87 2.11 4.75.72 6.89.12.1.22.21.36.31.2.16.47.36.81.59.34.24.56.39.66.47.42.31.73.57.94.78.32.32.6.65.84 1 .25.35.44.69.59 1.04.14.35.21.68.18 1-.02.32-.14.59-.36.81s-.49.34-.81.36c-.31.02-.65-.04-.99-.19-.35-.14-.7-.34-1.04-.59-.35-.24-.68-.52-1-.84-.21-.21-.47-.52-.77-.93-.1-.13-.25-.35-.47-.66-.22-.32-.4-.57-.56-.78-.16-.2-.29-.35-.44-.5-2.07 1.09-4.69.76-6.44-.98-2.14-2.15-2.14-5.64 0-7.78 2.15-2.15 5.63-2.15 7.78 0zm-1.41 6.36c1.36-1.37 1.36-3.58 0-4.95-1.37-1.37-3.59-1.37-4.95 0-1.37 1.37-1.37 3.58 0 4.95 1.36 1.37 3.58 1.37 4.95 0z" + d="M13.5 6C10.5 6 8 8.5 8 11.5c0 1.1.3 2.1.9 3l-3.4 3 1 1.1 3.4-2.9c1 .9 2.2 1.4 3.6 1.4 3 0 5.5-2.5 5.5-5.5C19 8.5 16.5 6 13.5 6zm0 9.5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z" /> </svg> </div> @@ -14570,8 +15452,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` separator </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14583,8 +15465,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14596,8 +15478,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14624,11 +15506,11 @@ exports[`Storyshots Icons/Icon Library 1`] = ` } } > - shortcode + share </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14636,12 +15518,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M16 4.2v1.5h2.5v12.5H16v1.5h4V4.2h-4zM4.2 19.8h4v-1.5H5.8V5.8h2.5V4.2h-4l-.1 15.6zm5.1-3.1l1.4.6 4-10-1.4-.6-4 10z" + d="M9 11.8l6.1-4.5c.1.4.4.7.9.7h2c.6 0 1-.4 1-1V5c0-.6-.4-1-1-1h-2c-.6 0-1 .4-1 1v.4l-6.4 4.8c-.2-.1-.4-.2-.6-.2H6c-.6 0-1 .4-1 1v2c0 .6.4 1 1 1h2c.2 0 .4-.1.6-.2l6.4 4.8v.4c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-2c0-.6-.4-1-1-1h-2c-.5 0-.8.3-.9.7L9 12.2v-.4z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14649,12 +15531,12 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M16 4.2v1.5h2.5v12.5H16v1.5h4V4.2h-4zM4.2 19.8h4v-1.5H5.8V5.8h2.5V4.2h-4l-.1 15.6zm5.1-3.1l1.4.6 4-10-1.4-.6-4 10z" + d="M9 11.8l6.1-4.5c.1.4.4.7.9.7h2c.6 0 1-.4 1-1V5c0-.6-.4-1-1-1h-2c-.6 0-1 .4-1 1v.4l-6.4 4.8c-.2-.1-.4-.2-.6-.2H6c-.6 0-1 .4-1 1v2c0 .6.4 1 1 1h2c.2 0 .4-.1.6-.2l6.4 4.8v.4c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-2c0-.6-.4-1-1-1h-2c-.5 0-.8.3-.9.7L9 12.2v-.4z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14662,7 +15544,7 @@ exports[`Storyshots Icons/Icon Library 1`] = ` xmlns="http://www.w3.org/2000/svg" > <path - d="M16 4.2v1.5h2.5v12.5H16v1.5h4V4.2h-4zM4.2 19.8h4v-1.5H5.8V5.8h2.5V4.2h-4l-.1 15.6zm5.1-3.1l1.4.6 4-10-1.4-.6-4 10z" + d="M9 11.8l6.1-4.5c.1.4.4.7.9.7h2c.6 0 1-.4 1-1V5c0-.6-.4-1-1-1h-2c-.6 0-1 .4-1 1v.4l-6.4 4.8c-.2-.1-.4-.2-.6-.2H6c-.6 0-1 .4-1 1v2c0 .6.4 1 1 1h2c.2 0 .4-.1.6-.2l6.4 4.8v.4c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-2c0-.6-.4-1-1-1h-2c-.5 0-.8.3-.9.7L9 12.2v-.4z" /> </svg> </div> @@ -14681,45 +15563,45 @@ exports[`Storyshots Icons/Icon Library 1`] = ` } } > - globe + shortcode </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={24} xmlns="http://www.w3.org/2000/svg" > <path - d="M9 0C4.03 0 0 4.03 0 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zM1.11 9.68h2.51c.04.91.167 1.814.38 2.7H1.84c-.403-.85-.65-1.764-.73-2.7zm8.57-5.4V1.19c.964.366 1.756 1.08 2.22 2 .205.347.386.708.54 1.08l-2.76.01zm3.22 1.35c.232.883.37 1.788.41 2.7H9.68v-2.7h3.22zM8.32 1.19v3.09H5.56c.154-.372.335-.733.54-1.08.462-.924 1.255-1.64 2.22-2.01zm0 4.44v2.7H4.7c.04-.912.178-1.817.41-2.7h3.21zm-4.7 2.69H1.11c.08-.936.327-1.85.73-2.7H4c-.213.886-.34 1.79-.38 2.7zM4.7 9.68h3.62v2.7H5.11c-.232-.883-.37-1.788-.41-2.7zm3.63 4v3.09c-.964-.366-1.756-1.08-2.22-2-.205-.347-.386-.708-.54-1.08l2.76-.01zm1.35 3.09v-3.04h2.76c-.154.372-.335.733-.54 1.08-.464.92-1.256 1.634-2.22 2v-.04zm0-4.44v-2.7h3.62c-.04.912-.178 1.817-.41 2.7H9.68zm4.71-2.7h2.51c-.08.936-.327 1.85-.73 2.7H14c.21-.87.337-1.757.38-2.65l.01-.05zm0-1.35c-.046-.894-.176-1.78-.39-2.65h2.16c.403.85.65 1.764.73 2.7l-2.5-.05zm1-4H13.6c-.324-.91-.793-1.76-1.39-2.52 1.244.56 2.325 1.426 3.14 2.52h.04zm-9.6-2.52c-.597.76-1.066 1.61-1.39 2.52H2.65c.815-1.094 1.896-1.96 3.14-2.52zm-3.15 12H4.4c.324.91.793 1.76 1.39 2.52-1.248-.567-2.33-1.445-3.14-2.55l-.01.03zm9.56 2.52c.597-.76 1.066-1.61 1.39-2.52h1.76c-.82 1.08-1.9 1.933-3.14 2.48l-.01.04z" + d="M16 4.2v1.5h2.5v12.5H16v1.5h4V4.2h-4zM4.2 19.8h4v-1.5H5.8V5.8h2.5V4.2h-4l-.1 15.6zm5.1-3.1l1.4.6 4-10-1.4-.6-4 10z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={36} xmlns="http://www.w3.org/2000/svg" > <path - d="M9 0C4.03 0 0 4.03 0 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zM1.11 9.68h2.51c.04.91.167 1.814.38 2.7H1.84c-.403-.85-.65-1.764-.73-2.7zm8.57-5.4V1.19c.964.366 1.756 1.08 2.22 2 .205.347.386.708.54 1.08l-2.76.01zm3.22 1.35c.232.883.37 1.788.41 2.7H9.68v-2.7h3.22zM8.32 1.19v3.09H5.56c.154-.372.335-.733.54-1.08.462-.924 1.255-1.64 2.22-2.01zm0 4.44v2.7H4.7c.04-.912.178-1.817.41-2.7h3.21zm-4.7 2.69H1.11c.08-.936.327-1.85.73-2.7H4c-.213.886-.34 1.79-.38 2.7zM4.7 9.68h3.62v2.7H5.11c-.232-.883-.37-1.788-.41-2.7zm3.63 4v3.09c-.964-.366-1.756-1.08-2.22-2-.205-.347-.386-.708-.54-1.08l2.76-.01zm1.35 3.09v-3.04h2.76c-.154.372-.335.733-.54 1.08-.464.92-1.256 1.634-2.22 2v-.04zm0-4.44v-2.7h3.62c-.04.912-.178 1.817-.41 2.7H9.68zm4.71-2.7h2.51c-.08.936-.327 1.85-.73 2.7H14c.21-.87.337-1.757.38-2.65l.01-.05zm0-1.35c-.046-.894-.176-1.78-.39-2.65h2.16c.403.85.65 1.764.73 2.7l-2.5-.05zm1-4H13.6c-.324-.91-.793-1.76-1.39-2.52 1.244.56 2.325 1.426 3.14 2.52h.04zm-9.6-2.52c-.597.76-1.066 1.61-1.39 2.52H2.65c.815-1.094 1.896-1.96 3.14-2.52zm-3.15 12H4.4c.324.91.793 1.76 1.39 2.52-1.248-.567-2.33-1.445-3.14-2.55l-.01.03zm9.56 2.52c.597-.76 1.066-1.61 1.39-2.52h1.76c-.82 1.08-1.9 1.933-3.14 2.48l-.01.04z" + d="M16 4.2v1.5h2.5v12.5H16v1.5h4V4.2h-4zM4.2 19.8h4v-1.5H5.8V5.8h2.5V4.2h-4l-.1 15.6zm5.1-3.1l1.4.6 4-10-1.4-.6-4 10z" /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" - viewBox="-2 -2 24 24" + viewBox="0 0 24 24" width={48} xmlns="http://www.w3.org/2000/svg" > <path - d="M9 0C4.03 0 0 4.03 0 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zM1.11 9.68h2.51c.04.91.167 1.814.38 2.7H1.84c-.403-.85-.65-1.764-.73-2.7zm8.57-5.4V1.19c.964.366 1.756 1.08 2.22 2 .205.347.386.708.54 1.08l-2.76.01zm3.22 1.35c.232.883.37 1.788.41 2.7H9.68v-2.7h3.22zM8.32 1.19v3.09H5.56c.154-.372.335-.733.54-1.08.462-.924 1.255-1.64 2.22-2.01zm0 4.44v2.7H4.7c.04-.912.178-1.817.41-2.7h3.21zm-4.7 2.69H1.11c.08-.936.327-1.85.73-2.7H4c-.213.886-.34 1.79-.38 2.7zM4.7 9.68h3.62v2.7H5.11c-.232-.883-.37-1.788-.41-2.7zm3.63 4v3.09c-.964-.366-1.756-1.08-2.22-2-.205-.347-.386-.708-.54-1.08l2.76-.01zm1.35 3.09v-3.04h2.76c-.154.372-.335.733-.54 1.08-.464.92-1.256 1.634-2.22 2v-.04zm0-4.44v-2.7h3.62c-.04.912-.178 1.817-.41 2.7H9.68zm4.71-2.7h2.51c-.08.936-.327 1.85-.73 2.7H14c.21-.87.337-1.757.38-2.65l.01-.05zm0-1.35c-.046-.894-.176-1.78-.39-2.65h2.16c.403.85.65 1.764.73 2.7l-2.5-.05zm1-4H13.6c-.324-.91-.793-1.76-1.39-2.52 1.244.56 2.325 1.426 3.14 2.52h.04zm-9.6-2.52c-.597.76-1.066 1.61-1.39 2.52H2.65c.815-1.094 1.896-1.96 3.14-2.52zm-3.15 12H4.4c.324.91.793 1.76 1.39 2.52-1.248-.567-2.33-1.445-3.14-2.55l-.01.03zm9.56 2.52c.597-.76 1.066-1.61 1.39-2.52h1.76c-.82 1.08-1.9 1.933-3.14 2.48l-.01.04z" + d="M16 4.2v1.5h2.5v12.5H16v1.5h4V4.2h-4zM4.2 19.8h4v-1.5H5.8V5.8h2.5V4.2h-4l-.1 15.6zm5.1-3.1l1.4.6 4-10-1.4-.6-4 10z" /> </svg> </div> @@ -14741,8 +15623,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` starEmpty </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -14754,8 +15636,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -14767,8 +15649,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -14798,8 +15680,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` starFilled </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -14811,8 +15693,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -14824,8 +15706,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -14855,8 +15737,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` starHalf </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -14868,8 +15750,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -14881,8 +15763,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -14912,8 +15794,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` stretchFullWidth </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14925,8 +15807,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14938,8 +15820,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -14969,8 +15851,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` stretchWide </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -14982,8 +15864,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -14995,8 +15877,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15026,8 +15908,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tableColumnAfter </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15039,8 +15921,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15052,8 +15934,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15083,8 +15965,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tableColumnBefore </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15096,8 +15978,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15109,8 +15991,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15140,8 +16022,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tableColumnDelete </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15153,8 +16035,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15166,8 +16048,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15197,8 +16079,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tableRowAfter </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15210,8 +16092,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15223,8 +16105,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15254,8 +16136,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tableRowBefore </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15267,8 +16149,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15280,8 +16162,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15311,8 +16193,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tableRowDelete </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15324,8 +16206,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15337,8 +16219,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15368,8 +16250,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` table </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15381,8 +16263,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15394,8 +16276,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15425,8 +16307,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` tag </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15438,8 +16320,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15451,8 +16333,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15482,8 +16364,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` textColor </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15495,8 +16377,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15508,8 +16390,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15521,6 +16403,63 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> </div> + <div + style={ + Object { + "alignItems": "center", + "display": "flex", + } + } + > + <strong + style={ + Object { + "width": "120px", + } + } + > + tablet + </strong> + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M17 4H7c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H7c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h10c.3 0 .5.2.5.5v12zm-7.5-.5h4V16h-4v1.5z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={36} + role="img" + viewBox="0 0 24 24" + width={36} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M17 4H7c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H7c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h10c.3 0 .5.2.5.5v12zm-7.5-.5h4V16h-4v1.5z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={48} + role="img" + viewBox="0 0 24 24" + width={48} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M17 4H7c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm.5 14c0 .3-.2.5-.5.5H7c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h10c.3 0 .5.2.5.5v12zm-7.5-.5h4V16h-4v1.5z" + /> + </svg> + </div> <div style={ Object { @@ -15539,8 +16478,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` title </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15552,8 +16491,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15565,8 +16504,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15596,8 +16535,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` trash </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15609,8 +16548,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15622,8 +16561,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15635,6 +16574,63 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> </div> + <div + style={ + Object { + "alignItems": "center", + "display": "flex", + } + } + > + <strong + style={ + Object { + "width": "120px", + } + } + > + typography + </strong> + <svg + aria-hidden={true} + focusable={false} + height={24} + role="img" + viewBox="0 0 24 24" + width={24} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M6.9 7L3 17.8h1.7l1-2.8h4.1l1 2.8h1.7L8.6 7H6.9zm-.7 6.6l1.5-4.3 1.5 4.3h-3zM21.6 17c-.1.1-.2.2-.3.2-.1.1-.2.1-.4.1s-.3-.1-.4-.2c-.1-.1-.1-.3-.1-.6V12c0-.5 0-1-.1-1.4-.1-.4-.3-.7-.5-1-.2-.2-.5-.4-.9-.5-.4 0-.8-.1-1.3-.1s-1 .1-1.4.2c-.4.1-.7.3-1 .4-.2.2-.4.3-.6.5-.1.2-.2.4-.2.7 0 .3.1.5.2.8.2.2.4.3.8.3.3 0 .6-.1.8-.3.2-.2.3-.4.3-.7 0-.3-.1-.5-.2-.7-.2-.2-.4-.3-.6-.4.2-.2.4-.3.7-.4.3-.1.6-.1.8-.1.3 0 .6 0 .8.1.2.1.4.3.5.5.1.2.2.5.2.9v1.1c0 .3-.1.5-.3.6-.2.2-.5.3-.9.4-.3.1-.7.3-1.1.4-.4.1-.8.3-1.1.5-.3.2-.6.4-.8.7-.2.3-.3.7-.3 1.2 0 .6.2 1.1.5 1.4.3.4.9.5 1.6.5.5 0 1-.1 1.4-.3.4-.2.8-.6 1.1-1.1 0 .4.1.7.3 1 .2.3.6.4 1.2.4.4 0 .7-.1.9-.2.2-.1.5-.3.7-.4h-.3zm-3-.9c-.2.4-.5.7-.8.8-.3.2-.6.2-.8.2-.4 0-.6-.1-.9-.3-.2-.2-.3-.6-.3-1.1 0-.5.1-.9.3-1.2s.5-.5.8-.7c.3-.2.7-.3 1-.5.3-.1.6-.3.7-.6v3.4z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={36} + role="img" + viewBox="0 0 24 24" + width={36} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M6.9 7L3 17.8h1.7l1-2.8h4.1l1 2.8h1.7L8.6 7H6.9zm-.7 6.6l1.5-4.3 1.5 4.3h-3zM21.6 17c-.1.1-.2.2-.3.2-.1.1-.2.1-.4.1s-.3-.1-.4-.2c-.1-.1-.1-.3-.1-.6V12c0-.5 0-1-.1-1.4-.1-.4-.3-.7-.5-1-.2-.2-.5-.4-.9-.5-.4 0-.8-.1-1.3-.1s-1 .1-1.4.2c-.4.1-.7.3-1 .4-.2.2-.4.3-.6.5-.1.2-.2.4-.2.7 0 .3.1.5.2.8.2.2.4.3.8.3.3 0 .6-.1.8-.3.2-.2.3-.4.3-.7 0-.3-.1-.5-.2-.7-.2-.2-.4-.3-.6-.4.2-.2.4-.3.7-.4.3-.1.6-.1.8-.1.3 0 .6 0 .8.1.2.1.4.3.5.5.1.2.2.5.2.9v1.1c0 .3-.1.5-.3.6-.2.2-.5.3-.9.4-.3.1-.7.3-1.1.4-.4.1-.8.3-1.1.5-.3.2-.6.4-.8.7-.2.3-.3.7-.3 1.2 0 .6.2 1.1.5 1.4.3.4.9.5 1.6.5.5 0 1-.1 1.4-.3.4-.2.8-.6 1.1-1.1 0 .4.1.7.3 1 .2.3.6.4 1.2.4.4 0 .7-.1.9-.2.2-.1.5-.3.7-.4h-.3zm-3-.9c-.2.4-.5.7-.8.8-.3.2-.6.2-.8.2-.4 0-.6-.1-.9-.3-.2-.2-.3-.6-.3-1.1 0-.5.1-.9.3-1.2s.5-.5.8-.7c.3-.2.7-.3 1-.5.3-.1.6-.3.7-.6v3.4z" + /> + </svg> + <svg + aria-hidden={true} + focusable={false} + height={48} + role="img" + viewBox="0 0 24 24" + width={48} + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M6.9 7L3 17.8h1.7l1-2.8h4.1l1 2.8h1.7L8.6 7H6.9zm-.7 6.6l1.5-4.3 1.5 4.3h-3zM21.6 17c-.1.1-.2.2-.3.2-.1.1-.2.1-.4.1s-.3-.1-.4-.2c-.1-.1-.1-.3-.1-.6V12c0-.5 0-1-.1-1.4-.1-.4-.3-.7-.5-1-.2-.2-.5-.4-.9-.5-.4 0-.8-.1-1.3-.1s-1 .1-1.4.2c-.4.1-.7.3-1 .4-.2.2-.4.3-.6.5-.1.2-.2.4-.2.7 0 .3.1.5.2.8.2.2.4.3.8.3.3 0 .6-.1.8-.3.2-.2.3-.4.3-.7 0-.3-.1-.5-.2-.7-.2-.2-.4-.3-.6-.4.2-.2.4-.3.7-.4.3-.1.6-.1.8-.1.3 0 .6 0 .8.1.2.1.4.3.5.5.1.2.2.5.2.9v1.1c0 .3-.1.5-.3.6-.2.2-.5.3-.9.4-.3.1-.7.3-1.1.4-.4.1-.8.3-1.1.5-.3.2-.6.4-.8.7-.2.3-.3.7-.3 1.2 0 .6.2 1.1.5 1.4.3.4.9.5 1.6.5.5 0 1-.1 1.4-.3.4-.2.8-.6 1.1-1.1 0 .4.1.7.3 1 .2.3.6.4 1.2.4.4 0 .7-.1.9-.2.2-.1.5-.3.7-.4h-.3zm-3-.9c-.2.4-.5.7-.8.8-.3.2-.6.2-.8.2-.4 0-.6-.1-.9-.3-.2-.2-.3-.6-.3-1.1 0-.5.1-.9.3-1.2s.5-.5.8-.7c.3-.2.7-.3 1-.5.3-.1.6-.3.7-.6v3.4z" + /> + </svg> + </div> <div style={ Object { @@ -15653,8 +16649,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` undo </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15666,8 +16662,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15679,8 +16675,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15710,8 +16706,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` update </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -15723,8 +16719,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -15736,8 +16732,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" @@ -15767,8 +16763,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` upload </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15780,8 +16776,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15793,8 +16789,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15824,8 +16820,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` verse </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15837,8 +16833,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15850,8 +16846,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15881,8 +16877,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` video </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15894,8 +16890,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15907,8 +16903,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15938,8 +16934,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` widget </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="0 0 24 24" @@ -15951,8 +16947,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="0 0 24 24" @@ -15964,8 +16960,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="0 0 24 24" @@ -15995,8 +16991,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` wordpress </strong> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={24} role="img" viewBox="-2 -2 24 24" @@ -16008,8 +17004,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={36} role="img" viewBox="-2 -2 24 24" @@ -16021,8 +17017,8 @@ exports[`Storyshots Icons/Icon Library 1`] = ` /> </svg> <svg - aria-hidden="true" - focusable="false" + aria-hidden={true} + focusable={false} height={48} role="img" viewBox="-2 -2 24 24" diff --git a/storybook/test/index.js b/storybook/test/index.js index 8752847743e0b8..fdaf755f6abcc7 100644 --- a/storybook/test/index.js +++ b/storybook/test/index.js @@ -25,7 +25,6 @@ initStoryshots( { const parentElement = document.createElement( 'div' ); parentElement.appendChild( currentElement ); } - return currentElement; }, } ) ), diff --git a/test/integration/full-content/server-registered.json b/test/integration/full-content/server-registered.json index 95514917078471..a17d53a4f227c7 100644 --- a/test/integration/full-content/server-registered.json +++ b/test/integration/full-content/server-registered.json @@ -1 +1 @@ -{"core\/archives":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"displayAsDropdown":{"type":"boolean","default":false},"showPostCounts":{"type":"boolean","default":false}}},"core\/block":{"attributes":{"ref":{"type":"number"}}},"core\/calendar":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"month":{"type":"integer"},"year":{"type":"integer"}}},"core\/categories":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"displayAsDropdown":{"type":"boolean","default":false},"showHierarchy":{"type":"boolean","default":false},"showPostCounts":{"type":"boolean","default":false}}},"core\/latest-comments":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"commentsToShow":{"type":"number","default":5,"minimum":1,"maximum":100},"displayAvatar":{"type":"boolean","default":true},"displayDate":{"type":"boolean","default":true},"displayExcerpt":{"type":"boolean","default":true}}},"core\/latest-posts":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"categories":{"type":"string"},"postsToShow":{"type":"number","default":5},"displayPostContent":{"type":"boolean","default":false},"displayPostContentRadio":{"type":"string","default":"excerpt"},"excerptLength":{"type":"number","default":55},"displayPostDate":{"type":"boolean","default":false},"postLayout":{"type":"string","default":"list"},"columns":{"type":"number","default":3},"order":{"type":"string","default":"desc"},"orderBy":{"type":"string","default":"date"},"displayFeaturedImage":{"type":"boolean","default":false},"featuredImageAlign":{"type":"string","enum":["left","center","right"]},"featuredImageSizeSlug":{"type":"string","default":"thumbnail"},"featuredImageSizeWidth":{"type":"number","default":null},"featuredImageSizeHeight":{"type":"number","default":null}}},"core\/legacy-widget":{"attributes":{"widgetClass":{"type":"string"},"id":{"type":"string"},"idBase":{"type":"string"},"number":{"type":"number"},"instance":{"type":"object"}}},"core\/navigation":{"attributes":{"className":{"type":"string"},"textColor":{"type":"string"},"customTextColor":{"type":"string"},"rgbTextColor":{"type":"string"},"backgroundColor":{"type":"string"},"customBackgroundColor":{"type":"string"},"rgbBackgroundColor":{"type":"string"},"fontSize":{"type":"string"},"customFontSize":{"type":"number"},"itemsJustification":{"type":"string"},"showSubmenuIcon":{"type":"boolean","default":true}}},"core\/post-comments-count":{"attributes":{"className":{"type":"string"}}},"core\/post-excerpt":{"attributes":{"wordCount":{"type":"number","default":55},"moreText":{"type":"string"},"showMoreOnNewLine":{"type":"boolean","default":true}}},"core\/rss":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"columns":{"type":"number","default":2},"blockLayout":{"type":"string","default":"list"},"feedURL":{"type":"string","default":""},"itemsToShow":{"type":"number","default":5},"displayExcerpt":{"type":"boolean","default":false},"displayAuthor":{"type":"boolean","default":false},"displayDate":{"type":"boolean","default":false},"excerptLength":{"type":"number","default":55}}},"core\/search":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"label":{"type":"string","default":"Search"},"placeholder":{"type":"string","default":""},"buttonText":{"type":"string","default":"Search"}}},"core\/tag-cloud":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"taxonomy":{"type":"string","default":"post_tag"},"showTagCounts":{"type":"boolean","default":false}}},"core\/template-part":{"attributes":{"postId":{"type":"number"},"slug":{"type":"string"},"theme":{"type":"string"}}}} +{"core\/archives":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"displayAsDropdown":{"type":"boolean","default":false},"showPostCounts":{"type":"boolean","default":false}}},"core\/block":{"attributes":{"ref":{"type":"number"}}},"core\/calendar":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"month":{"type":"integer"},"year":{"type":"integer"}}},"core\/categories":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"displayAsDropdown":{"type":"boolean","default":false},"showHierarchy":{"type":"boolean","default":false},"showPostCounts":{"type":"boolean","default":false}}},"core\/latest-comments":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"commentsToShow":{"type":"number","default":5,"minimum":1,"maximum":100},"displayAvatar":{"type":"boolean","default":true},"displayDate":{"type":"boolean","default":true},"displayExcerpt":{"type":"boolean","default":true}}},"core\/legacy-widget":{"attributes":{"widgetClass":{"type":"string"},"id":{"type":"string"},"idBase":{"type":"string"},"number":{"type":"number"},"instance":{"type":"object"}}},"core\/navigation":{"attributes":{"className":{"type":"string"},"textColor":{"type":"string"},"customTextColor":{"type":"string"},"rgbTextColor":{"type":"string"},"backgroundColor":{"type":"string"},"customBackgroundColor":{"type":"string"},"rgbBackgroundColor":{"type":"string"},"fontSize":{"type":"string"},"customFontSize":{"type":"number"},"itemsJustification":{"type":"string"},"showSubmenuIcon":{"type":"boolean","default":true}}},"core\/rss":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"columns":{"type":"number","default":2},"blockLayout":{"type":"string","default":"list"},"feedURL":{"type":"string","default":""},"itemsToShow":{"type":"number","default":5},"displayExcerpt":{"type":"boolean","default":false},"displayAuthor":{"type":"boolean","default":false},"displayDate":{"type":"boolean","default":false},"excerptLength":{"type":"number","default":55}}},"core\/search":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"label":{"type":"string","default":"Search"},"placeholder":{"type":"string","default":""},"buttonText":{"type":"string","default":"Search"}}},"core\/tag-cloud":{"attributes":{"align":{"type":"string","enum":["left","center","right","wide","full"]},"className":{"type":"string"},"taxonomy":{"type":"string","default":"post_tag"},"showTagCounts":{"type":"boolean","default":false}}},"core\/template-part":{"attributes":{"postId":{"type":"number"},"slug":{"type":"string"},"theme":{"type":"string"}}}} diff --git a/test/native/__mocks__/styleMock.js b/test/native/__mocks__/styleMock.js index 6a1481e6fe388f..55fa4dd0a954c9 100644 --- a/test/native/__mocks__/styleMock.js +++ b/test/native/__mocks__/styleMock.js @@ -90,4 +90,7 @@ module.exports = { blockBorder: { width: 1, }, + defaultBlock: { + marginTop: 16, + }, }; diff --git a/test/native/setup.js b/test/native/setup.js index 8dcf3c00f58dbd..7d656b41eafb42 100644 --- a/test/native/setup.js +++ b/test/native/setup.js @@ -13,6 +13,7 @@ jest.mock( 'react-native-gutenberg-bridge', () => { subscribeSetFocusOnTitle: jest.fn(), subscribeUpdateHtml: jest.fn(), subscribeMediaAppend: jest.fn(), + subscribeAndroidModalClosed: jest.fn(), subscribePreferredColorScheme: () => 'light', editorDidMount: jest.fn(), editorDidAutosave: jest.fn(), diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 00000000000000..afabdbaf82e30d --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,45 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "allowSyntheticDefaultImports": true, + "jsx": "preserve", + "target": "esnext", + "module": "esnext", + "lib": [ "dom", "esnext" ], + "declaration": true, + "declarationMap": true, + "composite": true, + "emitDeclarationOnly": true, + "isolatedModules": true, + + /* Strict Type-Checking Options */ + "strict": true, + "strictNullChecks": true, + "noImplicitAny": true, + + /* Additional Checks */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + + /* Module Resolution Options */ + "moduleResolution": "node", + + /* This needs to be false so our types are possible to consume without setting this */ + "esModuleInterop": false, + "resolveJsonModule": true, + + "typeRoots": [ "./node_modules/@types" ] + }, + "exclude": [ + "**/benchmark", + "**/test/**", + "**/build/**", + "**/build-*/**", + "**/*.android.js", + "**/*.ios.js", + "**/*.native.js" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 7a0eb51600233b..28f48647436b52 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,51 +1,24 @@ { - "compilerOptions": { - "allowJs": true, - "allowSyntheticDefaultImports": true, - "checkJs": true, - "jsx": "preserve", - "lib": ["dom", "esnext"], - "module": "commonjs", - "noEmit": true, - "resolveJsonModule": true, - "target": "esnext", - - /* Project Imports */ - "baseUrl": ".", - "paths": { - "@wordpress/*": [ - "packages/*/index.js", - "packages/*/src/index.js" - ] - }, - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - "strictNullChecks": true, - "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ - - /* Additional Checks */ - "noUnusedLocals": true, /* Report errors on unused locals. */ - "noUnusedParameters": true, /* Report errors on unused parameters. */ - "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - }, - "include": [ - "./packages/a11y/**/*.js", - "./packages/blob/**/*.js", - "./packages/dom-ready/**/*.js", - "./packages/i18n/**/*.js", - "./packages/is-shallow-equal/**/*.js", - "./packages/priority-queue/**/*.js", - "./packages/project-management-automation/**/*.js", - "./packages/token-list/**/*.js", - "./packages/url/src/**/*.js", - "./packages/warning/**/*.js", + "references": [ + { "path": "bin" }, + { "path": "packages/a11y" }, + { "path": "packages/autop" }, + { "path": "packages/blob" }, + { "path": "packages/block-editor" }, + { "path": "packages/element" }, + { "path": "packages/dom-ready" }, + { "path": "packages/escape-html" }, + { "path": "packages/html-entities" }, + { "path": "packages/i18n" }, + { "path": "packages/icons" }, + { "path": "packages/is-shallow-equal" }, + { "path": "packages/prettier-config" }, + { "path": "packages/primitives" }, + { "path": "packages/priority-queue" }, + { "path": "packages/project-management-automation" }, + { "path": "packages/token-list" }, + { "path": "packages/url" }, + { "path": "packages/warning" } ], - "exclude": [ - "./packages/*/benchmark", - "./packages/**/test/**", - "./packages/**/build/**", - "./packages/**/build-module/**" - ] + "files": [] } diff --git a/webpack.config.js b/webpack.config.js index 2251ffe338e383..e7663e00b4b1b3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,7 +26,7 @@ const { } = process.env; const WORDPRESS_NAMESPACE = '@wordpress/'; -const BUNDLED_PACKAGES = [ '@wordpress/icons' ]; +const BUNDLED_PACKAGES = [ '@wordpress/icons', '@wordpress/interface' ]; const gutenbergPackages = Object.keys( dependencies ) .filter(