Apply prettier formatting
This commit is contained in:
@@ -34,7 +34,7 @@ import {
|
||||
* have to be manually mirrored in KeyBindingDefaults.
|
||||
*/
|
||||
const getUIOnlyShortcuts = (): IKeyboardShortcuts => {
|
||||
const ctrlEnterToSend = SettingsStore.getValue('MessageComposerInput.ctrlEnterToSend');
|
||||
const ctrlEnterToSend = SettingsStore.getValue("MessageComposerInput.ctrlEnterToSend");
|
||||
|
||||
const keyboardShortcuts: IKeyboardShortcuts = {
|
||||
[KeyBindingAction.SendMessage]: {
|
||||
@@ -94,26 +94,25 @@ const getUIOnlyShortcuts = (): IKeyboardShortcuts => {
|
||||
export const getKeyboardShortcuts = (): IKeyboardShortcuts => {
|
||||
const overrideBrowserShortcuts = PlatformPeg.get().overrideBrowserShortcuts();
|
||||
|
||||
return Object.keys(KEYBOARD_SHORTCUTS).filter((k: KeyBindingAction) => {
|
||||
if (KEYBOARD_SHORTCUTS[k]?.controller?.settingDisabled) return false;
|
||||
if (MAC_ONLY_SHORTCUTS.includes(k) && !IS_MAC) return false;
|
||||
if (DESKTOP_SHORTCUTS.includes(k) && !overrideBrowserShortcuts) return false;
|
||||
return Object.keys(KEYBOARD_SHORTCUTS)
|
||||
.filter((k: KeyBindingAction) => {
|
||||
if (KEYBOARD_SHORTCUTS[k]?.controller?.settingDisabled) return false;
|
||||
if (MAC_ONLY_SHORTCUTS.includes(k) && !IS_MAC) return false;
|
||||
if (DESKTOP_SHORTCUTS.includes(k) && !overrideBrowserShortcuts) return false;
|
||||
|
||||
return true;
|
||||
}).reduce((o, key) => {
|
||||
o[key] = KEYBOARD_SHORTCUTS[key];
|
||||
return o;
|
||||
}, {} as IKeyboardShortcuts);
|
||||
return true;
|
||||
})
|
||||
.reduce((o, key) => {
|
||||
o[key] = KEYBOARD_SHORTCUTS[key];
|
||||
return o;
|
||||
}, {} as IKeyboardShortcuts);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets keyboard shortcuts that should be presented to the user in the UI.
|
||||
*/
|
||||
export const getKeyboardShortcutsForUI = (): IKeyboardShortcuts => {
|
||||
const entries = [
|
||||
...Object.entries(getUIOnlyShortcuts()),
|
||||
...Object.entries(getKeyboardShortcuts()),
|
||||
];
|
||||
const entries = [...Object.entries(getUIOnlyShortcuts()), ...Object.entries(getKeyboardShortcuts())];
|
||||
|
||||
return entries.reduce((acc, [key, value]) => {
|
||||
acc[key] = value;
|
||||
|
||||
@@ -23,103 +23,103 @@ import { KeyCombo } from "../KeyBindingsManager";
|
||||
|
||||
export enum KeyBindingAction {
|
||||
/** Send a message */
|
||||
SendMessage = 'KeyBinding.sendMessageInComposer',
|
||||
SendMessage = "KeyBinding.sendMessageInComposer",
|
||||
/** Go backwards through the send history and use the message in composer view */
|
||||
SelectPrevSendHistory = 'KeyBinding.previousMessageInComposerHistory',
|
||||
SelectPrevSendHistory = "KeyBinding.previousMessageInComposerHistory",
|
||||
/** Go forwards through the send history */
|
||||
SelectNextSendHistory = 'KeyBinding.nextMessageInComposerHistory',
|
||||
SelectNextSendHistory = "KeyBinding.nextMessageInComposerHistory",
|
||||
/** Start editing the user's last sent message */
|
||||
EditPrevMessage = 'KeyBinding.editPreviousMessage',
|
||||
EditPrevMessage = "KeyBinding.editPreviousMessage",
|
||||
/** Start editing the user's next sent message */
|
||||
EditNextMessage = 'KeyBinding.editNextMessage',
|
||||
EditNextMessage = "KeyBinding.editNextMessage",
|
||||
/** Cancel editing a message or cancel replying to a message */
|
||||
CancelReplyOrEdit = 'KeyBinding.cancelReplyInComposer',
|
||||
CancelReplyOrEdit = "KeyBinding.cancelReplyInComposer",
|
||||
/** Show the sticker picker */
|
||||
ShowStickerPicker = 'KeyBinding.showStickerPicker',
|
||||
ShowStickerPicker = "KeyBinding.showStickerPicker",
|
||||
|
||||
/** Set bold format the current selection */
|
||||
FormatBold = 'KeyBinding.toggleBoldInComposer',
|
||||
FormatBold = "KeyBinding.toggleBoldInComposer",
|
||||
/** Set italics format the current selection */
|
||||
FormatItalics = 'KeyBinding.toggleItalicsInComposer',
|
||||
FormatItalics = "KeyBinding.toggleItalicsInComposer",
|
||||
/** Insert link for current selection */
|
||||
FormatLink = 'KeyBinding.FormatLink',
|
||||
FormatLink = "KeyBinding.FormatLink",
|
||||
/** Set code format for current selection */
|
||||
FormatCode = 'KeyBinding.FormatCode',
|
||||
FormatCode = "KeyBinding.FormatCode",
|
||||
/** Format the current selection as quote */
|
||||
FormatQuote = 'KeyBinding.toggleQuoteInComposer',
|
||||
FormatQuote = "KeyBinding.toggleQuoteInComposer",
|
||||
/** Undo the last editing */
|
||||
EditUndo = 'KeyBinding.editUndoInComposer',
|
||||
EditUndo = "KeyBinding.editUndoInComposer",
|
||||
/** Redo editing */
|
||||
EditRedo = 'KeyBinding.editRedoInComposer',
|
||||
EditRedo = "KeyBinding.editRedoInComposer",
|
||||
/** Insert new line */
|
||||
NewLine = 'KeyBinding.newLineInComposer',
|
||||
NewLine = "KeyBinding.newLineInComposer",
|
||||
/** Move the cursor to the start of the message */
|
||||
MoveCursorToStart = 'KeyBinding.jumpToStartInComposer',
|
||||
MoveCursorToStart = "KeyBinding.jumpToStartInComposer",
|
||||
/** Move the cursor to the end of the message */
|
||||
MoveCursorToEnd = 'KeyBinding.jumpToEndInComposer',
|
||||
MoveCursorToEnd = "KeyBinding.jumpToEndInComposer",
|
||||
|
||||
/** Accepts chosen autocomplete selection */
|
||||
CompleteAutocomplete = 'KeyBinding.completeAutocomplete',
|
||||
CompleteAutocomplete = "KeyBinding.completeAutocomplete",
|
||||
/** Accepts chosen autocomplete selection or,
|
||||
* if the autocompletion window is not shown, open the window and select the first selection */
|
||||
ForceCompleteAutocomplete = 'KeyBinding.forceCompleteAutocomplete',
|
||||
ForceCompleteAutocomplete = "KeyBinding.forceCompleteAutocomplete",
|
||||
/** Move to the previous autocomplete selection */
|
||||
PrevSelectionInAutocomplete = 'KeyBinding.previousOptionInAutoComplete',
|
||||
PrevSelectionInAutocomplete = "KeyBinding.previousOptionInAutoComplete",
|
||||
/** Move to the next autocomplete selection */
|
||||
NextSelectionInAutocomplete = 'KeyBinding.nextOptionInAutoComplete',
|
||||
NextSelectionInAutocomplete = "KeyBinding.nextOptionInAutoComplete",
|
||||
/** Close the autocompletion window */
|
||||
CancelAutocomplete = 'KeyBinding.cancelAutoComplete',
|
||||
CancelAutocomplete = "KeyBinding.cancelAutoComplete",
|
||||
|
||||
/** Clear room list filter field */
|
||||
ClearRoomFilter = 'KeyBinding.clearRoomFilter',
|
||||
ClearRoomFilter = "KeyBinding.clearRoomFilter",
|
||||
/** Navigate up/down in the room list */
|
||||
PrevRoom = 'KeyBinding.downerRoom',
|
||||
PrevRoom = "KeyBinding.downerRoom",
|
||||
/** Navigate down in the room list */
|
||||
NextRoom = 'KeyBinding.upperRoom',
|
||||
NextRoom = "KeyBinding.upperRoom",
|
||||
/** Select room from the room list */
|
||||
SelectRoomInRoomList = 'KeyBinding.selectRoomInRoomList',
|
||||
SelectRoomInRoomList = "KeyBinding.selectRoomInRoomList",
|
||||
/** Collapse room list section */
|
||||
CollapseRoomListSection = 'KeyBinding.collapseSectionInRoomList',
|
||||
CollapseRoomListSection = "KeyBinding.collapseSectionInRoomList",
|
||||
/** Expand room list section, if already expanded, jump to first room in the selection */
|
||||
ExpandRoomListSection = 'KeyBinding.expandSectionInRoomList',
|
||||
ExpandRoomListSection = "KeyBinding.expandSectionInRoomList",
|
||||
|
||||
/** Scroll up in the timeline */
|
||||
ScrollUp = 'KeyBinding.scrollUpInTimeline',
|
||||
ScrollUp = "KeyBinding.scrollUpInTimeline",
|
||||
/** Scroll down in the timeline */
|
||||
ScrollDown = 'KeyBinding.scrollDownInTimeline',
|
||||
ScrollDown = "KeyBinding.scrollDownInTimeline",
|
||||
/** Dismiss read marker and jump to bottom */
|
||||
DismissReadMarker = 'KeyBinding.dismissReadMarkerAndJumpToBottom',
|
||||
DismissReadMarker = "KeyBinding.dismissReadMarkerAndJumpToBottom",
|
||||
/** Jump to oldest unread message */
|
||||
JumpToOldestUnread = 'KeyBinding.jumpToOldestUnreadMessage',
|
||||
JumpToOldestUnread = "KeyBinding.jumpToOldestUnreadMessage",
|
||||
/** Upload a file */
|
||||
UploadFile = 'KeyBinding.uploadFileToRoom',
|
||||
UploadFile = "KeyBinding.uploadFileToRoom",
|
||||
/** Focus search message in a room (must be enabled) */
|
||||
SearchInRoom = 'KeyBinding.searchInRoom',
|
||||
SearchInRoom = "KeyBinding.searchInRoom",
|
||||
/** Jump to the first (downloaded) message in the room */
|
||||
JumpToFirstMessage = 'KeyBinding.jumpToFirstMessageInTimeline',
|
||||
JumpToFirstMessage = "KeyBinding.jumpToFirstMessageInTimeline",
|
||||
/** Jump to the latest message in the room */
|
||||
JumpToLatestMessage = 'KeyBinding.jumpToLastMessageInTimeline',
|
||||
JumpToLatestMessage = "KeyBinding.jumpToLastMessageInTimeline",
|
||||
|
||||
/** Jump to room search (search for a room) */
|
||||
FilterRooms = 'KeyBinding.filterRooms',
|
||||
FilterRooms = "KeyBinding.filterRooms",
|
||||
/** Toggle the space panel */
|
||||
ToggleSpacePanel = 'KeyBinding.toggleSpacePanel',
|
||||
ToggleSpacePanel = "KeyBinding.toggleSpacePanel",
|
||||
/** Toggle the room side panel */
|
||||
ToggleRoomSidePanel = 'KeyBinding.toggleRightPanel',
|
||||
ToggleRoomSidePanel = "KeyBinding.toggleRightPanel",
|
||||
/** Toggle the user menu */
|
||||
ToggleUserMenu = 'KeyBinding.toggleTopLeftMenu',
|
||||
ToggleUserMenu = "KeyBinding.toggleTopLeftMenu",
|
||||
/** Toggle the short cut help dialog */
|
||||
ShowKeyboardSettings = 'KeyBinding.showKeyBindingsSettings',
|
||||
ShowKeyboardSettings = "KeyBinding.showKeyBindingsSettings",
|
||||
/** Got to the Element home screen */
|
||||
GoToHome = 'KeyBinding.goToHomeView',
|
||||
GoToHome = "KeyBinding.goToHomeView",
|
||||
/** Select prev room */
|
||||
SelectPrevRoom = 'KeyBinding.previousRoom',
|
||||
SelectPrevRoom = "KeyBinding.previousRoom",
|
||||
/** Select next room */
|
||||
SelectNextRoom = 'KeyBinding.nextRoom',
|
||||
SelectNextRoom = "KeyBinding.nextRoom",
|
||||
/** Select prev room with unread messages */
|
||||
SelectPrevUnreadRoom = 'KeyBinding.previousUnreadRoom',
|
||||
SelectPrevUnreadRoom = "KeyBinding.previousUnreadRoom",
|
||||
/** Select next room with unread messages */
|
||||
SelectNextUnreadRoom = 'KeyBinding.nextUnreadRoom',
|
||||
SelectNextUnreadRoom = "KeyBinding.nextUnreadRoom",
|
||||
|
||||
/** Switches to a space by number */
|
||||
SwitchToSpaceByNumber = "KeyBinding.switchToSpaceByNumber",
|
||||
@@ -151,20 +151,20 @@ export enum KeyBindingAction {
|
||||
Comma = "KeyBinding.comma",
|
||||
|
||||
/** Toggle visibility of hidden events */
|
||||
ToggleHiddenEventVisibility = 'KeyBinding.toggleHiddenEventVisibility',
|
||||
ToggleHiddenEventVisibility = "KeyBinding.toggleHiddenEventVisibility",
|
||||
}
|
||||
|
||||
type KeyboardShortcutSetting = IBaseSetting<KeyCombo>;
|
||||
|
||||
export type IKeyboardShortcuts = {
|
||||
// TODO: We should figure out what to do with the keyboard shortcuts that are not handled by KeybindingManager
|
||||
[k in (KeyBindingAction)]?: KeyboardShortcutSetting;
|
||||
[k in KeyBindingAction]?: KeyboardShortcutSetting;
|
||||
};
|
||||
|
||||
export interface ICategory {
|
||||
categoryLabel?: string;
|
||||
// TODO: We should figure out what to do with the keyboard shortcuts that are not handled by KeybindingManager
|
||||
settingNames: (KeyBindingAction)[];
|
||||
settingNames: KeyBindingAction[];
|
||||
}
|
||||
|
||||
export enum CategoryName {
|
||||
@@ -227,13 +227,12 @@ export const CATEGORIES: Record<CategoryName, ICategory> = {
|
||||
KeyBindingAction.SelectPrevSendHistory,
|
||||
KeyBindingAction.ShowStickerPicker,
|
||||
],
|
||||
}, [CategoryName.CALLS]: {
|
||||
},
|
||||
[CategoryName.CALLS]: {
|
||||
categoryLabel: _td("Calls"),
|
||||
settingNames: [
|
||||
KeyBindingAction.ToggleMicInCall,
|
||||
KeyBindingAction.ToggleWebcamInCall,
|
||||
],
|
||||
}, [CategoryName.ROOM]: {
|
||||
settingNames: [KeyBindingAction.ToggleMicInCall, KeyBindingAction.ToggleWebcamInCall],
|
||||
},
|
||||
[CategoryName.ROOM]: {
|
||||
categoryLabel: _td("Room"),
|
||||
settingNames: [
|
||||
KeyBindingAction.SearchInRoom,
|
||||
@@ -245,7 +244,8 @@ export const CATEGORIES: Record<CategoryName, ICategory> = {
|
||||
KeyBindingAction.JumpToFirstMessage,
|
||||
KeyBindingAction.JumpToLatestMessage,
|
||||
],
|
||||
}, [CategoryName.ROOM_LIST]: {
|
||||
},
|
||||
[CategoryName.ROOM_LIST]: {
|
||||
categoryLabel: _td("Room List"),
|
||||
settingNames: [
|
||||
KeyBindingAction.SelectRoomInRoomList,
|
||||
@@ -255,7 +255,8 @@ export const CATEGORIES: Record<CategoryName, ICategory> = {
|
||||
KeyBindingAction.NextRoom,
|
||||
KeyBindingAction.PrevRoom,
|
||||
],
|
||||
}, [CategoryName.ACCESSIBILITY]: {
|
||||
},
|
||||
[CategoryName.ACCESSIBILITY]: {
|
||||
categoryLabel: _td("Accessibility"),
|
||||
settingNames: [
|
||||
KeyBindingAction.Escape,
|
||||
@@ -271,7 +272,8 @@ export const CATEGORIES: Record<CategoryName, ICategory> = {
|
||||
KeyBindingAction.ArrowDown,
|
||||
KeyBindingAction.Comma,
|
||||
],
|
||||
}, [CategoryName.NAVIGATION]: {
|
||||
},
|
||||
[CategoryName.NAVIGATION]: {
|
||||
categoryLabel: _td("Navigation"),
|
||||
settingNames: [
|
||||
KeyBindingAction.ToggleUserMenu,
|
||||
@@ -289,7 +291,8 @@ export const CATEGORIES: Record<CategoryName, ICategory> = {
|
||||
KeyBindingAction.PreviousVisitedRoomOrSpace,
|
||||
KeyBindingAction.NextVisitedRoomOrSpace,
|
||||
],
|
||||
}, [CategoryName.AUTOCOMPLETE]: {
|
||||
},
|
||||
[CategoryName.AUTOCOMPLETE]: {
|
||||
categoryLabel: _td("Autocomplete"),
|
||||
settingNames: [
|
||||
KeyBindingAction.CancelAutocomplete,
|
||||
@@ -298,11 +301,10 @@ export const CATEGORIES: Record<CategoryName, ICategory> = {
|
||||
KeyBindingAction.CompleteAutocomplete,
|
||||
KeyBindingAction.ForceCompleteAutocomplete,
|
||||
],
|
||||
}, [CategoryName.LABS]: {
|
||||
},
|
||||
[CategoryName.LABS]: {
|
||||
categoryLabel: _td("Labs"),
|
||||
settingNames: [
|
||||
KeyBindingAction.ToggleHiddenEventVisibility,
|
||||
],
|
||||
settingNames: [KeyBindingAction.ToggleHiddenEventVisibility],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -313,9 +315,7 @@ export const DESKTOP_SHORTCUTS = [
|
||||
KeyBindingAction.NextVisitedRoomOrSpace,
|
||||
];
|
||||
|
||||
export const MAC_ONLY_SHORTCUTS = [
|
||||
KeyBindingAction.OpenUserSettings,
|
||||
];
|
||||
export const MAC_ONLY_SHORTCUTS = [KeyBindingAction.OpenUserSettings];
|
||||
|
||||
// This is very intentionally modelled after SETTINGS as it will make it easier
|
||||
// to implement customizable keyboard shortcuts
|
||||
|
||||
@@ -117,7 +117,7 @@ export const reducer = (state: IState, action: IAction) => {
|
||||
}
|
||||
|
||||
case Type.Unregister: {
|
||||
const oldIndex = state.refs.findIndex(r => r === action.payload.ref);
|
||||
const oldIndex = state.refs.findIndex((r) => r === action.payload.ref);
|
||||
|
||||
if (oldIndex === -1) {
|
||||
return state; // already removed, this should not happen
|
||||
@@ -129,8 +129,8 @@ export const reducer = (state: IState, action: IAction) => {
|
||||
if (oldIndex >= state.refs.length) {
|
||||
state.activeRef = findSiblingElement(state.refs, state.refs.length - 1, true);
|
||||
} else {
|
||||
state.activeRef = findSiblingElement(state.refs, oldIndex)
|
||||
|| findSiblingElement(state.refs, oldIndex, true);
|
||||
state.activeRef =
|
||||
findSiblingElement(state.refs, oldIndex) || findSiblingElement(state.refs, oldIndex, true);
|
||||
}
|
||||
if (document.activeElement === document.body) {
|
||||
// if the focus got reverted to the body then the user was likely focused on the unmounted element
|
||||
@@ -159,9 +159,7 @@ interface IProps {
|
||||
handleHomeEnd?: boolean;
|
||||
handleUpDown?: boolean;
|
||||
handleLeftRight?: boolean;
|
||||
children(renderProps: {
|
||||
onKeyDownHandler(ev: React.KeyboardEvent);
|
||||
});
|
||||
children(renderProps: { onKeyDownHandler(ev: React.KeyboardEvent) });
|
||||
onKeyDown?(ev: React.KeyboardEvent, state: IState);
|
||||
}
|
||||
|
||||
@@ -199,96 +197,107 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
|
||||
|
||||
const context = useMemo<IContext>(() => ({ state, dispatch }), [state]);
|
||||
|
||||
const onKeyDownHandler = useCallback((ev: React.KeyboardEvent) => {
|
||||
if (onKeyDown) {
|
||||
onKeyDown(ev, context.state);
|
||||
if (ev.defaultPrevented) {
|
||||
return;
|
||||
const onKeyDownHandler = useCallback(
|
||||
(ev: React.KeyboardEvent) => {
|
||||
if (onKeyDown) {
|
||||
onKeyDown(ev, context.state);
|
||||
if (ev.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let handled = false;
|
||||
const action = getKeyBindingsManager().getAccessibilityAction(ev);
|
||||
let focusRef: RefObject<HTMLElement>;
|
||||
// Don't interfere with input default keydown behaviour
|
||||
// but allow people to move focus from it with Tab.
|
||||
if (checkInputableElement(ev.target as HTMLElement)) {
|
||||
switch (action) {
|
||||
case KeyBindingAction.Tab:
|
||||
handled = true;
|
||||
if (context.state.refs.length > 0) {
|
||||
const idx = context.state.refs.indexOf(context.state.activeRef);
|
||||
focusRef = findSiblingElement(context.state.refs, idx + (ev.shiftKey ? -1 : 1), ev.shiftKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// check if we actually have any items
|
||||
switch (action) {
|
||||
case KeyBindingAction.Home:
|
||||
if (handleHomeEnd) {
|
||||
handled = true;
|
||||
// move focus to first (visible) item
|
||||
focusRef = findSiblingElement(context.state.refs, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyBindingAction.End:
|
||||
if (handleHomeEnd) {
|
||||
handled = true;
|
||||
// move focus to last (visible) item
|
||||
focusRef = findSiblingElement(context.state.refs, context.state.refs.length - 1, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyBindingAction.ArrowDown:
|
||||
case KeyBindingAction.ArrowRight:
|
||||
if ((action === KeyBindingAction.ArrowDown && handleUpDown) ||
|
||||
(action === KeyBindingAction.ArrowRight && handleLeftRight)
|
||||
) {
|
||||
let handled = false;
|
||||
const action = getKeyBindingsManager().getAccessibilityAction(ev);
|
||||
let focusRef: RefObject<HTMLElement>;
|
||||
// Don't interfere with input default keydown behaviour
|
||||
// but allow people to move focus from it with Tab.
|
||||
if (checkInputableElement(ev.target as HTMLElement)) {
|
||||
switch (action) {
|
||||
case KeyBindingAction.Tab:
|
||||
handled = true;
|
||||
if (context.state.refs.length > 0) {
|
||||
const idx = context.state.refs.indexOf(context.state.activeRef);
|
||||
focusRef = findSiblingElement(context.state.refs, idx + 1);
|
||||
focusRef = findSiblingElement(
|
||||
context.state.refs,
|
||||
idx + (ev.shiftKey ? -1 : 1),
|
||||
ev.shiftKey,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// check if we actually have any items
|
||||
switch (action) {
|
||||
case KeyBindingAction.Home:
|
||||
if (handleHomeEnd) {
|
||||
handled = true;
|
||||
// move focus to first (visible) item
|
||||
focusRef = findSiblingElement(context.state.refs, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyBindingAction.ArrowUp:
|
||||
case KeyBindingAction.ArrowLeft:
|
||||
if ((action === KeyBindingAction.ArrowUp && handleUpDown) ||
|
||||
(action === KeyBindingAction.ArrowLeft && handleLeftRight)
|
||||
) {
|
||||
handled = true;
|
||||
if (context.state.refs.length > 0) {
|
||||
const idx = context.state.refs.indexOf(context.state.activeRef);
|
||||
focusRef = findSiblingElement(context.state.refs, idx - 1, true);
|
||||
case KeyBindingAction.End:
|
||||
if (handleHomeEnd) {
|
||||
handled = true;
|
||||
// move focus to last (visible) item
|
||||
focusRef = findSiblingElement(context.state.refs, context.state.refs.length - 1, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case KeyBindingAction.ArrowDown:
|
||||
case KeyBindingAction.ArrowRight:
|
||||
if (
|
||||
(action === KeyBindingAction.ArrowDown && handleUpDown) ||
|
||||
(action === KeyBindingAction.ArrowRight && handleLeftRight)
|
||||
) {
|
||||
handled = true;
|
||||
if (context.state.refs.length > 0) {
|
||||
const idx = context.state.refs.indexOf(context.state.activeRef);
|
||||
focusRef = findSiblingElement(context.state.refs, idx + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyBindingAction.ArrowUp:
|
||||
case KeyBindingAction.ArrowLeft:
|
||||
if (
|
||||
(action === KeyBindingAction.ArrowUp && handleUpDown) ||
|
||||
(action === KeyBindingAction.ArrowLeft && handleLeftRight)
|
||||
) {
|
||||
handled = true;
|
||||
if (context.state.refs.length > 0) {
|
||||
const idx = context.state.refs.indexOf(context.state.activeRef);
|
||||
focusRef = findSiblingElement(context.state.refs, idx - 1, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
if (handled) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
if (focusRef) {
|
||||
focusRef.current?.focus();
|
||||
// programmatic focus doesn't fire the onFocus handler, so we must do the do ourselves
|
||||
dispatch({
|
||||
type: Type.SetFocus,
|
||||
payload: {
|
||||
ref: focusRef,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [context, onKeyDown, handleHomeEnd, handleUpDown, handleLeftRight]);
|
||||
if (focusRef) {
|
||||
focusRef.current?.focus();
|
||||
// programmatic focus doesn't fire the onFocus handler, so we must do the do ourselves
|
||||
dispatch({
|
||||
type: Type.SetFocus,
|
||||
payload: {
|
||||
ref: focusRef,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
[context, onKeyDown, handleHomeEnd, handleUpDown, handleLeftRight],
|
||||
);
|
||||
|
||||
return <RovingTabIndexContext.Provider value={context}>
|
||||
{ children({ onKeyDownHandler }) }
|
||||
</RovingTabIndexContext.Provider>;
|
||||
return (
|
||||
<RovingTabIndexContext.Provider value={context}>
|
||||
{children({ onKeyDownHandler })}
|
||||
</RovingTabIndexContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Hook to register a roving tab index
|
||||
|
||||
@@ -20,8 +20,7 @@ import { RovingTabIndexProvider } from "./RovingTabIndex";
|
||||
import { getKeyBindingsManager } from "../KeyBindingsManager";
|
||||
import { KeyBindingAction } from "./KeyboardShortcuts";
|
||||
|
||||
interface IProps extends Omit<React.HTMLProps<HTMLDivElement>, "onKeyDown"> {
|
||||
}
|
||||
interface IProps extends Omit<React.HTMLProps<HTMLDivElement>, "onKeyDown"> {}
|
||||
|
||||
// This component implements the Toolbar design pattern from the WAI-ARIA Authoring Practices guidelines.
|
||||
// https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar
|
||||
@@ -39,7 +38,7 @@ const Toolbar: React.FC<IProps> = ({ children, ...props }) => {
|
||||
switch (action) {
|
||||
case KeyBindingAction.ArrowUp:
|
||||
case KeyBindingAction.ArrowDown:
|
||||
if (target.hasAttribute('aria-haspopup')) {
|
||||
if (target.hasAttribute("aria-haspopup")) {
|
||||
target.click();
|
||||
}
|
||||
break;
|
||||
@@ -54,11 +53,15 @@ const Toolbar: React.FC<IProps> = ({ children, ...props }) => {
|
||||
}
|
||||
};
|
||||
|
||||
return <RovingTabIndexProvider handleHomeEnd handleLeftRight onKeyDown={onKeyDown}>
|
||||
{ ({ onKeyDownHandler }) => <div {...props} onKeyDown={onKeyDownHandler} role="toolbar">
|
||||
{ children }
|
||||
</div> }
|
||||
</RovingTabIndexProvider>;
|
||||
return (
|
||||
<RovingTabIndexProvider handleHomeEnd handleLeftRight onKeyDown={onKeyDown}>
|
||||
{({ onKeyDownHandler }) => (
|
||||
<div {...props} onKeyDown={onKeyDownHandler} role="toolbar">
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
</RovingTabIndexProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Toolbar;
|
||||
|
||||
@@ -45,7 +45,7 @@ export const ContextMenuButton: React.FC<IProps> = ({
|
||||
aria-haspopup={true}
|
||||
aria-expanded={isExpanded}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</AccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ export const ContextMenuTooltipButton: React.FC<IProps> = ({
|
||||
aria-expanded={isExpanded}
|
||||
forceHide={isExpanded}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</AccessibleTooltipButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -24,7 +24,9 @@ interface IProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
|
||||
// Semantic component for representing a role=group for grouping menu radios/checkboxes
|
||||
export const MenuGroup: React.FC<IProps> = ({ children, label, ...props }) => {
|
||||
return <div {...props} role="group" aria-label={label}>
|
||||
{ children }
|
||||
</div>;
|
||||
return (
|
||||
<div {...props} role="group" aria-label={label}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -30,14 +30,16 @@ export const MenuItem: React.FC<IProps> = ({ children, label, tooltip, ...props
|
||||
const ariaLabel = props["aria-label"] || label;
|
||||
|
||||
if (tooltip) {
|
||||
return <RovingAccessibleTooltipButton {...props} role="menuitem" aria-label={ariaLabel} title={tooltip}>
|
||||
{ children }
|
||||
</RovingAccessibleTooltipButton>;
|
||||
return (
|
||||
<RovingAccessibleTooltipButton {...props} role="menuitem" aria-label={ariaLabel} title={tooltip}>
|
||||
{children}
|
||||
</RovingAccessibleTooltipButton>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<RovingAccessibleButton {...props} role="menuitem" aria-label={ariaLabel}>
|
||||
{ children }
|
||||
{children}
|
||||
</RovingAccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ export const MenuItemCheckbox: React.FC<IProps> = ({ children, label, active, di
|
||||
disabled={disabled}
|
||||
aria-label={label}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</RovingAccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ export const MenuItemRadio: React.FC<IProps> = ({ children, label, active, disab
|
||||
disabled={disabled}
|
||||
aria-label={label}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</RovingAccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ export const StyledMenuItemCheckbox: React.FC<IProps> = ({ children, label, onCh
|
||||
inputRef={ref}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</StyledCheckbox>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ export const StyledMenuItemRadio: React.FC<IProps> = ({ children, label, onChang
|
||||
inputRef={ref}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
{ children }
|
||||
{children}
|
||||
</StyledRadioButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -27,14 +27,15 @@ interface IProps extends Omit<React.ComponentProps<typeof AccessibleButton>, "in
|
||||
// Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components.
|
||||
export const RovingAccessibleButton: React.FC<IProps> = ({ inputRef, onFocus, ...props }) => {
|
||||
const [onFocusInternal, isActive, ref] = useRovingTabIndex(inputRef);
|
||||
return <AccessibleButton
|
||||
{...props}
|
||||
onFocus={event => {
|
||||
onFocusInternal();
|
||||
onFocus?.(event);
|
||||
}}
|
||||
inputRef={ref}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
/>;
|
||||
return (
|
||||
<AccessibleButton
|
||||
{...props}
|
||||
onFocus={(event) => {
|
||||
onFocusInternal();
|
||||
onFocus?.(event);
|
||||
}}
|
||||
inputRef={ref}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,14 +28,15 @@ interface IProps extends Omit<ATBProps, "inputRef" | "tabIndex"> {
|
||||
// Wrapper to allow use of useRovingTabIndex for simple AccessibleTooltipButtons outside of React Functional Components.
|
||||
export const RovingAccessibleTooltipButton: React.FC<IProps> = ({ inputRef, onFocus, ...props }) => {
|
||||
const [onFocusInternal, isActive, ref] = useRovingTabIndex(inputRef);
|
||||
return <AccessibleTooltipButton
|
||||
{...props}
|
||||
onFocus={event => {
|
||||
onFocusInternal();
|
||||
onFocus?.(event);
|
||||
}}
|
||||
inputRef={ref}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
/>;
|
||||
return (
|
||||
<AccessibleTooltipButton
|
||||
{...props}
|
||||
onFocus={(event) => {
|
||||
onFocusInternal();
|
||||
onFocus?.(event);
|
||||
}}
|
||||
inputRef={ref}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -21,11 +21,7 @@ import { FocusHandler, Ref } from "./types";
|
||||
|
||||
interface IProps {
|
||||
inputRef?: Ref;
|
||||
children(renderProps: {
|
||||
onFocus: FocusHandler;
|
||||
isActive: boolean;
|
||||
ref: Ref;
|
||||
});
|
||||
children(renderProps: { onFocus: FocusHandler; isActive: boolean; ref: Ref });
|
||||
}
|
||||
|
||||
// Wrapper to allow use of useRovingTabIndex outside of React Functional Components.
|
||||
|
||||
Reference in New Issue
Block a user