mirror of
https://github.com/codex-team/editor.js
synced 2026-03-16 15:45:47 +01:00
Add confirmation support to popover
This commit is contained in:
parent
fbff33704d
commit
58a2f97112
4 changed files with 122 additions and 27 deletions
|
|
@ -72,6 +72,9 @@ export default class DeleteTune implements BlockTune {
|
|||
label: this.api.i18n.t('Delete'),
|
||||
onClick: (item, e): void => this.handleClick(e),
|
||||
name: 'delete',
|
||||
confirmation: {
|
||||
label: 'Click to delete',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -85,36 +88,36 @@ export default class DeleteTune implements BlockTune {
|
|||
* if block is not waiting the confirmation, subscribe on block-settings-closing event to reset
|
||||
* otherwise delete block
|
||||
*/
|
||||
if (!this.needConfirmation) {
|
||||
this.setConfirmation(true);
|
||||
const button = (event.target as HTMLElement)
|
||||
.closest('.' + Popover.CSS.item)
|
||||
.querySelector('.' + Popover.CSS.itemIcon);
|
||||
// if (!this.needConfirmation) {
|
||||
// this.setConfirmation(true);
|
||||
// const button = (event.target as HTMLElement)
|
||||
// .closest('.' + Popover.CSS.item)
|
||||
// .querySelector('.' + Popover.CSS.itemIcon);
|
||||
|
||||
button.classList.add(this.CSS.buttonDelete);
|
||||
button.classList.add(this.CSS.buttonConfirm);
|
||||
// button.classList.add(this.CSS.buttonDelete);
|
||||
// button.classList.add(this.CSS.buttonConfirm);
|
||||
|
||||
/**
|
||||
* Subscribe on event.
|
||||
* When toolbar block settings is closed but block deletion is not confirmed,
|
||||
* then reset confirmation state
|
||||
*/
|
||||
this.api.events.on('block-settings-closed', this.resetConfirmation);
|
||||
} else {
|
||||
/**
|
||||
* Unsubscribe from block-settings closing event
|
||||
*/
|
||||
this.api.events.off('block-settings-closed', this.resetConfirmation);
|
||||
// /**
|
||||
// * Subscribe on event.
|
||||
// * When toolbar block settings is closed but block deletion is not confirmed,
|
||||
// * then reset confirmation state
|
||||
// */
|
||||
// this.api.events.on('block-settings-closed', this.resetConfirmation);
|
||||
// } else {
|
||||
/**
|
||||
* Unsubscribe from block-settings closing event
|
||||
*/
|
||||
// this.api.events.off('block-settings-closed', this.resetConfirmation);
|
||||
|
||||
this.api.blocks.delete();
|
||||
this.api.toolbar.close();
|
||||
this.api.tooltip.hide();
|
||||
this.api.blocks.delete();
|
||||
this.api.toolbar.close();
|
||||
this.api.tooltip.hide();
|
||||
|
||||
/**
|
||||
* Prevent firing ui~documentClicked that can drop currentBlock pointer
|
||||
*/
|
||||
event.stopPropagation();
|
||||
}
|
||||
/**
|
||||
* Prevent firing ui~documentClicked that can drop currentBlock pointer
|
||||
*/
|
||||
event.stopPropagation();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -48,6 +48,13 @@ export interface PopoverItem {
|
|||
* True if popover should close once item is activated
|
||||
*/
|
||||
closeOnActivate?: boolean;
|
||||
|
||||
/**
|
||||
* If action requires confirmation, first click on the item will turn it into object specified in this field.
|
||||
* Second click will perform the action.
|
||||
*/
|
||||
confirmation?: boolean | Partial<PopoverItem>;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,6 +153,7 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
|
|||
itemLabel: string;
|
||||
itemIcon: string;
|
||||
itemSecondaryLabel: string;
|
||||
itemConfirmation: string;
|
||||
noFoundMessage: string;
|
||||
noFoundMessageShown: string;
|
||||
popoverOverlay: string;
|
||||
|
|
@ -162,6 +170,7 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
|
|||
itemFlippable: 'ce-popover__item--flippable',
|
||||
itemFocused: 'ce-popover__item--focused',
|
||||
itemActive: 'ce-popover__item--active',
|
||||
itemConfirmation: 'ce-popover__item--confirmation',
|
||||
itemLabel: 'ce-popover__item-label',
|
||||
itemIcon: 'ce-popover__item-icon',
|
||||
itemSecondaryLabel: 'ce-popover__item-secondary-label',
|
||||
|
|
@ -184,6 +193,11 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
|
|||
*/
|
||||
private api: API;
|
||||
|
||||
/**
|
||||
* Reference to popover item that was clicked but requires second click to confirm action
|
||||
*/
|
||||
private itemAwaitngConfirmation = null;
|
||||
|
||||
/**
|
||||
* Creates the Popover
|
||||
*
|
||||
|
|
@ -286,6 +300,8 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
|
|||
|
||||
this.isShown = false;
|
||||
this.nodes.wrapper.classList.remove(this.className + '--opened-top');
|
||||
|
||||
this.cleanUpConfirmationState();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -460,6 +476,12 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
|
|||
const itemIndex = Array.from(allItems).indexOf(itemEl);
|
||||
const clickedItem = this.items[itemIndex];
|
||||
|
||||
const ignoreClick = this.handleConfirmation(itemEl, clickedItem);
|
||||
|
||||
if (ignoreClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
clickedItem.onClick(clickedItem, event);
|
||||
|
||||
if (clickedItem.closeOnActivate) {
|
||||
|
|
@ -467,6 +489,57 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles case when item needs confirmation before calling onClick callback.
|
||||
* Returns true if click should be ignored.
|
||||
*
|
||||
* @param itemEl - clicked HTML element
|
||||
* @param clickedItem - corresponding popover item
|
||||
*/
|
||||
private handleConfirmation(itemEl: HTMLElement, clickedItem: PopoverItem): boolean {
|
||||
if (this.itemAwaitngConfirmation !== clickedItem && clickedItem.confirmation) {
|
||||
/**
|
||||
* Item requires confirmation.
|
||||
* If configured, item's label, icon and other params should be replaced with values defined for confirmation state.
|
||||
* Click is ignored.
|
||||
*/
|
||||
this.itemAwaitngConfirmation = clickedItem;
|
||||
|
||||
const itemData = {
|
||||
...clickedItem,
|
||||
...clickedItem.confirmation as PopoverItem,
|
||||
confirmation: false,
|
||||
};
|
||||
const confirmationStateItemEl = this.createItem(itemData);
|
||||
|
||||
confirmationStateItemEl.classList.add(Popover.CSS.itemConfirmation);
|
||||
itemEl.parentElement.replaceChild(confirmationStateItemEl, itemEl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If item requiring confirmation is clicked for the second time or any other item is clicked,
|
||||
* get rid of confirmation state on item
|
||||
*/
|
||||
this.cleanUpConfirmationState();
|
||||
}
|
||||
|
||||
/**
|
||||
* If popover contains an item in confirmation state, bring it to default state
|
||||
*/
|
||||
private cleanUpConfirmationState(): void {
|
||||
if (!this.itemAwaitngConfirmation) {
|
||||
return;
|
||||
}
|
||||
const defaultStateItemEl = this.createItem(this.itemAwaitngConfirmation);
|
||||
const confirmationStateItemEl = this.nodes.wrapper.querySelector(`.${Popover.CSS.itemConfirmation}`);
|
||||
|
||||
confirmationStateItemEl.parentElement.replaceChild(defaultStateItemEl, confirmationStateItemEl);
|
||||
defaultStateItemEl.classList.remove(Popover.CSS.itemConfirmation);
|
||||
this.itemAwaitngConfirmation = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Flipper instance to be able to leaf tools
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -76,6 +76,25 @@
|
|||
@apply --button-active;
|
||||
}
|
||||
|
||||
&--confirmation {
|
||||
background: var(--color-confirm);
|
||||
|
||||
@media (--can-hover) {
|
||||
&:hover {
|
||||
background: #ce4343;
|
||||
}
|
||||
}
|
||||
|
||||
.ce-popover__item-icon {
|
||||
color: var(--color-confirm);
|
||||
}
|
||||
|
||||
.ce-popover__item-label {
|
||||
color: white;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&-icon {
|
||||
@apply --tool-icon;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@
|
|||
|
||||
--button-active: {
|
||||
background: rgba(56, 138, 229, 0.1);
|
||||
color: #388AE5;
|
||||
color: var(--color-active-icon);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue