mirror of
https://github.com/codex-team/editor.js
synced 2024-06-17 21:25:05 +02:00
New block lifecycle hook and BlockToolAPI: "moved" (#1007)
* Update CHANGELOG.md * feat: add swapped lifecycle hook * feat: deprecate swap and add move instead * feat: set fromIndex by default, add MoveEvent, add indices checks in blockManager * refactor: MoveEvent interface more event-like; docs: added docs for MoveEvent * fix asterix alignment due to tslint error * fix tslint * extending CustomEvent * update bundle * Update CHANGELOG.md Co-authored-by: Peter Savchenko <specc.dev@gmail.com> Co-authored-by: Murod Khaydarov <murod.haydarov@gmail.com>
This commit is contained in:
parent
3877380ee1
commit
8b838bf8aa
2
dist/editor.js
vendored
2
dist/editor.js
vendored
File diff suppressed because one or more lines are too long
|
@ -10,6 +10,8 @@
|
|||
- `Fix` - Fix block-tune buttons alignment in some CSS-resetors that forces `box-sizing: border-box` rule [#1003](https://github.com/codex-team/editor.js/issues/1003)
|
||||
- `Improvements` - New style of a Block Settings button. Focused block background removed.
|
||||
- `New` — Add in-house copy-paste support through `application/x-editor-js` mime-type
|
||||
- `New` Block [lifecycle hook](tools.md#block-lifecycle-hooks) `moved`
|
||||
- `Deprecated` — [`blocks.swap(fromIndex, toIndex)`](api.md) method is deprecated. Use `blocks.move(toIndex, fromIndex)` instead.
|
||||
|
||||
### 2.16.1
|
||||
|
||||
|
|
|
@ -26,7 +26,11 @@ Methods that working with Blocks
|
|||
|
||||
`renderFromHTML(data)` - parse and render passed HTML string (*not for production use*)
|
||||
|
||||
`swap(fromIndex, toIndex)` - swaps two Blocks by their positions
|
||||
`swap(fromIndex, toIndex)` - swaps two Blocks by their positions (deprecated:
|
||||
use 'move' instead)
|
||||
|
||||
`move(toIndex, fromIndex)` - moves block from one index to another position.
|
||||
`fromIndex` will be the current block's index by default.
|
||||
|
||||
`delete(blockIndex?: Number)` - deletes Block with passed index
|
||||
|
||||
|
|
|
@ -476,3 +476,8 @@ Called each time Block contents is updated
|
|||
### `removed()`
|
||||
|
||||
Called after Block contents is removed from the page but before Block instance deleted
|
||||
|
||||
### `moved(MoveEvent)`
|
||||
|
||||
Called after Block was moved. `MoveEvent` contains `fromIndex` and `toIndex`
|
||||
respectively.
|
||||
|
|
|
@ -92,7 +92,7 @@ export default class MoveDownTune implements BlockTune {
|
|||
window.scrollTo(0, scrollOffset);
|
||||
|
||||
/** Change blocks positions */
|
||||
this.api.blocks.swap(currentBlockIndex, currentBlockIndex + 1);
|
||||
this.api.blocks.move(currentBlockIndex + 1);
|
||||
|
||||
/** Hide the Tooltip */
|
||||
this.api.tooltip.hide();
|
||||
|
|
|
@ -46,7 +46,7 @@ export default class MoveUpTune implements BlockTune {
|
|||
'click',
|
||||
(event) => this.handleClick(event as MouseEvent, moveUpButton),
|
||||
false,
|
||||
);
|
||||
);
|
||||
|
||||
/**
|
||||
* Enable tooltip module on button
|
||||
|
@ -99,7 +99,7 @@ export default class MoveUpTune implements BlockTune {
|
|||
window.scrollBy(0, -1 * scrollUpOffset);
|
||||
|
||||
/** Change blocks positions */
|
||||
this.api.blocks.swap(currentBlockIndex, currentBlockIndex - 1);
|
||||
this.api.blocks.move(currentBlockIndex - 1);
|
||||
|
||||
/** Hide the Tooltip */
|
||||
this.api.tooltip.hide();
|
||||
|
|
|
@ -38,6 +38,7 @@ export enum BlockToolAPI {
|
|||
*/
|
||||
APPEND_CALLBACK = 'appendCallback',
|
||||
RENDERED = 'rendered',
|
||||
MOVED = 'moved',
|
||||
UPDATED = 'updated',
|
||||
REMOVED = 'removed',
|
||||
ON_PASTE = 'onPaste',
|
||||
|
@ -441,7 +442,7 @@ export default class Block {
|
|||
* @param {Object} data
|
||||
*/
|
||||
public async mergeWith(data: BlockToolData): Promise<void> {
|
||||
await this.tool.merge(data);
|
||||
await this.tool.merge(data);
|
||||
}
|
||||
/**
|
||||
* Extracts data from Block
|
||||
|
@ -465,7 +466,7 @@ export default class Block {
|
|||
return {
|
||||
tool: this.name,
|
||||
data: finishedExtraction,
|
||||
time : measuringEnd - measuringStart,
|
||||
time: measuringEnd - measuringStart,
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -562,7 +563,7 @@ export default class Block {
|
|||
private compose(): HTMLDivElement {
|
||||
const wrapper = $.make('div', Block.CSS.wrapper) as HTMLDivElement,
|
||||
contentNode = $.make('div', Block.CSS.content),
|
||||
pluginsContent = this.tool.render();
|
||||
pluginsContent = this.tool.render();
|
||||
|
||||
contentNode.appendChild(pluginsContent);
|
||||
wrapper.appendChild(contentNode);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import * as _ from './utils';
|
||||
import $ from './dom';
|
||||
import Block, {BlockToolAPI} from './block';
|
||||
import Block, { BlockToolAPI } from './block';
|
||||
import {MoveEvent, MoveEventDetail} from '../../types/tools';
|
||||
|
||||
/**
|
||||
* @class Blocks
|
||||
|
@ -127,6 +128,7 @@ export default class Blocks {
|
|||
* Swaps blocks with indexes first and second
|
||||
* @param {Number} first - first block index
|
||||
* @param {Number} second - second block index
|
||||
* @deprecated — use 'move' instead
|
||||
*/
|
||||
public swap(first: number, second: number): void {
|
||||
const secondBlock = this.blocks[second];
|
||||
|
@ -143,6 +145,42 @@ export default class Blocks {
|
|||
this.blocks[first] = secondBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a block from one to another index
|
||||
* @param {Number} toIndex - new index of the block
|
||||
* @param {Number} fromIndex - block to move
|
||||
*/
|
||||
public move(toIndex: number, fromIndex: number): void {
|
||||
/**
|
||||
* cut out the block, move the DOM element and insert at the desired index
|
||||
* again (the shifting within the blocks array will happen automatically).
|
||||
* @see https://stackoverflow.com/a/44932690/1238150
|
||||
*/
|
||||
const block = this.blocks.splice(fromIndex, 1)[0];
|
||||
|
||||
// manipulate DOM
|
||||
const prevIndex = toIndex - 1;
|
||||
const previousBlockIndex = Math.max(0, prevIndex);
|
||||
const previousBlock = this.blocks[previousBlockIndex];
|
||||
|
||||
if (toIndex > 0) {
|
||||
this.insertToDOM(block, 'afterend', previousBlock);
|
||||
} else {
|
||||
this.insertToDOM(block, 'beforebegin', previousBlock);
|
||||
}
|
||||
|
||||
// move in array
|
||||
this.blocks.splice(toIndex, 0, block);
|
||||
|
||||
// invoke hook
|
||||
const event: MoveEvent = this.composeBlockEvent('move', {
|
||||
fromIndex,
|
||||
toIndex,
|
||||
});
|
||||
|
||||
block.call(BlockToolAPI.MOVED, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert new Block at passed index
|
||||
*
|
||||
|
@ -261,4 +299,17 @@ export default class Blocks {
|
|||
|
||||
block.call(BlockToolAPI.RENDERED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes Block event with passed type and details
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {MoveEventDetail} detail
|
||||
*/
|
||||
private composeBlockEvent(type: string, detail: MoveEventDetail): MoveEvent {
|
||||
return new CustomEvent(type, {
|
||||
detail,
|
||||
},
|
||||
) as MoveEvent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ export default class Dom {
|
|||
* Swap two elements in parent
|
||||
* @param {HTMLElement} el1 - from
|
||||
* @param {HTMLElement} el2 - to
|
||||
* @deprecated
|
||||
*/
|
||||
public static swap(el1: HTMLElement, el2: HTMLElement): void {
|
||||
// create marker element and insert it where el1 is
|
||||
|
|
|
@ -20,6 +20,7 @@ export default class BlocksAPI extends Module {
|
|||
renderFromHTML: (data: string) => this.renderFromHTML(data),
|
||||
delete: () => this.delete(),
|
||||
swap: (fromIndex: number, toIndex: number) => this.swap(fromIndex, toIndex),
|
||||
move: (toIndex: number, fromIndex?: number) => this.move(toIndex, fromIndex),
|
||||
getBlockByIndex: (index: number) => this.getBlockByIndex(index),
|
||||
getCurrentBlockIndex: () => this.getCurrentBlockIndex(),
|
||||
getBlocksCount: () => this.getBlocksCount(),
|
||||
|
@ -60,6 +61,7 @@ export default class BlocksAPI extends Module {
|
|||
* Call Block Manager method that swap Blocks
|
||||
* @param {number} fromIndex - position of first Block
|
||||
* @param {number} toIndex - position of second Block
|
||||
* @deprecated — use 'move' instead
|
||||
*/
|
||||
public swap(fromIndex: number, toIndex: number): void {
|
||||
this.Editor.BlockManager.swap(fromIndex, toIndex);
|
||||
|
@ -71,6 +73,21 @@ export default class BlocksAPI extends Module {
|
|||
this.Editor.Toolbar.move(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move block from one index to another
|
||||
* @param {Number} toIndex
|
||||
* @param {number} fromIndex
|
||||
*/
|
||||
public move(toIndex: number, fromIndex?: number): void {
|
||||
this.Editor.BlockManager.move(toIndex, fromIndex);
|
||||
|
||||
/**
|
||||
* Move toolbar
|
||||
* DO not close the settings
|
||||
*/
|
||||
this.Editor.Toolbar.move(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Block
|
||||
* @param blockIndex
|
||||
|
|
|
@ -552,6 +552,7 @@ export default class BlockManager extends Module {
|
|||
* Swap Blocks Position
|
||||
* @param {Number} fromIndex
|
||||
* @param {Number} toIndex
|
||||
* @deprecated — use 'move' instead
|
||||
*/
|
||||
public swap(fromIndex, toIndex): void {
|
||||
/** Move up current Block */
|
||||
|
@ -561,6 +562,30 @@ export default class BlockManager extends Module {
|
|||
this.currentBlockIndex = toIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a block to a new index
|
||||
* @param {Number} toIndex
|
||||
* @param {Number} fromIndex
|
||||
*/
|
||||
public move(toIndex, fromIndex = this.currentBlockIndex): void {
|
||||
// make sure indexes are valid and within a valid range
|
||||
if (isNaN(toIndex) || isNaN(fromIndex)) {
|
||||
_.log(`Warning during 'move' call: incorrect indices provided.`, 'warn');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.validateIndex(toIndex) || !this.validateIndex(fromIndex)) {
|
||||
_.log(`Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.`, 'warn');
|
||||
return;
|
||||
}
|
||||
|
||||
/** Move up current Block */
|
||||
this._blocks.move(toIndex, fromIndex);
|
||||
|
||||
/** Now actual block moved so that current block index changed */
|
||||
this.currentBlockIndex = toIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current Block Index -1 which means unknown
|
||||
* and clear highlightings
|
||||
|
@ -604,4 +629,16 @@ export default class BlockManager extends Module {
|
|||
Listeners.on(block.holder, 'dragover', (event) => BlockEvents.dragOver(event as DragEvent));
|
||||
Listeners.on(block.holder, 'dragleave', (event) => BlockEvents.dragLeave(event as DragEvent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the given index is not lower than 0 or higher than the amount of blocks
|
||||
* @param {number} index - index of blocks array to validate
|
||||
*/
|
||||
private validateIndex(index: number): boolean {
|
||||
if (index < 0 || index >= this._blocks.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
8
types/api/blocks.d.ts
vendored
8
types/api/blocks.d.ts
vendored
|
@ -33,9 +33,17 @@ export interface Blocks {
|
|||
* Swaps two Blocks
|
||||
* @param {number} fromIndex - block to swap
|
||||
* @param {number} toIndex - block to swap with
|
||||
* @deprecated — use 'move' instead
|
||||
*/
|
||||
swap(fromIndex: number, toIndex: number): void;
|
||||
|
||||
/**
|
||||
* Moves a block to a new index
|
||||
* @param {number} toIndex - index where the block is moved to
|
||||
* @param {number} fromIndex - block to move
|
||||
*/
|
||||
move(toIndex: number, fromIndex?: number): void;
|
||||
|
||||
/**
|
||||
* Returns Block holder by Block index
|
||||
* @param {number} index
|
||||
|
|
20
types/tools/block-tool.d.ts
vendored
20
types/tools/block-tool.d.ts
vendored
|
@ -1,9 +1,10 @@
|
|||
import {ConversionConfig, PasteConfig, SanitizerConfig} from '../configs';
|
||||
import {BlockToolData} from './block-tool-data';
|
||||
import {BaseTool, BaseToolConstructable} from './tool';
|
||||
import {ToolConfig} from './tool-config';
|
||||
import {API} from '../index';
|
||||
import {PasteEvent} from './paste-events';
|
||||
import { ConversionConfig, PasteConfig, SanitizerConfig } from '../configs';
|
||||
import { BlockToolData } from './block-tool-data';
|
||||
import { BaseTool, BaseToolConstructable } from './tool';
|
||||
import { ToolConfig } from './tool-config';
|
||||
import { API } from '../index';
|
||||
import { PasteEvent } from './paste-events';
|
||||
import { MoveEvent } from './hook-events';
|
||||
/**
|
||||
* Describe Block Tool object
|
||||
* @see {@link docs/tools.md}
|
||||
|
@ -65,6 +66,11 @@ export interface BlockTool extends BaseTool {
|
|||
* Called after block removed from the page but before instance is deleted
|
||||
*/
|
||||
removed?(): void;
|
||||
|
||||
/**
|
||||
* Called after block was moved
|
||||
*/
|
||||
moved?(event: MoveEvent): void;
|
||||
}
|
||||
|
||||
export interface BlockToolConstructable extends BaseToolConstructable {
|
||||
|
@ -97,5 +103,5 @@ export interface BlockToolConstructable extends BaseToolConstructable {
|
|||
* @constructor
|
||||
* @return {BlockTool}
|
||||
*/
|
||||
new (config: {api: API, config: ToolConfig, data: BlockToolData}): BlockTool;
|
||||
new(config: { api: API, config: ToolConfig, data: BlockToolData }): BlockTool;
|
||||
}
|
||||
|
|
23
types/tools/hook-events.d.ts
vendored
Normal file
23
types/tools/hook-events.d.ts
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Event detail for block relocation
|
||||
*/
|
||||
export interface MoveEventDetail {
|
||||
/**
|
||||
* index the block was moved from
|
||||
*/
|
||||
fromIndex: number;
|
||||
/**
|
||||
* index the block was moved to
|
||||
*/
|
||||
toIndex: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move event for block relocation
|
||||
*/
|
||||
export interface MoveEvent extends CustomEvent {
|
||||
/**
|
||||
* Override detail property of CustomEvent by MoveEvent hook
|
||||
*/
|
||||
readonly detail: MoveEventDetail;
|
||||
}
|
1
types/tools/index.d.ts
vendored
1
types/tools/index.d.ts
vendored
|
@ -9,6 +9,7 @@ export * from './tool';
|
|||
export * from './tool-config';
|
||||
export * from './tool-settings';
|
||||
export * from './paste-events';
|
||||
export * from './hook-events';
|
||||
|
||||
export type Tool = BaseTool | BlockTool | InlineTool;
|
||||
export type ToolConstructable = BaseToolConstructable | BlockToolConstructable | InlineToolConstructable;
|
||||
|
|
Loading…
Reference in a new issue