[Draft] Feature/tooltip enhancements (#907)

* initial

* update

* make module standalone

* use tooltips as external module

* update

* build via prod mode

* add tooltips as external module

* add declaration file and options param

* add api tooltip

* update

* removed submodule

* removed due to the incorrect setip

* setup tooltips again

* wip

* update tooltip module

* toolbox, inline toolbar

* Tooltips in block tunes not uses shorthand

* shorthand in a plus and block settings

* fix doc

* Update tools-inline.md

* Delete tooltip.css

* Update CHANGELOG.md

* Update codex.tooltips

* Update api.md
This commit is contained in:
Murod Khaydarov 2019-11-30 16:08:46 +03:00 committed by Peter Savchenko
parent 3e2bf87841
commit 36f69f083a
34 changed files with 438 additions and 160 deletions

3
.gitmodules vendored
View file

@ -46,3 +46,6 @@
[submodule "example/tools/warning"]
path = example/tools/warning
url = https://github.com/editor-js/warning
[submodule "src/components/external/codex.tooltips"]
path = src/components/external/codex.tooltips
url = https://github.com/codex-team/codex.tooltips

View file

@ -175,7 +175,7 @@
END OF TERMS AND CONDITIONS
Copyright © 2015-2018 CodeX
Copyright © 2015-present CodeX
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

22
dist/editor.js vendored

File diff suppressed because one or more lines are too long

View file

@ -150,6 +150,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
codex-tooltip
MIT
Copyright 2019 CodeX https://codex.so
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
core-js
MIT
Copyright (c) 2014-2018 Denis Pushkarev

View file

@ -4,6 +4,8 @@
- `Improvements` — Inline Toolbar design improved
- `Improvements` — Conversion Toolbar now included in the Inline Toolbar [#853](https://github.com/codex-team/editor.js/issues/853)
- `Improvements` — All buttons now have beautiful Tooltips provided by [CodeX Tooltips](https://github.com/codex-team/codex.tooltips)
- `New` — new Tooltips API for displaying tooltips near your custom elements
`New` *API* — Block [lifecycle hooks](tools.md#block-lifecycle-hooks)
- `Fix` — On selection from end to start backspace is working as expected now [#869](https://github.com/codex-team/editor.js/issues/869)
`Fix` — Fix flipper with empty dom iterator [#926](https://github.com/codex-team/editor.js/issues/926)

View file

@ -160,7 +160,55 @@ It makes following steps:
After executing the `destroy` method, editor inctance becomes an empty object. This way you will free occupied JS Heap on your page.
### Shorthands
### Tooltip API
Methods for showing Tooltip helper near your elements. Parameters are the same as in [CodeX Tooltips](http://github.com/codex-team/codex.tooltips) lib.
![](https://capella.pics/00e7094a-fdb9-429b-8015-9c56f19b4ef5.jpg)
#### Show
Method shows tooltip with custom content on passed element
```js
this.api.tooltip.show(element, content, options);
```
| parameter | type | description |
| -- | -- | -- |
| `element` | _HTMLElement_ | Tooltip will be showed near this element |
| `content` | _String_ or _Node_ | Content that will be appended to the Tooltip |
| `options` | _Object_ | Some displaying options, see below |
Available showing options
| name | type | action |
| -- | -- | -- |
| placement | `top`, `bottom`, `left`, `right` | Where to place the tooltip. Default value is `bottom' |
| marginTop | _Number_ | Offset above the tooltip with `top` placement |
| marginBottom | _Number_ | Offset below the tooltip with `bottom` placement |
| marginLeft | _Number_ | Offset at left from the tooltip with `left` placement |
| marginRight | _Number_ | Offset at right from the tooltip with `right` placement |
| delay | _Number_ | Delay before showing, in ms. Default is `70` |
| hidingDelay | _Number_ | Delay before hiding, in ms. Default is `0` |
#### Hide
Method hides the Tooltip.
```js
this.api.tooltip.hide();
```
#### onHover
Decorator for showing tooltip near some element by "mouseenter" and hide by "mouseleave".
```js
this.api.tooltip.onHover(element, content, options);
```
### API Shorthands
Editor`s API provides some shorthands for API methods.
@ -179,3 +227,4 @@ const editor = EditorJS();
editor.focus();
editor.save();
```

View file

@ -123,3 +123,28 @@ static get sanitize() {
```
Read more about Sanitizer configuration at the [Tools#sanitize](tools.md#sanitize)
### Specifying a title
You can pass your Tool's title via `title` static getter. It can be used, for example, in the Tooltip with
icon description that appears by hover.
![](https://capella.pics/00e7094a-fdb9-429b-8015-9c56f19b4ef5.jpg)
```ts
export default class BoldInlineTool implements InlineTool {
/**
* Specifies Tool as Inline Toolbar Tool
*
* @return {boolean}
*/
public static isInline = true;
/**
* Title for hover-tooltip
*/
public static title: string = 'Bold';
// ... other methods
}
```

@ -1 +1 @@
Subproject commit 4be61b52257911ce4bfbbddd55199e7eb952e839
Subproject commit 0b7338d8021683e55b6325302dfa779e237b5c80

@ -1 +1 @@
Subproject commit 522f4bcf56776ffb573f462be6a4eb87d6fc9e7b
Subproject commit db609762f726516333570d7e3979ff829c4b717b

@ -1 +1 @@
Subproject commit c306bcb33c88eaa3c172eaf387fbcd06ae6b297f
Subproject commit cd5409cad9fb8667d94d707bc29864cc90112221

View file

@ -64,6 +64,12 @@ export default class DeleteTune implements BlockTune {
this.nodes.button = $.make('div', [this.CSS.button, this.CSS.buttonDelete], {});
this.nodes.button.appendChild($.svg('cross', 12, 12));
this.api.listeners.on(this.nodes.button, 'click', (event: MouseEvent) => this.handleClick(event), false);
/**
* Enable tooltip module
*/
this.api.tooltip.onHover(this.nodes.button, 'Delete');
return this.nodes.button;
}
@ -95,8 +101,8 @@ export default class DeleteTune implements BlockTune {
this.api.events.off('block-settings-closed', this.resetConfirmation);
this.api.blocks.delete();
this.api.toolbar.close();
this.api.tooltip.hide();
/**
* Prevent firing ui~documentClicked that can drop currentBlock pointer

View file

@ -46,6 +46,12 @@ export default class MoveDownTune implements BlockTune {
(event) => this.handleClick(event as MouseEvent, moveDownButton),
false,
);
/**
* Enable tooltip module on button
*/
this.api.tooltip.onHover(moveDownButton, 'Move down');
return moveDownButton;
}
@ -88,5 +94,7 @@ export default class MoveDownTune implements BlockTune {
/** Change blocks positions */
this.api.blocks.swap(currentBlockIndex, currentBlockIndex + 1);
/** Hide the Tooltip */
this.api.tooltip.hide();
}
}

View file

@ -47,6 +47,12 @@ export default class MoveUpTune implements BlockTune {
(event) => this.handleClick(event as MouseEvent, moveUpButton),
false,
);
/**
* Enable tooltip module on button
*/
this.api.tooltip.onHover(moveUpButton, 'Move up');
return moveUpButton;
}
@ -94,5 +100,8 @@ export default class MoveUpTune implements BlockTune {
/** Change blocks positions */
this.api.blocks.swap(currentBlockIndex, currentBlockIndex - 1);
/** Hide the Tooltip */
this.api.tooltip.hide();
}
}

@ -0,0 +1 @@
Subproject commit c4ccca4bdc8553fdf083ccb81b020f83e3b58720

View file

@ -17,6 +17,11 @@ export default class BoldInlineTool implements InlineTool {
*/
public static isInline = true;
/**
* Title for hover-tooltip
*/
public static title: string = 'Bold';
/**
* Sanitizer Rule
* Leave <b> tags

View file

@ -17,6 +17,11 @@ export default class ItalicInlineTool implements InlineTool {
*/
public static isInline = true;
/**
* Title for hover-tooltip
*/
public static title: string = 'Italic';
/**
* Sanitizer Rule
* Leave <i> tags

View file

@ -21,6 +21,11 @@ export default class LinkInlineTool implements InlineTool {
*/
public static isInline = true;
/**
* Title for hover-tooltip
*/
public static title: string = 'Link';
/**
* Sanitizer Rule
* Leave <a> tags

View file

@ -25,6 +25,7 @@ export default class API extends Module {
styles: this.Editor.StylesAPI.classes,
toolbar: this.Editor.ToolbarAPI.methods,
inlineToolbar: this.Editor.InlineToolbarAPI.methods,
tooltip: this.Editor.TooltipAPI.methods,
} as APIInterfaces;
}
}

View file

@ -0,0 +1,55 @@
import Module from '../../__module';
import { Tooltip } from '../../../../types/api';
import {TooltipContent, TooltipOptions} from '../../external/codex.tooltips';
/**
* @class TooltipAPI
* @classdesc Tooltip API
*/
export default class TooltipAPI extends Module {
/**
* Available methods
*/
get methods(): Tooltip {
return {
show: (element: HTMLElement,
content: TooltipContent,
options?: TooltipOptions,
) => this.show(element, content, options),
hide: () => this.hide(),
onHover: (element: HTMLElement,
content: TooltipContent,
options?: TooltipOptions,
) => this.onHover(element, content, options),
};
}
/**
* Method show tooltip on element with passed HTML content
*
* @param {HTMLElement} element
* @param {TooltipContent} content
* @param {TooltipOptions} options
*/
public show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions) {
this.Editor.Tooltip.show(element, content, options);
}
/**
* Method hides tooltip on HTML page
*/
public hide() {
this.Editor.Tooltip.hide();
}
/**
* Decorator for showing Tooltip by mouseenter/mouseleave
*
* @param {HTMLElement} element
* @param {TooltipContent} content
* @param {TooltipOptions} options
*/
public onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions) {
this.Editor.Tooltip.onHover(element, content, options);
}
}

View file

@ -85,6 +85,7 @@ export default class Toolbar extends Module {
// Content Zone
plusButton: 'ce-toolbar__plus',
plusButtonShortcut: 'ce-toolbar__plus-shortcut',
plusButtonHidden: 'ce-toolbar__plus--hidden',
// Actions Zone
@ -113,33 +114,22 @@ export default class Toolbar extends Module {
* - Toolbox
*/
this.nodes.plusButton = $.make('div', this.CSS.plusButton);
$.append(this.nodes.plusButton, $.svg('plus', 14, 14));
$.append(this.nodes.content, this.nodes.plusButton);
this.Editor.Listeners.on(this.nodes.plusButton, 'click', () => this.plusButtonClicked(), false);
/**
* Add events to show/hide tooltip for plus button
*/
this.Editor.Listeners.on(this.nodes.plusButton, 'mouseenter', () => {
const tooltip = this.Editor.Toolbox.nodes.tooltip;
const fragment = document.createDocumentFragment();
const tooltipContent = $.make('div');
fragment.appendChild(document.createTextNode('Add'));
fragment.appendChild($.make('div', this.Editor.Toolbox.CSS.tooltipShortcut, {
textContent: '⇥ Tab',
}));
tooltipContent.appendChild(document.createTextNode('Add'));
tooltipContent.appendChild($.make('div', this.CSS.plusButtonShortcut, {
textContent: '⇥ Tab',
}));
tooltip.style.left = '-17px';
tooltip.innerHTML = '';
tooltip.appendChild(fragment);
tooltip.classList.add(this.Editor.Toolbox.CSS.tooltipShown);
});
this.Editor.Listeners.on(this.nodes.plusButton, 'mouseleave', () => {
this.Editor.Toolbox.hideTooltip();
});
$.append(this.nodes.plusButton, $.svg('plus', 14, 14));
$.append(this.nodes.content, this.nodes.plusButton);
this.Editor.Listeners.on(this.nodes.plusButton, 'click', () => this.plusButtonClicked(), false);
this.Editor.Tooltip.onHover(this.nodes.plusButton, tooltipContent);
/**
* Make a Toolbox
@ -160,6 +150,10 @@ export default class Toolbar extends Module {
$.append(this.nodes.blockActionsButtons, this.nodes.settingsToggler);
$.append(this.nodes.actions, this.nodes.blockActionsButtons);
this.Editor.Tooltip.onHover(this.nodes.settingsToggler, 'Click to tune', {
placement: 'top',
});
/**
* Make and append Settings Panel
*/

View file

@ -23,6 +23,7 @@ export default class InlineToolbar extends Module {
inlineToolbarShowed: 'ce-inline-toolbar--showed',
inlineToolbarLeftOriented: 'ce-inline-toolbar--left-oriented',
inlineToolbarRightOriented: 'ce-inline-toolbar--right-oriented',
inlineToolbarShortcut: 'ce-inline-toolbar__shortcut',
buttonsWrapper: 'ce-inline-toolbar__buttons',
actionsWrapper: 'ce-inline-toolbar__actions',
inlineToolButton: 'ce-inline-tool',
@ -420,6 +421,11 @@ export default class InlineToolbar extends Module {
}
});
});
this.Editor.Tooltip.onHover(this.nodes.conversionToggler, 'Convert to', {
placement: 'top',
hidingDelay: 100,
});
}
/**
@ -483,6 +489,7 @@ export default class InlineToolbar extends Module {
const {
Listeners,
Tools,
Tooltip,
} = this.Editor;
const button = tool.render();
@ -540,6 +547,26 @@ export default class InlineToolbar extends Module {
if (shortcut) {
this.enableShortcuts(tool, shortcut);
}
/**
* Enable tooltip module on button
*/
const tooltipContent = $.make('div');
const toolTitle = Tools.toolsClasses[toolName][Tools.INTERNAL_SETTINGS.TITLE] || _.capitalize(toolName);
tooltipContent.appendChild($.text(toolTitle));
if (shortcut) {
tooltipContent.appendChild($.make('div', this.CSS.inlineToolbarShortcut, {
textContent: _.beautifyShortcut(shortcut),
}));
}
Tooltip.onHover(button, tooltipContent, {
placement: 'top',
hidingDelay: 100,
});
}
/**

View file

@ -28,10 +28,10 @@ export default class Toolbox extends Module {
toolboxButton: 'ce-toolbox__button',
toolboxButtonActive : 'ce-toolbox__button--active',
toolboxOpened: 'ce-toolbox--opened',
tooltip: 'ce-toolbox__tooltip',
tooltipShown: 'ce-toolbox__tooltip--shown',
tooltipShortcut: 'ce-toolbox__tooltip-shortcut',
openedToolbarHolderModifier: 'codex-editor--toolbox-opened',
buttonTooltip: 'ce-toolbox-button-tooltip',
buttonShortcut: 'ce-toolbox-button-tooltip__shortcut',
};
}
@ -54,11 +54,9 @@ export default class Toolbox extends Module {
*/
public nodes: {
toolbox: HTMLElement,
tooltip: HTMLElement,
buttons: HTMLElement[],
} = {
toolbox: null,
tooltip: null,
buttons: [],
};
@ -82,7 +80,6 @@ export default class Toolbox extends Module {
$.append(this.Editor.Toolbar.nodes.content, this.nodes.toolbox);
this.addTools();
this.addTooltip();
this.enableFlipper();
}
@ -117,8 +114,6 @@ export default class Toolbox extends Module {
* Close Toolbox
*/
public close(): void {
this.hideTooltip();
this.nodes.toolbox.classList.remove(this.CSS.toolboxOpened);
this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolbarHolderModifier);
@ -137,13 +132,6 @@ export default class Toolbox extends Module {
}
}
/**
* Hide toolbox tooltip
*/
public hideTooltip(): void {
this.nodes.tooltip.classList.remove(this.CSS.tooltipShown);
}
/**
* Iterates available tools and appends them to the Toolbox
*/
@ -211,12 +199,11 @@ export default class Toolbox extends Module {
/**
* Add listeners to show/hide toolbox tooltip
*/
this.Editor.Listeners.on(button, 'mouseenter', () => {
this.showTooltip(button, toolName);
});
const tooltipContent = this.drawTooltip(toolName);
this.Editor.Listeners.on(button, 'mouseleave', () => {
this.hideTooltip();
this.Editor.Tooltip.onHover(button, tooltipContent, {
placement: 'bottom',
hidingDelay: 200,
});
/**
@ -233,22 +220,12 @@ export default class Toolbox extends Module {
}
/**
* Add toolbox tooltip to page
* Draw tooltip for toolbox tools
*
* @param {String} toolName - toolbox tool name
* @return { HTMLElement }
*/
private addTooltip(): void {
this.nodes.tooltip = $.make('div', this.CSS.tooltip, {
innerHTML: '',
});
$.append(this.Editor.Toolbar.nodes.content, this.nodes.tooltip);
}
/**
* Show tooltip for toolbox button
* @param {HTMLElement} button
* @param {string} toolName
*/
private showTooltip(button: HTMLElement, toolName: string): void {
private drawTooltip(toolName: string): HTMLElement {
const toolSettings = this.Editor.Tools.getToolSettings(toolName);
const toolboxSettings = this.Editor.Tools.available[toolName][this.Editor.Tools.INTERNAL_SETTINGS.TOOLBOX] || {};
const userToolboxSettings = toolSettings.toolbox || {};
@ -256,48 +233,20 @@ export default class Toolbox extends Module {
let shortcut = toolSettings[this.Editor.Tools.USER_SETTINGS.SHORTCUT];
const fragment = document.createDocumentFragment();
const tooltip = $.make('div', this.CSS.buttonTooltip);
const hint = document.createTextNode(_.capitalize(name));
fragment.appendChild(hint);
tooltip.appendChild(hint);
if (shortcut) {
const OS = _.getUserOS();
shortcut = _.beautifyShortcut(shortcut);
shortcut = shortcut
.replace(/shift/gi, '⇧')
.replace(/backspace/gi, '⌫')
.replace(/enter/gi, '⏎')
.replace(/up/gi, '↑')
.replace(/left/gi, '→')
.replace(/down/gi, '↓')
.replace(/right/gi, '←')
.replace(/escape/gi, '⎋')
.replace(/insert/gi, 'Ins')
.replace(/delete/gi, '␡')
.replace(/\+/gi, ' + ');
if (OS.mac) {
shortcut = shortcut.replace(/ctrl|cmd/gi, '⌘').replace(/alt/gi, '⌥');
} else {
shortcut = shortcut.replace(/cmd/gi, 'Ctrl').replace(/windows/gi, 'WIN');
}
fragment.appendChild($.make('div', this.CSS.tooltipShortcut, {
tooltip.appendChild($.make('div', this.CSS.buttonShortcut, {
textContent: shortcut,
}));
}
const leftOffset = 16;
const coordinate = button.offsetLeft;
const topOffset = Math.floor(this.Editor.BlockManager.currentBlock.holder.offsetHeight / 2);
this.nodes.tooltip.innerHTML = '';
this.nodes.tooltip.appendChild(fragment);
this.nodes.tooltip.style.left = `${coordinate + leftOffset}px`;
this.nodes.tooltip.style.transform = `translate3d(-50%, ${topOffset}px, 0)`;
this.nodes.tooltip.classList.add(this.CSS.tooltipShown);
return tooltip;
}
/**

View file

@ -130,6 +130,7 @@ export default class Tools extends Module {
return {
IS_ENABLED_LINE_BREAKS: 'enableLineBreaks',
IS_INLINE: 'isInline',
TITLE: 'title', // for Inline Tools. Block Tools can pass title along with icon through the 'toolbox' static prop.
SHORTCUT: 'shortcut',
TOOLBOX: 'toolbox',
SANITIZE_CONFIG: 'sanitize',

View file

@ -0,0 +1,58 @@
import Module from '../__module';
/**
* Use external module CodeX Tooltip
*/
import CodeXTooltips, { TooltipContent, TooltipOptions } from '../external/codex.tooltips';
import {ModuleConfig} from '../../types-internal/module-config';
/**
* Tooltip
*
* Decorates any tooltip module like adapter
*/
export default class Tooltip extends Module {
/**
* Tooltips lib: CodeX Tooltips
* @see https://github.com/codex-team/codex.tooltips
*/
private lib: CodeXTooltips = new CodeXTooltips();
/**
* @constructor
* @param {EditorConfig}
*/
constructor({config}: ModuleConfig) {
super({config});
}
/**
* Shows tooltip on element with passed HTML content
*
* @param {HTMLElement} element - any HTML element in DOM
* @param {TooltipContent} content - tooltip's content
* @param {TooltipOptions} options - showing settings
*/
public show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
this.lib.show(element, content, options);
}
/**
* Hides tooltip
*/
public hide(): void {
this.lib.hide();
}
/**
* Binds 'mouseenter' and 'mouseleave' events that shows/hides the Tooltip
*
* @param {HTMLElement} element - any HTML element in DOM
* @param {TooltipContent} content - tooltip's content
* @param {TooltipOptions} options - showing settings
*/
public onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
this.lib.onHover(element, content, options);
}
}

@ -1 +1 @@
Subproject commit 69f0c1a24cdfa443dcda9dca71015472709ae2fb
Subproject commit 4884666a2b6990eed036e318020bc465f52ae950

View file

@ -386,4 +386,33 @@ export default class Util {
public static typeof(object: any): string {
return Object.prototype.toString.call(object).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
/**
* Make shortcut command more human-readable
* @param {string} shortcut string like 'CMD+B'
*/
public static beautifyShortcut(shortcut: string): string {
const OS = this.getUserOS();
shortcut = shortcut
.replace(/shift/gi, '⇧')
.replace(/backspace/gi, '⌫')
.replace(/enter/gi, '⏎')
.replace(/up/gi, '↑')
.replace(/left/gi, '→')
.replace(/down/gi, '↓')
.replace(/right/gi, '←')
.replace(/escape/gi, '⎋')
.replace(/insert/gi, 'Ins')
.replace(/delete/gi, '␡')
.replace(/\+/gi, ' + ');
if (OS.mac) {
shortcut = shortcut.replace(/ctrl|cmd/gi, '⌘').replace(/alt/gi, '⌥');
} else {
shortcut = shortcut.replace(/cmd/gi, 'Ctrl').replace(/windows/gi, 'WIN');
}
return shortcut;
}
}

View file

@ -72,6 +72,12 @@
margin-left: 4px;
}
}
&__shortcut {
opacity: 0.6;
word-spacing: -3px;
margin-top: 3px;
}
}
.ce-inline-tool {

View file

@ -43,6 +43,12 @@
left: calc(var(--toolbox-buttons-size) * -1);
flex-shrink: 0;
&-shortcut {
opacity: 0.6;
word-spacing: -2px;
margin-top: 5px;
}
&--hidden {
display: none;
}

View file

@ -22,55 +22,15 @@
@apply --toolbox-button;
flex-shrink: 0;
}
&__tooltip {
position: absolute;
top: 25px;
padding: 6px 10px;
border-radius: 5px;
opacity: 0;
background: var(--bg-light);
box-shadow: 0 10px 12px -9px rgba(26, 39, 54, 0.32), 0 3px 2px -2px rgba(33, 48, 73, 0.05);
color: #5C6174;
font-size: 12px;
text-align: center;
user-select: none;
pointer-events: none;
transition: opacity 150ms ease-in, left 0.1s linear;
will-change: opacity, left;
letter-spacing: 0.02em;
line-height: 1em;
@media (--mobile) {
display: none;
}
&-shortcut {
color: rgba(100, 105, 122, 0.6);
word-spacing: -2px;
margin-top: 5px;
}
&--shown {
opacity: 1;
transition-delay: 0.1s, 0s;
}
&::before {
content: '';
width: 10px;
height: 10px;
position: absolute;
top: -5px;
left: 50%;
margin-left: -5px;
transform: rotate(-45deg);
background-color: var(--bg-light);
z-index: -1;
}
}
}
.ce-toolbox-button-tooltip {
&__shortcut {
opacity: 0.6;
word-spacing: -3px;
margin-top: 3px;
}
}
/**
* Styles for Narrow mode

View file

@ -9,6 +9,7 @@ import Events from '../components/modules/events';
import Shortcuts from '../components/modules/shortcuts';
import Paste from '../components/modules/paste';
import Notifier from '../components/modules/notifier';
import Tooltip from '../components/modules/tooltip';
import DragNDrop from '../components/modules/dragNDrop';
import ModificationsObserver from '../components/modules/modificationsObserver';
import Renderer from '../components/modules/renderer';
@ -33,6 +34,7 @@ import RectangleSelection from '../components/modules/RectangleSelection';
import InlineToolbarAPI from '../components/modules/api/inlineToolbar';
import CrossBlockSelection from '../components/modules/crossBlockSelection';
import ConversionToolbar from '../components/modules/toolbar/conversion';
import TooltipAPI from '../components/modules/api/tooltip';
export interface EditorModules {
UI: UI;
@ -57,6 +59,7 @@ export interface EditorModules {
Caret: Caret;
Saver: Saver;
Notifier: Notifier;
Tooltip: Tooltip;
BlockManager: BlockManager;
BlocksAPI: BlocksAPI;
CaretAPI: CaretAPI;
@ -70,4 +73,5 @@ export interface EditorModules {
InlineToolbarAPI: InlineToolbarAPI;
CrossBlockSelection: CrossBlockSelection;
NotifierAPI: NotifierAPI;
TooltipAPI: TooltipAPI;
}

View file

@ -8,4 +8,5 @@ export * from './styles';
export * from './caret';
export * from './toolbar';
export * from './notifier';
export * from './inline-toolbar'
export * from './tooltip';
export * from './inline-toolbar';

30
types/api/tooltip.d.ts vendored Normal file
View file

@ -0,0 +1,30 @@
/**
* Tooltip API
*/
import {TooltipContent, TooltipOptions} from '../../src/components/external/codex.tooltips';
export interface Tooltip {
/**
* Show tooltip
*
* @param {HTMLElement} element
* @param {TooltipContent} content
* @param {TooltipOptions} options
*/
show: (element: HTMLElement, content: TooltipContent, options?: TooltipOptions) => void;
/**
* Hides tooltip
*/
hide: () => void;
/**
* Decorator for showing Tooltip by mouseenter/mouseleave
*
* @param {HTMLElement} element
* @param {TooltipContent} content
* @param {TooltipOptions} options
*/
onHover: (element: HTMLElement, content: TooltipContent, options?: TooltipOptions) => void;
}

32
types/index.d.ts vendored
View file

@ -5,8 +5,21 @@
*/
import {EditorConfig} from './configs';
import {Blocks, Caret, Events, Listeners, Notifier, Sanitizer, Saver, Selection, Styles, Toolbar, InlineToolbar} from './api';
import {OutputData} from "./data-formats/output-data";
import {
Blocks,
Caret,
Events,
InlineToolbar,
Listeners,
Notifier,
Sanitizer,
Saver,
Selection,
Styles,
Toolbar,
Tooltip,
} from './api';
import {OutputData} from './data-formats/output-data';
/**
* Interfaces used for development
@ -53,6 +66,7 @@ export interface API {
styles: Styles;
toolbar: Toolbar;
inlineToolbar: InlineToolbar;
tooltip: Tooltip;
}
/**
@ -82,37 +96,37 @@ declare class EditorJS {
/**
* @see Saver.save
*/
save(): Promise<OutputData>;
public save(): Promise<OutputData>;
/**
* @see Blocks.clear
*/
clear(): void;
public clear(): void;
/**
* @see Blocks.render
*/
render(data: OutputData): Promise<void>;
public render(data: OutputData): Promise<void>;
/**
* @see Caret.focus
*/
focus(atEnd?: boolean): boolean;
public focus(atEnd?: boolean): boolean;
/**
* @see Events.on
*/
on(eventName: string, callback: (data?: any) => void): void;
public on(eventName: string, callback: (data?: any) => void): void;
/**
* @see Events.off
*/
off(eventName: string, callback: (data?: any) => void): void;
public off(eventName: string, callback: (data?: any) => void): void;
/**
* @see Events.emit
*/
emit(eventName: string, data: any): void;
public emit(eventName: string, data: any): void;
/**
* Destroy Editor instance and related DOM elements

View file

@ -15,7 +15,6 @@ export interface BaseTool {
}
export interface BaseToolConstructable {
/**
* Define Tool type as Inline
*/
@ -26,6 +25,11 @@ export interface BaseToolConstructable {
*/
sanitize?: SanitizerConfig;
/**
* Title of Inline Tool
*/
title?: string;
/**
* Describe constructor parameters
*/