diff --git a/package-lock.json b/package-lock.json index eb5245bdb..eec5236a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.23.3-alpha-2", + "version": "1.23.3-pre-0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.23.3-alpha-2", + "version": "1.23.3-pre-0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 0b542367f..2fe6b3e1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.23.3-alpha-2", + "version": "1.23.3-pre-0", "description": "Supporting common component library", "type": "module", "main": "dist/index.js", diff --git a/src/Shared/Components/Popover/types.ts b/src/Shared/Components/Popover/types.ts index f224838d1..6909ecb42 100644 --- a/src/Shared/Components/Popover/types.ts +++ b/src/Shared/Components/Popover/types.ts @@ -115,6 +115,10 @@ export interface UsePopoverReturnType { * A function to close the popover. */ closePopover: () => void + /** + * A function to open the popover. + */ + openPopover: () => void } export type PopoverProps = Pick & { diff --git a/src/Shared/Components/Popover/usePopover.hook.ts b/src/Shared/Components/Popover/usePopover.hook.ts index 885138b16..66039ae7a 100644 --- a/src/Shared/Components/Popover/usePopover.hook.ts +++ b/src/Shared/Components/Popover/usePopover.hook.ts @@ -65,6 +65,10 @@ export const usePopover = ({ updateOpenState(!open) } + const openPopover = () => { + updateOpenState(true) + } + const closePopover = () => { if (disableClose) { return @@ -141,7 +145,7 @@ export const usePopover = ({ // eslint-disable-next-line consistent-return return () => { - scrollableRef.current.removeEventListener('wheel', handleWheel) + scrollableRef.current?.removeEventListener('wheel', handleWheel) window.removeEventListener('resize', updatePopoverPosition) } }, [open, position, alignment, isBackdropMounted]) @@ -181,5 +185,6 @@ export const usePopover = ({ }, scrollableRef, closePopover, + openPopover, } } diff --git a/src/Shared/Components/SelectPicker/GroupedFilterSelectPicker.tsx b/src/Shared/Components/SelectPicker/GroupedFilterSelectPicker.tsx index aad328598..715763923 100644 --- a/src/Shared/Components/SelectPicker/GroupedFilterSelectPicker.tsx +++ b/src/Shared/Components/SelectPicker/GroupedFilterSelectPicker.tsx @@ -14,14 +14,15 @@ * limitations under the License. */ -import { KeyboardEvent, useEffect, useRef, useState } from 'react' +import { KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react' import { useRegisterShortcut } from '@Common/Hooks' import { ActionMenu, ActionMenuItemType, ActionMenuProps } from '../ActionMenu' import { Icon } from '../Icon' +import { Popover, usePopover } from '../Popover' import FilterSelectPicker from './FilterSelectPicker' -import { GroupedFilterSelectPickerProps } from './type' +import { FilterSelectPickerMapSelectPickerVariant, GroupedFilterSelectPickerProps } from './type' import './selectPicker.scss' @@ -41,6 +42,29 @@ export const GroupedFilterSelectPicker = ({ // HOOKS const { registerShortcut, unregisterShortcut } = useRegisterShortcut() + const selectedItemConfig = selectedActionMenuItem ? filterSelectPickerPropsMap[selectedActionMenuItem] : null + const isPopOverVariant = selectedItemConfig?.variant === 'popover' + + const { + open: isFilterPopoverOpen, + triggerProps: filterPopoverTriggerProps, + overlayProps: filterPopoverOverlayProps, + popoverProps: filterPopoverContentProps, + openPopover: openFilterPopover, + closePopover: closeFilterPopover, + scrollableRef: filterPopoverScrollableRef, + } = usePopover({ + id: `${id}-grouped-filter-popover`, + position: isPopOverVariant ? selectedItemConfig.popoverConfig?.position : undefined, + alignment: isPopOverVariant ? selectedItemConfig.popoverConfig?.alignment : undefined, + width: isPopOverVariant ? selectedItemConfig.popoverConfig?.width : undefined, + onOpen: (open) => { + if (!open) { + setSelectedActionMenuItem(null) + } + }, + }) + useEffect(() => { const shortcutCallback = () => { triggerButtonRef.current?.click() @@ -60,6 +84,12 @@ export const GroupedFilterSelectPicker = ({ } }, [selectedActionMenuItem]) + useEffect(() => { + if (selectedActionMenuItem && isPopOverVariant) { + openFilterPopover() + } + }, [selectedActionMenuItem]) + // HANDLERS const handleMenuItemClick: ActionMenuProps['onClick'] = (item) => { setSelectedActionMenuItem(item.id) @@ -76,18 +106,8 @@ export const GroupedFilterSelectPicker = ({ } } - return selectedActionMenuItem ? ( -
- -
- ) : ( - + const filterTriggerButton = useMemo( + () => ( - + ), + [isFilterApplied], ) + + const renderContent = () => { + if (selectedActionMenuItem && isPopOverVariant) { + return ( + + {selectedItemConfig.component(closeFilterPopover, filterPopoverScrollableRef)} + + ) + } + + if (selectedActionMenuItem) { + const config = filterSelectPickerPropsMap[selectedActionMenuItem] + if (config.variant !== 'popover') { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { variant: _variant, ...filterProps } = config as FilterSelectPickerMapSelectPickerVariant + return ( +
+ +
+ ) + } + } + + return ( + + {filterTriggerButton} + + ) + } + + return
{renderContent()}
} diff --git a/src/Shared/Components/SelectPicker/type.ts b/src/Shared/Components/SelectPicker/type.ts index e09ce9ee4..f3547722a 100644 --- a/src/Shared/Components/SelectPicker/type.ts +++ b/src/Shared/Components/SelectPicker/type.ts @@ -29,6 +29,7 @@ import { ComponentSizeType } from '@Shared/constants' import { ActionMenuProps } from '../ActionMenu' import { ButtonComponentType, ButtonProps, ButtonVariantType } from '../Button' import { FormFieldWrapperProps } from '../FormFieldWrapper/types' +import { UsePopoverProps, UsePopoverReturnType } from '../Popover' export interface SelectPickerOptionType extends OptionType { @@ -373,14 +374,32 @@ export type SelectPickerTextAreaProps = Omit< > & Pick +export type FilterSelectPickerMapSelectPickerVariant = { + variant?: 'selectPicker' +} & Omit + +type FilterSelectPickerMapPopOverVariant = { + variant: 'popover' + /** + * Component rendered inside the Popover. + * Receives `closePopover` as a prop to allow programmatic closing. + */ + component: (closePopover: () => void, scrollableRef: UsePopoverReturnType['scrollableRef']) => ReactElement + /** + * Optional positioning config forwarded to usePopover + */ + popoverConfig?: Pick +} + +export type GroupedFilterSelectPickerMapValue = + | FilterSelectPickerMapSelectPickerVariant + | FilterSelectPickerMapPopOverVariant + export interface GroupedFilterSelectPickerProps extends Omit< ActionMenuProps, 'onClick' | 'disableDescriptionEllipsis' | 'children' | 'buttonProps' | 'isSearchable' > { isFilterApplied?: boolean - filterSelectPickerPropsMap: Record< - T, - Omit - > + filterSelectPickerPropsMap: Record } diff --git a/src/Shared/Components/Table/InternalTable.tsx b/src/Shared/Components/Table/InternalTable.tsx index b35cd5297..bae8902a5 100644 --- a/src/Shared/Components/Table/InternalTable.tsx +++ b/src/Shared/Components/Table/InternalTable.tsx @@ -201,9 +201,8 @@ const InternalTable = < ) : (