Add Keyboard navigation on IconPicker (#2778)

* Add Add Keyboard navigation on IconPicker

Co-authored-by: Matheus <matheus_benini@hotmail.com>

* Add Keyboard navigation on IconPicker

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>

* Add Keyboard navigation on IconPicker

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>

* Add Keyboard navigation on IconPicker

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>

* Implement IconPicker

* Remove onEnter clicked

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
gitstart-twenty
2023-12-09 15:30:40 +05:45
committed by GitHub
parent 130e4c8313
commit 7c40dc7b81
14 changed files with 281 additions and 125 deletions

View File

@ -4,7 +4,6 @@ import { useRecoilValue } from 'recoil';
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
import { Activity } from '@/activities/types/Activity'; import { Activity } from '@/activities/types/Activity';
import { CommandMenuSelectableListEffect } from '@/command-menu/components/CommandMenuSelectableListEffect';
import { Company } from '@/companies/types/Company'; import { Company } from '@/companies/types/Company';
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu'; import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
@ -86,7 +85,7 @@ export const StyledEmpty = styled.div`
`; `;
export const CommandMenu = () => { export const CommandMenu = () => {
const { toggleCommandMenu, closeCommandMenu } = useCommandMenu(); const { toggleCommandMenu } = useCommandMenu();
const openActivityRightDrawer = useOpenActivityRightDrawer(); const openActivityRightDrawer = useOpenActivityRightDrawer();
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
@ -109,17 +108,6 @@ export const CommandMenu = () => {
[toggleCommandMenu, setSearch], [toggleCommandMenu, setSearch],
); );
useScopedHotkeys(
'esc',
() => {
setSearch('');
closeKeyboardShortcutMenu();
closeCommandMenu();
},
AppHotkeyScope.CommandMenu,
[toggleCommandMenu, setSearch],
);
const { records: people } = useFindManyRecords<Person>({ const { records: people } = useFindManyRecords<Person>({
skip: !isCommandMenuOpened, skip: !isCommandMenuOpened,
objectNameSingular: 'person', objectNameSingular: 'person',
@ -198,12 +186,13 @@ export const CommandMenu = () => {
<StyledList> <StyledList>
<ScrollWrapper> <ScrollWrapper>
<StyledInnerList> <StyledInnerList>
<CommandMenuSelectableListEffect
selectableItemIds={selectableItemIds}
/>
<SelectableList <SelectableList
selectableListId="command-menu-list" selectableListId="command-menu-list"
selectableItemIds={selectableItemIds} selectableItemIds={[selectableItemIds]}
hotkeyScope={AppHotkeyScope.CommandMenu}
onEnter={(itemId) => {
console.log(itemId);
}}
> >
{!matchingCreateCommand.length && {!matchingCreateCommand.length &&
!matchingNavigateCommand.length && !matchingNavigateCommand.length &&

View File

@ -1,5 +1,3 @@
import { useNavigate } from 'react-router-dom';
import { IconArrowUpRight } from '@/ui/display/icon'; import { IconArrowUpRight } from '@/ui/display/icon';
import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
@ -26,8 +24,7 @@ export const CommandMenuItem = ({
firstHotKey, firstHotKey,
secondHotKey, secondHotKey,
}: CommandMenuItemProps) => { }: CommandMenuItemProps) => {
const navigate = useNavigate(); const { onItemClick } = useCommandMenu();
const { toggleCommandMenu } = useCommandMenu();
if (to && !Icon) { if (to && !Icon) {
Icon = IconArrowUpRight; Icon = IconArrowUpRight;
@ -35,26 +32,13 @@ export const CommandMenuItem = ({
const { isSelectedItemId } = useSelectableList({ itemId: id }); const { isSelectedItemId } = useSelectableList({ itemId: id });
const onItemClick = () => {
toggleCommandMenu();
if (onClick) {
onClick();
return;
}
if (to) {
navigate(to);
return;
}
};
return ( return (
<MenuItemCommand <MenuItemCommand
LeftIcon={Icon} LeftIcon={Icon}
text={label} text={label}
firstHotKey={firstHotKey} firstHotKey={firstHotKey}
secondHotKey={secondHotKey} secondHotKey={secondHotKey}
onClick={onItemClick} onClick={() => onItemClick(onClick, to)}
isSelected={isSelectedItemId} isSelected={isSelectedItemId}
/> />
); );

View File

@ -1,21 +0,0 @@
import { useEffect } from 'react';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
type CommandMenuSelectableListEffectProps = {
selectableItemIds: string[];
};
export const CommandMenuSelectableListEffect = ({
selectableItemIds,
}: CommandMenuSelectableListEffectProps) => {
const { setSelectableItemIds } = useSelectableList({
selectableListId: 'command-menu-list',
});
useEffect(() => {
setSelectableItemIds(selectableItemIds);
}, [selectableItemIds, setSelectableItemIds]);
return <></>;
};

View File

@ -1,4 +1,5 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
@ -10,6 +11,7 @@ import { isCommandMenuOpenedState } from '../states/isCommandMenuOpenedState';
import { Command } from '../types/Command'; import { Command } from '../types/Command';
export const useCommandMenu = () => { export const useCommandMenu = () => {
const navigate = useNavigate();
const setIsCommandMenuOpened = useSetRecoilState(isCommandMenuOpenedState); const setIsCommandMenuOpened = useSetRecoilState(isCommandMenuOpenedState);
const setCommands = useSetRecoilState(commandMenuCommandsState); const setCommands = useSetRecoilState(commandMenuCommandsState);
const { const {
@ -50,11 +52,28 @@ export const useCommandMenu = () => {
setCommands(commandMenuCommands); setCommands(commandMenuCommands);
}; };
const onItemClick = useCallback(
(onClick?: () => void, to?: string) => {
toggleCommandMenu();
if (onClick) {
onClick();
return;
}
if (to) {
navigate(to);
return;
}
},
[navigate, toggleCommandMenu],
);
return { return {
openCommandMenu, openCommandMenu,
closeCommandMenu, closeCommandMenu,
toggleCommandMenu, toggleCommandMenu,
addToCommandMenu, addToCommandMenu,
onItemClick,
setToIntitialCommandMenu, setToIntitialCommandMenu,
}; };
}; };

View File

@ -9,6 +9,10 @@ import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/Dropdow
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { arrayToChunks } from '~/utils/array/array-to-chunks';
import { IconButton, IconButtonVariant } from '../button/components/IconButton'; import { IconButton, IconButtonVariant } from '../button/components/IconButton';
import { LightIconButton } from '../button/components/LightIconButton'; import { LightIconButton } from '../button/components/LightIconButton';
@ -44,6 +48,34 @@ const StyledLightIconButton = styled(LightIconButton)<{ isSelected?: boolean }>`
const convertIconKeyToLabel = (iconKey: string) => const convertIconKeyToLabel = (iconKey: string) =>
iconKey.replace(/[A-Z]/g, (letter) => ` ${letter}`).trim(); iconKey.replace(/[A-Z]/g, (letter) => ` ${letter}`).trim();
type IconPickerIconProps = {
iconKey: string;
onClick: () => void;
selectedIconKey?: string;
Icon: IconComponent;
};
const IconPickerIcon = ({
iconKey,
onClick,
selectedIconKey,
Icon,
}: IconPickerIconProps) => {
const { isSelectedItemId } = useSelectableList({ itemId: iconKey });
return (
<StyledLightIconButton
key={iconKey}
aria-label={convertIconKeyToLabel(iconKey)}
size="medium"
title={iconKey}
isSelected={iconKey === selectedIconKey || isSelectedItemId}
Icon={Icon}
onClick={onClick}
/>
);
};
export const IconPicker = ({ export const IconPicker = ({
disabled, disabled,
dropdownScopeId = 'icon-picker', dropdownScopeId = 'icon-picker',
@ -56,6 +88,10 @@ export const IconPicker = ({
className, className,
}: IconPickerProps) => { }: IconPickerProps) => {
const [searchString, setSearchString] = useState(''); const [searchString, setSearchString] = useState('');
const {
goBackToPreviousHotkeyScope,
setHotkeyScopeAndMemorizePreviousScope,
} = usePreviousHotkeyScope();
const { closeDropdown } = useDropdown({ dropdownScopeId }); const { closeDropdown } = useDropdown({ dropdownScopeId });
@ -79,6 +115,11 @@ export const IconPicker = ({
).slice(0, 25); ).slice(0, 25);
}, [icons, searchString, selectedIconKey]); }, [icons, searchString, selectedIconKey]);
const iconKeys2d = useMemo(
() => arrayToChunks(iconKeys.slice(), 5),
[iconKeys],
);
return ( return (
<DropdownScope dropdownScopeId={dropdownScopeId}> <DropdownScope dropdownScopeId={dropdownScopeId}>
<div className={className}> <div className={className}>
@ -93,36 +134,53 @@ export const IconPicker = ({
} }
dropdownMenuWidth={176} dropdownMenuWidth={176}
dropdownComponents={ dropdownComponents={
<DropdownMenu width={176}> <SelectableList
<DropdownMenuSearchInput selectableListId="icon-list"
placeholder="Search icon" selectableItemIds={iconKeys2d}
autoFocus hotkeyScope={IconPickerHotkeyScope.IconPicker}
onChange={(event) => setSearchString(event.target.value)} onEnter={(iconKey) => {
/> onChange({ iconKey, Icon: icons[iconKey] });
<DropdownMenuSeparator /> closeDropdown();
<DropdownMenuItemsContainer> }}
{isLoading ? ( >
<DropdownMenuSkeletonItem /> <DropdownMenu width={176}>
) : ( <DropdownMenuSearchInput
<StyledMenuIconItemsContainer> placeholder="Search icon"
{iconKeys.map((iconKey) => ( autoFocus
<StyledLightIconButton onChange={(event) => setSearchString(event.target.value)}
key={iconKey} />
aria-label={convertIconKeyToLabel(iconKey)} <DropdownMenuSeparator />
isSelected={selectedIconKey === iconKey} <div
size="medium" onMouseEnter={() => {
title={iconKey} setHotkeyScopeAndMemorizePreviousScope(
Icon={icons[iconKey]} IconPickerHotkeyScope.IconPicker,
onClick={() => { );
onChange({ iconKey, Icon: icons[iconKey] }); }}
closeDropdown(); onMouseLeave={goBackToPreviousHotkeyScope}
}} >
/> <DropdownMenuItemsContainer>
))} {isLoading ? (
</StyledMenuIconItemsContainer> <DropdownMenuSkeletonItem />
)} ) : (
</DropdownMenuItemsContainer> <StyledMenuIconItemsContainer>
</DropdownMenu> {iconKeys.map((iconKey) => (
<IconPickerIcon
key={iconKey}
iconKey={iconKey}
onClick={() => {
onChange({ iconKey, Icon: icons[iconKey] });
closeDropdown();
}}
selectedIconKey={selectedIconKey}
Icon={icons[iconKey]}
/>
))}
</StyledMenuIconItemsContainer>
)}
</DropdownMenuItemsContainer>
</div>
</DropdownMenu>
</SelectableList>
} }
onClickOutside={onClickOutside} onClickOutside={onClickOutside}
onClose={() => { onClose={() => {

View File

@ -1,13 +1,17 @@
import { ReactNode } from 'react'; import { ReactNode, useEffect } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useSelectableListHotKeys } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys'; import { useSelectableListHotKeys } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { SelectableListScope } from '@/ui/layout/selectable-list/scopes/SelectableListScope'; import { SelectableListScope } from '@/ui/layout/selectable-list/scopes/SelectableListScope';
type SelectableListProps = { type SelectableListProps = {
children: ReactNode; children: ReactNode;
selectableListId: string; selectableListId: string;
selectableItemIds: string[]; selectableItemIds: string[][];
onSelect?: (selected: string) => void; onSelect?: (selected: string) => void;
hotkeyScope: string;
onEnter?: (itemId: string) => void;
}; };
const StyledSelectableItemsContainer = styled.div` const StyledSelectableItemsContainer = styled.div`
@ -17,8 +21,23 @@ const StyledSelectableItemsContainer = styled.div`
export const SelectableList = ({ export const SelectableList = ({
children, children,
selectableListId, selectableListId,
hotkeyScope,
selectableItemIds,
onEnter,
}: SelectableListProps) => { }: SelectableListProps) => {
useSelectableListHotKeys(selectableListId); useSelectableListHotKeys(selectableListId, hotkeyScope);
const { setSelectableItemIds, setSelectableListOnEnter } = useSelectableList({
selectableListId,
});
useEffect(() => {
setSelectableListOnEnter(() => onEnter);
}, [onEnter, setSelectableListOnEnter]);
useEffect(() => {
setSelectableItemIds(selectableItemIds);
}, [selectableItemIds, setSelectableItemIds]);
return ( return (
<SelectableListScope selectableListScopeId={selectableListId}> <SelectableListScope selectableListScopeId={selectableListId}>

View File

@ -1,16 +1,37 @@
import { isNull } from '@sniptt/guards';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
import { getSelectableListScopedStates } from '@/ui/layout/selectable-list/utils/internal/getSelectableListScopedStates'; import { getSelectableListScopedStates } from '@/ui/layout/selectable-list/utils/internal/getSelectableListScopedStates';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
export const useSelectableListHotKeys = (scopeId: string) => { type Direction = 'up' | 'down' | 'left' | 'right';
export const useSelectableListHotKeys = (
scopeId: string,
hotkeyScope: string,
) => {
const findPosition = (
selectableItemIds: string[][],
selectedItemId?: string | null,
) => {
if (!selectedItemId) {
// If nothing is selected, return the default position
return { row: 0, col: 0 };
}
for (let row = 0; row < selectableItemIds.length; row++) {
const col = selectableItemIds[row].indexOf(selectedItemId);
if (col !== -1) {
return { row, col };
}
}
return { row: 0, col: 0 };
};
const handleSelect = useRecoilCallback( const handleSelect = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
(direction: 'up' | 'down') => { (direction: Direction) => {
const { selectedItemIdState, selectableItemIdsState } = const { selectedItemIdState, selectableItemIdsState } =
getSelectableListScopedStates({ getSelectableListScopedStates({
selectableListScopeId: scopeId, selectableListScopeId: scopeId,
@ -21,31 +42,54 @@ export const useSelectableListHotKeys = (scopeId: string) => {
selectableItemIdsState, selectableItemIdsState,
); );
const computeNextId = (direction: 'up' | 'down') => { const { row: currentRow, col: currentCol } = findPosition(
selectableItemIds,
selectedItemId,
);
const computeNextId = (direction: Direction) => {
if (selectableItemIds.length === 0) { if (selectableItemIds.length === 0) {
return; return;
} }
if (isNull(selectedItemId)) { const isSingleRow = selectableItemIds.length === 1;
return direction === 'up'
? selectableItemIds[selectableItemIds.length - 1] let nextRow: number;
: selectableItemIds[0]; let nextCol: number;
switch (direction) {
case 'up':
nextRow = isSingleRow ? currentRow : Math.max(0, currentRow - 1);
nextCol = isSingleRow ? Math.max(0, currentCol - 1) : currentCol;
break;
case 'down':
nextRow = isSingleRow
? currentRow
: Math.min(selectableItemIds.length - 1, currentRow + 1);
nextCol = isSingleRow
? Math.min(
selectableItemIds[currentRow].length - 1,
currentCol + 1,
)
: currentCol;
break;
case 'left':
nextRow = currentRow;
nextCol = Math.max(0, currentCol - 1);
break;
case 'right':
nextRow = currentRow;
nextCol = Math.min(
selectableItemIds[currentRow].length - 1,
currentCol + 1,
);
break;
default:
nextRow = currentRow;
nextCol = currentCol;
} }
const currentIndex = selectableItemIds.indexOf(selectedItemId); return selectableItemIds[nextRow][nextCol];
if (currentIndex === -1) {
return direction === 'up'
? selectableItemIds[selectableItemIds.length - 1]
: selectableItemIds[0];
}
return direction === 'up'
? currentIndex == 0
? selectableItemIds[selectableItemIds.length - 1]
: selectableItemIds[currentIndex - 1]
: currentIndex == selectableItemIds.length - 1
? selectableItemIds[0]
: selectableItemIds[currentIndex + 1];
}; };
const nextId = computeNextId(direction); const nextId = computeNextId(direction);
@ -70,17 +114,45 @@ export const useSelectableListHotKeys = (scopeId: string) => {
[scopeId], [scopeId],
); );
useScopedHotkeys(Key.ArrowUp, () => handleSelect('up'), hotkeyScope, []);
useScopedHotkeys(Key.ArrowDown, () => handleSelect('down'), hotkeyScope, []);
useScopedHotkeys(Key.ArrowLeft, () => handleSelect('left'), hotkeyScope, []);
useScopedHotkeys( useScopedHotkeys(
Key.ArrowUp, Key.ArrowRight,
() => handleSelect('up'), () => handleSelect('right'),
AppHotkeyScope.CommandMenu, hotkeyScope,
[], [],
); );
useScopedHotkeys( useScopedHotkeys(
Key.ArrowDown, Key.Enter,
() => handleSelect('down'), useRecoilCallback(
AppHotkeyScope.CommandMenu, ({ snapshot }) =>
() => {
const { selectedItemIdState, selectableListOnEnterState } =
getSelectableListScopedStates({
selectableListScopeId: scopeId,
});
const selectedItemId = getSnapshotValue(
snapshot,
selectedItemIdState,
);
const onEnter = getSnapshotValue(
snapshot,
selectableListOnEnterState,
);
if (selectedItemId) {
onEnter?.(selectedItemId);
}
},
[scopeId],
),
hotkeyScope,
[], [],
); );

View File

@ -20,6 +20,7 @@ export const useSelectableListScopedStates = (
selectedItemIdState, selectedItemIdState,
selectableItemIdsState, selectableItemIdsState,
isSelectedItemIdSelector, isSelectedItemIdSelector,
selectableListOnEnterState,
} = getSelectableListScopedStates({ } = getSelectableListScopedStates({
selectableListScopeId: scopeId, selectableListScopeId: scopeId,
itemId: itemId, itemId: itemId,
@ -30,5 +31,6 @@ export const useSelectableListScopedStates = (
isSelectedItemIdSelector, isSelectedItemIdSelector,
selectableItemIdsState, selectableItemIdsState,
selectedItemIdState, selectedItemIdState,
selectableListOnEnterState,
}; };
}; };

View File

@ -15,18 +15,25 @@ export const useSelectableList = (props?: UseSelectableListProps) => {
props?.selectableListId, props?.selectableListId,
); );
const { selectableItemIdsState, isSelectedItemIdSelector } = const {
useSelectableListScopedStates({ selectableItemIdsState,
selectableListScopeId: scopeId, isSelectedItemIdSelector,
itemId: props?.itemId, selectableListOnEnterState,
}); } = useSelectableListScopedStates({
selectableListScopeId: scopeId,
itemId: props?.itemId,
});
const setSelectableItemIds = useSetRecoilState(selectableItemIdsState); const setSelectableItemIds = useSetRecoilState(selectableItemIdsState);
const setSelectableListOnEnter = useSetRecoilState(
selectableListOnEnterState,
);
const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector); const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector);
return { return {
setSelectableItemIds, setSelectableItemIds,
isSelectedItemId, isSelectedItemId,
setSelectableListOnEnter,
selectableListId: scopeId, selectableListId: scopeId,
isSelectedItemIdSelector, isSelectedItemIdSelector,
}; };

View File

@ -1,6 +1,6 @@
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState'; import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
export const selectableItemIdsScopedState = createScopedState<string[]>({ export const selectableItemIdsScopedState = createScopedState<string[][]>({
key: 'selectableItemIdsScopedState', key: 'selectableItemIdsScopedState',
defaultValue: [], defaultValue: [[]],
}); });

View File

@ -0,0 +1,8 @@
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
export const selectableListOnEnterScopedState = createScopedState<
((itemId: string) => void) | undefined
>({
key: 'selectableListOnEnterScopedState',
defaultValue: undefined,
});

View File

@ -1,4 +1,5 @@
import { selectableItemIdsScopedState } from '@/ui/layout/selectable-list/states/selectableItemIdsScopedState'; import { selectableItemIdsScopedState } from '@/ui/layout/selectable-list/states/selectableItemIdsScopedState';
import { selectableListOnEnterScopedState } from '@/ui/layout/selectable-list/states/selectableListOnEnterScopedState';
import { selectedItemIdScopedState } from '@/ui/layout/selectable-list/states/selectedItemIdScopedState'; import { selectedItemIdScopedState } from '@/ui/layout/selectable-list/states/selectedItemIdScopedState';
import { isSelectedItemIdScopedFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdScopedFamilySelector'; import { isSelectedItemIdScopedFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdScopedFamilySelector';
import { getScopedState } from '@/ui/utilities/recoil-scope/utils/getScopedState'; import { getScopedState } from '@/ui/utilities/recoil-scope/utils/getScopedState';
@ -27,9 +28,15 @@ export const getSelectableListScopedStates = ({
selectableListScopeId, selectableListScopeId,
); );
const selectableListOnEnterState = getScopedState(
selectableListOnEnterScopedState,
selectableListScopeId,
);
return { return {
isSelectedItemIdSelector, isSelectedItemIdSelector,
selectableItemIdsState, selectableItemIdsState,
selectedItemIdState, selectedItemIdState,
selectableListOnEnterState,
}; };
}; };

View File

@ -74,6 +74,7 @@ export const useSetHotkeyScope = () =>
} }
scopesToSet.push(newHotkeyScope.scope); scopesToSet.push(newHotkeyScope.scope);
console.log(scopesToSet);
set(internalHotkeysEnabledScopesState, scopesToSet); set(internalHotkeysEnabledScopesState, scopesToSet);
set(currentHotkeyScopeState, newHotkeyScope); set(currentHotkeyScopeState, newHotkeyScope);
}, },

View File

@ -0,0 +1,11 @@
// split an array into subarrays of a given size
export const arrayToChunks = <T>(array: T[], size: number) => {
const arrayCopy = [...array];
const results = [];
while (arrayCopy.length) {
results.push(arrayCopy.splice(0, size));
}
return results;
};