mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-23 20:13:21 +03:00
fix glitch for relation picker search (#8040)
Fix for #7957 --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
parent
f633f0d330
commit
9c923ba8d5
@ -1,5 +1,5 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
import { gql } from '@apollo/client';
|
||||
export type Maybe<T> = T | null;
|
||||
export type InputMaybe<T> = Maybe<T>;
|
||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||
@ -1160,6 +1160,7 @@ export type UpdateObjectPayload = {
|
||||
labelSingular?: InputMaybe<Scalars['String']>;
|
||||
namePlural?: InputMaybe<Scalars['String']>;
|
||||
nameSingular?: InputMaybe<Scalars['String']>;
|
||||
shortcut?: InputMaybe<Scalars['String']>;
|
||||
shouldSyncLabelAndName?: InputMaybe<Scalars['Boolean']>;
|
||||
};
|
||||
|
||||
@ -1477,6 +1478,7 @@ export type Object = {
|
||||
labelSingular: Scalars['String'];
|
||||
namePlural: Scalars['String'];
|
||||
nameSingular: Scalars['String'];
|
||||
shortcut?: Maybe<Scalars['String']>;
|
||||
shouldSyncLabelAndName: Scalars['Boolean'];
|
||||
updatedAt: Scalars['DateTime'];
|
||||
};
|
||||
|
@ -31,7 +31,7 @@ const StyledContainer = styled.div`
|
||||
|
||||
const StyledColumnContainer = styled.div`
|
||||
display: flex;
|
||||
& > *:not(:first-child) {
|
||||
& > *:not(:first-of-type) {
|
||||
border-left: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
}
|
||||
`;
|
||||
|
@ -18,7 +18,7 @@ const StyledHeaderContainer = styled.div`
|
||||
top: 0;
|
||||
}
|
||||
|
||||
& > *:not(:first-child) {
|
||||
& > *:not(:first-of-type) {
|
||||
border-left: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
}
|
||||
`;
|
||||
|
@ -10,6 +10,7 @@ import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldM
|
||||
import { MultiRecordSelect } from '@/object-record/relation-picker/components/MultiRecordSelect';
|
||||
import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer';
|
||||
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
type RelationFromManyFieldInputProps = {
|
||||
onSubmit?: FieldInputEvent;
|
||||
@ -50,6 +51,8 @@ export const RelationFromManyFieldInput = ({
|
||||
recordId,
|
||||
});
|
||||
|
||||
const { dropdownPlacement } = useDropdown(relationPickerScopeId);
|
||||
|
||||
return (
|
||||
<>
|
||||
<RelationPickerScope relationPickerScopeId={relationPickerScopeId}>
|
||||
@ -58,6 +61,7 @@ export const RelationFromManyFieldInput = ({
|
||||
onSubmit={handleSubmit}
|
||||
onChange={updateRelation}
|
||||
onCreate={createNewRecordAndOpenRightDrawer}
|
||||
dropdownPlacement={dropdownPlacement}
|
||||
/>
|
||||
</RelationPickerScope>
|
||||
</>
|
||||
|
@ -82,7 +82,8 @@ export const RecordDetailRelationSection = ({
|
||||
|
||||
const dropdownId = `record-field-card-relation-picker-${fieldDefinition.label}-${recordId}`;
|
||||
|
||||
const { closeDropdown, isDropdownOpen } = useDropdown(dropdownId);
|
||||
const { closeDropdown, isDropdownOpen, dropdownPlacement } =
|
||||
useDropdown(dropdownId);
|
||||
|
||||
const { setRelationPickerSearchFilter } = useRelationPicker({
|
||||
relationPickerScopeId: dropdownId,
|
||||
@ -183,7 +184,7 @@ export const RecordDetailRelationSection = ({
|
||||
<DropdownScope dropdownScopeId={dropdownId}>
|
||||
<StyledAddDropdown
|
||||
dropdownId={dropdownId}
|
||||
dropdownPlacement="right-start"
|
||||
dropdownPlacement="left-start"
|
||||
onClose={handleCloseRelationPickerDropdown}
|
||||
clickableComponent={
|
||||
<LightIconButton
|
||||
@ -204,6 +205,7 @@ export const RecordDetailRelationSection = ({
|
||||
}
|
||||
relationPickerScopeId={dropdownId}
|
||||
onCreate={createNewRecordAndOpenRightDrawer}
|
||||
dropdownPlacement={dropdownPlacement}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
@ -212,6 +214,7 @@ export const RecordDetailRelationSection = ({
|
||||
onCreate={createNewRecordAndOpenRightDrawer}
|
||||
onChange={updateRelation}
|
||||
onSubmit={closeDropdown}
|
||||
dropdownPlacement={dropdownPlacement}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
@ -5,6 +5,7 @@ import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/r
|
||||
import { useRelationPickerScopedStates } from '@/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates';
|
||||
import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
|
||||
import { CreateNewButton } from '@/ui/input/relation-picker/components/CreateNewButton';
|
||||
import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
@ -18,11 +19,12 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import styled from '@emotion/styled';
|
||||
import { Placement } from '@floating-ui/react';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { IconPlus, isDefined } from 'twenty-ui';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
export const StyledSelectableItem = styled(SelectableItem)`
|
||||
height: 100%;
|
||||
@ -33,10 +35,12 @@ export const MultiRecordSelect = ({
|
||||
onChange,
|
||||
onSubmit,
|
||||
onCreate,
|
||||
dropdownPlacement,
|
||||
}: {
|
||||
onChange?: (changedRecordForSelectId: string) => void;
|
||||
onSubmit?: () => void;
|
||||
onCreate?: ((searchInput?: string) => void) | (() => void);
|
||||
dropdownPlacement?: Placement | null;
|
||||
}) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
@ -55,6 +59,7 @@ export const MultiRecordSelect = ({
|
||||
const recordMultiSelectIsLoading = useRecoilValue(
|
||||
recordMultiSelectIsLoadingState,
|
||||
);
|
||||
|
||||
const objectRecordsIdsMultiSelect = useRecoilValue(
|
||||
objectRecordsIdsMultiSelectState,
|
||||
);
|
||||
@ -67,9 +72,6 @@ export const MultiRecordSelect = ({
|
||||
const relationPickerSearchFilter = useRecoilValue(
|
||||
relationPickerSearchFilterState,
|
||||
);
|
||||
const debouncedSetSearchFilter = useDebouncedCallback(setSearchFilter, 100, {
|
||||
leading: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setHotkeyScope(relationPickerScopedId);
|
||||
@ -86,16 +88,53 @@ export const MultiRecordSelect = ({
|
||||
[onSubmit, goBackToPreviousHotkeyScope, resetSelectedItem],
|
||||
);
|
||||
|
||||
const debouncedOnCreate = useDebouncedCallback(
|
||||
() => onCreate?.(relationPickerSearchFilter),
|
||||
500,
|
||||
);
|
||||
|
||||
const handleFilterChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
debouncedSetSearchFilter(event.currentTarget.value);
|
||||
setSearchFilter(event.currentTarget.value);
|
||||
},
|
||||
[debouncedSetSearchFilter],
|
||||
[setSearchFilter],
|
||||
);
|
||||
|
||||
const results = (
|
||||
<DropdownMenuItemsContainer hasMaxHeight>
|
||||
<SelectableList
|
||||
selectableListId={MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID}
|
||||
selectableItemIdArray={objectRecordsIdsMultiSelect}
|
||||
hotkeyScope={relationPickerScopedId}
|
||||
onEnter={(selectedId) => {
|
||||
onChange?.(selectedId);
|
||||
resetSelectedItem();
|
||||
}}
|
||||
>
|
||||
{objectRecordsIdsMultiSelect?.map((recordId) => {
|
||||
return (
|
||||
<MultipleObjectRecordSelectItem
|
||||
key={recordId}
|
||||
objectRecordId={recordId}
|
||||
onChange={(recordId) => {
|
||||
onChange?.(recordId);
|
||||
resetSelectedItem();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</SelectableList>
|
||||
{objectRecordsIdsMultiSelect?.length === 0 &&
|
||||
!recordMultiSelectIsLoading && <MenuItem text="No result" />}
|
||||
</DropdownMenuItemsContainer>
|
||||
);
|
||||
|
||||
const createNewButton = isDefined(onCreate) && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<CreateNewButton
|
||||
onClick={() => onCreate?.(relationPickerSearchFilter)}
|
||||
LeftIcon={IconPlus}
|
||||
text="Add New"
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
@ -107,55 +146,30 @@ export const MultiRecordSelect = ({
|
||||
}}
|
||||
/>
|
||||
<DropdownMenu ref={containerRef} data-select-disable>
|
||||
{dropdownPlacement?.includes('end') && (
|
||||
<>
|
||||
{createNewButton}
|
||||
{results}
|
||||
{recordMultiSelectIsLoading && !relationPickerSearchFilter && (
|
||||
<DropdownMenuSkeletonItem />
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuSearchInput
|
||||
value={relationPickerSearchFilter}
|
||||
onChange={handleFilterChange}
|
||||
autoFocus
|
||||
/>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer hasMaxHeight hasMinHeight>
|
||||
{recordMultiSelectIsLoading ? (
|
||||
<MenuItem text="Loading..." />
|
||||
) : (
|
||||
<>
|
||||
<SelectableList
|
||||
selectableListId={MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID}
|
||||
selectableItemIdArray={objectRecordsIdsMultiSelect}
|
||||
hotkeyScope={relationPickerScopedId}
|
||||
onEnter={(selectedId) => {
|
||||
onChange?.(selectedId);
|
||||
resetSelectedItem();
|
||||
}}
|
||||
>
|
||||
{objectRecordsIdsMultiSelect?.map((recordId) => {
|
||||
return (
|
||||
<MultipleObjectRecordSelectItem
|
||||
key={recordId}
|
||||
objectRecordId={recordId}
|
||||
onChange={(recordId) => {
|
||||
onChange?.(recordId);
|
||||
resetSelectedItem();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</SelectableList>
|
||||
{objectRecordsIdsMultiSelect?.length === 0 && (
|
||||
<MenuItem text="No result" />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuItemsContainer>
|
||||
{isDefined(onCreate) && (
|
||||
{(dropdownPlacement?.includes('start') ||
|
||||
isUndefinedOrNull(dropdownPlacement)) && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<CreateNewButton
|
||||
onClick={debouncedOnCreate}
|
||||
LeftIcon={IconPlus}
|
||||
text="Add New"
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
{recordMultiSelectIsLoading && !relationPickerSearchFilter && (
|
||||
<DropdownMenuSkeletonItem />
|
||||
)}
|
||||
{results}
|
||||
{createNewButton}
|
||||
</>
|
||||
)}
|
||||
</DropdownMenu>
|
||||
|
@ -36,6 +36,7 @@ export type SingleEntitySelectMenuItemsProps = {
|
||||
isAllEntitySelectShown?: boolean;
|
||||
onAllEntitySelected?: () => void;
|
||||
hotkeyScope?: string;
|
||||
isFiltered: boolean;
|
||||
};
|
||||
|
||||
export const SingleEntitySelectMenuItems = ({
|
||||
@ -54,6 +55,7 @@ export const SingleEntitySelectMenuItems = ({
|
||||
isAllEntitySelectShown,
|
||||
onAllEntitySelected,
|
||||
hotkeyScope = RelationPickerHotkeyScope.RelationPicker,
|
||||
isFiltered,
|
||||
}: SingleEntitySelectMenuItemsProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -139,9 +141,11 @@ export const SingleEntitySelectMenuItems = ({
|
||||
}}
|
||||
>
|
||||
<DropdownMenuItemsContainer hasMaxHeight>
|
||||
{loading ? (
|
||||
{loading && !isFiltered ? (
|
||||
<DropdownMenuSkeletonItem />
|
||||
) : entitiesInDropdown.length === 0 && !isAllEntitySelectShown ? (
|
||||
) : entitiesInDropdown.length === 0 &&
|
||||
!isAllEntitySelectShown &&
|
||||
!loading ? (
|
||||
<>
|
||||
<MenuItem text="No result" />
|
||||
{entitiesToSelect.length > 0 && <DropdownMenuSeparator />}
|
||||
|
@ -6,7 +6,9 @@ import { useEntitySelectSearch } from '@/object-record/relation-picker/hooks/use
|
||||
import { useRelationPickerEntitiesOptions } from '@/object-record/relation-picker/hooks/useRelationPickerEntitiesOptions';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { Placement } from '@floating-ui/react';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
export type SingleEntitySelectMenuItemsWithSearchProps = {
|
||||
excludedRelationRecordIds?: string[];
|
||||
@ -14,6 +16,7 @@ export type SingleEntitySelectMenuItemsWithSearchProps = {
|
||||
relationObjectNameSingular: string;
|
||||
relationPickerScopeId?: string;
|
||||
selectedRelationRecordIds: string[];
|
||||
dropdownPlacement?: Placement | null;
|
||||
} & Pick<
|
||||
SingleEntitySelectMenuItemsProps,
|
||||
| 'EmptyIcon'
|
||||
@ -34,6 +37,7 @@ export const SingleEntitySelectMenuItemsWithSearch = ({
|
||||
relationPickerScopeId = 'relation-picker',
|
||||
selectedEntity,
|
||||
selectedRelationRecordIds,
|
||||
dropdownPlacement,
|
||||
}: SingleEntitySelectMenuItemsWithSearchProps) => {
|
||||
const { handleSearchFilterChange } = useEntitySelectSearch({
|
||||
relationPickerScopeId,
|
||||
@ -62,29 +66,45 @@ export const SingleEntitySelectMenuItemsWithSearch = ({
|
||||
};
|
||||
}
|
||||
|
||||
const results = (
|
||||
<SingleEntitySelectMenuItems
|
||||
entitiesToSelect={entities.entitiesToSelect}
|
||||
loading={entities.loading}
|
||||
selectedEntity={
|
||||
selectedEntity ??
|
||||
(entities.selectedEntities.length === 1
|
||||
? entities.selectedEntities[0]
|
||||
: undefined)
|
||||
}
|
||||
hotkeyScope={relationPickerScopeId}
|
||||
onCreate={onCreateWithInput}
|
||||
isFiltered={!!relationPickerSearchFilter}
|
||||
{...{
|
||||
EmptyIcon,
|
||||
emptyLabel,
|
||||
onCancel,
|
||||
onEntitySelected,
|
||||
showCreateButton,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{dropdownPlacement?.includes('end') && (
|
||||
<>
|
||||
{results}
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuSearchInput onChange={handleSearchFilterChange} autoFocus />
|
||||
<DropdownMenuSeparator />
|
||||
<SingleEntitySelectMenuItems
|
||||
entitiesToSelect={entities.entitiesToSelect}
|
||||
loading={entities.loading}
|
||||
selectedEntity={
|
||||
selectedEntity ??
|
||||
(entities.selectedEntities.length === 1
|
||||
? entities.selectedEntities[0]
|
||||
: undefined)
|
||||
}
|
||||
hotkeyScope={relationPickerScopeId}
|
||||
onCreate={onCreateWithInput}
|
||||
{...{
|
||||
EmptyIcon,
|
||||
emptyLabel,
|
||||
onCancel,
|
||||
onEntitySelected,
|
||||
showCreateButton,
|
||||
}}
|
||||
/>
|
||||
{(dropdownPlacement?.includes('start') ||
|
||||
isUndefinedOrNull(dropdownPlacement)) && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
{results}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
Placement,
|
||||
useFloating,
|
||||
} from '@floating-ui/react';
|
||||
import { MouseEvent, useRef } from 'react';
|
||||
import { MouseEvent, useEffect, useRef } from 'react';
|
||||
import { Keys } from 'react-hotkeys-hook';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
@ -64,8 +64,13 @@ export const Dropdown = ({
|
||||
}: DropdownProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { isDropdownOpen, toggleDropdown, closeDropdown, dropdownWidth } =
|
||||
useDropdown(dropdownId);
|
||||
const {
|
||||
isDropdownOpen,
|
||||
toggleDropdown,
|
||||
closeDropdown,
|
||||
dropdownWidth,
|
||||
setDropdownPlacement,
|
||||
} = useDropdown(dropdownId);
|
||||
|
||||
const offsetMiddlewares = [];
|
||||
|
||||
@ -77,13 +82,17 @@ export const Dropdown = ({
|
||||
offsetMiddlewares.push(offset({ mainAxis: dropdownOffset.y }));
|
||||
}
|
||||
|
||||
const { refs, floatingStyles } = useFloating({
|
||||
const { refs, floatingStyles, placement } = useFloating({
|
||||
placement: dropdownPlacement,
|
||||
middleware: [flip(), ...offsetMiddlewares],
|
||||
whileElementsMounted: autoUpdate,
|
||||
strategy: dropdownStrategy,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setDropdownPlacement(placement);
|
||||
}, [placement, setDropdownPlacement]);
|
||||
|
||||
const handleHotkeyTriggered = () => {
|
||||
toggleDropdown();
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import styled from '@emotion/styled';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
|
||||
const StyledDropdownMenuItemsExternalContainer = styled.div<{
|
||||
hasMinHeight?: boolean;
|
||||
hasMaxHeight?: boolean;
|
||||
}>`
|
||||
--padding: ${({ theme }) => theme.spacing(1)};
|
||||
@ -13,7 +12,6 @@ const StyledDropdownMenuItemsExternalContainer = styled.div<{
|
||||
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-height: ${({ hasMinHeight }) => (hasMinHeight ? '150px' : '100%')};
|
||||
max-height: ${({ hasMaxHeight }) => (hasMaxHeight ? '188px' : 'none')};
|
||||
overflow-y: auto;
|
||||
|
||||
@ -38,18 +36,13 @@ const StyledDropdownMenuItemsInternalContainer = styled.div`
|
||||
|
||||
export const DropdownMenuItemsContainer = ({
|
||||
children,
|
||||
hasMinHeight,
|
||||
hasMaxHeight,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
hasMinHeight?: boolean;
|
||||
hasMaxHeight?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<StyledDropdownMenuItemsExternalContainer
|
||||
hasMaxHeight={hasMaxHeight}
|
||||
hasMinHeight={hasMinHeight}
|
||||
>
|
||||
<StyledDropdownMenuItemsExternalContainer hasMaxHeight={hasMaxHeight}>
|
||||
{hasMaxHeight ? (
|
||||
<StyledScrollWrapper contextProviderName="dropdownMenuItemsContainer">
|
||||
<StyledDropdownMenuItemsInternalContainer>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { DropdownScopeInternalContext } from '@/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext';
|
||||
import { dropdownHotkeyComponentState } from '@/ui/layout/dropdown/states/dropdownHotkeyComponentState';
|
||||
import { dropdownPlacementComponentState } from '@/ui/layout/dropdown/states/dropdownPlacementComponentState';
|
||||
import { dropdownWidthComponentState } from '@/ui/layout/dropdown/states/dropdownWidthComponentState';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
@ -19,6 +20,10 @@ export const useDropdownStates = ({
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
dropdownPlacementState: extractComponentState(
|
||||
dropdownPlacementComponentState,
|
||||
scopeId,
|
||||
),
|
||||
dropdownHotkeyScopeState: extractComponentState(
|
||||
dropdownHotkeyComponentState,
|
||||
scopeId,
|
||||
|
@ -12,6 +12,7 @@ export const useDropdown = (dropdownId?: string) => {
|
||||
dropdownHotkeyScopeState,
|
||||
dropdownWidthState,
|
||||
isDropdownOpenState,
|
||||
dropdownPlacementState,
|
||||
} = useDropdownStates({
|
||||
dropdownScopeId: getScopeIdOrUndefinedFromComponentId(dropdownId),
|
||||
});
|
||||
@ -25,6 +26,10 @@ export const useDropdown = (dropdownId?: string) => {
|
||||
|
||||
const [dropdownWidth, setDropdownWidth] = useRecoilState(dropdownWidthState);
|
||||
|
||||
const [dropdownPlacement, setDropdownPlacement] = useRecoilState(
|
||||
dropdownPlacementState,
|
||||
);
|
||||
|
||||
const [isDropdownOpen, setIsDropdownOpen] =
|
||||
useRecoilState(isDropdownOpenState);
|
||||
|
||||
@ -59,5 +64,7 @@ export const useDropdown = (dropdownId?: string) => {
|
||||
openDropdown,
|
||||
dropdownWidth,
|
||||
setDropdownWidth,
|
||||
dropdownPlacement,
|
||||
setDropdownPlacement,
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
import { Placement } from '@floating-ui/react';
|
||||
|
||||
export const dropdownPlacementComponentState =
|
||||
createComponentState<Placement | null>({
|
||||
key: 'dropdownPlacementComponentState',
|
||||
defaultValue: null,
|
||||
});
|
Loading…
Reference in New Issue
Block a user