Release/2.15.1 (#888)

* Feature: mobile ux improvements (#802)

* Inline Toolbar now works on mobile devices

* Some styles updates

* Inline Toolbar now detects left and rigth sides of content

* listen selection change only on touch devices

* improve toolbar paddings

* invalidate content rectangle cache on resize

* Toolbar now works on mobile devices

* prod bundle

* add changelog

* upd texts

* do not hide toolbar on window resize

* rm sever

* Added typeof method (#812)

* Add typeof method to check exact type of object #805

* Update changelog

* [Feature/issue-704]: Conversion toolbar (#787)

* [issue-748]: update Readme (#773)

* Do not start multi-block selection on UI elements (#662)

* Do not start multi-block selection on UI elements

* Do not prevent mousedown event on inline toolbar actions

* Remove log

* Add comment

* Add link to issue

closes #646

* Fix loss of pointer (#666)

* Fix loss of pointer when click is outside of the editor but selection is inside

* Remove log

* Update shortcuts module (#685)

* Fixed possible grammatical typo (#681)

Thanks

* Update shortcuts module

* update changelog

* update

* Remove margin top for inline-link icon (#690)

* Remove margin top for inline-link icon

resolves #674

* Update CHANGELOG.md

* Remove unused style

* Pull fresh tools

* Remove changelog contents from readme (#700)

* #665 API to open and close inline-toolbar (#711)

* API to open and close inline-toolbar

* Fixed documentation

* renamed inline -> inline-toolbar

* removed dist

* reset editor.js

* added editor.js bundle

* Fixed build error

* Null checks on toolbar/inline@open

* updated bundle

* Improve some comments

* Updatd api.md CHANGELOG.md

* Change feature to new instead of improvement

* Allow holderId work with ref on dom element (#710)

* done

* update types

* attempt to simplify code

* remove useless helper

* revert holderId logic and add holder property

* Apply suggestions from code review

Co-Authored-By: dimensi <eddimensi@gmail.com>

* update holder type on string | HTMLElement

* fix typo

* add deprecated notice and fix typos

* fix wrong compare

* fix comments

* swap console.log on _.log

* update types for editor config

* update examples

* update docs

* update build

* Activating Open Collective (#736)

Hi, I'm making updates for Open Collective. Either you or a supporter signed this repo up for Open Collective. This pull request adds backers and sponsors from your Open Collective https://opencollective.com/editorjs❤️

It adds two badges at the top to show the latest number of backers and sponsors. It also adds placeholders so that the avatar/logo of new backers/sponsors can automatically be shown without having to update your README.md. [more info](https://github.com/opencollective/opencollective/wiki/Github-banner). See how it looks on this [repo](https://github.com/apex/apex#backers).

You can also add a postinstall script to let people know after npm|yarn install that you are welcoming donations (optional). [More info](https://github.com/OpenCollective/opencollective-cli)
You can also add a "Donate" button to your website and automatically show your backers and sponsors there with our widgets. Have a look here: https://opencollective.com/widgets

P.S: As with any pull request, feel free to comment or suggest changes. The only thing "required" are the placeholders on the README because we believe it's important to acknowledge the people in your community that are contributing (financially or with code!).

Thank you for your great contribution to the open source community. You are awesome! 🙌
And welcome to the open collective community! 😊

Come chat with us in the #opensource channel on https://slack.opencollective.com - great place to ask questions and share best practices with other open source sustainers!

* Do not install editor.js as dev-dependency (#731)

Resolves #730

* Move codex-notifier to dependencies for typescript declarations (#728)

* Close inline toolbar after creating new link by pressing ENTER (#722)

* Method to clear current selection and close inline toolbar

* clearSelection with optional collapsed range

* refactored selection.ts

* removed experimental function

* Update src/components/selection.ts

Co-Authored-By: tanmayv <12tanmayvijay@gmail.com>

* update version, add changelog

* Link Logo Image to homepage (#738)

* Update README.md (#744)

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

Co-Authored-By: neSpecc <specc.dev@gmail.com>

* Config minHeight option that allows to customize bottom zone (#745)

* issue-739: allow Block's editable element selection (#747)

* issue-739: allow Block's input selection

* little improvements

* update Changelog and cache inputs

* small fix

* delete map file

* fix inputs.count condition

* Fix typo in example paragraph (#749)

* Fix typo

* Update example-dev.html

* minor release

* update link to the minified script

* bump version

* Prefer user settings during tools merge (#774)

* Prefer user settings during tools merge

* issue-705: Leaf BlockSettings and InlineTools via keyboard (#723)

* Do not start multi-block selection on UI elements (#662)

* Do not start multi-block selection on UI elements

* Do not prevent mousedown event on inline toolbar actions

* Remove log

* Add comment

* Add link to issue

closes #646

* Fix loss of pointer (#666)

* Fix loss of pointer when click is outside of the editor but selection is inside

* Remove log

* Update shortcuts module (#685)

* Fixed possible grammatical typo (#681)

Thanks

* Update shortcuts module

* update changelog

* update

* Remove margin top for inline-link icon (#690)

* Remove margin top for inline-link icon

resolves #674

* Update CHANGELOG.md

* Remove unused style

* Pull fresh tools

* Remove changelog contents from readme (#700)

* #665 API to open and close inline-toolbar (#711)

* API to open and close inline-toolbar

* Fixed documentation

* renamed inline -> inline-toolbar

* removed dist

* reset editor.js

* added editor.js bundle

* Fixed build error

* Null checks on toolbar/inline@open

* updated bundle

* Improve some comments

* Updatd api.md CHANGELOG.md

* Change feature to new instead of improvement

* leaf buttons: initial

* leaf inline toolbar buttons

* Allow holderId work with ref on dom element (#710)

* done

* update types

* attempt to simplify code

* remove useless helper

* revert holderId logic and add holder property

* Apply suggestions from code review

Co-Authored-By: dimensi <eddimensi@gmail.com>

* update holder type on string | HTMLElement

* fix typo

* add deprecated notice and fix typos

* fix wrong compare

* fix comments

* swap console.log on _.log

* update types for editor config

* update examples

* update docs

* update build

* leaf inline tools and drop index after click

* leaf toolbox and clear active button after activation

* debugging blockSettings

* Activating Open Collective (#736)

Hi, I'm making updates for Open Collective. Either you or a supporter signed this repo up for Open Collective. This pull request adds backers and sponsors from your Open Collective https://opencollective.com/editorjs❤️

It adds two badges at the top to show the latest number of backers and sponsors. It also adds placeholders so that the avatar/logo of new backers/sponsors can automatically be shown without having to update your README.md. [more info](https://github.com/opencollective/opencollective/wiki/Github-banner). See how it looks on this [repo](https://github.com/apex/apex#backers).

You can also add a postinstall script to let people know after npm|yarn install that you are welcoming donations (optional). [More info](https://github.com/OpenCollective/opencollective-cli)
You can also add a "Donate" button to your website and automatically show your backers and sponsors there with our widgets. Have a look here: https://opencollective.com/widgets

P.S: As with any pull request, feel free to comment or suggest changes. The only thing "required" are the placeholders on the README because we believe it's important to acknowledge the people in your community that are contributing (financially or with code!).

Thank you for your great contribution to the open source community. You are awesome! 🙌
And welcome to the open collective community! 😊

Come chat with us in the #opensource channel on https://slack.opencollective.com - great place to ask questions and share best practices with other open source sustainers!

* Do not install editor.js as dev-dependency (#731)

Resolves #730

* Move codex-notifier to dependencies for typescript declarations (#728)

* Close inline toolbar after creating new link by pressing ENTER (#722)

* Method to clear current selection and close inline toolbar

* clearSelection with optional collapsed range

* refactored selection.ts

* removed experimental function

* Update src/components/selection.ts

Co-Authored-By: tanmayv <12tanmayvijay@gmail.com>

* update version, add changelog

* Link Logo Image to homepage (#738)

* Update README.md (#744)

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

Co-Authored-By: neSpecc <specc.dev@gmail.com>

* Config minHeight option that allows to customize bottom zone (#745)

* issue-739: allow Block's editable element selection (#747)

* issue-739: allow Block's input selection

* little improvements

* update Changelog and cache inputs

* small fix

* delete map file

* fix inputs.count condition

* Fix typo in example paragraph (#749)

* Fix typo

* Update example-dev.html

* minor release

* done

* requested changes

* production build

* update package.json

* some improvements

* ready for testing

* update

* ready

* requested changes

* updates

* use setToBlock instead of focus

* active -> focused

* update

* refactor types

* fix inline tools flipping

* inhancements

* rm check for focus at the handleShowingEvent

* fix IT closing after second enter

* add animation to settings buttons

* Click animation

* Add changelog

* do not patch version

* conversion toolbar

* positioning and flipping initial

* conversion toolbar is ready

* save changes

* update

* bump version

* save changes

* ready

* open conversion toolbar via keyup

* save changes

* ready to be reviewed

* restore some useless changes

* several improvements

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* ready

* Update src/components/modules/toolbar/conversion.ts

Co-Authored-By: Peter Savchenko <specc.dev@gmail.com>

* requested changes

* update

* update comment

* define types

* simplify keydowns

* Update blockEvents.ts

* Don't use handleShowingEvent to close Inline/Conversion Toolbars

* battle with events

* bundle

* bundle

* rm console.trace

* bundle

* small improvements

* improve types description

* add docs, improve types

* improve anchor links

* fix move

* fix toolbar movement

* conversion toolbar fix movement

* improve margins

* bundle

* add changelog

* rm commented code

* tools goes to master

* Enable cross-block mouse selection (#737)

* Add support of different link types (#817)

* [Fix]: issue with leading new lines (#816)

* [Fix] Tool setting types (#825)

* [Feature]: insert() API method (#814)

* [Fix]: Handle native inputs changes (#815)

* [Feature] Keyboard cbs (#824)

* Updated Readme.md (#811)

* Update CHANGELOG.md

* Add option to disable paste handling (#813)

* Fix: hide Inlie Toolbar when user strart typing

* Enable cbs only for left mouse button

* Change changelog order

* Update submodules

* Update bundle

* 2.16.0

* [Refactor] Separate internal and external settings (#845)

* Enable flipping tools via standalone class (#830)

* Enable flipping tools via standalone class

* use flipper to refactor (#842)

* use flipper to refactor

* save changes

* update

* fix flipper on inline toolbar

* ready for testing

* requested changes

* update doc

* updates

* destroy flippers

* some requested changes

* update

* update

* ready

* update

* last changes

* update docs

* Hghl active button of CT, simplify activate/deactivate

* separate dom iterator

* unhardcode directions

* fixed a link in readme.md (#856)

* Fix Block selection via CMD+A (#829)

* Fix Block selection via CMD+A

* Delete editor.js.map

* update

* update

* Update CHANGELOG.md

* Improve style of selected blocks (#858)

* Cross-block-selection style improved

* Update CHANGELOG.md

* Fix case when property 'observer' in modificationObserver is not defined (#866)

* Bump lodash.template from 4.4.0 to 4.5.0 (#885)

Bumps [lodash.template](https://github.com/lodash/lodash) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.4.0...4.5.0)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump eslint-utils from 1.3.1 to 1.4.2 (#886)

Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.3.1 to 1.4.2.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.3.1...v1.4.2)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump mixin-deep from 1.3.1 to 1.3.2 (#887)

Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot[bot] <support@github.com>

* update bundle and readme

* Update README.md

* upd codeowners, fix funding

* rebuild

* Update CHANGELOG.md

* Fix flipper tab after enter behaviour (#889)

* Fix flipper tab after enter behaviour

* Fix: case when fillper opens to wrong block and disallow navigation by up/down

* Update src/components/flipper.ts

Co-Authored-By: Murod Khaydarov <murod.haydarov@gmail.com>
This commit is contained in:
Peter Savchenko 2019-09-09 13:03:18 +03:00 committed by GitHub
parent 13dc0c9bad
commit 0600233e63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 818 additions and 614 deletions

2
.github/FUNDING.yml vendored
View file

@ -1,5 +1,5 @@
# These are supported funding model platforms
github: codex-team/editor.js
github: neSpecc
patreon: editorjs
open_collective: editorjs

View file

@ -1 +1 @@
* @neSpecc @gohabereg @khaydarov @talyguryn
* @neSpecc @gohabereg @khaydarov

View file

@ -8,21 +8,35 @@
[![](https://flat.badgen.net/npm/license/@editorjs/editorjs)](https://www.npmjs.com/package/@editorjs/editorjs)
[![Join the chat at https://gitter.im/codex-team/editor.js](https://badges.gitter.im/codex-team/editor.js.svg)](https://gitter.im/codex-team/editor.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Version 2.0 is here!
We are glad to introduce the next version of Editor.js. Totally new core, structure and plugins — that was an impressive adventure 🤓.
Join [public Telegram-chat](//t.me/codex_editor) or [Gitter-channel](https://gitter.im/codex-team/editor.js) where you can always find a support.
### Browsers support
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera |
| --------- | --------- | --------- | --------- | --------- | --------- |
| Edge 12+ | Firefox 18+ | Chrome 49+ | Safari 10+ | Safari 10+ | Opera 36+
## ⭐️ If you like a project
## If you like a project 💗💗💗
If you like Editor.js you can support project improvements and development of new features with a small donation on [Open Collective](https://opencollective.com/editorjs) or [Patreon](https://www.patreon.com/editorjs)
If you like Editor.js you can support project improvements and development of new features with a donation to our collective.
👉 [https://opencollective.com/editorjs](https://opencollective.com/editorjs)
👉 Bitcoin: `3DCCemgtE6GrzehVpU6Sa2RJHFUUh8iT9q`
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/editorjs#sponsor)]
<a href="https://opencollective.com/editorjs/sponsor/0/website" target="_blank"><img src="https://opencollective.com/editorjs/sponsor/0/avatar.svg"></a>
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/editorjs#backer)]
<a href="https://opencollective.com/editorjs#backers" target="_blank"><img src="https://opencollective.com/editorjs/backers.svg?width=890"></a>
### Contributors
This project exists thanks to all the people who contribute. <img src="https://opencollective.com/editorjs/contributors.svg?width=890&button=false" />
We are really welcome new contributors. If you want to make some code with us, please take a look at the [Good First Tasks](https://github.com/codex-team/editor.js/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+task%22). You can write to us on `team@codex.so` or via special [Telegram chat](https://t.me/editorjsdev), or any other way.
## Documentation
@ -37,15 +51,13 @@ Please, visit [https://editorjs.io/](https://editorjs.io) to view all documentat
You can join a [Gitter-channel](https://gitter.im/codex-team/editor.js) or [Telegram-chat](//t.me/codex_editor) and ask a question.
---
## Changelog
See a whole [Changelog](/docs/CHANGELOG.md)
# So how to use Editor.js
## So how to use Editor.js
## Basics
### Basics
Editor.js is a Block-Styled editor. Blocks are structural units, of which the Entry is composed.
For example, `Paragraph`, `Heading`, `Image`, `Video`, `List` are Blocks. Each Block is represented by Plugin.
@ -69,7 +81,7 @@ or apply Tool's settings, if it provided. For example, set a Heading level or Li
![](https://capella.pics/01a55381-46cd-47c7-b92e-34765434f2ca.jpg)
## Shortcuts
### Shortcuts
We really appreciate shortcuts. So there are few presets.
@ -103,7 +115,7 @@ var editor = new EditorJS({
```
# Installation Guide
## Installation Guide
There are few steps to run Editor.js on your site.
@ -111,7 +123,7 @@ There are few steps to run Editor.js on your site.
2. [Load Tools](#load-tools)
3. [Initialize Editor's instance](#create-editor-instance)
## Load Editor's core
### Load Editor's core
Firstly you need to get Editor.js itself. It is a [minified script](dist/editor.js) with Editor's core and some default must-have tools.
@ -121,7 +133,7 @@ Choose the most usable method of getting Editor for you.
- Source from CDN
- Local file from project
### Node.js
#### Node.js
Install the package via NPM or Yarn
@ -135,7 +147,7 @@ Include module in your application
const EditorJS = require('@editorjs/editorjs');
```
### Use from CDN
#### Use from CDN
You can load specific version of package from [jsDelivr CDN](https://www.jsdelivr.com/package/npm/@editorjs/editorjs).
@ -147,15 +159,15 @@ Then require this script.
<script src="..."></script>
```
### Save sources to project
#### Save sources to project
Copy [editor.js](build/editor.js) file to your project and load it.
Copy [editor.js](dist/editor.js) file to your project and load it.
```html
<script src="editor.js"></script>
```
## Load Tools
### Load Tools
Each Block at the Editor.js is represented by [Tools](docs/tools.md). There are simple external scripts with their own logic. Probably you want to use several Block Tools that should be connected.
@ -171,7 +183,7 @@ Check [Editor.js's community](https://github.com/editor-js/) to see more ready-t
<script src="https://cdn.jsdelivr.net/npm/codex.editor.header@2.0.4/dist/bundle.js"></script>
```
## Create Editor instance
### Create Editor instance
Create an instance of Editor.js and pass [Configuration Object](types/configs/editor-config.d.ts) with `holderId` and tools list.
@ -217,7 +229,7 @@ var editor = new EditorJS({
});
```
## Saving Data
### Saving Data
Call `editor.save()` and handle returned Promise with saved data.
@ -228,7 +240,7 @@ editor.save()
});
```
## Example
### Example
Take a look at the [example.html](example/example.html) to view more detailed examples.
@ -236,31 +248,7 @@ Take a look at the [example.html](example/example.html) to view more detailed ex
- We use [HTMLJanitor](https://github.com/guardian/html-janitor) module in our Sanitizer module.
# Support project improvements
Love Editor.js? Please consider supporting our collective:
👉 [https://opencollective.com/editorjs](https://opencollective.com/editorjs)
👉 [Patreon](https://www.patreon.com/editorjs)
## Contributors
This project exists thanks to all the people who contribute. <img src="https://opencollective.com/editorjs/contributors.svg?width=890&button=false" />
## Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/editorjs#backer)]
<a href="https://opencollective.com/editorjs#backers" target="_blank"><img src="https://opencollective.com/editorjs/backers.svg?width=890"></a>
## Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/editorjs#sponsor)]
<a href="https://opencollective.com/editorjs/sponsor/0/website" target="_blank"><img src="https://opencollective.com/editorjs/sponsor/0/avatar.svg"></a>
# About team
## About team
We are CodeX and we build products for developers and makers.

10
dist/editor.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,13 @@
# Changelog
### 2.15.1
- `Refactoring` — Constants of tools settings separated by internal and external to correspond API
- `Refactoring` — Created universal Flipper class that responses for navigation by keyboard inside of any Toolbars
- `Fix` — First CMD+A on block with now uses default behaviour. Fixed problem with second CMD+A after selection clearing [#827](https://github.com/codex-team/editor.js/issues/827)
- `Improvements` — Style of inline selection and selected blocks improved
- `Fix` - Fixed problem when property 'observer' in modificationObserver is not defined
### 2.15
- `New` — New [`blocks.insert()`](api.md) API method [#715](https://github.com/codex-team/editor.js/issues/715).

View file

@ -1,6 +1,6 @@
{
"name": "@editorjs/editorjs",
"version": "2.15.0",
"version": "2.15.1",
"description": "Editor.js — Native JS, based on API and Open Source",
"main": "dist/editor.js",
"types": "./types/index.d.ts",

View file

@ -519,85 +519,6 @@ export default class Dom {
}, []);
}
/**
* Leafs nodes inside the target list from active element
*
* @param {HTMLElement[]} nodeList - target list of nodes
* @param {number} activeIndex index of active node. By default it must be -1
* @param {string} direction - leaf direction. Can be 'left' or 'right'
* @param {string} activeCSSClass - css class that will be added
*
* @return {Number} index of active node
*/
public static leafNodesAndReturnIndex(
nodeList: HTMLElement[],
activeIndex: number,
direction: string,
activeCSSClass: string,
): number {
/**
* If activeButtonIndex === -1 then we have no chosen Tool in Toolbox
*/
if (activeIndex === -1) {
/**
* Normalize "previous" Tool index depending on direction.
* We need to do this to highlight "first" Tool correctly
*
* Order of Tools: [0] [1] ... [n - 1]
* [0 = n] because of: n % n = 0 % n
*
* Direction 'right': for [0] the [n - 1] is a previous index
* [n - 1] -> [0]
*
* Direction 'left': for [n - 1] the [0] is a previous index
* [n - 1] <- [0]
*
* @type {number}
*/
activeIndex = direction === 'right' ? -1 : 0;
} else {
/**
* If we have chosen Tool then remove highlighting
*/
nodeList[activeIndex].classList.remove(activeCSSClass);
}
/**
* Count index for next Tool
*/
if (direction === 'right') {
/**
* If we go right then choose next (+1) Tool
* @type {number}
*/
activeIndex = (activeIndex + 1) % nodeList.length;
} else {
/**
* If we go left then choose previous (-1) Tool
* Before counting module we need to add length before because of "The JavaScript Modulo Bug"
* @type {number}
*/
activeIndex = (nodeList.length + activeIndex - 1) % nodeList.length;
}
if (Dom.isNativeInput(nodeList[activeIndex])) {
/**
* Focus input
*/
nodeList[activeIndex].focus();
}
/**
* Highlight new chosen Tool
*/
nodeList[activeIndex].classList.add(activeCSSClass);
/**
* Return Active index
*/
return activeIndex;
}
/*
* Helper for get holder from {string} or return HTMLElement
* @param element

View file

@ -0,0 +1,163 @@
import Dom from './dom';
/**
* Iterator above passed Elements list.
* Each next or previous action adds provides CSS-class and sets cursor to this item
*/
export default class DomIterator {
/**
* This is a static property that defines iteration directions
* @type {{RIGHT: string, LEFT: string}}
*/
public static directions = {
RIGHT: 'right',
LEFT: 'left',
};
/**
* User-provided CSS-class name for focused button
*/
private focusedCssClass: string;
/**
* Focused button index.
* Default is -1 which means nothing is active
* @type {number}
*/
private cursor: number = -1;
/**
* Items to flip
*/
private items: HTMLElement[] = [];
/**
* @param {HTMLElement[]} nodeList the list of iterable HTML-items
* @param {string} focusedCssClass - user-provided CSS-class that will be set in flipping process
*/
constructor(
nodeList: HTMLElement[],
focusedCssClass: string,
) {
this.items = nodeList || [];
this.focusedCssClass = focusedCssClass;
}
/**
* Returns Focused button Node
* @return {HTMLElement}
*/
public get currentItem(): HTMLElement {
if (this.cursor === -1) {
return null;
}
return this.items[this.cursor];
}
/**
* Sets items. Can be used when iterable items changed dynamically
* @param {HTMLElement[]} nodeList
*/
public setItems(nodeList: HTMLElement[]): void {
this.items = nodeList;
}
/**
* Sets cursor next to the current
*/
public next(): void {
this.cursor = this.leafNodesAndReturnIndex(DomIterator.directions.RIGHT);
}
/**
* Sets cursor before current
*/
public previous(): void {
this.cursor = this.leafNodesAndReturnIndex(DomIterator.directions.LEFT);
}
/**
* Sets cursor to the default position and removes CSS-class from previously focused item
*/
public dropCursor(): void {
if (this.cursor === -1) {
return;
}
this.items[this.cursor].classList.remove(this.focusedCssClass);
this.cursor = -1;
}
/**
* Leafs nodes inside the target list from active element
*
* @param {string} direction - leaf direction. Can be 'left' or 'right'
* @return {Number} index of focused node
*/
private leafNodesAndReturnIndex(direction: string): number {
let focusedButtonIndex = this.cursor;
/**
* If activeButtonIndex === -1 then we have no chosen Tool in Toolbox
*/
if (focusedButtonIndex === -1) {
/**
* Normalize "previous" Tool index depending on direction.
* We need to do this to highlight "first" Tool correctly
*
* Order of Tools: [0] [1] ... [n - 1]
* [0 = n] because of: n % n = 0 % n
*
* Direction 'right': for [0] the [n - 1] is a previous index
* [n - 1] -> [0]
*
* Direction 'left': for [n - 1] the [0] is a previous index
* [n - 1] <- [0]
*
* @type {number}
*/
focusedButtonIndex = direction === DomIterator.directions.RIGHT ? -1 : 0;
} else {
/**
* If we have chosen Tool then remove highlighting
*/
this.items[focusedButtonIndex].classList.remove(this.focusedCssClass);
}
/**
* Count index for next Tool
*/
if (direction === DomIterator.directions.RIGHT) {
/**
* If we go right then choose next (+1) Tool
* @type {number}
*/
focusedButtonIndex = (focusedButtonIndex + 1) % this.items.length;
} else {
/**
* If we go left then choose previous (-1) Tool
* Before counting module we need to add length before because of "The JavaScript Modulo Bug"
* @type {number}
*/
focusedButtonIndex = (this.items.length + focusedButtonIndex - 1) % this.items.length;
}
if (Dom.isNativeInput(this.items[focusedButtonIndex])) {
/**
* Focus input
*/
this.items[focusedButtonIndex].focus();
}
/**
* Highlight new chosen Tool
*/
this.items[focusedButtonIndex].classList.add(this.focusedCssClass);
/**
* Return focused button's index
*/
return focusedButtonIndex;
}
}

249
src/components/flipper.ts Normal file
View file

@ -0,0 +1,249 @@
import DomIterator from './domIterator';
import _ from './utils';
/**
* Flipper construction options
*/
export interface FlipperOptions {
/**
* CSS-modifier for focused item
*/
focusedItemClass?: string;
/**
* If flipping items are the same for all Block (for ex. Toolbox), ypu can pass it on constructing
*/
items?: HTMLElement[];
/**
* Defines arrows usage. By default Flipper leafs items also via RIGHT/LEFT.
*
* true by default
*
* Pass 'false' if you don't need this behaviour
* (for example, Inline Toolbar should be closed by arrows,
* because it means caret moving with selection clearing)
*/
allowArrows?: boolean;
/**
* Optional callback for button click
*/
activateCallback?: () => void;
}
/**
* Flipper is a component that iterates passed items array by TAB or Arrows and clicks it by ENTER
*/
export default class Flipper {
/**
* Instance of flipper iterator
* @type {DomIterator|null}
*/
private readonly iterator: DomIterator = null;
/**
* Flag that defines activation status
* @type {boolean}
*/
private activated: boolean = false;
/**
* Flag that allows arrows usage to flip items
* @type {boolean}
*/
private readonly allowArrows: boolean = true;
/**
* Call back for button click/enter
*/
private readonly activateCallback: () => void;
/**
* @constructor
*
* @param {FlipperOptions} options - different constructing settings
* @
*/
constructor(options: FlipperOptions) {
this.allowArrows = typeof options.allowArrows === 'boolean' ? options.allowArrows : true;
this.iterator = new DomIterator(options.items, options.focusedItemClass);
this.activateCallback = options.activateCallback;
/**
* Listening all keydowns on document and react on TAB/Enter press
* TAB will leaf iterator items
* ENTER will click the focused item
*/
document.addEventListener('keydown', (event) => {
const isReady = this.isEventReadyForHandling(event);
if (!isReady) {
return;
}
/**
* Prevent only used keys default behaviour
* (allows to navigate by ARROW DOWN, for example)
*/
if (Flipper.usedKeys.includes(event.keyCode)) {
event.preventDefault();
}
switch (event.keyCode) {
case _.keyCodes.TAB:
this.handleTabPress(event);
break;
case _.keyCodes.LEFT:
this.flipLeft();
break;
case _.keyCodes.RIGHT:
this.flipRight();
break;
case _.keyCodes.ENTER:
this.handleEnterPress(event);
break;
}
}, false);
}
/**
* Array of keys (codes) that is handled by Flipper
* Used to:
* - preventDefault only for this keys, not all keywdowns (@see constructor)
* - to skip external behaviours only for these keys, when filler is activated (@see BlockEvents@arrowRightAndDown)
*/
public static get usedKeys(): number[] {
return [
_.keyCodes.TAB,
_.keyCodes.LEFT,
_.keyCodes.RIGHT,
_.keyCodes.ENTER,
];
}
/**
* Active tab/arrows handling by flipper
* @param {HTMLElement[]} items - Some modules (like, InlineToolbar, BlockSettings) might refresh buttons dynamically
*/
public activate(items?: HTMLElement[]): void {
this.activated = true;
if (items) {
this.iterator.setItems(items);
}
}
/**
* Disable tab/arrows handling by flipper
*/
public deactivate(): void {
this.activated = false;
this.dropCursor();
}
/**
* Return current focused button
* @return {HTMLElement|null}
*/
public get currentItem(): HTMLElement|null {
return this.iterator.currentItem;
}
/**
* Focus first item
*/
public focusFirst(): void {
this.dropCursor();
this.flipRight();
}
/**
* Drops flipper's iterator cursor
* @see DomIterator#dropCursor
*/
private dropCursor(): void {
this.iterator.dropCursor();
}
/**
* This function is fired before handling flipper keycodes
* The result of this function defines if it is need to be handled or not
* @param {KeyboardEvent} event
* @return {boolean}
*/
private isEventReadyForHandling(event: KeyboardEvent): boolean {
const handlingKeyCodeList = [
_.keyCodes.TAB,
_.keyCodes.ENTER,
];
if (this.allowArrows) {
handlingKeyCodeList.push(
_.keyCodes.LEFT,
_.keyCodes.RIGHT,
);
}
if (!this.activated || handlingKeyCodeList.indexOf(event.keyCode) === -1) {
return false;
}
return true;
}
/**
* When flipper is activated tab press will leaf the items
* @param {KeyboardEvent} event
*/
private handleTabPress(event: KeyboardEvent): void {
/** this property defines leaf direction */
const shiftKey = event.shiftKey,
direction = shiftKey ? DomIterator.directions.LEFT : DomIterator.directions.RIGHT;
switch (direction) {
case DomIterator.directions.RIGHT:
this.flipRight();
break;
case DomIterator.directions.LEFT:
this.flipLeft();
break;
}
}
/**
* Focuses previous flipper iterator item
*/
private flipLeft(): void {
this.iterator.previous();
}
/**
* Focuses next flipper iterator item
*/
private flipRight(): void {
this.iterator.next();
}
/**
* Enter press will click current item if flipper is activated
* @param {KeyboardEvent} event
*/
private handleEnterPress(event: KeyboardEvent): void {
if (!this.activated) {
return;
}
if (this.iterator.currentItem) {
this.iterator.currentItem.click();
}
if (typeof this.activateCallback === 'function') {
this.activateCallback();
}
event.preventDefault();
event.stopPropagation();
}
}

View file

@ -4,6 +4,7 @@
import Module from '../__module';
import _ from '../utils';
import SelectionUtils from '../selection';
import Flipper from "../flipper";
export default class BlockEvents extends Module {
@ -101,7 +102,7 @@ export default class BlockEvents extends Module {
return;
}
const { InlineToolbar, ConversionToolbar, UI, BlockManager } = this.Editor;
const { InlineToolbar, ConversionToolbar, UI, BlockManager, BlockSettings } = this.Editor;
const block = BlockManager.getBlock(event.target);
/**
@ -110,6 +111,7 @@ export default class BlockEvents extends Module {
*/
if (SelectionUtils.almostAllSelected(block.pluginsContent.textContent)) {
InlineToolbar.close();
BlockSettings.close();
ConversionToolbar.tryToShow(block);
} else {
ConversionToolbar.close();
@ -165,6 +167,12 @@ export default class BlockEvents extends Module {
* @param {MouseEvent} event
*/
public mouseDown(event: MouseEvent): void {
/**
* Each mouse down on Block must disable selectAll state
*/
if (!SelectionUtils.isCollapsed) {
this.Editor.BlockSelection.clearSelection(event);
}
this.Editor.CrossBlockSelection.watchSelection(event);
}
@ -178,36 +186,24 @@ export default class BlockEvents extends Module {
*/
this.Editor.BlockSelection.clearSelection(event);
const { BlockManager, Tools, ConversionToolbar, InlineToolbar } = this.Editor;
const { BlockManager, Tools, InlineToolbar, ConversionToolbar } = this.Editor;
const currentBlock = BlockManager.currentBlock;
if (!currentBlock) {
return;
}
/** Prevent Default behaviour */
event.preventDefault();
event.stopPropagation();
/** this property defines leaf direction */
const shiftKey = event.shiftKey,
direction = shiftKey ? 'left' : 'right';
const canLeafToolbox = Tools.isInitial(currentBlock.tool) && currentBlock.isEmpty;
const canLeafInlineToolbar = !currentBlock.isEmpty && !SelectionUtils.isCollapsed && InlineToolbar.opened;
const canLeafConversionToolbar = !currentBlock.isEmpty && ConversionToolbar.opened;
const canOpenToolbox = Tools.isInitial(currentBlock.tool) && currentBlock.isEmpty;
const conversionToolbarOpened = !currentBlock.isEmpty && ConversionToolbar.opened;
const inlineToolbarOpened = !currentBlock.isEmpty && !SelectionUtils.isCollapsed && InlineToolbar.opened;
/**
* For empty Blocks we show Plus button via Toobox only for initial Blocks
* For empty Blocks we show Plus button via Toolbox only for initial Blocks
*/
if (canLeafToolbox) {
this.leafToolboxTools(direction);
} else if (canLeafInlineToolbar) {
this.leafInlineToolbarTools(direction);
} else if (canLeafConversionToolbar) {
this.leafConversionToolbarTools(direction);
} else {
this.leafBlockSettingsTools(direction);
if (canOpenToolbox) {
this.activateToolbox();
} else if (!conversionToolbarOpened && !inlineToolbarOpened) {
this.activateBlockSettings();
}
}
@ -229,6 +225,8 @@ export default class BlockEvents extends Module {
this.Editor.BlockSettings.close();
} else if (this.Editor.InlineToolbar.opened) {
this.Editor.InlineToolbar.close();
} else if (this.Editor.ConversionToolbar.opened) {
this.Editor.ConversionToolbar.close();
} else {
this.Editor.Toolbar.close();
}
@ -312,7 +310,7 @@ export default class BlockEvents extends Module {
* @param {KeyboardEvent} event - keydown
*/
private enter(event: KeyboardEvent): void {
const { BlockManager, Toolbox, BlockSettings, InlineToolbar, ConversionToolbar, Tools } = this.Editor;
const { BlockManager, Tools, UI } = this.Editor;
const currentBlock = BlockManager.currentBlock;
const tool = Tools.available[currentBlock.name];
@ -320,29 +318,14 @@ export default class BlockEvents extends Module {
* Don't handle Enter keydowns when Tool sets enableLineBreaks to true.
* Uses for Tools like <code> where line breaks should be handled by default behaviour.
*/
if (tool
&& tool[Tools.apiSettings.IS_ENABLED_LINE_BREAKS]
&& !BlockSettings.opened
&& !InlineToolbar.opened
&& !ConversionToolbar.opened) {
if (tool && tool[Tools.INTERNAL_SETTINGS.IS_ENABLED_LINE_BREAKS]) {
return;
}
if (Toolbox.opened && Toolbox.getActiveTool) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
Toolbox.toolButtonActivate(event, Toolbox.getActiveTool);
return;
}
if (InlineToolbar.opened && InlineToolbar.focusedButton) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
InlineToolbar.focusedButton.click();
/**
* Opened Toolbars uses Flipper with own Enter handling
*/
if (UI.someToolbarOpened) {
return;
}
@ -386,8 +369,6 @@ export default class BlockEvents extends Module {
}
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
}
/**
@ -434,7 +415,7 @@ export default class BlockEvents extends Module {
*
* But if caret is at start of the block, we allow to remove it by backspaces
*/
if (tool && tool[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS] && !Caret.isAtStart) {
if (tool && tool[this.Editor.Tools.INTERNAL_SETTINGS.IS_ENABLED_LINE_BREAKS] && !Caret.isAtStart) {
return;
}
@ -500,6 +481,20 @@ export default class BlockEvents extends Module {
* Handle right and down keyboard keys
*/
private arrowRightAndDown(event: KeyboardEvent): void {
/**
* Arrows might be handled on toolbars by flipper
* Check for Flipper.usedKeys to allow navigate by DOWN and disallow by RIGHT
*/
if (this.Editor.UI.someToolbarOpened && Flipper.usedKeys.includes(event.keyCode)) {
return;
}
/**
* Close Toolbar and highlighting when user moves cursor
*/
this.Editor.BlockManager.clearFocused();
this.Editor.Toolbar.close();
const shouldEnableCBS = this.Editor.Caret.isAtEnd || this.Editor.BlockSelection.anyBlockSelected;
if (event.shiftKey && event.keyCode === _.keyCodes.DOWN && shouldEnableCBS) {
@ -534,6 +529,20 @@ export default class BlockEvents extends Module {
* Handle left and up keyboard keys
*/
private arrowLeftAndUp(event: KeyboardEvent): void {
/**
* Arrows might be handled on toolbars by flipper
* Check for Flipper.usedKeys to allow navigate by UP and disallow by LEFT
*/
if (this.Editor.UI.someToolbarOpened && Flipper.usedKeys.includes(event.keyCode)) {
return;
}
/**
* Close Toolbar and highlighting when user moves cursor
*/
this.Editor.BlockManager.clearFocused();
this.Editor.Toolbar.close();
const shouldEnableCBS = this.Editor.Caret.isAtStart || this.Editor.BlockSelection.anyBlockSelected;
if (event.shiftKey && event.keyCode === _.keyCodes.UP && shouldEnableCBS) {
@ -596,46 +605,20 @@ export default class BlockEvents extends Module {
/**
* If Toolbox is not open, then just open it and show plus button
* Next Tab press will leaf Toolbox Tools
*
* @param {string} direction
*/
private leafToolboxTools(direction: string): void {
private activateToolbox(): void {
if (!this.Editor.Toolbar.opened) {
this.Editor.Toolbar.open(false , false);
this.Editor.Toolbar.plusButton.show();
} else {
this.Editor.Toolbox.leaf(direction);
}
this.Editor.Toolbox.open();
}
/**
* If InlineToolbar is not open, just open it and focus first button
* Next Tab press will leaf InlineToolbar Tools
*
* @param {string} direction
*/
private leafInlineToolbarTools(direction: string): void {
if (this.Editor.InlineToolbar.opened) {
this.Editor.InlineToolbar.leaf(direction);
}
}
/**
* Leaf Conversion Toolbar Tools
* @param {string} direction
*/
private leafConversionToolbarTools(direction: string): void {
this.Editor.ConversionToolbar.leaf(direction);
}
/**
* Open Toolbar and show BlockSettings before flipping Tools
* @param {string} direction
*/
private leafBlockSettingsTools(direction: string): void {
private activateBlockSettings(): void {
if (!this.Editor.Toolbar.opened) {
this.Editor.BlockManager.currentBlock.focused = true;
this.Editor.Toolbar.open(true, false);
@ -649,7 +632,5 @@ export default class BlockEvents extends Module {
if (!this.Editor.BlockSettings.opened) {
this.Editor.BlockSettings.open();
}
this.Editor.BlockSettings.leaf(direction);
}
}

View file

@ -263,8 +263,8 @@ export default class BlockSelection extends Module {
this.Editor.RectangleSelection.clearSelection();
/** allow default selection on native inputs */
if ($.isNativeInput(event.target) && !this.nativeInputSelected) {
this.nativeInputSelected = true;
if ($.isNativeInput(event.target) && !this.readyToBlockSelection) {
this.readyToBlockSelection = true;
return;
}
@ -280,30 +280,35 @@ export default class BlockSelection extends Module {
return;
}
if (inputs.length === 1 && !this.needToSelectAll) {
this.needToSelectAll = true;
return;
}
if (this.needToSelectAll) {
/** Prevent default selection */
/**
* Prevent default selection
*/
event.preventDefault();
/**
* Save selection
* Will be restored when closeSelection fired
*/
this.selection.save();
/**
* Remove Ranges from Selection
*/
SelectionUtils.get()
.removeAllRanges();
this.selectAllBlocks();
/**
* Disable any selection after all Blocks selected
*/
this.needToSelectAll = false;
this.readyToBlockSelection = false;
/**
* Close ConversionToolbar when all Blocks selected
*/
this.Editor.ConversionToolbar.close();
} else {
} else if (this.readyToBlockSelection) {
this.selectBlockByIndex();
/**
* Enable all Blocks selection if current Block is selected
*/
this.needToSelectAll = true;
}
}
@ -313,6 +318,18 @@ export default class BlockSelection extends Module {
* Each Block has selected setter that makes Block copyable
*/
private selectAllBlocks() {
/**
* Save selection
* Will be restored when closeSelection fired
*/
this.selection.save();
/**
* Remove Ranges from Selection
*/
SelectionUtils.get()
.removeAllRanges();
this.allBlocksSelected = true;
}
}

View file

@ -47,7 +47,9 @@ export default class ModificationsObserver extends Module {
*/
public destroy() {
this.mutationDebouncer = null;
this.observer.disconnect();
if (this.observer) {
this.observer.disconnect();
}
this.observer = null;
this.nativeInputs.forEach((input) => this.Editor.Listeners.off(input, 'input', this.mutationDebouncer));
}

View file

@ -146,7 +146,7 @@ export default class Sanitizer extends Module {
return this.configCache[toolName];
}
const sanitizeGetter = this.Editor.Tools.apiSettings.SANITIZE_CONFIG;
const sanitizeGetter = this.Editor.Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG;
const toolClass = this.Editor.Tools.available[toolName];
const baseConfig = this.getInlineToolsConfig(toolName);
@ -199,7 +199,7 @@ export default class Sanitizer extends Module {
(enableInlineTools as string[]).map( (inlineToolName) => {
config = Object.assign(
config,
Tools.inline[inlineToolName][Tools.apiSettings.SANITIZE_CONFIG],
Tools.inline[inlineToolName][Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG],
) as SanitizerConfig;
});
}
@ -221,7 +221,7 @@ export default class Sanitizer extends Module {
Object.entries(Tools.inline)
.forEach( ([name, inlineTool]: [string, InlineToolConstructable]) => {
Object.assign(config, inlineTool[Tools.apiSettings.SANITIZE_CONFIG]);
Object.assign(config, inlineTool[Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG]);
});
this.inlineToolsConfigCache = config;

View file

@ -43,8 +43,6 @@ export default class Shortcuts extends Module {
* @param {ShortcutData} shortcut
*/
public add(shortcut: ShortcutData): void {
const { UI } = this.Editor;
const newShortcut = new Shortcut({
name: shortcut.name,
on: document, // UI.nodes.redactor

View file

@ -1,5 +1,7 @@
import Module from '../../__module';
import $ from '../../dom';
import Flipper, {FlipperOptions} from '../../flipper';
import _ from '../../utils';
/**
* Block Settings
@ -67,9 +69,10 @@ export default class BlockSettings extends Module {
private buttons: HTMLElement[] = [];
/**
* Index of active button
* Instance of class that responses for leafing buttons by arrows/tab
* @type {Flipper|null}
*/
private focusedButtonIndex: number = -1;
private flipper: Flipper = null;
/**
* Panel with block settings with 2 sections:
@ -85,6 +88,12 @@ export default class BlockSettings extends Module {
this.nodes.defaultSettings = $.make('div', this.CSS.defaultSettings);
$.append(this.nodes.wrapper, [this.nodes.toolSettings, this.nodes.defaultSettings]);
/**
* Active leafing by arrows/tab
* Buttons will be filled on opening
*/
this.enableFlipper();
}
/**
@ -105,6 +114,8 @@ export default class BlockSettings extends Module {
/** Tell to subscribers that block settings is opened */
this.Editor.Events.emit(this.events.opened);
this.flipper.activate(this.blockTunesButtons);
}
/**
@ -124,8 +135,7 @@ export default class BlockSettings extends Module {
this.buttons = [];
/** Clear focus on active button */
this.focusedButtonIndex = -1;
this.flipper.deactivate();
}
/**
@ -144,11 +154,8 @@ export default class BlockSettings extends Module {
const toolSettings = this.nodes.toolSettings.querySelectorAll(`.${this.Editor.StylesAPI.classes.settingsButton}`);
const defaultSettings = this.nodes.defaultSettings.querySelectorAll(`.${this.CSS.button}`);
toolSettings.forEach((item, index) => {
toolSettings.forEach((item) => {
this.buttons.push((item as HTMLElement));
if (item.classList.contains(this.CSS.focusedButton)) {
this.focusedButtonIndex = index;
}
});
defaultSettings.forEach((item) => {
@ -158,27 +165,6 @@ export default class BlockSettings extends Module {
return this.buttons;
}
/**
* Leaf Block Tunes
* @param {string} direction
*/
public leaf(direction: string = 'right'): void {
this.focusedButtonIndex = $.leafNodesAndReturnIndex(
this.blockTunesButtons, this.focusedButtonIndex, direction, this.CSS.focusedButton,
);
}
/**
* Returns active button HTML element
* @return {HTMLElement}
*/
public get focusedButton(): HTMLElement {
if (this.focusedButtonIndex === -1) {
return null;
}
return (this.buttons[this.focusedButtonIndex] as HTMLElement);
}
/**
* Add Tool's settings
*/
@ -194,4 +180,23 @@ export default class BlockSettings extends Module {
private addDefaultSettings(): void {
$.append(this.nodes.defaultSettings, this.Editor.BlockManager.currentBlock.renderTunes());
}
/**
* Active leafing by arrows/tab
* Buttons will be filled on opening
*/
private enableFlipper(): void {
this.flipper = new Flipper({
focusedItemClass: this.CSS.focusedButton,
activateCallback: () => {
/**
* Restoring focus on current Block after settings clicked.
* For example, when H3 changed to H2 DOM Elements replaced, so we need to focus a new one
*/
_.delay( () => {
this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock);
}, 10)();
},
} as FlipperOptions);
}
}

View file

@ -4,6 +4,7 @@ import {BlockToolConstructable} from '../../../../types';
import _ from '../../utils';
import {SavedData} from '../../../types-internal/block-data';
import Block from '../../block';
import Flipper from '../../flipper';
/**
* Block Converter
@ -38,18 +39,17 @@ export default class ConversionToolbar extends Module {
*/
public opened: boolean = false;
/**
* Focused button index
* -1 equals no chosen Tool
* @type {number}
*/
private focusedButtonIndex: number = -1;
/**
* Available tools
*/
private tools: { [key: string]: HTMLElement } = {};
/**
* Instance of class that responses for leafing buttons by arrows/tab
* @type {Flipper|null}
*/
private flipper: Flipper = null;
/**
* Create UI of Conversion Toolbar
*/
@ -62,6 +62,11 @@ export default class ConversionToolbar extends Module {
*/
this.addTools();
/**
* Prepare Flipper to be able to leaf tools by arrows/tab
*/
this.enableFlipper();
$.append(this.nodes.wrapper, this.nodes.tools);
$.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);
}
@ -77,27 +82,16 @@ export default class ConversionToolbar extends Module {
return;
}
const currentToolName = block.name;
/**
* Focus current tool in conversion toolbar
*/
if (this.tools[currentToolName]) {
/**
* Drop previous active button before moving
*/
if (this.focusedButton && this.focusedButton.classList.contains(ConversionToolbar.CSS.conversionToolActive)) {
this.focusedButton.classList.remove(ConversionToolbar.CSS.conversionToolActive);
}
this.tools[currentToolName].classList.add(ConversionToolbar.CSS.conversionToolActive);
}
this.move(block);
if (!this.opened) {
this.open();
}
/**
* Mark current block's button with color
*/
this.highlightActiveTool(block.name);
}
/**
@ -105,6 +99,8 @@ export default class ConversionToolbar extends Module {
*/
public open(): void {
this.opened = true;
this.flipper.activate(Object.values(this.tools));
this.flipper.focusFirst();
this.nodes.wrapper.classList.add(ConversionToolbar.CSS.conversionToolbarShowed);
}
@ -113,43 +109,8 @@ export default class ConversionToolbar extends Module {
*/
public close(): void {
this.opened = false;
this.flipper.deactivate();
this.nodes.wrapper.classList.remove(ConversionToolbar.CSS.conversionToolbarShowed);
this.dropFocusedButton();
}
/**
* Leaf tools by Tab
* @todo use class with tool iterator
*/
public leaf(direction: string = 'right'): void {
const toolsElements = (Array.from(this.nodes.tools.childNodes) as HTMLElement[]);
this.focusedButtonIndex = $.leafNodesAndReturnIndex(
toolsElements, this.focusedButtonIndex, direction, ConversionToolbar.CSS.conversionToolFocused,
);
}
/**
* Returns focused tool as HTML element
* @return {HTMLElement}
*/
public get focusedButton(): HTMLElement {
if (this.focusedButtonIndex === -1) {
return null;
}
return (this.nodes.tools.childNodes[this.focusedButtonIndex] as HTMLElement);
}
/**
* Drops focused button
*/
public dropFocusedButton() {
Object.values(this.tools).forEach( (tool) => {
(tool as HTMLElement).classList
.remove(ConversionToolbar.CSS.conversionToolActive, ConversionToolbar.CSS.conversionToolFocused);
});
this.focusedButtonIndex = -1;
}
/**
@ -266,10 +227,10 @@ export default class ConversionToolbar extends Module {
continue;
}
const api = this.Editor.Tools.apiSettings;
const internalSettings = this.Editor.Tools.INTERNAL_SETTINGS;
const toolClass = tools[toolName] as BlockToolConstructable;
const toolToolboxSettings = toolClass[api.TOOLBOX];
const conversionConfig = toolClass[api.CONVERSION_CONFIG];
const toolToolboxSettings = toolClass[internalSettings.TOOLBOX];
const conversionConfig = toolClass[internalSettings.CONVERSION_CONFIG];
/**
* Skip tools that don't pass 'toolbox' property
@ -305,4 +266,31 @@ export default class ConversionToolbar extends Module {
await this.replaceWithBlock(toolName);
});
}
/**
* Marks current Blocks button with highlighting color
*/
private highlightActiveTool(toolName: string): void {
if (!this.tools[toolName]) {
return;
}
/**
* Drop previous active button
*/
Object.values(this.tools).forEach((el) => {
el.classList.remove(ConversionToolbar.CSS.conversionToolActive);
});
this.tools[toolName].classList.add(ConversionToolbar.CSS.conversionToolActive);
}
/**
* Prepare Flipper to be able to leaf tools by arrows/tab
*/
private enableFlipper(): void {
this.flipper = new Flipper({
focusedItemClass: ConversionToolbar.CSS.conversionToolFocused,
});
}
}

View file

@ -1,5 +1,6 @@
import Module from '../../__module';
import $ from '../../dom';
import _ from '../../utils';
/**
*
@ -229,7 +230,7 @@ export default class Toolbar extends Module {
* This flag allows to open Toolbar with Toolbox
*/
public open(withBlockActions: boolean = true, needToCloseToolbox: boolean = true): void {
setTimeout(() => {
_.delay(() => {
this.move(needToCloseToolbox);
this.nodes.wrapper.classList.add(this.CSS.toolbarOpened);
@ -238,7 +239,7 @@ export default class Toolbar extends Module {
} else {
this.blockActions.hide();
}
}, 50);
}, 50)();
}
/**

View file

@ -1,12 +1,10 @@
import Module from '../../__module';
import $ from '../../dom';
import BoldInlineTool from '../../inline-tools/inline-tool-bold';
import ItalicInlineTool from '../../inline-tools/inline-tool-italic';
import LinkInlineTool from '../../inline-tools/inline-tool-link';
import SelectionUtils from '../../selection';
import _ from '../../utils';
import {InlineTool, InlineToolConstructable, ToolConstructable, ToolSettings} from '../../../../types';
import Flipper from '../../flipper';
/**
* Inline toolbar with actions that modifies selected text fragment
@ -68,25 +66,17 @@ export default class InlineToolbar extends Module {
*/
private buttonsList: NodeList = null;
/**
* Visible Buttons
* Some Blocks might disable inline tools
* @type {HTMLElement[]}
*/
private visibleButtonsList: HTMLElement[] = [];
/**
* Focused button index
* @type {number}
*/
private focusedButtonIndex: number = -1;
/**
* Cache for Inline Toolbar width
* @type {number}
*/
private width: number = 0;
/**
* Instance of class that responses for leafing buttons by arrows/tab
*/
private flipper: Flipper = null;
/**
* Inline Toolbar Tools
*
@ -141,6 +131,12 @@ export default class InlineToolbar extends Module {
* Recalculate initial width with all buttons
*/
this.recalculateWidth();
/**
* Allow to leaf buttons by arrows / tab
* Buttons will be filled on opening
*/
this.enableFlipper();
}
/**
@ -218,47 +214,6 @@ export default class InlineToolbar extends Module {
this.nodes.wrapper.style.top = Math.floor(newCoords.y) + 'px';
}
/**
* Leaf Inline Tools
* @param {string} direction
*/
public leaf(direction: string = 'right'): void {
this.visibleButtonsList = (Array.from(this.buttonsList)
.filter((tool) => !(tool as HTMLElement).hidden) as HTMLElement[]);
if (this.visibleButtonsList.length === 0) {
return;
}
this.focusedButtonIndex = $.leafNodesAndReturnIndex(
this.visibleButtonsList, this.focusedButtonIndex, direction, this.CSS.focusedButton,
);
}
/**
* Drops focused button index
*/
public dropFocusedButtonIndex(): void {
if (this.focusedButtonIndex === -1) {
return;
}
this.visibleButtonsList[this.focusedButtonIndex].classList.remove(this.CSS.focusedButton);
this.focusedButtonIndex = -1;
}
/**
* Returns Focused button Node
* @return {HTMLElement}
*/
public get focusedButton(): HTMLElement {
if (this.focusedButtonIndex === -1) {
return null;
}
return this.visibleButtonsList[this.focusedButtonIndex];
}
/**
* Hides Inline Toolbar
*/
@ -272,17 +227,13 @@ export default class InlineToolbar extends Module {
this.opened = false;
if (this.focusedButtonIndex !== -1) {
this.visibleButtonsList[this.focusedButtonIndex].classList.remove(this.CSS.focusedButton);
this.focusedButtonIndex = -1;
}
this.flipper.deactivate();
}
/**
* Shows Inline Toolbar
*/
public open(): void {
/**
* Filter inline-tools and show only allowed by Block's Tool
*/
@ -304,6 +255,14 @@ export default class InlineToolbar extends Module {
this.buttonsList = this.nodes.buttons.querySelectorAll(`.${this.CSS.inlineToolButton}`);
this.opened = true;
/**
* Get currently visible buttons to pass it to the Flipper
*/
const visibleTools = Array.from(this.buttonsList)
.filter((tool) => !(tool as HTMLElement).hidden) as HTMLElement[];
this.flipper.activate(visibleTools);
}
/**
@ -352,7 +311,7 @@ export default class InlineToolbar extends Module {
const toolSettings = this.Editor.Tools.getToolSettings(currentBlock.name);
return toolSettings && toolSettings[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR];
return toolSettings && toolSettings[this.Editor.Tools.USER_SETTINGS.ENABLED_INLINE_TOOLS];
}
/**
@ -363,7 +322,7 @@ export default class InlineToolbar extends Module {
currentBlock = this.Editor.BlockManager.getBlock(currentSelection.anchorNode as HTMLElement);
const toolSettings = this.Editor.Tools.getToolSettings(currentBlock.name),
inlineToolbarSettings = toolSettings && toolSettings[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR];
inlineToolbarSettings = toolSettings && toolSettings[this.Editor.Tools.USER_SETTINGS.ENABLED_INLINE_TOOLS];
/**
* All Inline Toolbar buttons
@ -469,10 +428,10 @@ export default class InlineToolbar extends Module {
.entries(Tools.internalTools)
.filter(([name, toolClass]: [string, ToolConstructable | ToolSettings]) => {
if (_.isFunction(toolClass)) {
return toolClass[Tools.apiSettings.IS_INLINE];
return toolClass[Tools.INTERNAL_SETTINGS.IS_INLINE];
}
return (toolClass as ToolSettings).class[Tools.apiSettings.IS_INLINE];
return (toolClass as ToolSettings).class[Tools.INTERNAL_SETTINGS.IS_INLINE];
})
.map(([name]: [string, InlineToolConstructable | ToolSettings]) => name);
@ -481,9 +440,9 @@ export default class InlineToolbar extends Module {
* 2) For external tools, check tool's settings
*/
if (internalTools.includes(toolName)) {
shortcut = this.inlineTools[toolName].shortcut;
} else if (toolSettings && toolSettings[Tools.apiSettings.SHORTCUT]) {
shortcut = toolSettings[Tools.apiSettings.SHORTCUT];
shortcut = this.inlineTools[toolName][Tools.INTERNAL_SETTINGS.SHORTCUT];
} else if (toolSettings && toolSettings[Tools.USER_SETTINGS.SHORTCUT]) {
shortcut = toolSettings[Tools.USER_SETTINGS.SHORTCUT];
}
if (shortcut) {
@ -518,7 +477,7 @@ export default class InlineToolbar extends Module {
const toolSettings = this.Editor.Tools.getToolSettings(currentBlock.name);
if (!toolSettings || !toolSettings[this.Editor.Tools.apiSettings.IS_ENABLED_INLINE_TOOLBAR]) {
if (!toolSettings || !toolSettings[this.Editor.Tools.USER_SETTINGS.ENABLED_INLINE_TOOLS]) {
return;
}
@ -565,4 +524,15 @@ export default class InlineToolbar extends Module {
return result;
}
/**
* Allow to leaf buttons by arrows / tab
* Buttons will be filled on opening
*/
private enableFlipper(): void {
this.flipper = new Flipper({
focusedItemClass: this.CSS.focusedButton,
allowArrows: false,
});
}
}

View file

@ -1,7 +1,8 @@
import Module from '../../__module';
import $ from '../../dom';
import _ from '../../utils';
import {BlockToolConstructable, ToolboxConfig} from '../../../../types';
import {BlockToolConstructable} from '../../../../types';
import Flipper from '../../flipper';
/**
* @class Toolbox
@ -33,22 +34,6 @@ export default class Toolbox extends Module {
};
}
/**
* get tool name when it is selected
* In case when nothing selected returns null
*
* @return {String|null}
*/
public get getActiveTool(): string {
const childNodes = this.nodes.toolbox.childNodes;
if (this.activeButtonIndex === -1) {
return null;
}
return (childNodes[this.activeButtonIndex] as HTMLElement).dataset.tool;
}
/**
* Returns True if Toolbox is Empty and nothing to show
* @return {boolean}
@ -57,11 +42,6 @@ export default class Toolbox extends Module {
return this.displayedToolsCount === 0;
}
private static LEAF_DIRECTIONS = {
RIGHT: 'right',
LEFT: 'left',
};
/**
* Opening state
* @type {boolean}
@ -81,19 +61,18 @@ export default class Toolbox extends Module {
buttons: [],
};
/**
* Active button index
* -1 equals no chosen Tool
* @type {number}
*/
private activeButtonIndex: number = -1;
/**
* How many tools displayed in Toolbox
* @type {number}
*/
private displayedToolsCount: number = 0;
/**
* Instance of class that responses for leafing buttons by arrows/tab
* @type {Flipper|null}
*/
private flipper: Flipper = null;
/**
* Makes the Toolbox
*/
@ -103,6 +82,7 @@ export default class Toolbox extends Module {
this.addTools();
this.addTooltip();
this.enableFlipper();
}
/**
@ -129,6 +109,7 @@ export default class Toolbox extends Module {
this.nodes.toolbox.classList.add(this.CSS.toolboxOpened);
this.opened = true;
this.flipper.activate();
}
/**
@ -141,16 +122,7 @@ export default class Toolbox extends Module {
this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolbarHolderModifier);
this.opened = false;
/**
* Remove active item pointer
*/
if (this.activeButtonIndex !== -1) {
(this.nodes.toolbox.childNodes[this.activeButtonIndex] as HTMLElement)
.classList.remove(this.CSS.toolboxButtonActive);
this.activeButtonIndex = -1;
}
this.flipper.deactivate();
}
/**
@ -164,18 +136,6 @@ export default class Toolbox extends Module {
}
}
/**
* Leaf
* flip through the toolbox items
* @param {String} direction - leaf direction, right is default
*/
public leaf(direction: string = Toolbox.LEAF_DIRECTIONS.RIGHT): void {
const childNodes = (Array.from(this.nodes.toolbox.childNodes) as HTMLElement[]);
this.activeButtonIndex = $.leafNodesAndReturnIndex(
childNodes, this.activeButtonIndex, direction, this.CSS.toolboxButtonActive,
);
}
/**
* Hide toolbox tooltip
*/
@ -203,9 +163,10 @@ export default class Toolbox extends Module {
* @param {BlockToolConstructable} tool - tool class
*/
private addTool(toolName: string, tool: BlockToolConstructable): void {
const api = this.Editor.Tools.apiSettings;
const internalSettings = this.Editor.Tools.INTERNAL_SETTINGS;
const userSettings = this.Editor.Tools.USER_SETTINGS;
const toolToolboxSettings = tool[api.TOOLBOX];
const toolToolboxSettings = tool[internalSettings.TOOLBOX];
/**
* Skip tools that don't pass 'toolbox' property
@ -227,7 +188,7 @@ export default class Toolbox extends Module {
// return;
// }
const {toolbox: userToolboxSettings = {} as ToolboxConfig} = this.Editor.Tools.getToolSettings(toolName);
const userToolboxSettings = this.Editor.Tools.getToolSettings(toolName)[userSettings.TOOLBOX] || {};
const button = $.make('li', [ this.CSS.toolboxButton ]);
@ -262,8 +223,8 @@ export default class Toolbox extends Module {
*/
const toolSettings = this.Editor.Tools.getToolSettings(toolName);
if (toolSettings && toolSettings[this.Editor.Tools.apiSettings.SHORTCUT]) {
this.enableShortcut(tool, toolName, toolSettings[this.Editor.Tools.apiSettings.SHORTCUT]);
if (toolSettings && toolSettings[this.Editor.Tools.USER_SETTINGS.SHORTCUT]) {
this.enableShortcut(tool, toolName, toolSettings[this.Editor.Tools.USER_SETTINGS.SHORTCUT]);
}
/** Increment Tools count */
@ -288,11 +249,11 @@ export default class Toolbox extends Module {
*/
private showTooltip(button: HTMLElement, toolName: string): void {
const toolSettings = this.Editor.Tools.getToolSettings(toolName);
const toolboxSettings = this.Editor.Tools.available[toolName][this.Editor.Tools.apiSettings.TOOLBOX] || {};
const toolboxSettings = this.Editor.Tools.available[toolName][this.Editor.Tools.INTERNAL_SETTINGS.TOOLBOX] || {};
const userToolboxSettings = toolSettings.toolbox || {};
const name = userToolboxSettings.title || toolboxSettings.title || toolName;
let shortcut = toolSettings[this.Editor.Tools.apiSettings.SHORTCUT];
let shortcut = toolSettings[this.Editor.Tools.USER_SETTINGS.SHORTCUT];
const fragment = document.createDocumentFragment();
const hint = document.createTextNode(_.capitalize(name));
@ -354,6 +315,17 @@ export default class Toolbox extends Module {
});
}
/**
* Creates Flipper instance to be able to leaf tools
*/
private enableFlipper(): void {
const tools = Array.from(this.nodes.toolbox.childNodes) as HTMLElement[];
this.flipper = new Flipper({
items: tools,
focusedItemClass: this.CSS.toolboxButtonActive,
});
}
/**
* Inserts new block
* Can be called when button clicked on Toolbox or by ShortcutData

View file

@ -65,7 +65,7 @@ export default class Tools extends Module {
}
const tools = Object.entries(this.available).filter( ([name, tool]) => {
if (!tool[this.apiSettings.IS_INLINE]) {
if (!tool[this.INTERNAL_SETTINGS.IS_INLINE]) {
return false;
}
@ -108,7 +108,7 @@ export default class Tools extends Module {
public get blockTools(): {[name: string]: BlockToolConstructable} {
// eslint-disable-next-line no-unused-vars
const tools = Object.entries(this.available).filter( ([name, tool]) => {
return !tool[this.apiSettings.IS_INLINE];
return !tool[this.INTERNAL_SETTINGS.IS_INLINE];
});
/**
@ -122,17 +122,14 @@ export default class Tools extends Module {
}
/**
* Constant for available Tools Settings
* @todo separate internal and external options
* Constant for available Tools internal settings provided by Tool developer
*
* @return {object}
*/
public get apiSettings() {
public get INTERNAL_SETTINGS() {
return {
CONFIG: 'config',
IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar',
IS_ENABLED_LINE_BREAKS: 'enableLineBreaks',
IS_INLINE: 'isInline',
IS_PASTE_DISALLOWED: 'disallowPaste',
SHORTCUT: 'shortcut',
TOOLBOX: 'toolbox',
SANITIZE_CONFIG: 'sanitize',
@ -140,6 +137,20 @@ export default class Tools extends Module {
};
}
/**
* Constant for available Tools settings provided by user
*
* return {object}
*/
public get USER_SETTINGS() {
return {
SHORTCUT: 'shortcut',
TOOLBOX: 'toolbox',
ENABLED_INLINE_TOOLS: 'inlineToolbar',
CONFIG: 'config',
};
}
/**
* Map {name: Class, ...} where:
* name block type name in JSON. Got from EditorConfig.tools keys
@ -304,7 +315,7 @@ export default class Tools extends Module {
/**
* Configuration to be passed to the Tool's constructor
*/
const config = this.toolsSettings[tool][this.apiSettings.CONFIG] || {};
const config = this.toolsSettings[tool][this.USER_SETTINGS.CONFIG] || {};
// Pass placeholder to initial Block config
if (tool === this.config.initialBlock && !config.placeholder) {
@ -336,7 +347,7 @@ export default class Tools extends Module {
*/
const constructorOptions = {
api: this.Editor.API.methods,
config: toolSettings[this.apiSettings.CONFIG] || {},
config: (toolSettings[this.USER_SETTINGS.CONFIG] || {}) as ToolSettings,
};
return new tool(constructorOptions) as InlineTool;
@ -382,7 +393,7 @@ export default class Tools extends Module {
function: toolClass.prepare,
data: {
toolName,
config: this.toolsSettings[toolName][this.apiSettings.CONFIG],
config: this.toolsSettings[toolName][this.USER_SETTINGS.CONFIG],
},
});
} else {

View file

@ -186,6 +186,17 @@ export default class UI extends Module {
this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty, BlockManager.isEditorEmpty);
}
/**
* Check if one of Toolbar is opened
* Used to prevent global keydowns (for example, Enter) conflicts with Enter-on-toolbar
* @return {boolean}
*/
public get someToolbarOpened() {
const { Toolbox, BlockSettings, InlineToolbar, ConversionToolbar } = this.Editor;
return BlockSettings.opened || InlineToolbar.opened || ConversionToolbar.opened || Toolbox.opened;
}
/**
* Clean editor`s UI
*/
@ -373,67 +384,9 @@ export default class UI extends Module {
* @param event
*/
private enterPressed(event: KeyboardEvent): void {
const { BlockManager, BlockSelection, Caret, BlockSettings, ConversionToolbar } = this.Editor;
const { BlockManager, BlockSelection, Caret } = this.Editor;
const hasPointerToBlock = BlockManager.currentBlockIndex >= 0;
/**
* If Block Settings is opened and have some active button
* Enter press is fired as out of the Block and that's why
* we handle it here
*/
if (BlockSettings.opened && BlockSettings.focusedButton) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
/** Click on settings button */
BlockSettings.focusedButton.click();
/**
* Focused button can be deleted by click, for example with 'Remove Block' api
*/
if (BlockSettings.focusedButton) {
/**
* Add animation on click
*/
BlockSettings.focusedButton.classList.add(BlockSettings.CSS.focusedButtonAnimated);
/**
* Remove animation class
*/
_.delay( () => {
if (BlockSettings.focusedButton) {
BlockSettings.focusedButton.classList.remove(BlockSettings.CSS.focusedButtonAnimated);
}
}, 280)();
}
/**
* Restoring focus on current Block
*
* After changing Block state (when settings clicked, for example)
* Block's content points to the Node that is not in DOM, that's why we can not
* set caret and leaf next (via Tab)
*
* For that set cursor via Caret module to the current Block's content
* after some timeout
*/
_.delay( () => {
Caret.setToBlock(BlockManager.currentBlock);
}, 10)();
return;
}
if (ConversionToolbar.opened && ConversionToolbar.focusedButton) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
ConversionToolbar.focusedButton.click();
return;
}
if (BlockSelection.anyBlockSelected) {
const selectionPositionIndex = BlockManager.removeSelectedBlocks();
Caret.setToBlock(BlockManager.insertInitialBlockAtIndex(selectionPositionIndex, true), Caret.positions.START);
@ -459,7 +412,7 @@ export default class UI extends Module {
* So, BlockManager points some Block and Enter press is on Body
* We can create a new block
*/
if (hasPointerToBlock && (event.target as HTMLElement).tagName === 'BODY') {
if (!this.someToolbarOpened && hasPointerToBlock && (event.target as HTMLElement).tagName === 'BODY') {
/**
* Insert initial typed Block
*/
@ -487,6 +440,13 @@ export default class UI extends Module {
* @param {MouseEvent} event - Click
*/
private documentClicked(event: MouseEvent): void {
/**
* Sometimes we emulate click on some UI elements, for example by Enter on Block Settings button
* We don't need to handle such events, because they handled in other place.
*/
if (!event.isTrusted) {
return;
}
/**
* Close Inline Toolbar when nothing selected
* Do not fire check on clicks at the Inline Toolbar buttons

View file

@ -17,9 +17,6 @@
&--selected &__content {
background: var(--selectionColor);
box-shadow: 0 31px 23px -22px rgba(175, 220, 255, 1);
animation: selectionBounce 0.2s 1;
animation-fill-mode: forwards;
/**
* Workaround Safari case when user can select inline-fragment with cross-block-selection
@ -43,6 +40,7 @@
position: relative;
max-width: var(--content-width);
margin: 0 auto;
transition: background-color 150ms ease;
}
&--drop-target &__content {

View file

@ -96,7 +96,7 @@
* Set color for native selection
*/
::selection{
background-color: var(--selectionColor);
background-color: var(--inlineSelectionColor);
}
.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus::before {

View file

@ -5,7 +5,8 @@
/**
* Selection color
*/
--selectionColor: #a8d6ff;
--selectionColor: #e1f2ff;
--inlineSelectionColor: #d4ecff;
/**
* Toolbar buttons

135
yarn.lock
View file

@ -1018,7 +1018,7 @@ async-each@^1.0.0:
async@^1.3.0:
version "1.5.2"
resolved "http://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
resolved "https://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.4.1:
version "2.6.1"
@ -1155,7 +1155,7 @@ brorand@^1.0.1:
browserify-aes@^1.0.0, browserify-aes@^1.0.4:
version "1.2.0"
resolved "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
dependencies:
buffer-xor "^1.0.3"
cipher-base "^1.0.0"
@ -1183,7 +1183,7 @@ browserify-des@^1.0.0:
browserify-rsa@^4.0.0:
version "4.0.1"
resolved "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
dependencies:
bn.js "^4.1.0"
randombytes "^2.0.1"
@ -1232,7 +1232,7 @@ buffer-xor@^1.0.3:
buffer@^4.3.0:
version "4.9.1"
resolved "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
@ -1326,7 +1326,7 @@ ccount@^1.0.0:
chalk@^1.1.3:
version "1.1.3"
resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
dependencies:
ansi-styles "^2.2.1"
escape-string-regexp "^1.0.2"
@ -1372,7 +1372,7 @@ chardet@^0.7.0:
cheerio@^0.19.0:
version "0.19.0"
resolved "http://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925"
resolved "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz#772e7015f2ee29965096d71ea4175b75ab354925"
dependencies:
css-select "~1.0.0"
dom-serializer "~0.1.0"
@ -1509,10 +1509,6 @@ color@^3.0.0:
color-convert "^1.9.1"
color-string "^1.5.2"
colors@>=0.6.0:
version "1.3.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
commander@^2.12.1, commander@^2.19.0, commander@^2.8.1:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
@ -1611,7 +1607,7 @@ create-ecdh@^4.0.0:
create-hash@^1.1.0, create-hash@^1.1.2:
version "1.2.0"
resolved "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
dependencies:
cipher-base "^1.0.1"
inherits "^2.0.1"
@ -1621,7 +1617,7 @@ create-hash@^1.1.0, create-hash@^1.1.2:
create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
version "1.1.7"
resolved "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
dependencies:
cipher-base "^1.0.3"
create-hash "^1.1.0"
@ -1717,7 +1713,7 @@ css-select@^2.0.0:
css-select@~1.0.0:
version "1.0.0"
resolved "http://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0"
resolved "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz#b1121ca51848dd264e2244d058cee254deeb44b0"
dependencies:
boolbase "~1.0.0"
css-what "1.0"
@ -1748,7 +1744,7 @@ css-url-regex@^1.1.0:
css-what@1.0:
version "1.0.0"
resolved "http://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c"
resolved "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz#d7cc2df45180666f99d2b14462639469e00f736c"
css-what@^2.1.2:
version "2.1.3"
@ -1945,7 +1941,7 @@ diff@^3.2.0:
diffie-hellman@^5.0.0:
version "5.0.3"
resolved "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
dependencies:
bn.js "^4.1.0"
miller-rabin "^4.0.0"
@ -1984,7 +1980,7 @@ domelementtype@^1.3.1:
domelementtype@~1.1.1:
version "1.1.3"
resolved "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
domhandler@2.3:
version "2.3.0"
@ -2077,7 +2073,7 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
entities@1.0:
version "1.0.0"
resolved "http://registry.npmjs.org/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26"
resolved "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26"
entities@^1.1.1, entities@~1.1.1:
version "1.1.2"
@ -2126,7 +2122,7 @@ es-to-primitive@^1.1.1, es-to-primitive@^1.2.0:
es6-promise@^2.3.0:
version "2.3.0"
resolved "http://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc"
resolved "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc"
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
@ -2157,12 +2153,14 @@ eslint-scope@^4.0.2:
estraverse "^4.1.1"
eslint-utils@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
version "1.4.2"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab"
dependencies:
eslint-visitor-keys "^1.0.0"
eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
version "1.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
eslint@^5.15.1:
version "5.15.1"
@ -2239,7 +2237,7 @@ esutils@^2.0.2:
events@^1.0.0:
version "1.1.1"
resolved "http://registry.npmjs.org/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
resolved "https://registry.npmjs.org/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
version "1.0.3"
@ -2333,7 +2331,7 @@ extract-text-webpack-plugin@^3.0.2:
fast-deep-equal@^1.0.0:
version "1.1.0"
resolved "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
fast-deep-equal@^2.0.1:
version "2.0.1"
@ -2538,7 +2536,7 @@ get-stdin@^6.0.0:
get-stream@^3.0.0:
version "3.0.0"
resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
resolved "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
@ -2757,7 +2755,7 @@ htmlparser2@^3.10.0:
htmlparser2@~3.8.1:
version "3.8.3"
resolved "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068"
resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068"
dependencies:
domelementtype "1"
domhandler "2.3"
@ -2959,7 +2957,7 @@ is-buffer@^2.0.0:
is-builtin-module@^1.0.0:
version "1.0.0"
resolved "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
dependencies:
builtin-modules "^1.0.0"
@ -3066,7 +3064,7 @@ is-number@^3.0.0:
is-obj@^1.0.0:
version "1.0.1"
resolved "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
is-plain-obj@^1.1.0:
version "1.1.0"
@ -3202,7 +3200,7 @@ json-stable-stringify-without-jsonify@^1.0.1:
json5@^0.5.0:
version "0.5.1"
resolved "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
resolved "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
json5@^1.0.1:
version "1.0.1"
@ -3314,7 +3312,7 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
lodash._reinterpolate@~3.0.0:
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@ -3327,17 +3325,17 @@ lodash.memoize@^4.1.2:
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
lodash.template@^4.2.4:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
dependencies:
lodash._reinterpolate "~3.0.0"
lodash._reinterpolate "^3.0.0"
lodash.templatesettings "^4.0.0"
lodash.templatesettings@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316"
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
dependencies:
lodash._reinterpolate "~3.0.0"
lodash._reinterpolate "^3.0.0"
lodash.uniq@^4.5.0:
version "4.5.0"
@ -3345,7 +3343,7 @@ lodash.uniq@^4.5.0:
lodash@^3.2.0:
version "3.10.1"
resolved "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
resolved "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4:
version "4.17.11"
@ -3503,10 +3501,6 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
mime@^1.2.9:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
@ -3534,19 +3528,15 @@ minimist-options@^3.0.1:
minimist@0.0.8:
version "0.0.8"
resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
minimist@1.1.x:
version "1.1.3"
resolved "http://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
resolved "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
minimist@^1.2.0:
version "1.2.0"
resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
minipass@^2.2.1, minipass@^2.3.4:
version "2.3.5"
@ -3577,15 +3567,15 @@ mississippi@^3.0.0:
through2 "^2.0.0"
mixin-deep@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
dependencies:
for-in "^1.0.2"
is-extendable "^1.0.1"
mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1"
resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
@ -3711,14 +3701,6 @@ node-releases@^1.1.8:
dependencies:
semver "^5.3.0"
node-static@^0.7.11:
version "0.7.11"
resolved "https://registry.yarnpkg.com/node-static/-/node-static-0.7.11.tgz#60120d349f3cef533e4e820670057eb631882e7f"
dependencies:
colors ">=0.6.0"
mime "^1.2.9"
optimist ">=0.3.4"
nopt@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
@ -3857,13 +3839,6 @@ onetime@^2.0.0:
dependencies:
mimic-fn "^1.0.0"
optimist@>=0.3.4:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
dependencies:
minimist "~0.0.1"
wordwrap "~0.0.2"
optionator@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
@ -3912,7 +3887,7 @@ p-finally@^1.0.0:
p-is-promise@^1.1.0:
version "1.1.0"
resolved "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
resolved "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
p-limit@^1.1.0:
version "1.3.0"
@ -3966,7 +3941,7 @@ parent-module@^1.0.0:
parse-asn1@^5.0.0:
version "5.1.1"
resolved "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8"
resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8"
dependencies:
asn1.js "^4.0.0"
browserify-aes "^1.0.0"
@ -4052,7 +4027,7 @@ pbkdf2@^3.0.3:
pify@^2.3.0:
version "2.3.0"
resolved "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
pify@^3.0.0:
version "3.0.0"
@ -4903,7 +4878,7 @@ read-pkg@^3.0.0:
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6:
version "2.3.6"
resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
@ -4915,7 +4890,7 @@ read-pkg@^3.0.0:
readable-stream@1.1:
version "1.1.13"
resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e"
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
@ -5183,7 +5158,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2,
safe-regex@^1.1.0:
version "1.1.0"
resolved "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
dependencies:
ret "~0.1.10"
@ -5245,7 +5220,7 @@ setimmediate@^1.0.4:
sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.11"
resolved "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
dependencies:
inherits "^2.0.1"
safe-buffer "^5.0.1"
@ -5484,7 +5459,7 @@ stringify-entities@^1.0.1:
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
dependencies:
ansi-regex "^2.0.0"
@ -5506,7 +5481,7 @@ strip-bom@^3.0.0:
strip-eof@^1.0.0:
version "1.0.0"
resolved "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
strip-indent@^2.0.0:
version "2.0.0"
@ -5723,7 +5698,7 @@ through2@^2.0.0:
through@^2.3.6:
version "2.3.8"
resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
timers-browserify@^2.0.4:
version "2.0.10"
@ -6006,7 +5981,7 @@ util.promisify@^1.0.0, util.promisify@~1.0.0:
util@0.10.3:
version "0.10.3"
resolved "http://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
dependencies:
inherits "2.0.1"
@ -6132,10 +6107,6 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2 || 2"
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
@ -6148,7 +6119,7 @@ worker-farm@^1.5.2:
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"