Skip to content

Commit 4ef6024

Browse files
(Lookup): reimplement createKeyHandler() with a hook
1 parent 2078825 commit 4ef6024

File tree

1 file changed

+144
-148
lines changed

1 file changed

+144
-148
lines changed

src/scripts/Lookup.tsx

Lines changed: 144 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ type KeyHandlerConfig = {
6060
};
6161

6262
/**
63-
* Creates a keyboard event handler for lookup components
63+
* Custom hook for keyboard event handling in lookup components
6464
*/
65-
const createKeyHandler = (config: KeyHandlerConfig) => {
66-
return (e: KeyboardEvent) => {
65+
const useKeyHandler = (config: KeyHandlerConfig) => {
66+
return useEventCallback((e: KeyboardEvent) => {
6767
const {
6868
opened,
6969
onOpen,
@@ -114,7 +114,7 @@ const createKeyHandler = (config: KeyHandlerConfig) => {
114114
}
115115
break;
116116
}
117-
};
117+
});
118118
};
119119

120120
/**
@@ -958,83 +958,81 @@ export const Lookup = createFC<LookupProps, { isFormElement: boolean }>(
958958
}, 10);
959959
});
960960

961-
const onInputKeyDown = useEventCallback(
962-
createKeyHandler({
963-
type: 'search',
964-
opened,
965-
onOpen: () => {
961+
const onInputKeyDown = useKeyHandler({
962+
type: 'search',
963+
opened,
964+
onOpen: () => {
965+
setOpened(true);
966+
onLookupRequest_?.(searchText);
967+
},
968+
onClose: () => {
969+
setOpened(false);
970+
onComplete?.(true);
971+
},
972+
onNavigateDown: () => {
973+
const nextValue = getNextValue(focusedValue);
974+
setFocusedValue(nextValue);
975+
scrollFocusedElementIntoView(nextValue);
976+
},
977+
onNavigateUp: () => {
978+
const prevValue = getPrevValue(focusedValue);
979+
setFocusedValue(prevValue);
980+
scrollFocusedElementIntoView(prevValue);
981+
},
982+
onSelect: () => {
983+
if (opened && focusedValue) {
984+
const selectedEntry = data.find(
985+
(entry) => entry.value === focusedValue
986+
);
987+
if (selectedEntry) {
988+
onSelect(selectedEntry);
989+
setOpened(false);
990+
onComplete?.();
991+
}
992+
} else if (searchText) {
966993
setOpened(true);
967994
onLookupRequest_?.(searchText);
968-
},
969-
onClose: () => {
970-
setOpened(false);
971-
onComplete?.(true);
972-
},
973-
onNavigateDown: () => {
974-
const nextValue = getNextValue(focusedValue);
975-
setFocusedValue(nextValue);
976-
scrollFocusedElementIntoView(nextValue);
977-
},
978-
onNavigateUp: () => {
979-
const prevValue = getPrevValue(focusedValue);
980-
setFocusedValue(prevValue);
981-
scrollFocusedElementIntoView(prevValue);
982-
},
983-
onSelect: () => {
984-
if (opened && focusedValue) {
985-
const selectedEntry = data.find(
986-
(entry) => entry.value === focusedValue
987-
);
988-
if (selectedEntry) {
989-
onSelect(selectedEntry);
990-
setOpened(false);
991-
onComplete?.();
992-
}
993-
} else if (searchText) {
994-
setOpened(true);
995-
onLookupRequest_?.(searchText);
995+
}
996+
},
997+
isTabNavigationIgnored: (direction) => {
998+
const optionValues = getOptionValues();
999+
const currentIndex = focusedValue
1000+
? optionValues.indexOf(focusedValue)
1001+
: -1;
1002+
1003+
return (
1004+
currentIndex === -1 ||
1005+
(direction === 'backward' && currentIndex <= 0) ||
1006+
(direction === 'forward' && currentIndex >= optionValues.length - 1)
1007+
);
1008+
},
1009+
onTabNavigation: (direction) => {
1010+
const optionValues = getOptionValues();
1011+
const currentIndex = focusedValue
1012+
? optionValues.indexOf(focusedValue)
1013+
: -1;
1014+
1015+
if (direction === 'backward') {
1016+
if (currentIndex <= 0) {
1017+
setOpened(false);
1018+
onComplete?.();
1019+
} else {
1020+
const prevValue = getPrevValue(focusedValue);
1021+
setFocusedValue(prevValue);
1022+
scrollFocusedElementIntoView(prevValue);
9961023
}
997-
},
998-
isTabNavigationIgnored: (direction) => {
999-
const optionValues = getOptionValues();
1000-
const currentIndex = focusedValue
1001-
? optionValues.indexOf(focusedValue)
1002-
: -1;
1003-
1004-
return (
1005-
currentIndex === -1 ||
1006-
(direction === 'backward' && currentIndex <= 0) ||
1007-
(direction === 'forward' && currentIndex >= optionValues.length - 1)
1008-
);
1009-
},
1010-
onTabNavigation: (direction) => {
1011-
const optionValues = getOptionValues();
1012-
const currentIndex = focusedValue
1013-
? optionValues.indexOf(focusedValue)
1014-
: -1;
1015-
1016-
if (direction === 'backward') {
1017-
if (currentIndex <= 0) {
1018-
setOpened(false);
1019-
onComplete?.();
1020-
} else {
1021-
const prevValue = getPrevValue(focusedValue);
1022-
setFocusedValue(prevValue);
1023-
scrollFocusedElementIntoView(prevValue);
1024-
}
1024+
} else {
1025+
if (currentIndex >= optionValues.length - 1) {
1026+
setOpened(false);
1027+
onComplete?.();
10251028
} else {
1026-
if (currentIndex >= optionValues.length - 1) {
1027-
setOpened(false);
1028-
onComplete?.();
1029-
} else {
1030-
const nextValue = getNextValue(focusedValue);
1031-
setFocusedValue(nextValue);
1032-
scrollFocusedElementIntoView(nextValue);
1033-
}
1029+
const nextValue = getNextValue(focusedValue);
1030+
setFocusedValue(nextValue);
1031+
scrollFocusedElementIntoView(nextValue);
10341032
}
1035-
},
1036-
})
1037-
);
1033+
}
1034+
},
1035+
});
10381036

10391037
const onOptionClick = useEventCallback((entry: LookupEntry) => {
10401038
onSelect(entry);
@@ -1068,82 +1066,80 @@ export const Lookup = createFC<LookupProps, { isFormElement: boolean }>(
10681066
onScopeMenuClick_?.();
10691067
});
10701068

1071-
const onScopeKeyDown = useEventCallback(
1072-
createKeyHandler({
1073-
type: 'scope',
1074-
opened: scopeOpened,
1075-
onOpen: () => {
1076-
if (!scopes) return;
1077-
setScopeOpened(true);
1078-
setScopeFocusedIndex(0);
1079-
},
1080-
onClose: () => {
1081-
setScopeOpened(false);
1082-
setScopeFocusedIndex(-1);
1083-
},
1084-
onNavigateDown: () => {
1085-
if (!scopes) return;
1086-
const nextIndex = Math.min(scopeFocusedIndex + 1, scopes.length - 1);
1087-
setScopeFocusedIndex(nextIndex);
1088-
scrollFocusedScopeIntoView(nextIndex);
1089-
},
1090-
onNavigateUp: () => {
1091-
if (!scopes) return;
1092-
const prevIndex = Math.max(scopeFocusedIndex - 1, 0);
1093-
setScopeFocusedIndex(prevIndex);
1094-
scrollFocusedScopeIntoView(prevIndex);
1095-
},
1096-
onSelect: () => {
1097-
if (!scopes) return;
1098-
if (scopeOpened && scopeFocusedIndex >= 0) {
1099-
const selectedScope = scopes[scopeFocusedIndex];
1100-
if (selectedScope) {
1101-
onScopeSelect(selectedScope.label);
1102-
setScopeOpened(false);
1103-
setScopeFocusedIndex(-1);
1104-
}
1105-
} else {
1106-
setScopeOpened(!scopeOpened);
1107-
}
1108-
},
1109-
isTabNavigationIgnored: (direction) => {
1110-
if (!scopes) {
1111-
return false;
1069+
const onScopeKeyDown = useKeyHandler({
1070+
type: 'scope',
1071+
opened: scopeOpened,
1072+
onOpen: () => {
1073+
if (!scopes) return;
1074+
setScopeOpened(true);
1075+
setScopeFocusedIndex(0);
1076+
},
1077+
onClose: () => {
1078+
setScopeOpened(false);
1079+
setScopeFocusedIndex(-1);
1080+
},
1081+
onNavigateDown: () => {
1082+
if (!scopes) return;
1083+
const nextIndex = Math.min(scopeFocusedIndex + 1, scopes.length - 1);
1084+
setScopeFocusedIndex(nextIndex);
1085+
scrollFocusedScopeIntoView(nextIndex);
1086+
},
1087+
onNavigateUp: () => {
1088+
if (!scopes) return;
1089+
const prevIndex = Math.max(scopeFocusedIndex - 1, 0);
1090+
setScopeFocusedIndex(prevIndex);
1091+
scrollFocusedScopeIntoView(prevIndex);
1092+
},
1093+
onSelect: () => {
1094+
if (!scopes) return;
1095+
if (scopeOpened && scopeFocusedIndex >= 0) {
1096+
const selectedScope = scopes[scopeFocusedIndex];
1097+
if (selectedScope) {
1098+
onScopeSelect(selectedScope.label);
1099+
setScopeOpened(false);
1100+
setScopeFocusedIndex(-1);
11121101
}
1102+
} else {
1103+
setScopeOpened(!scopeOpened);
1104+
}
1105+
},
1106+
isTabNavigationIgnored: (direction) => {
1107+
if (!scopes) {
1108+
return false;
1109+
}
11131110

1114-
return (
1115-
scopeFocusedIndex === -1 ||
1116-
(direction === 'backward' && scopeFocusedIndex <= 0) ||
1117-
(direction === 'forward' && scopeFocusedIndex >= scopes.length - 1)
1118-
);
1119-
},
1120-
onTabNavigation: (direction) => {
1121-
if (!scopes) return;
1122-
if (direction === 'backward') {
1123-
if (scopeFocusedIndex <= 0) {
1124-
setScopeOpened(false);
1125-
setScopeFocusedIndex(-1);
1126-
} else {
1127-
const prevIndex = Math.max(scopeFocusedIndex - 1, 0);
1128-
setScopeFocusedIndex(prevIndex);
1129-
scrollFocusedScopeIntoView(prevIndex);
1130-
}
1111+
return (
1112+
scopeFocusedIndex === -1 ||
1113+
(direction === 'backward' && scopeFocusedIndex <= 0) ||
1114+
(direction === 'forward' && scopeFocusedIndex >= scopes.length - 1)
1115+
);
1116+
},
1117+
onTabNavigation: (direction) => {
1118+
if (!scopes) return;
1119+
if (direction === 'backward') {
1120+
if (scopeFocusedIndex <= 0) {
1121+
setScopeOpened(false);
1122+
setScopeFocusedIndex(-1);
11311123
} else {
1132-
if (scopeFocusedIndex >= scopes.length - 1) {
1133-
setScopeOpened(false);
1134-
setScopeFocusedIndex(-1);
1135-
} else {
1136-
const nextIndex = Math.min(
1137-
scopeFocusedIndex + 1,
1138-
scopes.length - 1
1139-
);
1140-
setScopeFocusedIndex(nextIndex);
1141-
scrollFocusedScopeIntoView(nextIndex);
1142-
}
1124+
const prevIndex = Math.max(scopeFocusedIndex - 1, 0);
1125+
setScopeFocusedIndex(prevIndex);
1126+
scrollFocusedScopeIntoView(prevIndex);
11431127
}
1144-
},
1145-
})
1146-
);
1128+
} else {
1129+
if (scopeFocusedIndex >= scopes.length - 1) {
1130+
setScopeOpened(false);
1131+
setScopeFocusedIndex(-1);
1132+
} else {
1133+
const nextIndex = Math.min(
1134+
scopeFocusedIndex + 1,
1135+
scopes.length - 1
1136+
);
1137+
setScopeFocusedIndex(nextIndex);
1138+
scrollFocusedScopeIntoView(nextIndex);
1139+
}
1140+
}
1141+
},
1142+
});
11471143

11481144
const onScopeBlur = useEventCallback((e: FocusEvent) => {
11491145
if (e.relatedTarget !== null) {

0 commit comments

Comments
 (0)