@faststore/ui 2.0.37-alpha.0 → 2.0.41-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/base/tokens.scss +1 -1
- package/src/components/molecules/Accordion/styles.scss +70 -0
- package/src/components/molecules/Dropdown/styles.scss +93 -0
- package/src/index.ts +0 -26
- package/src/styles/components.scss +2 -0
- package/dist/components/molecules/Accordion/Accordion.d.ts +0 -26
- package/dist/components/molecules/Accordion/Accordion.js +0 -21
- package/dist/components/molecules/Accordion/Accordion.js.map +0 -1
- package/dist/components/molecules/Accordion/AccordionButton.d.ts +0 -10
- package/dist/components/molecules/Accordion/AccordionButton.js +0 -37
- package/dist/components/molecules/Accordion/AccordionButton.js.map +0 -1
- package/dist/components/molecules/Accordion/AccordionItem.d.ts +0 -31
- package/dist/components/molecules/Accordion/AccordionItem.js +0 -22
- package/dist/components/molecules/Accordion/AccordionItem.js.map +0 -1
- package/dist/components/molecules/Accordion/AccordionPanel.d.ts +0 -10
- package/dist/components/molecules/Accordion/AccordionPanel.js +0 -10
- package/dist/components/molecules/Accordion/AccordionPanel.js.map +0 -1
- package/dist/components/molecules/Accordion/index.d.ts +0 -8
- package/dist/components/molecules/Accordion/index.js +0 -5
- package/dist/components/molecules/Accordion/index.js.map +0 -1
- package/dist/components/molecules/Dropdown/Dropdown.d.ts +0 -9
- package/dist/components/molecules/Dropdown/Dropdown.js +0 -67
- package/dist/components/molecules/Dropdown/Dropdown.js.map +0 -1
- package/dist/components/molecules/Dropdown/DropdownButton.d.ts +0 -10
- package/dist/components/molecules/Dropdown/DropdownButton.js +0 -11
- package/dist/components/molecules/Dropdown/DropdownButton.js.map +0 -1
- package/dist/components/molecules/Dropdown/DropdownItem.d.ts +0 -10
- package/dist/components/molecules/Dropdown/DropdownItem.js +0 -26
- package/dist/components/molecules/Dropdown/DropdownItem.js.map +0 -1
- package/dist/components/molecules/Dropdown/DropdownMenu.d.ts +0 -22
- package/dist/components/molecules/Dropdown/DropdownMenu.js +0 -65
- package/dist/components/molecules/Dropdown/DropdownMenu.js.map +0 -1
- package/dist/components/molecules/Dropdown/contexts/DropdownContext.d.ts +0 -41
- package/dist/components/molecules/Dropdown/contexts/DropdownContext.js +0 -11
- package/dist/components/molecules/Dropdown/contexts/DropdownContext.js.map +0 -1
- package/dist/components/molecules/Dropdown/hooks/useDropdown.d.ts +0 -6
- package/dist/components/molecules/Dropdown/hooks/useDropdown.js +0 -14
- package/dist/components/molecules/Dropdown/hooks/useDropdown.js.map +0 -1
- package/dist/components/molecules/Dropdown/hooks/useDropdownPosition.d.ts +0 -8
- package/dist/components/molecules/Dropdown/hooks/useDropdownPosition.js +0 -25
- package/dist/components/molecules/Dropdown/hooks/useDropdownPosition.js.map +0 -1
- package/dist/components/molecules/Dropdown/index.d.ts +0 -8
- package/dist/components/molecules/Dropdown/index.js +0 -5
- package/dist/components/molecules/Dropdown/index.js.map +0 -1
- package/src/components/molecules/Accordion/Accordion.tsx +0 -76
- package/src/components/molecules/Accordion/AccordionButton.tsx +0 -81
- package/src/components/molecules/Accordion/AccordionItem.tsx +0 -92
- package/src/components/molecules/Accordion/AccordionPanel.tsx +0 -40
- package/src/components/molecules/Accordion/index.ts +0 -11
- package/src/components/molecules/Dropdown/Dropdown.tsx +0 -102
- package/src/components/molecules/Dropdown/DropdownButton.tsx +0 -42
- package/src/components/molecules/Dropdown/DropdownItem.tsx +0 -69
- package/src/components/molecules/Dropdown/DropdownMenu.tsx +0 -139
- package/src/components/molecules/Dropdown/contexts/DropdownContext.ts +0 -53
- package/src/components/molecules/Dropdown/hooks/useDropdown.ts +0 -18
- package/src/components/molecules/Dropdown/hooks/useDropdownPosition.ts +0 -33
- package/src/components/molecules/Dropdown/index.ts +0 -11
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react'
|
|
2
|
-
import React, { useRef, useMemo, useState, useEffect, useCallback } from 'react'
|
|
3
|
-
|
|
4
|
-
import DropdownContext from './contexts/DropdownContext'
|
|
5
|
-
|
|
6
|
-
export type DropdownProps = {
|
|
7
|
-
children: ReactNode
|
|
8
|
-
onDismiss?(): void
|
|
9
|
-
isOpen?: boolean
|
|
10
|
-
id?: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const Dropdown = ({
|
|
14
|
-
children,
|
|
15
|
-
isOpen: isOpenDefault = false,
|
|
16
|
-
onDismiss,
|
|
17
|
-
id = 'store-dropdown',
|
|
18
|
-
}: DropdownProps) => {
|
|
19
|
-
const [isOpen, setIsOpen] = useState(isOpenDefault)
|
|
20
|
-
const dropdownItemsRef = useRef<HTMLButtonElement[]>([])
|
|
21
|
-
const selectedDropdownItemIndexRef = useRef(0)
|
|
22
|
-
const dropdownButtonRef = useRef<HTMLButtonElement>(null)
|
|
23
|
-
|
|
24
|
-
const close = useCallback(() => {
|
|
25
|
-
setIsOpen(false)
|
|
26
|
-
onDismiss?.()
|
|
27
|
-
dropdownButtonRef.current?.focus()
|
|
28
|
-
}, [onDismiss])
|
|
29
|
-
|
|
30
|
-
const open = () => {
|
|
31
|
-
setIsOpen(true)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const toggle = useCallback(() => {
|
|
35
|
-
setIsOpen((old) => {
|
|
36
|
-
if (old) {
|
|
37
|
-
onDismiss?.()
|
|
38
|
-
dropdownButtonRef.current?.focus()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return !old
|
|
42
|
-
})
|
|
43
|
-
}, [onDismiss])
|
|
44
|
-
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
setIsOpen(isOpenDefault)
|
|
47
|
-
}, [isOpenDefault])
|
|
48
|
-
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
isOpen && dropdownItemsRef?.current[0]?.focus()
|
|
51
|
-
}, [isOpen])
|
|
52
|
-
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
let firstClick = true
|
|
55
|
-
|
|
56
|
-
const event = (e: MouseEvent) => {
|
|
57
|
-
const someItemWasClicked = dropdownItemsRef?.current.some(
|
|
58
|
-
(item) => e.target === item
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
if (firstClick) {
|
|
62
|
-
firstClick = false
|
|
63
|
-
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
!someItemWasClicked && close()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (isOpen) {
|
|
71
|
-
document.addEventListener('click', event)
|
|
72
|
-
} else {
|
|
73
|
-
document.removeEventListener('click', event)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return () => {
|
|
77
|
-
document.removeEventListener('click', event)
|
|
78
|
-
}
|
|
79
|
-
}, [close, isOpen])
|
|
80
|
-
|
|
81
|
-
const value = useMemo(() => {
|
|
82
|
-
return {
|
|
83
|
-
isOpen,
|
|
84
|
-
close,
|
|
85
|
-
open,
|
|
86
|
-
toggle,
|
|
87
|
-
dropdownButtonRef,
|
|
88
|
-
onDismiss,
|
|
89
|
-
selectedDropdownItemIndexRef,
|
|
90
|
-
dropdownItemsRef,
|
|
91
|
-
id,
|
|
92
|
-
}
|
|
93
|
-
}, [close, id, isOpen, onDismiss, toggle])
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<DropdownContext.Provider value={value}>
|
|
97
|
-
{children}
|
|
98
|
-
</DropdownContext.Provider>
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export default Dropdown
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { ButtonHTMLAttributes } from 'react'
|
|
2
|
-
import React, { forwardRef, useImperativeHandle } from 'react'
|
|
3
|
-
|
|
4
|
-
import { useDropdown } from './hooks/useDropdown'
|
|
5
|
-
|
|
6
|
-
export interface DropdownButtonProps
|
|
7
|
-
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
-
/**
|
|
9
|
-
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
10
|
-
*/
|
|
11
|
-
testId?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const DropdownButton = forwardRef<HTMLButtonElement, DropdownButtonProps>(
|
|
15
|
-
function Button(
|
|
16
|
-
{ children, testId = 'store-dropdown-button', ...otherProps },
|
|
17
|
-
ref
|
|
18
|
-
) {
|
|
19
|
-
const { toggle, dropdownButtonRef, isOpen, id } = useDropdown()
|
|
20
|
-
|
|
21
|
-
useImperativeHandle(ref, () => dropdownButtonRef!.current!, [
|
|
22
|
-
dropdownButtonRef,
|
|
23
|
-
])
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<button
|
|
27
|
-
data-fs-dropdown-button
|
|
28
|
-
onClick={toggle}
|
|
29
|
-
data-testid={testId}
|
|
30
|
-
ref={dropdownButtonRef}
|
|
31
|
-
aria-expanded={isOpen}
|
|
32
|
-
aria-haspopup="menu"
|
|
33
|
-
aria-controls={id}
|
|
34
|
-
{...otherProps}
|
|
35
|
-
>
|
|
36
|
-
{children}
|
|
37
|
-
</button>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
export default DropdownButton
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { ButtonHTMLAttributes } from 'react'
|
|
2
|
-
import React, { useImperativeHandle, forwardRef, useRef, useState } from 'react'
|
|
3
|
-
|
|
4
|
-
import { useDropdown } from './hooks/useDropdown'
|
|
5
|
-
|
|
6
|
-
export interface DropdownItemProps
|
|
7
|
-
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
-
/**
|
|
9
|
-
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
10
|
-
*/
|
|
11
|
-
testId?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const DropdownItem = forwardRef<HTMLButtonElement, DropdownItemProps>(
|
|
15
|
-
function Button(
|
|
16
|
-
{ children, onClick, testId = 'store-dropdown-item', ...otherProps },
|
|
17
|
-
ref
|
|
18
|
-
) {
|
|
19
|
-
const { dropdownItemsRef, selectedDropdownItemIndexRef, close } =
|
|
20
|
-
useDropdown()
|
|
21
|
-
|
|
22
|
-
const [dropdownItemIndex, setDropdownItemIndex] = useState(0)
|
|
23
|
-
const dropdownItemRef = useRef<HTMLButtonElement>()
|
|
24
|
-
|
|
25
|
-
const addToRefs = (el: HTMLButtonElement) => {
|
|
26
|
-
if (el && !dropdownItemsRef?.current.includes(el)) {
|
|
27
|
-
dropdownItemsRef?.current.push(el)
|
|
28
|
-
setDropdownItemIndex(
|
|
29
|
-
dropdownItemsRef?.current.findIndex((element) => element === el) ?? 0
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
dropdownItemRef.current = el
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const onFocusItem = () => {
|
|
37
|
-
selectedDropdownItemIndexRef!.current = dropdownItemIndex
|
|
38
|
-
dropdownItemsRef?.current[selectedDropdownItemIndexRef!.current]?.focus()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const handleOnClickItem = (
|
|
42
|
-
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
|
43
|
-
) => {
|
|
44
|
-
onClick?.(event)
|
|
45
|
-
close?.()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
useImperativeHandle(ref, () => dropdownItemRef.current!, [])
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<button
|
|
52
|
-
data-fs-dropdown-item
|
|
53
|
-
data-testid={testId}
|
|
54
|
-
ref={addToRefs}
|
|
55
|
-
onFocus={onFocusItem}
|
|
56
|
-
onMouseEnter={onFocusItem}
|
|
57
|
-
onClick={handleOnClickItem}
|
|
58
|
-
role="menuitem"
|
|
59
|
-
tabIndex={-1}
|
|
60
|
-
data-index={dropdownItemIndex}
|
|
61
|
-
{...otherProps}
|
|
62
|
-
>
|
|
63
|
-
{children}
|
|
64
|
-
</button>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
export default DropdownItem
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AriaAttributes,
|
|
3
|
-
KeyboardEvent,
|
|
4
|
-
PropsWithChildren,
|
|
5
|
-
MouseEvent,
|
|
6
|
-
ReactNode,
|
|
7
|
-
} from 'react'
|
|
8
|
-
import React from 'react'
|
|
9
|
-
import { createPortal } from 'react-dom'
|
|
10
|
-
|
|
11
|
-
import type { ModalContentProps } from '../Modal/ModalContent'
|
|
12
|
-
import { useDropdown } from './hooks/useDropdown'
|
|
13
|
-
import { useDropdownPosition } from './hooks/useDropdownPosition'
|
|
14
|
-
|
|
15
|
-
export interface DropdownMenuProps extends ModalContentProps {
|
|
16
|
-
/**
|
|
17
|
-
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
18
|
-
*/
|
|
19
|
-
testId?: string
|
|
20
|
-
/**
|
|
21
|
-
* Identifies the element (or elements) that labels the current element.
|
|
22
|
-
* @see aria-labelledby https://www.w3.org/TR/wai-aria-1.1/#aria-labelledby
|
|
23
|
-
*/
|
|
24
|
-
'aria-labelledby'?: AriaAttributes['aria-label']
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* This function is called whenever the user hits "Escape" or clicks outside
|
|
28
|
-
* the dialog.
|
|
29
|
-
*/
|
|
30
|
-
onDismiss?: (event: MouseEvent | KeyboardEvent) => void
|
|
31
|
-
|
|
32
|
-
children: ReactNode[] | ReactNode
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/*
|
|
36
|
-
* This component is based on @reach/dialog.
|
|
37
|
-
* https://github.com/reach/reach-ui/blob/main/packages/dialog/src/index.tsx
|
|
38
|
-
* https://reach.tech/dialog
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
const DropdownMenu = ({
|
|
42
|
-
children,
|
|
43
|
-
testId = 'store-dropdown-menu',
|
|
44
|
-
style,
|
|
45
|
-
...otherProps
|
|
46
|
-
}: PropsWithChildren<DropdownMenuProps>) => {
|
|
47
|
-
const { isOpen, close, dropdownItemsRef, selectedDropdownItemIndexRef, id } =
|
|
48
|
-
useDropdown()
|
|
49
|
-
|
|
50
|
-
const dropdownPosition = useDropdownPosition()
|
|
51
|
-
|
|
52
|
-
const childrenLength = React.Children.toArray(children).length
|
|
53
|
-
|
|
54
|
-
const handleDownPress = () => {
|
|
55
|
-
if (selectedDropdownItemIndexRef!.current < childrenLength - 1) {
|
|
56
|
-
selectedDropdownItemIndexRef!.current++
|
|
57
|
-
} else {
|
|
58
|
-
selectedDropdownItemIndexRef!.current = 0
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
dropdownItemsRef?.current[selectedDropdownItemIndexRef!.current]?.focus()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const handleUpPress = () => {
|
|
65
|
-
if (selectedDropdownItemIndexRef!.current > 0) {
|
|
66
|
-
selectedDropdownItemIndexRef!.current--
|
|
67
|
-
} else {
|
|
68
|
-
selectedDropdownItemIndexRef!.current = childrenLength - 1
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
dropdownItemsRef?.current[selectedDropdownItemIndexRef!.current]?.focus()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const handleHomePress = () => {
|
|
75
|
-
selectedDropdownItemIndexRef!.current = 0
|
|
76
|
-
dropdownItemsRef?.current[selectedDropdownItemIndexRef!.current]?.focus()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const handleEndPress = () => {
|
|
80
|
-
selectedDropdownItemIndexRef!.current = childrenLength - 1
|
|
81
|
-
dropdownItemsRef?.current[selectedDropdownItemIndexRef!.current]?.focus()
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const handleEscapePress = () => {
|
|
85
|
-
close?.()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const handleBackdropKeyDown = (event: KeyboardEvent) => {
|
|
89
|
-
if (event.defaultPrevented || event.key === 'Enter') {
|
|
90
|
-
return
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
event.preventDefault()
|
|
94
|
-
|
|
95
|
-
event.key === 'Escape' && handleEscapePress()
|
|
96
|
-
|
|
97
|
-
event.key === 'ArrowDown' && handleDownPress()
|
|
98
|
-
|
|
99
|
-
event.key === 'ArrowUp' && handleUpPress()
|
|
100
|
-
|
|
101
|
-
event.key === 'Home' && handleHomePress()
|
|
102
|
-
|
|
103
|
-
event.key === 'End' && handleEndPress()
|
|
104
|
-
|
|
105
|
-
event.stopPropagation()
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const clearChildrenReferences = () => {
|
|
109
|
-
dropdownItemsRef!.current = []
|
|
110
|
-
|
|
111
|
-
return null
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return isOpen
|
|
115
|
-
? createPortal(
|
|
116
|
-
<div
|
|
117
|
-
role="presentation"
|
|
118
|
-
data-fs-dropdown-overlay
|
|
119
|
-
onKeyDown={handleBackdropKeyDown}
|
|
120
|
-
data-testid={`${testId}-overlay`}
|
|
121
|
-
>
|
|
122
|
-
<div
|
|
123
|
-
role="menu"
|
|
124
|
-
aria-orientation="vertical"
|
|
125
|
-
data-fs-dropdown-menu
|
|
126
|
-
data-testid={testId}
|
|
127
|
-
style={{ ...dropdownPosition, ...style }}
|
|
128
|
-
id={id}
|
|
129
|
-
{...otherProps}
|
|
130
|
-
>
|
|
131
|
-
{children}
|
|
132
|
-
</div>
|
|
133
|
-
</div>,
|
|
134
|
-
document.body
|
|
135
|
-
)
|
|
136
|
-
: clearChildrenReferences()
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export default DropdownMenu
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { createContext } from 'react'
|
|
2
|
-
|
|
3
|
-
export type DropdownContextState = {
|
|
4
|
-
/**
|
|
5
|
-
* Control de Dropdown state as Opened (true) or Closed (false).
|
|
6
|
-
*/
|
|
7
|
-
isOpen: boolean
|
|
8
|
-
/**
|
|
9
|
-
* Reference to DropdownButton, used to calculate a position for the DropdownMenu.
|
|
10
|
-
*/
|
|
11
|
-
dropdownButtonRef: React.RefObject<HTMLButtonElement> | null
|
|
12
|
-
/**
|
|
13
|
-
* Reference to a selected DropdownItem, used to manipulate focus.
|
|
14
|
-
*/
|
|
15
|
-
selectedDropdownItemIndexRef: React.MutableRefObject<number> | null
|
|
16
|
-
/**
|
|
17
|
-
* Array of References to dropdownItems in a DropdownMenu.
|
|
18
|
-
*/
|
|
19
|
-
dropdownItemsRef: React.MutableRefObject<HTMLButtonElement[]> | null
|
|
20
|
-
/**
|
|
21
|
-
* Close DropdownMenu event inherited from Modal.
|
|
22
|
-
*/
|
|
23
|
-
onDismiss?(): void
|
|
24
|
-
/**
|
|
25
|
-
* Function responsible for close the DropdownMenu in this context.
|
|
26
|
-
*/
|
|
27
|
-
close?(): void
|
|
28
|
-
/**
|
|
29
|
-
* Function responsible for open the DropdownMenu in this context.
|
|
30
|
-
*/
|
|
31
|
-
open?(): void
|
|
32
|
-
/**
|
|
33
|
-
* Function responsible for switch the the DropdownMenu state in this context.
|
|
34
|
-
*/
|
|
35
|
-
toggle?(): void
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Identifier to be used in aria-controls
|
|
39
|
-
*/
|
|
40
|
-
id: string
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const defaultState: DropdownContextState = {
|
|
44
|
-
isOpen: false,
|
|
45
|
-
dropdownButtonRef: null,
|
|
46
|
-
selectedDropdownItemIndexRef: null,
|
|
47
|
-
dropdownItemsRef: null,
|
|
48
|
-
id: 'store-dropdown',
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const DropdownContext = createContext<DropdownContextState>(defaultState)
|
|
52
|
-
|
|
53
|
-
export default DropdownContext
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { useContext } from 'react'
|
|
2
|
-
|
|
3
|
-
import type { DropdownContextState } from '../contexts/DropdownContext'
|
|
4
|
-
import DropdownContext from '../contexts/DropdownContext'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Hook to use the Dropdown context.
|
|
8
|
-
* @returns Dropdown context.
|
|
9
|
-
*/
|
|
10
|
-
export const useDropdown = () => {
|
|
11
|
-
const context = useContext<DropdownContextState>(DropdownContext)
|
|
12
|
-
|
|
13
|
-
if (context === undefined) {
|
|
14
|
-
throw new Error('Do not use useDropdown hook outside the Dropdown context.')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return context
|
|
18
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { useDropdown } from './useDropdown'
|
|
2
|
-
|
|
3
|
-
type DropdownPosition = Pick<React.CSSProperties, 'position' | 'top' | 'left'>
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hook used to find the DropdownMenu position in relation to DropdownButton
|
|
7
|
-
* @returns Style with positions.
|
|
8
|
-
*/
|
|
9
|
-
export const useDropdownPosition = (): DropdownPosition => {
|
|
10
|
-
const { dropdownButtonRef } = useDropdown()
|
|
11
|
-
|
|
12
|
-
// Necessary to use this component in SSR
|
|
13
|
-
const isBrowser = typeof window !== 'undefined'
|
|
14
|
-
|
|
15
|
-
const buttonRect = dropdownButtonRef?.current?.getBoundingClientRect()
|
|
16
|
-
const topLevel = buttonRect?.top ?? 0
|
|
17
|
-
const topOffset = buttonRect?.height ?? 0
|
|
18
|
-
const leftLevel = buttonRect?.left ?? 0
|
|
19
|
-
|
|
20
|
-
// The scroll properties fix the position of DropdownMenu when the scroll is activated.
|
|
21
|
-
const scrollTop = isBrowser ? document?.documentElement?.scrollTop : 0
|
|
22
|
-
const scrollLeft = isBrowser ? document?.documentElement?.scrollLeft : 0
|
|
23
|
-
|
|
24
|
-
const topPosition = topLevel + topOffset + scrollTop
|
|
25
|
-
|
|
26
|
-
const leftPosition = leftLevel + scrollLeft
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
position: 'absolute',
|
|
30
|
-
top: topPosition,
|
|
31
|
-
left: leftPosition,
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { default } from './Dropdown'
|
|
2
|
-
export type { DropdownProps } from './Dropdown'
|
|
3
|
-
|
|
4
|
-
export { default as DropdownButton } from './DropdownButton'
|
|
5
|
-
export type { DropdownButtonProps } from './DropdownButton'
|
|
6
|
-
|
|
7
|
-
export { default as DropdownItem } from './DropdownItem'
|
|
8
|
-
export type { DropdownItemProps } from './DropdownItem'
|
|
9
|
-
|
|
10
|
-
export { default as DropdownMenu } from './DropdownMenu'
|
|
11
|
-
export type { DropdownMenuProps } from './DropdownMenu'
|