mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-11 18:26:04 +00:00
feat(Map): Rework design of checkboxes in Signatures settings dialog. Rework design of checkboxes in Routes settings dialog. Now signature will deleteing by Delete hotkey was Backspace. Fixed size of group column in signatures list. Instead Updated column will be Added, updated may be turn on in settings. (#76)
Co-authored-by: achichenkov <aleksei.chichenkov@telleqt.ai>
This commit is contained in:
committed by
GitHub
parent
c1ecd3690e
commit
ef6b45d7a1
@@ -1,12 +1,11 @@
|
|||||||
import { Dialog } from 'primereact/dialog';
|
import { Dialog } from 'primereact/dialog';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { WdCheckbox } from '@/hooks/Mapper/components/ui-kit';
|
|
||||||
import {
|
import {
|
||||||
RoutesType,
|
RoutesType,
|
||||||
useRouteProvider,
|
useRouteProvider,
|
||||||
} from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
|
} from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
|
||||||
import { CheckboxChangeEvent } from 'primereact/checkbox';
|
import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components';
|
||||||
|
|
||||||
interface RoutesSettingsDialog {
|
interface RoutesSettingsDialog {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
@@ -38,8 +37,8 @@ export const RoutesSettingsDialog = ({ visible, setVisible }: RoutesSettingsDial
|
|||||||
currentData.current = data;
|
currentData.current = data;
|
||||||
|
|
||||||
const handleChangeEvent = useCallback(
|
const handleChangeEvent = useCallback(
|
||||||
(propName: keyof RoutesType) => (event: CheckboxChangeEvent) => {
|
(propName: keyof RoutesType) => (event: boolean) => {
|
||||||
optionsRef.current = { ...optionsRef.current, [propName]: event.checked };
|
optionsRef.current = { ...optionsRef.current, [propName]: event };
|
||||||
updateKey(x => x + 1);
|
updateKey(x => x + 1);
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
@@ -71,14 +70,14 @@ export const RoutesSettingsDialog = ({ visible, setVisible }: RoutesSettingsDial
|
|||||||
setVisible(false);
|
setVisible(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3 p-2.5">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2 mb-2">
|
||||||
{checkboxes.map(({ label, propName }) => (
|
{checkboxes.map(({ label, propName }) => (
|
||||||
<WdCheckbox
|
<PrettySwitchbox
|
||||||
key={propName}
|
key={propName}
|
||||||
label={label}
|
label={label}
|
||||||
value={optionsRef.current[propName]}
|
checked={optionsRef.current[propName]}
|
||||||
onChange={handleChangeEvent(propName)}
|
setChecked={handleChangeEvent(propName)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Dialog } from 'primereact/dialog';
|
import { Dialog } from 'primereact/dialog';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { Checkbox } from 'primereact/checkbox';
|
|
||||||
import { TabPanel, TabView } from 'primereact/tabview';
|
import { TabPanel, TabView } from 'primereact/tabview';
|
||||||
import styles from './SystemSignatureSettingsDialog.module.scss';
|
import styles from './SystemSignatureSettingsDialog.module.scss';
|
||||||
|
import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components';
|
||||||
|
|
||||||
export type Setting = { key: string; name: string; value: boolean; isFilter?: boolean };
|
export type Setting = { key: string; name: string; value: boolean; isFilter?: boolean };
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ export const SystemSignatureSettingsDialog = ({
|
|||||||
}, [onSave, settings]);
|
}, [onSave, settings]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog header="System Signatures Settings" visible={true} onHide={onCancel} className="w-full max-w-lg">
|
<Dialog header="System Signatures Settings" visible={true} onHide={onCancel} className="w-full max-w-lg h-[500px]">
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3 justify-between h-full">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className={styles.verticalTabsContainer}>
|
<div className={styles.verticalTabsContainer}>
|
||||||
<TabView
|
<TabView
|
||||||
@@ -54,16 +54,12 @@ export const SystemSignatureSettingsDialog = ({
|
|||||||
<div className="w-full h-full flex flex-col gap-1">
|
<div className="w-full h-full flex flex-col gap-1">
|
||||||
{filterSettings.map(setting => {
|
{filterSettings.map(setting => {
|
||||||
return (
|
return (
|
||||||
<div key={setting.key} className="flex items-center">
|
<PrettySwitchbox
|
||||||
<Checkbox
|
key={setting.key}
|
||||||
inputId={setting.key}
|
label={setting.name}
|
||||||
checked={setting.value}
|
checked={setting.value}
|
||||||
onChange={() => handleSettingsChange(setting.key)}
|
setChecked={() => handleSettingsChange(setting.key)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={setting.key} className="ml-2">
|
|
||||||
{setting.name}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -72,16 +68,12 @@ export const SystemSignatureSettingsDialog = ({
|
|||||||
<div className="w-full h-full flex flex-col gap-1">
|
<div className="w-full h-full flex flex-col gap-1">
|
||||||
{userSettings.map(setting => {
|
{userSettings.map(setting => {
|
||||||
return (
|
return (
|
||||||
<div key={setting.key} className="flex items-center">
|
<PrettySwitchbox
|
||||||
<Checkbox
|
key={setting.key}
|
||||||
inputId={setting.key}
|
label={setting.name}
|
||||||
checked={setting.value}
|
checked={setting.value}
|
||||||
onChange={() => handleSettingsChange(setting.key)}
|
setChecked={() => handleSettingsChange(setting.key)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={setting.key} className="ml-2">
|
|
||||||
{setting.name}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
|||||||
|
|
||||||
const SIGNATURE_SETTINGS_KEY = 'wanderer_system_signature_settings_v4_1';
|
const SIGNATURE_SETTINGS_KEY = 'wanderer_system_signature_settings_v4_1';
|
||||||
export const SHOW_DESCRIPTION_COLUMN_SETTING = 'show_description_column_setting';
|
export const SHOW_DESCRIPTION_COLUMN_SETTING = 'show_description_column_setting';
|
||||||
export const SHOW_INSERTED_COLUMN_SETTING = 'show_inserted_column_setting';
|
export const SHOW_UPDATED_COLUMN_SETTING = 'SHOW_UPDATED_COLUMN_SETTING';
|
||||||
|
|
||||||
const settings: Setting[] = [
|
const settings: Setting[] = [
|
||||||
{ key: SHOW_INSERTED_COLUMN_SETTING, name: 'Show Inserted Column', value: false, isFilter: false },
|
{ key: SHOW_UPDATED_COLUMN_SETTING, name: 'Show Updated Column', value: false, isFilter: false },
|
||||||
{ key: SHOW_DESCRIPTION_COLUMN_SETTING, name: 'Show Description Column', value: false, isFilter: false },
|
{ key: SHOW_DESCRIPTION_COLUMN_SETTING, name: 'Show Description Column', value: false, isFilter: false },
|
||||||
{ key: COSMIC_ANOMALY, name: 'Show Anomalies', value: true, isFilter: true },
|
{ key: COSMIC_ANOMALY, name: 'Show Anomalies', value: true, isFilter: true },
|
||||||
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true, isFilter: true },
|
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true, isFilter: true },
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||||
import { useClipboard } from '@/hooks/Mapper/hooks/useClipboard';
|
|
||||||
import { parseSignatures } from '@/hooks/Mapper/helpers';
|
import { parseSignatures } from '@/hooks/Mapper/helpers';
|
||||||
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||||
import { WdTooltip, WdTooltipHandlers } from '@/hooks/Mapper/components/ui-kit';
|
import { WdTooltip, WdTooltipHandlers } from '@/hooks/Mapper/components/ui-kit';
|
||||||
@@ -22,10 +21,10 @@ import {
|
|||||||
getRowColorByTimeLeft,
|
getRowColorByTimeLeft,
|
||||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers';
|
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers';
|
||||||
import {
|
import {
|
||||||
|
renderAddedTimeLeft,
|
||||||
renderDescription,
|
renderDescription,
|
||||||
renderIcon,
|
renderIcon,
|
||||||
renderInfoColumn,
|
renderInfoColumn,
|
||||||
renderInsertedTimeLeft,
|
|
||||||
renderUpdatedTimeLeft,
|
renderUpdatedTimeLeft,
|
||||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
|
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
|
||||||
import useLocalStorageState from 'use-local-storage-state';
|
import useLocalStorageState from 'use-local-storage-state';
|
||||||
@@ -36,7 +35,7 @@ import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrap
|
|||||||
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
|
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
|
||||||
import {
|
import {
|
||||||
SHOW_DESCRIPTION_COLUMN_SETTING,
|
SHOW_DESCRIPTION_COLUMN_SETTING,
|
||||||
SHOW_INSERTED_COLUMN_SETTING,
|
SHOW_UPDATED_COLUMN_SETTING,
|
||||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures';
|
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures';
|
||||||
type SystemSignaturesSortSettings = {
|
type SystemSignaturesSortSettings = {
|
||||||
sortField: string;
|
sortField: string;
|
||||||
@@ -44,7 +43,7 @@ type SystemSignaturesSortSettings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const SORT_DEFAULT_VALUES: SystemSignaturesSortSettings = {
|
const SORT_DEFAULT_VALUES: SystemSignaturesSortSettings = {
|
||||||
sortField: 'updated_at',
|
sortField: 'inserted_at',
|
||||||
sortOrder: -1,
|
sortOrder: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,11 +79,11 @@ export const SystemSignaturesContent = ({
|
|||||||
const tableRef = useRef<HTMLDivElement>(null);
|
const tableRef = useRef<HTMLDivElement>(null);
|
||||||
const compact = useMaxWidth(tableRef, 260);
|
const compact = useMaxWidth(tableRef, 260);
|
||||||
const medium = useMaxWidth(tableRef, 380);
|
const medium = useMaxWidth(tableRef, 380);
|
||||||
|
const refData = useRef({ selectable });
|
||||||
|
refData.current = { selectable };
|
||||||
|
|
||||||
const tooltipRef = useRef<WdTooltipHandlers>(null);
|
const tooltipRef = useRef<WdTooltipHandlers>(null);
|
||||||
|
|
||||||
const { clipboardContent } = useClipboard();
|
|
||||||
|
|
||||||
const handleResize = useCallback(() => {
|
const handleResize = useCallback(() => {
|
||||||
if (tableRef.current) {
|
if (tableRef.current) {
|
||||||
const tableWidth = tableRef.current.offsetWidth;
|
const tableWidth = tableRef.current.offsetWidth;
|
||||||
@@ -100,10 +99,7 @@ export const SystemSignaturesContent = ({
|
|||||||
[settings],
|
[settings],
|
||||||
);
|
);
|
||||||
|
|
||||||
const showInsertedColumn = useMemo(
|
const showUpdatedColumn = useMemo(() => settings.find(s => s.key === SHOW_UPDATED_COLUMN_SETTING)?.value, [settings]);
|
||||||
() => settings.find(s => s.key === SHOW_INSERTED_COLUMN_SETTING)?.value,
|
|
||||||
[settings],
|
|
||||||
);
|
|
||||||
|
|
||||||
const filteredSignatures = useMemo(() => {
|
const filteredSignatures = useMemo(() => {
|
||||||
return signatures
|
return signatures
|
||||||
@@ -160,19 +156,26 @@ export const SystemSignaturesContent = ({
|
|||||||
[outCommand, systemId],
|
[outCommand, systemId],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDeleteSelected = useCallback(async () => {
|
const handleDeleteSelected = useCallback(
|
||||||
if (selectable) {
|
async (e: KeyboardEvent) => {
|
||||||
return;
|
if (selectable) {
|
||||||
}
|
return;
|
||||||
if (selectedSignatures.length === 0) {
|
}
|
||||||
return;
|
if (selectedSignatures.length === 0) {
|
||||||
}
|
return;
|
||||||
const selectedSignaturesEveIds = selectedSignatures.map(x => x.eve_id);
|
}
|
||||||
await handleUpdateSignatures(
|
|
||||||
signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)),
|
e.preventDefault();
|
||||||
false,
|
e.stopPropagation();
|
||||||
);
|
|
||||||
}, [handleUpdateSignatures, selectable, signatures, selectedSignatures]);
|
const selectedSignaturesEveIds = selectedSignatures.map(x => x.eve_id);
|
||||||
|
await handleUpdateSignatures(
|
||||||
|
signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[handleUpdateSignatures, selectable, signatures, selectedSignatures],
|
||||||
|
);
|
||||||
|
|
||||||
const handleSelectAll = useCallback(() => {
|
const handleSelectAll = useCallback(() => {
|
||||||
setSelectedSignatures(signatures);
|
setSelectedSignatures(signatures);
|
||||||
@@ -201,12 +204,9 @@ export const SystemSignaturesContent = ({
|
|||||||
[onSelect, selectable],
|
[onSelect, selectable],
|
||||||
);
|
);
|
||||||
|
|
||||||
useHotkey(true, ['a'], handleSelectAll);
|
const handlePaste = async () => {
|
||||||
|
const clipboardContent = await navigator.clipboard.readText();
|
||||||
useHotkey(false, ['Backspace'], handleDeleteSelected);
|
if (refData.current.selectable) {
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (selectable) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,12 @@ export const SystemSignaturesContent = ({
|
|||||||
setParsedSignatures(newSignatures);
|
setParsedSignatures(newSignatures);
|
||||||
setAskUser(true);
|
setAskUser(true);
|
||||||
}
|
}
|
||||||
}, [clipboardContent, selectable]);
|
};
|
||||||
|
|
||||||
|
useHotkey(true, ['a'], handleSelectAll);
|
||||||
|
useHotkey(true, ['v'], handlePaste);
|
||||||
|
|
||||||
|
useHotkey(false, ['Delete'], handleDeleteSelected);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!systemId) {
|
if (!systemId) {
|
||||||
@@ -330,7 +335,7 @@ export const SystemSignaturesContent = ({
|
|||||||
return clsx(classes.TableRowCompact, 'bg-amber-500/50 hover:bg-amber-500/70 transition duration-200');
|
return clsx(classes.TableRowCompact, 'bg-amber-500/50 hover:bg-amber-500/70 transition duration-200');
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateClass = getRowColorByTimeLeft(row.updated_at ? new Date(row.updated_at) : undefined);
|
const dateClass = getRowColorByTimeLeft(row.inserted_at ? new Date(row.inserted_at) : undefined);
|
||||||
if (!dateClass) {
|
if (!dateClass) {
|
||||||
return clsx(classes.TableRowCompact, 'hover:bg-purple-400/20 transition duration-200');
|
return clsx(classes.TableRowCompact, 'hover:bg-purple-400/20 transition duration-200');
|
||||||
}
|
}
|
||||||
@@ -357,6 +362,7 @@ export const SystemSignaturesContent = ({
|
|||||||
header="Group"
|
header="Group"
|
||||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
hidden={compact}
|
hidden={compact}
|
||||||
|
style={{ maxWidth: 110, minWidth: 110, width: 110 }}
|
||||||
sortable
|
sortable
|
||||||
></Column>
|
></Column>
|
||||||
<Column
|
<Column
|
||||||
@@ -378,26 +384,26 @@ export const SystemSignaturesContent = ({
|
|||||||
></Column>
|
></Column>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showInsertedColumn && (
|
<Column
|
||||||
|
field="inserted_at"
|
||||||
|
header="Added"
|
||||||
|
dataType="date"
|
||||||
|
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
|
body={renderAddedTimeLeft}
|
||||||
|
sortable
|
||||||
|
></Column>
|
||||||
|
|
||||||
|
{showUpdatedColumn && (
|
||||||
<Column
|
<Column
|
||||||
field="inserted_at"
|
field="updated_at"
|
||||||
header="Inserted"
|
header="Updated"
|
||||||
dataType="date"
|
dataType="date"
|
||||||
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
||||||
body={renderInsertedTimeLeft}
|
body={renderUpdatedTimeLeft}
|
||||||
sortable
|
sortable
|
||||||
></Column>
|
></Column>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Column
|
|
||||||
field="updated_at"
|
|
||||||
header="Updated"
|
|
||||||
dataType="date"
|
|
||||||
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
|
|
||||||
body={renderUpdatedTimeLeft}
|
|
||||||
sortable
|
|
||||||
></Column>
|
|
||||||
|
|
||||||
{!selectable && (
|
{!selectable && (
|
||||||
<Column
|
<Column
|
||||||
bodyClassName="p-0 pl-1 pr-2"
|
bodyClassName="p-0 pl-1 pr-2"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export * from './renderIcon';
|
export * from './renderIcon';
|
||||||
export * from './renderDescription';
|
export * from './renderDescription';
|
||||||
export * from './renderName';
|
export * from './renderName';
|
||||||
export * from './renderInsertedTimeLeft';
|
export * from './renderAddedTimeLeft';
|
||||||
export * from './renderUpdatedTimeLeft';
|
export * from './renderUpdatedTimeLeft';
|
||||||
export * from './renderLinkedSystem';
|
export * from './renderLinkedSystem';
|
||||||
export * from './renderInfoColumn';
|
export * from './renderInfoColumn';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||||
import { TimeLeft } from '@/hooks/Mapper/components/ui-kit';
|
import { TimeLeft } from '@/hooks/Mapper/components/ui-kit';
|
||||||
|
|
||||||
export const renderInsertedTimeLeft = (row: SystemSignature) => {
|
export const renderAddedTimeLeft = (row: SystemSignature) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full items-center">
|
<div className="flex w-full items-center">
|
||||||
<TimeLeft cDate={row.inserted_at ? new Date(row.inserted_at) : undefined} />
|
<TimeLeft cDate={row.inserted_at ? new Date(row.inserted_at) : undefined} />
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
export const useHotkey = (isMetaKey: boolean, hotkeys: string[], callback: () => void) => {
|
export const useHotkey = (isMetaKey: boolean, hotkeys: string[], callback: (e: KeyboardEvent) => void) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if ((!isMetaKey || event.ctrlKey || event.metaKey) && hotkeys.includes(event.key)) {
|
if ((!isMetaKey || event.ctrlKey || event.metaKey) && hotkeys.includes(event.key)) {
|
||||||
@@ -8,14 +8,14 @@ export const useHotkey = (isMetaKey: boolean, hotkeys: string[], callback: () =>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
callback();
|
callback(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('keydown', handleKeyDown);
|
window.addEventListener('keydown', handleKeyDown, { capture: true });
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('keydown', handleKeyDown);
|
window.removeEventListener('keydown', handleKeyDown, { capture: true });
|
||||||
};
|
};
|
||||||
}, [isMetaKey, hotkeys, callback]);
|
}, [isMetaKey, hotkeys, callback]);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user