Skip to content

Commit 885fe22

Browse files
committed
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-common-lib into chore/update-vite
2 parents f1d5f57 + d6322e3 commit 885fe22

7 files changed

Lines changed: 120 additions & 23 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "1.23.3-beta-11",
3+
"version": "1.23.4-beta-1",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",

src/Shared/Components/Popover/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ export interface UsePopoverReturnType {
115115
* A function to close the popover.
116116
*/
117117
closePopover: () => void
118+
/**
119+
* A function to open the popover.
120+
*/
121+
openPopover: () => void
118122
}
119123

120124
export type PopoverProps = Pick<UsePopoverReturnType, 'open' | 'overlayProps' | 'popoverProps' | 'triggerProps'> & {

src/Shared/Components/Popover/usePopover.hook.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ export const usePopover = ({
6565
updateOpenState(!open)
6666
}
6767

68+
const openPopover = () => {
69+
updateOpenState(true)
70+
}
71+
6872
const closePopover = () => {
6973
if (disableClose) {
7074
return
@@ -141,7 +145,7 @@ export const usePopover = ({
141145

142146
// eslint-disable-next-line consistent-return
143147
return () => {
144-
scrollableRef.current.removeEventListener('wheel', handleWheel)
148+
scrollableRef.current?.removeEventListener('wheel', handleWheel)
145149
window.removeEventListener('resize', updatePopoverPosition)
146150
}
147151
}, [open, position, alignment, isBackdropMounted])
@@ -181,5 +185,6 @@ export const usePopover = ({
181185
},
182186
scrollableRef,
183187
closePopover,
188+
openPopover,
184189
}
185190
}

src/Shared/Components/SelectPicker/GroupedFilterSelectPicker.tsx

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { KeyboardEvent, useEffect, useRef, useState } from 'react'
17+
import { KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react'
1818

1919
import { useRegisterShortcut } from '@Common/Hooks'
2020

2121
import { ActionMenu, ActionMenuItemType, ActionMenuProps } from '../ActionMenu'
2222
import { Icon } from '../Icon'
23+
import { Popover, usePopover } from '../Popover'
2324
import FilterSelectPicker from './FilterSelectPicker'
24-
import { GroupedFilterSelectPickerProps } from './type'
25+
import { FilterSelectPickerMapSelectPickerVariant, GroupedFilterSelectPickerProps } from './type'
2526

2627
import './selectPicker.scss'
2728

@@ -41,6 +42,29 @@ export const GroupedFilterSelectPicker = <T extends string | number>({
4142
// HOOKS
4243
const { registerShortcut, unregisterShortcut } = useRegisterShortcut()
4344

45+
const selectedItemConfig = selectedActionMenuItem ? filterSelectPickerPropsMap[selectedActionMenuItem] : null
46+
const isPopOverVariant = selectedItemConfig?.variant === 'popover'
47+
48+
const {
49+
open: isFilterPopoverOpen,
50+
triggerProps: filterPopoverTriggerProps,
51+
overlayProps: filterPopoverOverlayProps,
52+
popoverProps: filterPopoverContentProps,
53+
openPopover: openFilterPopover,
54+
closePopover: closeFilterPopover,
55+
scrollableRef: filterPopoverScrollableRef,
56+
} = usePopover({
57+
id: `${id}-grouped-filter-popover`,
58+
position: isPopOverVariant ? selectedItemConfig.popoverConfig?.position : undefined,
59+
alignment: isPopOverVariant ? selectedItemConfig.popoverConfig?.alignment : undefined,
60+
width: isPopOverVariant ? selectedItemConfig.popoverConfig?.width : undefined,
61+
onOpen: (open) => {
62+
if (!open) {
63+
setSelectedActionMenuItem(null)
64+
}
65+
},
66+
})
67+
4468
useEffect(() => {
4569
const shortcutCallback = () => {
4670
triggerButtonRef.current?.click()
@@ -60,6 +84,12 @@ export const GroupedFilterSelectPicker = <T extends string | number>({
6084
}
6185
}, [selectedActionMenuItem])
6286

87+
useEffect(() => {
88+
if (selectedActionMenuItem && isPopOverVariant) {
89+
openFilterPopover()
90+
}
91+
}, [selectedActionMenuItem])
92+
6393
// HANDLERS
6494
const handleMenuItemClick: ActionMenuProps<T>['onClick'] = (item) => {
6595
setSelectedActionMenuItem(item.id)
@@ -76,18 +106,8 @@ export const GroupedFilterSelectPicker = <T extends string | number>({
76106
}
77107
}
78108

79-
return selectedActionMenuItem ? (
80-
<div className="grouped-filter-select-picker w-200">
81-
<FilterSelectPicker
82-
{...filterSelectPickerPropsMap[selectedActionMenuItem]}
83-
menuIsOpen
84-
onMenuClose={handleMenuClose}
85-
onKeyDown={handleKeyDown}
86-
autoFocus
87-
/>
88-
</div>
89-
) : (
90-
<ActionMenu {...restProps} id={id} isSearchable onClick={handleMenuItemClick}>
109+
const filterTriggerButton = useMemo(
110+
() => (
91111
<button
92112
type="button"
93113
ref={triggerButtonRef}
@@ -98,6 +118,51 @@ export const GroupedFilterSelectPicker = <T extends string | number>({
98118
<span className="fs-12 lh-20 fw-6 cn-9">Filter</span>
99119
<kbd className="icon-dim-20 flex bg__primary border__primary br-2 shadow__key fs-12 lh-20 cn-7">f</kbd>
100120
</button>
101-
</ActionMenu>
121+
),
122+
[isFilterApplied],
102123
)
124+
125+
const renderContent = () => {
126+
if (selectedActionMenuItem && isPopOverVariant) {
127+
return (
128+
<Popover
129+
open={isFilterPopoverOpen}
130+
triggerProps={{ ...filterPopoverTriggerProps, 'aria-haspopup': 'dialog' }}
131+
overlayProps={filterPopoverOverlayProps}
132+
popoverProps={{ ...filterPopoverContentProps, role: 'dialog' }}
133+
buttonProps={null}
134+
triggerElement={filterTriggerButton}
135+
>
136+
{selectedItemConfig.component(closeFilterPopover, filterPopoverScrollableRef)}
137+
</Popover>
138+
)
139+
}
140+
141+
if (selectedActionMenuItem) {
142+
const config = filterSelectPickerPropsMap[selectedActionMenuItem]
143+
if (config.variant !== 'popover') {
144+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
145+
const { variant: _variant, ...filterProps } = config as FilterSelectPickerMapSelectPickerVariant
146+
return (
147+
<div className="grouped-filter-select-picker w-200">
148+
<FilterSelectPicker
149+
{...filterProps}
150+
menuIsOpen
151+
onMenuClose={handleMenuClose}
152+
onKeyDown={handleKeyDown}
153+
autoFocus
154+
/>
155+
</div>
156+
)
157+
}
158+
}
159+
160+
return (
161+
<ActionMenu {...restProps} id={id} isSearchable onClick={handleMenuItemClick}>
162+
{filterTriggerButton}
163+
</ActionMenu>
164+
)
165+
}
166+
167+
return <div>{renderContent()}</div>
103168
}

src/Shared/Components/SelectPicker/type.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { ComponentSizeType } from '@Shared/constants'
2929
import { ActionMenuProps } from '../ActionMenu'
3030
import { ButtonComponentType, ButtonProps, ButtonVariantType } from '../Button'
3131
import { FormFieldWrapperProps } from '../FormFieldWrapper/types'
32+
import { UsePopoverProps, UsePopoverReturnType } from '../Popover'
3233

3334
export interface SelectPickerOptionType<OptionValue = string | number, OptionLabel = ReactNode> extends OptionType<
3435
OptionValue,
@@ -376,13 +377,31 @@ export type SelectPickerTextAreaProps = Omit<
376377
> &
377378
Pick<ResizableTagTextAreaProps, 'maxHeight' | 'minHeight' | 'refVar' | 'dependentRefs'>
378379

380+
export type FilterSelectPickerMapSelectPickerVariant = {
381+
variant?: 'selectPicker'
382+
} & Omit<FilterSelectPickerProps, 'autoFocus' | 'menuIsOpen' | 'onMenuClose' | 'onKeyDown' | 'selectRef'>
383+
384+
type FilterSelectPickerMapPopOverVariant = {
385+
variant: 'popover'
386+
/**
387+
* Component rendered inside the Popover.
388+
* Receives `closePopover` as a prop to allow programmatic closing.
389+
*/
390+
component: (closePopover: () => void, scrollableRef: UsePopoverReturnType['scrollableRef']) => ReactElement
391+
/**
392+
* Optional positioning config forwarded to usePopover
393+
*/
394+
popoverConfig?: Pick<UsePopoverProps, 'position' | 'alignment' | 'width'>
395+
}
396+
397+
export type GroupedFilterSelectPickerMapValue =
398+
| FilterSelectPickerMapSelectPickerVariant
399+
| FilterSelectPickerMapPopOverVariant
400+
379401
export interface GroupedFilterSelectPickerProps<T extends string | number = string | number> extends Omit<
380402
ActionMenuProps<T>,
381403
'onClick' | 'disableDescriptionEllipsis' | 'children' | 'buttonProps' | 'isSearchable'
382404
> {
383405
isFilterApplied?: boolean
384-
filterSelectPickerPropsMap: Record<
385-
T,
386-
Omit<FilterSelectPickerProps, 'autoFocus' | 'menuIsOpen' | 'onMenuClose' | 'onKeyDown' | 'selectRef'>
387-
>
406+
filterSelectPickerPropsMap: Record<T, GroupedFilterSelectPickerMapValue>
388407
}

src/Shared/Components/Table/styles.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,8 @@
153153
top: 0;
154154
position: absolute;
155155
}
156+
157+
.pagination__select-menu {
158+
z-index: 1;
159+
}
156160
}

0 commit comments

Comments
 (0)