mirror of
https://github.com/chartdb/chartdb.git
synced 2026-01-08 04:40:01 -06:00
add redo undo shortcuts
This commit is contained in:
committed by
Guy Ben-Aharon
parent
635bd57d1a
commit
f9c088e4ee
11
package-lock.json
generated
11
package-lock.json
generated
@@ -43,6 +43,7 @@
|
||||
"react": "^18.3.1",
|
||||
"react-code-blocks": "^0.1.6",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hotkeys-hook": "^4.5.0",
|
||||
"react-resizable-panels": "^2.0.22",
|
||||
"react-responsive": "^10.0.0",
|
||||
"react-router-dom": "^6.26.0",
|
||||
@@ -8019,6 +8020,16 @@
|
||||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-hotkeys-hook": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.5.0.tgz",
|
||||
"integrity": "sha512-Samb85GSgAWFQNvVt3PS90LPPGSf9mkH/r4au81ZP1yOIFayLC3QAvqTgGtJ8YEDMXtPmaVBs6NgipHO6h4Mug==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.1",
|
||||
"react-dom": ">=16.8.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"react": "^18.3.1",
|
||||
"react-code-blocks": "^0.1.6",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hotkeys-hook": "^4.5.0",
|
||||
"react-resizable-panels": "^2.0.22",
|
||||
"react-responsive": "^10.0.0",
|
||||
"react-router-dom": "^6.26.0",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
export interface KeyboardShortcutsContext {}
|
||||
|
||||
export const keyboardShortcutsContext = createContext<KeyboardShortcutsContext>(
|
||||
{}
|
||||
);
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { keyboardShortcutsContext } from './keyboard-shortcuts-context';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import {
|
||||
KeyboardShortcutAction,
|
||||
keyboardShortcutsForOS,
|
||||
} from './keyboard-shortcuts';
|
||||
import { useHistory } from '@/hooks/use-history';
|
||||
|
||||
export const KeyboardShortcutsProvider: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const { redo, undo } = useHistory();
|
||||
useHotkeys(
|
||||
keyboardShortcutsForOS[KeyboardShortcutAction.REDO].keyCombination,
|
||||
redo,
|
||||
[redo]
|
||||
);
|
||||
useHotkeys(
|
||||
keyboardShortcutsForOS[KeyboardShortcutAction.UNDO].keyCombination,
|
||||
undo,
|
||||
[undo]
|
||||
);
|
||||
return (
|
||||
<keyboardShortcutsContext.Provider value={{}}>
|
||||
{children}
|
||||
</keyboardShortcutsContext.Provider>
|
||||
);
|
||||
};
|
||||
70
src/context/keyboard-shortcuts-context/keyboard-shortcuts.ts
Normal file
70
src/context/keyboard-shortcuts-context/keyboard-shortcuts.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { getOperatingSystem } from '@/lib/utils';
|
||||
|
||||
export enum KeyboardShortcutAction {
|
||||
REDO = 'redo',
|
||||
UNDO = 'undo',
|
||||
}
|
||||
|
||||
export interface KeyboardShortcut {
|
||||
action: KeyboardShortcutAction;
|
||||
keyCombinationLabelMac: string;
|
||||
keyCombinationLabelWin: string;
|
||||
keyCombinationMac: string;
|
||||
keyCombinationWin: string;
|
||||
}
|
||||
|
||||
export const keyboardShortcuts: Record<
|
||||
KeyboardShortcutAction,
|
||||
KeyboardShortcut
|
||||
> = {
|
||||
[KeyboardShortcutAction.REDO]: {
|
||||
action: KeyboardShortcutAction.REDO,
|
||||
keyCombinationLabelMac: '⇧⌘Z',
|
||||
keyCombinationLabelWin: 'Ctrl+Shift+Z',
|
||||
keyCombinationMac: 'meta+shift+z',
|
||||
keyCombinationWin: 'ctrl+shift+z',
|
||||
},
|
||||
[KeyboardShortcutAction.UNDO]: {
|
||||
action: KeyboardShortcutAction.UNDO,
|
||||
keyCombinationLabelMac: '⌘Z',
|
||||
keyCombinationLabelWin: 'Ctrl+Z',
|
||||
keyCombinationMac: 'meta+z',
|
||||
keyCombinationWin: 'ctrl+z',
|
||||
},
|
||||
};
|
||||
|
||||
export interface KeyboardShortcutForOS {
|
||||
action: KeyboardShortcutAction;
|
||||
keyCombinationLabel: string;
|
||||
keyCombination: string;
|
||||
}
|
||||
|
||||
const operatingSystem = getOperatingSystem();
|
||||
|
||||
export const keyboardShortcutsForOS: Record<
|
||||
KeyboardShortcutAction,
|
||||
KeyboardShortcutForOS
|
||||
> = Object.keys(keyboardShortcuts).reduce(
|
||||
(acc, action) => {
|
||||
const keyboardShortcut =
|
||||
keyboardShortcuts[action as KeyboardShortcutAction];
|
||||
const keyCombinationLabel =
|
||||
operatingSystem === 'mac'
|
||||
? keyboardShortcut.keyCombinationLabelMac
|
||||
: keyboardShortcut.keyCombinationLabelWin;
|
||||
const keyCombination =
|
||||
operatingSystem === 'mac'
|
||||
? keyboardShortcut.keyCombinationMac
|
||||
: keyboardShortcut.keyCombinationWin;
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[action]: {
|
||||
action: keyboardShortcut.action,
|
||||
keyCombinationLabel,
|
||||
keyCombination,
|
||||
},
|
||||
};
|
||||
},
|
||||
{} as Record<KeyboardShortcutAction, KeyboardShortcutForOS>
|
||||
);
|
||||
@@ -13,3 +13,14 @@ export function cn(...inputs: ClassValue[]) {
|
||||
export const emptyFn = (): any => undefined;
|
||||
|
||||
export const generateId = () => randomId();
|
||||
|
||||
export const getOperatingSystem = (): 'mac' | 'windows' | 'unknown' => {
|
||||
const userAgent = window.navigator.userAgent;
|
||||
if (userAgent.includes('Mac OS X')) {
|
||||
return 'mac';
|
||||
}
|
||||
if (userAgent.includes('Windows')) {
|
||||
return 'windows';
|
||||
}
|
||||
return 'unknown';
|
||||
};
|
||||
|
||||
@@ -33,6 +33,11 @@ import { useConfig } from '@/hooks/use-config';
|
||||
import { IS_CHARTDB_IO } from '@/lib/env';
|
||||
import { useBreakpoint } from '@/hooks/use-breakpoint';
|
||||
import { DiagramIcon } from '@/components/diagram-icon/diagram-icon';
|
||||
import {
|
||||
KeyboardShortcutAction,
|
||||
keyboardShortcutsForOS,
|
||||
} from '@/context/keyboard-shortcuts-context/keyboard-shortcuts';
|
||||
import { useHistory } from '@/hooks/use-history';
|
||||
|
||||
export interface TopNavbarProps {}
|
||||
|
||||
@@ -50,6 +55,7 @@ export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
openExportSQLDialog,
|
||||
showAlert,
|
||||
} = useDialog();
|
||||
const { redo, undo, hasRedo, hasUndo } = useHistory();
|
||||
const { isMd: isDesktop } = useBreakpoint('md');
|
||||
const { config, updateConfig } = useConfig();
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
@@ -398,8 +404,26 @@ export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Edit</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem>Undo</MenubarItem>
|
||||
<MenubarItem>Redo</MenubarItem>
|
||||
<MenubarItem onClick={undo} disabled={!hasUndo}>
|
||||
Undo
|
||||
<MenubarShortcut>
|
||||
{
|
||||
keyboardShortcutsForOS[
|
||||
KeyboardShortcutAction.UNDO
|
||||
].keyCombinationLabel
|
||||
}
|
||||
</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={redo} disabled={!hasRedo}>
|
||||
Redo
|
||||
<MenubarShortcut>
|
||||
{
|
||||
keyboardShortcutsForOS[
|
||||
KeyboardShortcutAction.REDO
|
||||
].keyCombinationLabel
|
||||
}
|
||||
</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { DialogProvider } from './context/dialog-context/dialog-provider';
|
||||
import { ExportImageProvider } from './context/export-image-context/export-image-provider';
|
||||
import { FullScreenLoaderProvider } from './context/full-screen-spinner-context/full-screen-spinner-provider';
|
||||
import { ExamplesPage } from './pages/examples-page/examples-page';
|
||||
import { KeyboardShortcutsProvider } from './context/keyboard-shortcuts-context/keyboard-shortcuts-provider';
|
||||
|
||||
const routes: RouteObject[] = [
|
||||
...['', 'diagrams/:diagramId'].map((path) => ({
|
||||
@@ -28,9 +29,11 @@ const routes: RouteObject[] = [
|
||||
<DialogProvider>
|
||||
<ReactFlowProvider>
|
||||
<ExportImageProvider>
|
||||
{/* <ThemeProvider> */}
|
||||
<EditorPage />
|
||||
{/* </ThemeProvider> */}
|
||||
<KeyboardShortcutsProvider>
|
||||
{/* <ThemeProvider> */}
|
||||
<EditorPage />
|
||||
{/* </ThemeProvider> */}
|
||||
</KeyboardShortcutsProvider>
|
||||
</ExportImageProvider>
|
||||
</ReactFlowProvider>
|
||||
</DialogProvider>
|
||||
|
||||
Reference in New Issue
Block a user