Add Undo/Redo to contextmenu + add separator between categories

This commit is contained in:
Eric NGUYEN 2022-10-04 17:22:28 +02:00
parent cf3c966170
commit 1086bf58a1
2 changed files with 84 additions and 19 deletions

View file

@ -27,8 +27,37 @@ function InitActions(
configuration: IConfiguration, configuration: IConfiguration,
history: IHistoryState[], history: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setNewHistory: (newHistory: IHistoryState[]) => void setNewHistory: (newHistory: IHistoryState[]) => void,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
menuActions.set(
'',
[
{
text: 'Undo',
title: 'Undo last action',
shortcut: '<kbd>Ctrl</kbd>+<kbd>Z</kbd>',
action: () => {
if (historyCurrentStep <= 0) {
return;
}
setHistoryCurrentStep(historyCurrentStep - 1);
}
},
{
text: 'Redo',
title: 'Redo last action',
shortcut: '<kbd>Ctrl</kbd>+<kbd>Y</kbd>',
action: () => {
if (historyCurrentStep >= history.length - 1) {
return;
}
setHistoryCurrentStep(historyCurrentStep + 1);
}
}
]
);
menuActions.set( menuActions.set(
'elements-sidebar-row', 'elements-sidebar-row',
[{ [{
@ -46,6 +75,7 @@ function InitActions(
} }
}] }]
); );
menuActions.set( menuActions.set(
'symbols-sidebar-row', 'symbols-sidebar-row',
[{ [{
@ -237,7 +267,8 @@ export function Editor(props: IEditorProps): JSX.Element {
props.configuration, props.configuration,
history, history,
historyCurrentStep, historyCurrentStep,
setNewHistory setNewHistory,
setHistoryCurrentStep
); );
// Render // Render

View file

@ -91,23 +91,9 @@ export function Menu(props: IMenuProps): JSX.Element {
if (target !== undefined) { if (target !== undefined) {
let count = 0; let count = 0;
for (const className of target.classList) { count = AddClassSpecificActions(target, count, props, children);
count++; // Add universal actions
const actions = props.actions.get(className); AddUniversalActions(props, children, count, target);
if (actions === undefined) {
continue;
}
actions.forEach((action, index) => {
children.push(<MenuItem
key={`contextmenu-item-${count}-${index}`}
className={'contextmenu-item'}
text={action.text}
title={action.title}
shortcut={action.shortcut}
onClick={() => action.action(target)} />);
});
};
} }
const visible = isOpen && children.length > 0 ? 'visible opacity-1' : 'invisible opacity-0'; const visible = isOpen && children.length > 0 ? 'visible opacity-1' : 'invisible opacity-0';
@ -127,3 +113,51 @@ export function Menu(props: IMenuProps): JSX.Element {
</div> </div>
); );
} }
function AddClassSpecificActions(
target: HTMLElement,
count: number,
props: IMenuProps,
children: JSX.Element[]
): number {
for (const className of target.classList) {
count++;
const actions = props.actions.get(className);
// Only select action where classname matches
if (actions === undefined) {
continue;
}
actions.forEach((action, index) => {
children.push(<MenuItem
key={`contextmenu-item-${count}-${index}`}
className={'contextmenu-item'}
text={action.text}
title={action.title}
shortcut={action.shortcut}
onClick={() => action.action(target)} />);
});
children.push(<hr className='border-slate-400' />);
};
return count;
}
function AddUniversalActions(props: IMenuProps, children: JSX.Element[], count: number, target: HTMLElement): number {
const actions = props.actions.get('');
if (actions !== undefined) {
count++;
actions.forEach((action, index) => {
children.push(<MenuItem
key={`contextmenu-item-${count}-${index}`}
className={'contextmenu-item'}
text={action.text}
title={action.title}
shortcut={action.shortcut}
onClick={() => action.action(target)} />);
});
}
return count;
}