mirror of
https://github.com/codex-team/editor.js
synced 2024-06-11 02:12:31 +02:00
07b1ce2aca
* Add new popover class * Add flipper * confirmation * confirmation * Add confirmation support * Add search * Add toggle group support and update popover tests * Add custom content support * Fix scroll issue * Add mobile version * Integration * Fix animation * Cleanup * Fix popover position for narrow mode * Fix tests * Update version and changelog * Rename css classes * Move files * Stop using PopoverItem from outside of popover context * Fix jsdoc * Move error animation to popover item * Update css variables * Update docs/CHANGELOG.md Co-authored-by: Ilya Maroz <37909603+ilyamore88@users.noreply.github.com> * Update src/components/block-tunes/block-tune-move-down.ts Co-authored-by: Peter Savchenko <specc.dev@gmail.com> * Update src/components/block-tunes/block-tune-move-up.ts Co-authored-by: Peter Savchenko <specc.dev@gmail.com> * Fixes * Fix imports * Fix toolbox close event * Move search-input file * Fix comment * Rename method * Cleanup * Remove onFlip callback from popover item * Rename * Fix removing event listener * Move popover animations to popover.css file * Cleanup styles * Fix jsdoc * Fix confirmation chains * Close toolbox oly when it's open * Change activation error animation * Update version and changelog * Fix overlay * Update icon border-radius on mobile * Disable item text select * Update changelog * Update yarn.lock * Add rc postfix to version --------- Co-authored-by: Ilya Maroz <37909603+ilyamore88@users.noreply.github.com> Co-authored-by: Peter Savchenko <specc.dev@gmail.com>
214 lines
5.5 KiB
TypeScript
214 lines
5.5 KiB
TypeScript
import Module from '../../__module';
|
|
import $ from '../../dom';
|
|
import SelectionUtils from '../../selection';
|
|
import Block from '../../block';
|
|
import I18n from '../../i18n';
|
|
import { I18nInternalNS } from '../../i18n/namespace-internal';
|
|
import Flipper from '../../flipper';
|
|
import { TunesMenuConfigItem } from '../../../../types/tools';
|
|
import { resolveAliases } from '../../utils/resolve-aliases';
|
|
import Popover, { PopoverEvent } from '../../utils/popover';
|
|
|
|
/**
|
|
* HTML Elements that used for BlockSettings
|
|
*/
|
|
interface BlockSettingsNodes {
|
|
wrapper: HTMLElement;
|
|
}
|
|
|
|
/**
|
|
* Block Settings
|
|
*
|
|
* @todo Make Block Settings no-module but a standalone class, like Toolbox
|
|
*/
|
|
export default class BlockSettings extends Module<BlockSettingsNodes> {
|
|
/**
|
|
* Module Events
|
|
*
|
|
* @returns {{opened: string, closed: string}}
|
|
*/
|
|
public get events(): { opened: string; closed: string } {
|
|
return {
|
|
opened: 'block-settings-opened',
|
|
closed: 'block-settings-closed',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Block Settings CSS
|
|
*/
|
|
public get CSS(): { [name: string]: string } {
|
|
return {
|
|
settings: 'ce-settings',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Opened state
|
|
*/
|
|
public opened = false;
|
|
|
|
/**
|
|
* Getter for inner popover's flipper instance
|
|
*
|
|
* @todo remove once BlockSettings becomes standalone non-module class
|
|
*/
|
|
public get flipper(): Flipper {
|
|
return this.popover?.flipper;
|
|
}
|
|
|
|
/**
|
|
* Page selection utils
|
|
*/
|
|
private selection: SelectionUtils = new SelectionUtils();
|
|
|
|
/**
|
|
* Popover instance. There is a util for vertical lists.
|
|
*/
|
|
private popover: Popover | undefined;
|
|
|
|
|
|
/**
|
|
* Panel with block settings with 2 sections:
|
|
* - Tool's Settings
|
|
* - Default Settings [Move, Remove, etc]
|
|
*/
|
|
public make(): void {
|
|
this.nodes.wrapper = $.make('div', [ this.CSS.settings ]);
|
|
}
|
|
|
|
/**
|
|
* Destroys module
|
|
*/
|
|
public destroy(): void {
|
|
this.removeAllNodes();
|
|
}
|
|
|
|
/**
|
|
* Open Block Settings pane
|
|
*
|
|
* @param targetBlock - near which Block we should open BlockSettings
|
|
*/
|
|
public open(targetBlock: Block = this.Editor.BlockManager.currentBlock): void {
|
|
this.opened = true;
|
|
|
|
/**
|
|
* If block settings contains any inputs, focus will be set there,
|
|
* so we need to save current selection to restore it after block settings is closed
|
|
*/
|
|
this.selection.save();
|
|
|
|
/**
|
|
* Highlight content of a Block we are working with
|
|
*/
|
|
targetBlock.selected = true;
|
|
this.Editor.BlockSelection.clearCache();
|
|
|
|
/**
|
|
* Fill Tool's settings
|
|
*/
|
|
const [tunesItems, customHtmlTunesContainer] = targetBlock.getTunes();
|
|
|
|
/** Tell to subscribers that block settings is opened */
|
|
this.eventsDispatcher.emit(this.events.opened);
|
|
this.popover = new Popover({
|
|
searchable: true,
|
|
items: tunesItems.map(tune => this.resolveTuneAliases(tune)),
|
|
customContent: customHtmlTunesContainer,
|
|
customContentFlippableItems: this.getControls(customHtmlTunesContainer),
|
|
scopeElement: this.Editor.API.methods.ui.nodes.redactor,
|
|
messages: {
|
|
nothingFound: I18n.ui(I18nInternalNS.ui.popover, 'Nothing found'),
|
|
search: I18n.ui(I18nInternalNS.ui.popover, 'Filter'),
|
|
},
|
|
});
|
|
|
|
this.popover.on(PopoverEvent.Close, this.onPopoverClose);
|
|
|
|
this.nodes.wrapper.append(this.popover.getElement());
|
|
|
|
this.popover.show();
|
|
}
|
|
|
|
/**
|
|
* Returns root block settings element
|
|
*/
|
|
public getElement(): HTMLElement {
|
|
return this.nodes.wrapper;
|
|
}
|
|
|
|
/**
|
|
* Close Block Settings pane
|
|
*/
|
|
public close(): void {
|
|
this.opened = false;
|
|
|
|
/**
|
|
* If selection is at editor on Block Settings closing,
|
|
* it means that caret placed at some editable element inside the Block Settings.
|
|
* Previously we have saved the selection, then open the Block Settings and set caret to the input
|
|
*
|
|
* So, we need to restore selection back to Block after closing the Block Settings
|
|
*/
|
|
if (!SelectionUtils.isAtEditor) {
|
|
this.selection.restore();
|
|
}
|
|
|
|
this.selection.clearSaved();
|
|
|
|
/**
|
|
* Remove highlighted content of a Block we are working with
|
|
*/
|
|
if (!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted && this.Editor.BlockManager.currentBlock) {
|
|
this.Editor.BlockManager.currentBlock.selected = false;
|
|
}
|
|
|
|
/** Tell to subscribers that block settings is closed */
|
|
this.eventsDispatcher.emit(this.events.closed);
|
|
|
|
if (this.popover) {
|
|
this.popover.off(PopoverEvent.Close, this.onPopoverClose);
|
|
this.popover.destroy();
|
|
this.popover.getElement().remove();
|
|
this.popover = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles popover close event
|
|
*/
|
|
private onPopoverClose = (): void => {
|
|
this.close();
|
|
};
|
|
|
|
/**
|
|
* Returns list of buttons and inputs inside specified container
|
|
*
|
|
* @param container - container to query controls inside of
|
|
*/
|
|
private getControls(container: HTMLElement): HTMLElement[] {
|
|
const { StylesAPI } = this.Editor;
|
|
/** Query buttons and inputs inside tunes html */
|
|
const controls = container.querySelectorAll<HTMLElement>(
|
|
`.${StylesAPI.classes.settingsButton}, ${$.allInputsSelector}`
|
|
);
|
|
|
|
return Array.from(controls);
|
|
}
|
|
|
|
/**
|
|
* Resolves aliases in tunes menu items
|
|
*
|
|
* @param item - item with resolved aliases
|
|
*/
|
|
private resolveTuneAliases(item: TunesMenuConfigItem): TunesMenuConfigItem {
|
|
const result = resolveAliases(item, { label: 'title' });
|
|
|
|
if (item.confirmation) {
|
|
result.confirmation = this.resolveTuneAliases(item.confirmation);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|