@ltht-react/menu 2.0.148 → 2.0.149

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/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # Input
2
-
3
- <!-- STORY -->
4
-
5
- ### Import
6
-
7
- ```js
8
- import Menu from '@ltht-react/menu'
9
- ```
10
-
11
- ### Usage
12
-
13
- ```jsx
14
- <Menu />
15
- ```
1
+ # Input
2
+
3
+ <!-- STORY -->
4
+
5
+ ### Import
6
+
7
+ ```js
8
+ import Menu from '@ltht-react/menu'
9
+ ```
10
+
11
+ ### Usage
12
+
13
+ ```jsx
14
+ <Menu />
15
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ltht-react/menu",
3
- "version": "2.0.148",
3
+ "version": "2.0.149",
4
4
  "description": "ltht-react styled Menu component.",
5
5
  "author": "LTHT",
6
6
  "homepage": "",
@@ -28,12 +28,12 @@
28
28
  "dependencies": {
29
29
  "@emotion/react": "^11.0.0",
30
30
  "@emotion/styled": "^11.0.0",
31
- "@ltht-react/button": "^2.0.148",
32
- "@ltht-react/icon": "^2.0.148",
33
- "@ltht-react/styles": "^2.0.148",
31
+ "@ltht-react/button": "^2.0.149",
32
+ "@ltht-react/icon": "^2.0.149",
33
+ "@ltht-react/styles": "^2.0.149",
34
34
  "focus-trap-react": "^10.0.0",
35
35
  "react": "^18.2.0",
36
36
  "react-popper": "^2.3.0"
37
37
  },
38
- "gitHead": "d042cdf3ba470ebd90155a73b1f0529086585331"
38
+ "gitHead": "eadc927ed4b15612bb4c33b1364366c60569a731"
39
39
  }
package/src/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import ActionMenu, { ActionMenuOption } from './molecules/action-menu'
2
-
3
- export default ActionMenu
4
- export { ActionMenuOption }
1
+ import ActionMenu, { ActionMenuOption } from './molecules/action-menu'
2
+
3
+ export default ActionMenu
4
+ export { ActionMenuOption }
@@ -1,211 +1,211 @@
1
- import styled from '@emotion/styled'
2
- import Button, { ButtonProps } from '@ltht-react/button/lib/atoms/button'
3
- import Icon, { IconButton, IconProps } from '@ltht-react/icon'
4
- import { BTN_COLOURS, CSS_RESET, PopUp, TableDataWithPopUp, getZIndex } from '@ltht-react/styles'
5
- import FocusTrap from 'focus-trap-react'
6
- import { FC, HTMLAttributes, useRef, useState, useEffect } from 'react'
7
- import { usePopper } from 'react-popper'
8
-
9
- const defaultMenuButtonProps: IconButtonMenuProps = {
10
- type: 'icon',
11
- iconProps: {
12
- type: 'ellipsis-vertical',
13
- size: 'large',
14
- },
15
- }
16
-
17
- const StyledUnorderedList = styled.ul`
18
- ${CSS_RESET}
19
- list-style-type: none;
20
- padding: 0;
21
- margin: 0;
22
- `
23
-
24
- const StyledListItem = styled.li`
25
- ${CSS_RESET}
26
- background-color: 'white';
27
- padding: 0.5rem;
28
- line-height: 1em;
29
- display: flex;
30
- border-radius: 4px;
31
-
32
- &:hover {
33
- background: ${BTN_COLOURS.PRIMARY.VALUE};
34
- cursor: pointer;
35
- color: white;
36
- }
37
- `
38
-
39
- const StyledListItemIcon = styled.div`
40
- flex-basis: 25%;
41
- `
42
-
43
- const StyledListItemContent = styled.div`
44
- flex: 1;
45
- text-align: left;
46
- `
47
-
48
- const StyledCard = styled.div`
49
- ${CSS_RESET}
50
- display: inline-block;
51
- min-width: 10rem;
52
- z-index: 1;
53
- background: white;
54
- border-radius: 4px;
55
- box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.04), 0px 4px 5px rgba(0, 0, 0, 0.06), 0px 2px 4px -1px rgba(0, 0, 0, 0.09);
56
- `
57
-
58
- const StyledRightIcon = styled(Icon)`
59
- margin-right: 0.5rem;
60
- margin-left: 3rem;
61
- `
62
-
63
- const StyledLeftIcon = styled(Icon)`
64
- margin-right: 0.5rem;
65
- margin-left: 0.5rem;
66
- `
67
-
68
- const StyledMenuButtonWrapper = styled.div`
69
- display: inline-block;
70
- `
71
-
72
- const ActionMenu: FC<IProps> = ({
73
- actions,
74
- menuButtonOptions = defaultMenuButtonProps,
75
- id = 'action-menu-button',
76
- popupStyle = {},
77
- popupPlacement = 'bottom-start',
78
- ...rest
79
- }) => {
80
- const popperRef = useRef<HTMLDivElement>(null)
81
- const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null)
82
- const [containerElement, setContainerElement] = useState<HTMLDivElement | null>(null)
83
-
84
- const popper = usePopper(popperRef.current, popperElement, {
85
- placement: popupPlacement,
86
- strategy: 'fixed',
87
- })
88
-
89
- const closePopper = () => {
90
- setShowMenu(false)
91
- }
92
-
93
- const [showMenu, setShowMenu] = useState(false)
94
-
95
- useEffect(() => {
96
- if (containerElement?.parentElement?.style) {
97
- containerElement.parentElement.style.zIndex = showMenu
98
- ? `${getZIndex(PopUp)}`
99
- : `${getZIndex(TableDataWithPopUp)}`
100
- }
101
- }, [containerElement, showMenu])
102
-
103
- const menuButtonClickHandler = () => {
104
- setShowMenu(!showMenu)
105
- }
106
-
107
- return (
108
- <div ref={setContainerElement}>
109
- <FocusTrap
110
- active={showMenu}
111
- focusTrapOptions={{
112
- tabbableOptions: {
113
- displayCheck: 'none',
114
- },
115
- initialFocus: false,
116
- allowOutsideClick: false,
117
- clickOutsideDeactivates: true,
118
- onDeactivate: closePopper,
119
- }}
120
- >
121
- <StyledMenuButtonWrapper ref={popperRef}>
122
- {menuButtonOptions.type === 'icon' && (
123
- <IconButton
124
- iconProps={menuButtonOptions.iconProps}
125
- text={menuButtonOptions.text}
126
- {...rest}
127
- onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
128
- e.stopPropagation()
129
- menuButtonClickHandler()
130
- }}
131
- id={id}
132
- data-testid={id}
133
- />
134
- )}
135
- {menuButtonOptions.type === 'button' && (
136
- <Button
137
- {...menuButtonOptions.buttonProps}
138
- {...rest}
139
- onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
140
- e.stopPropagation()
141
- menuButtonClickHandler()
142
- }}
143
- id={id}
144
- data-testid={id}
145
- >
146
- {menuButtonOptions.text}
147
- </Button>
148
- )}
149
- {showMenu && (
150
- <StyledCard
151
- tabIndex={-1}
152
- ref={setPopperElement}
153
- style={{ ...popper.styles.popper, ...popupStyle }}
154
- {...popper.attributes.popper}
155
- >
156
- <StyledUnorderedList role="menu" aria-labelledby={id}>
157
- {actions.map((action, idx) => (
158
- <StyledListItem
159
- role="menuitem"
160
- key={`menu-action-${idx}`}
161
- onClick={(e) => {
162
- e.stopPropagation()
163
- menuButtonClickHandler()
164
- action.clickHandler()
165
- }}
166
- >
167
- <StyledListItemIcon>
168
- {action.leftIcon && <StyledLeftIcon {...action.leftIcon} />}
169
- </StyledListItemIcon>
170
- <StyledListItemContent>{action.text}</StyledListItemContent>
171
- <StyledListItemIcon>
172
- {action.rightIcon && <StyledRightIcon {...action.rightIcon} />}
173
- </StyledListItemIcon>
174
- </StyledListItem>
175
- ))}
176
- </StyledUnorderedList>
177
- </StyledCard>
178
- )}
179
- </StyledMenuButtonWrapper>
180
- </FocusTrap>
181
- </div>
182
- )
183
- }
184
-
185
- interface IProps extends HTMLAttributes<HTMLButtonElement> {
186
- actions: ActionMenuOption[]
187
- menuButtonOptions?: IconButtonMenuProps | ButtonMenuProps
188
- popupStyle?: React.CSSProperties
189
- popupPlacement?: 'bottom-start' | 'right-start'
190
- }
191
-
192
- interface IconButtonMenuProps {
193
- type: 'icon'
194
- iconProps: IconProps
195
- text?: string
196
- }
197
-
198
- interface ButtonMenuProps {
199
- type: 'button'
200
- buttonProps: ButtonProps
201
- text: string
202
- }
203
-
204
- export interface ActionMenuOption {
205
- text: string
206
- clickHandler: () => void
207
- leftIcon?: IconProps
208
- rightIcon?: IconProps
209
- }
210
-
211
- export default ActionMenu
1
+ import styled from '@emotion/styled'
2
+ import Button, { ButtonProps } from '@ltht-react/button/lib/atoms/button'
3
+ import Icon, { IconButton, IconProps } from '@ltht-react/icon'
4
+ import { BTN_COLOURS, CSS_RESET, PopUp, TableDataWithPopUp, getZIndex } from '@ltht-react/styles'
5
+ import FocusTrap from 'focus-trap-react'
6
+ import { FC, HTMLAttributes, useRef, useState, useEffect } from 'react'
7
+ import { usePopper } from 'react-popper'
8
+
9
+ const defaultMenuButtonProps: IconButtonMenuProps = {
10
+ type: 'icon',
11
+ iconProps: {
12
+ type: 'ellipsis-vertical',
13
+ size: 'large',
14
+ },
15
+ }
16
+
17
+ const StyledUnorderedList = styled.ul`
18
+ ${CSS_RESET}
19
+ list-style-type: none;
20
+ padding: 0;
21
+ margin: 0;
22
+ `
23
+
24
+ const StyledListItem = styled.li`
25
+ ${CSS_RESET}
26
+ background-color: 'white';
27
+ padding: 0.5rem;
28
+ line-height: 1em;
29
+ display: flex;
30
+ border-radius: 4px;
31
+
32
+ &:hover {
33
+ background: ${BTN_COLOURS.PRIMARY.VALUE};
34
+ cursor: pointer;
35
+ color: white;
36
+ }
37
+ `
38
+
39
+ const StyledListItemIcon = styled.div`
40
+ flex-basis: 25%;
41
+ `
42
+
43
+ const StyledListItemContent = styled.div`
44
+ flex: 1;
45
+ text-align: left;
46
+ `
47
+
48
+ const StyledCard = styled.div`
49
+ ${CSS_RESET}
50
+ display: inline-block;
51
+ min-width: 10rem;
52
+ z-index: 1;
53
+ background: white;
54
+ border-radius: 4px;
55
+ box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.04), 0px 4px 5px rgba(0, 0, 0, 0.06), 0px 2px 4px -1px rgba(0, 0, 0, 0.09);
56
+ `
57
+
58
+ const StyledRightIcon = styled(Icon)`
59
+ margin-right: 0.5rem;
60
+ margin-left: 3rem;
61
+ `
62
+
63
+ const StyledLeftIcon = styled(Icon)`
64
+ margin-right: 0.5rem;
65
+ margin-left: 0.5rem;
66
+ `
67
+
68
+ const StyledMenuButtonWrapper = styled.div`
69
+ display: inline-block;
70
+ `
71
+
72
+ const ActionMenu: FC<IProps> = ({
73
+ actions,
74
+ menuButtonOptions = defaultMenuButtonProps,
75
+ id = 'action-menu-button',
76
+ popupStyle = {},
77
+ popupPlacement = 'bottom-start',
78
+ ...rest
79
+ }) => {
80
+ const popperRef = useRef<HTMLDivElement>(null)
81
+ const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null)
82
+ const [containerElement, setContainerElement] = useState<HTMLDivElement | null>(null)
83
+
84
+ const popper = usePopper(popperRef.current, popperElement, {
85
+ placement: popupPlacement,
86
+ strategy: 'fixed',
87
+ })
88
+
89
+ const closePopper = () => {
90
+ setShowMenu(false)
91
+ }
92
+
93
+ const [showMenu, setShowMenu] = useState(false)
94
+
95
+ useEffect(() => {
96
+ if (containerElement?.parentElement?.style) {
97
+ containerElement.parentElement.style.zIndex = showMenu
98
+ ? `${getZIndex(PopUp)}`
99
+ : `${getZIndex(TableDataWithPopUp)}`
100
+ }
101
+ }, [containerElement, showMenu])
102
+
103
+ const menuButtonClickHandler = () => {
104
+ setShowMenu(!showMenu)
105
+ }
106
+
107
+ return (
108
+ <div ref={setContainerElement}>
109
+ <FocusTrap
110
+ active={showMenu}
111
+ focusTrapOptions={{
112
+ tabbableOptions: {
113
+ displayCheck: 'none',
114
+ },
115
+ initialFocus: false,
116
+ allowOutsideClick: false,
117
+ clickOutsideDeactivates: true,
118
+ onDeactivate: closePopper,
119
+ }}
120
+ >
121
+ <StyledMenuButtonWrapper ref={popperRef}>
122
+ {menuButtonOptions.type === 'icon' && (
123
+ <IconButton
124
+ iconProps={menuButtonOptions.iconProps}
125
+ text={menuButtonOptions.text}
126
+ {...rest}
127
+ onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
128
+ e.stopPropagation()
129
+ menuButtonClickHandler()
130
+ }}
131
+ id={id}
132
+ data-testid={id}
133
+ />
134
+ )}
135
+ {menuButtonOptions.type === 'button' && (
136
+ <Button
137
+ {...menuButtonOptions.buttonProps}
138
+ {...rest}
139
+ onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
140
+ e.stopPropagation()
141
+ menuButtonClickHandler()
142
+ }}
143
+ id={id}
144
+ data-testid={id}
145
+ >
146
+ {menuButtonOptions.text}
147
+ </Button>
148
+ )}
149
+ {showMenu && (
150
+ <StyledCard
151
+ tabIndex={-1}
152
+ ref={setPopperElement}
153
+ style={{ ...popper.styles.popper, ...popupStyle }}
154
+ {...popper.attributes.popper}
155
+ >
156
+ <StyledUnorderedList role="menu" aria-labelledby={id}>
157
+ {actions.map((action, idx) => (
158
+ <StyledListItem
159
+ role="menuitem"
160
+ key={`menu-action-${idx}`}
161
+ onClick={(e) => {
162
+ e.stopPropagation()
163
+ menuButtonClickHandler()
164
+ action.clickHandler()
165
+ }}
166
+ >
167
+ <StyledListItemIcon>
168
+ {action.leftIcon && <StyledLeftIcon {...action.leftIcon} />}
169
+ </StyledListItemIcon>
170
+ <StyledListItemContent>{action.text}</StyledListItemContent>
171
+ <StyledListItemIcon>
172
+ {action.rightIcon && <StyledRightIcon {...action.rightIcon} />}
173
+ </StyledListItemIcon>
174
+ </StyledListItem>
175
+ ))}
176
+ </StyledUnorderedList>
177
+ </StyledCard>
178
+ )}
179
+ </StyledMenuButtonWrapper>
180
+ </FocusTrap>
181
+ </div>
182
+ )
183
+ }
184
+
185
+ interface IProps extends HTMLAttributes<HTMLButtonElement> {
186
+ actions: ActionMenuOption[]
187
+ menuButtonOptions?: IconButtonMenuProps | ButtonMenuProps
188
+ popupStyle?: React.CSSProperties
189
+ popupPlacement?: 'bottom-start' | 'right-start'
190
+ }
191
+
192
+ interface IconButtonMenuProps {
193
+ type: 'icon'
194
+ iconProps: IconProps
195
+ text?: string
196
+ }
197
+
198
+ interface ButtonMenuProps {
199
+ type: 'button'
200
+ buttonProps: ButtonProps
201
+ text: string
202
+ }
203
+
204
+ export interface ActionMenuOption {
205
+ text: string
206
+ clickHandler: () => void
207
+ leftIcon?: IconProps
208
+ rightIcon?: IconProps
209
+ }
210
+
211
+ export default ActionMenu