@cloudflare/component-notifications 10.0.18 → 10.1.1

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.
@@ -0,0 +1,120 @@
1
+ import React from 'react';
2
+ import { Icon } from '@cloudflare/component-icon';
3
+ import {
4
+ createStyledComponent,
5
+ type ThemeProp
6
+ } from '@cloudflare/style-container';
7
+ import { getBorderColor } from './utils';
8
+ import { type TNotificationType } from './Notification';
9
+
10
+ const IconWrapper = createStyledComponent(() => ({
11
+ paddingRight: '6px',
12
+ display: 'flex'
13
+ }));
14
+
15
+ const NotificationWrapper = createStyledComponent(() => ({
16
+ display: 'flex'
17
+ }));
18
+
19
+ const CloseWrapper = createStyledComponent(() => ({
20
+ position: 'absolute',
21
+ top: '50%',
22
+ left: '50%',
23
+ transform: 'translate(-50%,-50%)'
24
+ }));
25
+
26
+ const NotificationMessage = createStyledComponent(
27
+ ({ theme }: ThemeProp) => ({
28
+ position: 'relative',
29
+ zIndex: 2,
30
+ color: theme.colors.white,
31
+ display: 'flex',
32
+ alignItems: 'center'
33
+ }),
34
+ 'span'
35
+ );
36
+
37
+ type TNotificationCloseProps = ThemeProp & {
38
+ type?: TNotificationType;
39
+ };
40
+
41
+ const NotificationClose = createStyledComponent(
42
+ ({ theme, type }: TNotificationCloseProps) => ({
43
+ position: 'absolute',
44
+ zIndex: 3,
45
+ top: 0,
46
+ right: 0,
47
+ bottom: 0,
48
+ width: '2.5em',
49
+ cursor: 'pointer',
50
+ '&:hover': {
51
+ backgroundColor: getBorderColor(theme, type)
52
+ },
53
+ '&::before': {
54
+ position: 'absolute',
55
+ top: '50%',
56
+ left: '50%',
57
+ transform: 'translate(-50%, -50%)'
58
+ }
59
+ }),
60
+ 'span'
61
+ );
62
+
63
+ type TNotificationItemProps = {
64
+ children?: string;
65
+ closable?: boolean;
66
+ handleClickClose?: () => void;
67
+ type?: TNotificationType;
68
+ };
69
+
70
+ const NotificationItem = ({
71
+ children,
72
+ closable,
73
+ handleClickClose,
74
+ type
75
+ }: TNotificationItemProps) => {
76
+ let iconType;
77
+
78
+ switch (type) {
79
+ case 'success':
80
+ iconType = 'ok-sign';
81
+ break;
82
+ case 'info':
83
+ iconType = 'info-sign';
84
+ break;
85
+ case 'warning':
86
+ iconType = 'exclamation-sign';
87
+ break;
88
+ case 'error':
89
+ iconType = 'exclamation-sign';
90
+ break;
91
+ default:
92
+ iconType = 'info-sign';
93
+ break;
94
+ }
95
+ return (
96
+ <NotificationWrapper>
97
+ <NotificationMessage>
98
+ <IconWrapper>
99
+ <Icon
100
+ type={iconType}
101
+ label={type ? type : 'info-sign'}
102
+ color="white"
103
+ size={24}
104
+ />
105
+ </IconWrapper>
106
+ {children}
107
+ </NotificationMessage>
108
+
109
+ {closable && (
110
+ <NotificationClose onClick={handleClickClose} type={type}>
111
+ <CloseWrapper>
112
+ <Icon type="remove" label="close" color="white" />
113
+ </CloseWrapper>
114
+ </NotificationClose>
115
+ )}
116
+ </NotificationWrapper>
117
+ );
118
+ };
119
+
120
+ export default NotificationItem;
@@ -0,0 +1,18 @@
1
+ import React, { type ReactNode } from 'react';
2
+ import { createStyledComponent } from '@cloudflare/style-container';
3
+
4
+ const styles = () => ({
5
+ marginTop: 0,
6
+ marginBottom: 0
7
+ });
8
+
9
+ type TNotificationListProps = {
10
+ className?: string;
11
+ children?: ReactNode;
12
+ };
13
+
14
+ const NotificationList = ({ className, children }: TNotificationListProps) => {
15
+ return <div className={className}>{children}</div>;
16
+ };
17
+
18
+ export default createStyledComponent(styles, NotificationList);
package/src/utils.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { isDarkMode } from '@cloudflare/style-const';
2
+ import { type TNotificationType } from './Notification';
3
+ import { type ThemeProp } from '@cloudflare/style-container';
4
+
5
+ export const getBorderColor = (
6
+ theme: ThemeProp['theme'],
7
+ type?: TNotificationType
8
+ ) => {
9
+ switch (type) {
10
+ case 'success':
11
+ return theme.colors.green[5];
12
+ case 'warning':
13
+ return theme.colors.orange[5];
14
+ case 'error':
15
+ return theme.colors.red[2];
16
+ case 'info':
17
+ default:
18
+ return theme.colors.blue[3];
19
+ }
20
+ };
21
+
22
+ export const getBackgroundColor = (
23
+ theme: ThemeProp['theme'],
24
+ type?: TNotificationType
25
+ ) => {
26
+ switch (type) {
27
+ case 'success':
28
+ return theme.colors.green[isDarkMode() ? 3 : 6];
29
+ case 'warning':
30
+ return theme.colors.orange[isDarkMode() ? 3 : 6];
31
+ case 'error':
32
+ return theme.colors.red[3];
33
+ case 'info':
34
+ default:
35
+ return theme.colors.blue[isDarkMode() ? 3 : 6];
36
+ }
37
+ };
@@ -1,291 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { isDarkMode } from '@cloudflare/style-const';
4
- import raf from 'raf';
5
- import { createComponent } from '@cloudflare/style-container';
6
-
7
- import { Icon } from '@cloudflare/component-icon';
8
-
9
- const getBorderColor = (type, theme) => {
10
- switch (type) {
11
- case 'success':
12
- return theme.colors.green[5];
13
- case 'warning':
14
- return theme.colors.orange[5];
15
- case 'error':
16
- return theme.colors.red[2];
17
- case 'info':
18
- default:
19
- return theme.colors.blue[3];
20
- }
21
- };
22
-
23
- const getBackgroundColor = (type, theme) => {
24
- switch (type) {
25
- case 'success':
26
- return theme.colors.green[isDarkMode() ? 3 : 6];
27
- case 'warning':
28
- return theme.colors.orange[isDarkMode() ? 3 : 6];
29
- case 'error':
30
- return theme.colors.red[3];
31
- case 'info':
32
- default:
33
- return theme.colors.blue[isDarkMode() ? 3 : 6];
34
- }
35
- };
36
-
37
- const NotificationMessage = createComponent(
38
- ({ theme }) => ({
39
- position: 'relative',
40
- zIndex: 2,
41
- color: theme.colors.white,
42
- display: 'flex',
43
- alignItems: 'center'
44
- }),
45
- 'span'
46
- );
47
-
48
- const NotificationClose = createComponent(
49
- ({ theme, type }) => ({
50
- position: 'absolute',
51
- zIndex: 3,
52
- top: 0,
53
- right: 0,
54
- bottom: 0,
55
- width: '2.5em',
56
- cursor: 'pointer',
57
- '&:hover': {
58
- backgroundColor: getBorderColor(type, theme)
59
- },
60
- '&::before': {
61
- position: 'absolute',
62
- top: '50%',
63
- left: '50%',
64
- transform: 'translate(-50%, -50%)'
65
- }
66
- }),
67
- 'span'
68
- );
69
-
70
- const NotificationContainer = createComponent(
71
- ({ theme, type }) => ({
72
- position: 'relative',
73
- padding: theme.space[2],
74
- verticalAlign: 'middle',
75
- '-webkit-text-stroke': '0',
76
- '-webkit-font-smoothing': 'antialiased',
77
- cursor: 'pointer',
78
- transformOrigin: 'bottom left',
79
- borderTopColor: getBorderColor(type, theme),
80
- borderBottomColor: getBorderColor(type, theme),
81
- borderLeftColor: getBorderColor(type, theme),
82
- borderRightColor: getBorderColor(type, theme),
83
- borderTopWidth: 1,
84
- borderRightWidth: 1,
85
- borderBottomWidth: 0,
86
- borderLeftWidth: 1,
87
- borderStyle: 'solid',
88
- backgroundColor: getBackgroundColor(type, theme),
89
- animationName: {
90
- '0%': {
91
- transform: 'scaleY(0)'
92
- },
93
- '100%': {
94
- transform: 'scaleY(1)'
95
- }
96
- },
97
- animationDuration: '200ms',
98
- animationTimingFunction: 'ease-in-out',
99
- '&::before': {
100
- position: 'absolute',
101
- top: '50%',
102
- left: '0.75rem',
103
- transform: 'translate(0, -50%)',
104
- lineHeight: '1',
105
- verticalAlign: 'middle'
106
- },
107
- '&:first-child': {
108
- borderTopWidth: 1
109
- }
110
- }),
111
- 'div'
112
- );
113
-
114
- const IconWrapper = createComponent(() => ({
115
- paddingRight: 6,
116
- display: 'flex'
117
- }));
118
-
119
- const NotificationWrapper = createComponent(() => ({
120
- display: 'flex'
121
- }));
122
-
123
- const CloseWrapper = createComponent(() => ({
124
- position: 'absolute',
125
- top: '50%',
126
- left: '50%',
127
- transform: 'translate(-50%,-50%)'
128
- }));
129
-
130
- const NotificationItem = createComponent(
131
- () => ({}),
132
- ({ children, closable, handleClickClose, type }) => {
133
- let iconType;
134
- switch (type) {
135
- case 'success':
136
- iconType = 'ok-sign';
137
- break;
138
- case 'info':
139
- iconType = 'info-sign';
140
- break;
141
- case 'warning':
142
- iconType = 'exclamation-sign';
143
- break;
144
- case 'error':
145
- iconType = 'exclamation-sign';
146
- break;
147
- default:
148
- iconType = 'info-sign';
149
- break;
150
- }
151
- return (
152
- <NotificationWrapper>
153
- <NotificationMessage>
154
- <IconWrapper>
155
- <Icon
156
- type={iconType}
157
- label={type ? type : 'info-sign'}
158
- color="white"
159
- size={24}
160
- />
161
- </IconWrapper>
162
- {children}
163
- </NotificationMessage>
164
- {closable && (
165
- <NotificationClose onClick={handleClickClose} type={type}>
166
- <CloseWrapper>
167
- <Icon type="remove" label="close" color="white" />
168
- </CloseWrapper>
169
- </NotificationClose>
170
- )}
171
- </NotificationWrapper>
172
- );
173
- }
174
- );
175
-
176
- NotificationItem.propTypes = {
177
- children: PropTypes.string,
178
- closable: PropTypes.bool,
179
- persist: PropTypes.bool,
180
- duration: PropTypes.number,
181
- active: PropTypes.bool,
182
- handleClickClose: PropTypes.func
183
- };
184
-
185
- class Notification extends React.Component {
186
- constructor(props) {
187
- super(props);
188
- this.state = {
189
- persist: this.props.persist,
190
- timeoutId: null
191
- };
192
- }
193
-
194
- componentDidMount() {
195
- // Read this https://stanko.github.io/react-rerender-in-component-did-mount/
196
- this._raf = raf(() => {
197
- this._raf = raf(() => {
198
- this._raf = null;
199
- this.startTimeout();
200
- });
201
- });
202
- }
203
-
204
- componentWillUnmount() {
205
- this.stopTimeout();
206
- }
207
-
208
- startTimeout() {
209
- // Don't dismiss errors if they're configured to be persisted,
210
- // or if we're in a testing environment
211
- if (this.state.persist || process.env.TESTING) {
212
- return;
213
- }
214
- this.stopTimeout();
215
- const timeoutId = setTimeout(() => this.props.onClose(), this.props.delay);
216
- this.setState({ timeoutId });
217
- }
218
-
219
- stopTimeout() {
220
- if (this._raf) {
221
- raf.cancel(this._raf);
222
- this._raf = null;
223
- }
224
- if (this.state.timeoutId) {
225
- clearTimeout(this.state.timeoutId);
226
- this.setState({ timeoutId: null });
227
- }
228
- }
229
-
230
- handleMouseEnter() {
231
- this.stopTimeout();
232
- }
233
-
234
- handleMouseLeave() {
235
- this.startTimeout();
236
- }
237
-
238
- handleClickClose() {
239
- this.props.onClose();
240
- }
241
-
242
- handleClick() {
243
- this.stopTimeout();
244
- this.setState({
245
- persist: true
246
- });
247
- }
248
-
249
- render() {
250
- return (
251
- <NotificationContainer
252
- role="alert"
253
- onClick={this.handleClick.bind(this)}
254
- onMouseEnter={this.handleMouseEnter.bind(this)}
255
- onMouseLeave={this.handleMouseLeave.bind(this)}
256
- type={this.props.type}
257
- >
258
- <NotificationItem
259
- closable={this.props.closable}
260
- handleClickClose={this.handleClickClose.bind(this)}
261
- duration={this.props.delay}
262
- persist={this.state.persist}
263
- active={!!this.state.timeoutId}
264
- type={this.props.type}
265
- >
266
- {this.props.message}
267
- </NotificationItem>
268
- </NotificationContainer>
269
- );
270
- }
271
- }
272
-
273
- Notification.propTypes = {
274
- type: PropTypes.oneOf(['success', 'error', 'info', 'warning']),
275
- message: PropTypes.string.isRequired,
276
-
277
- closable: PropTypes.bool,
278
- delay: PropTypes.number,
279
- persist: PropTypes.bool,
280
-
281
- onClose: PropTypes.func.isRequired
282
- };
283
-
284
- Notification.defaultProps = {
285
- closable: true,
286
- delay: 4000,
287
- persist: false,
288
- type: 'info'
289
- };
290
-
291
- export default Notification;
@@ -1,26 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { createComponent } from '@cloudflare/style-container';
4
-
5
- const styles = ({ theme }) => ({
6
- position: 'fixed',
7
- bottom: 0,
8
- left: 0,
9
- right: 0,
10
- maxHeight: '25%',
11
- overflow: 'auto',
12
- zIndex: 1600,
13
- fontSize: theme.fontSizes[3]
14
- });
15
-
16
- const NotificationGlobalContainer = ({ className, children }) => (
17
- <div className={className}>{children}</div>
18
- );
19
-
20
- NotificationGlobalContainer.propTypes = {
21
- children: PropTypes.node,
22
- className: PropTypes.string
23
- };
24
- NotificationGlobalContainer.displayName = 'NotificationGlobalContainer';
25
-
26
- export default createComponent(styles, NotificationGlobalContainer);
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { createComponent } from '@cloudflare/style-container';
4
-
5
- const styles = () => ({
6
- marginTop: 0,
7
- marginBottom: 0
8
- });
9
-
10
- const NotificationList = ({ className, children }) => (
11
- <div className={className}>{children}</div>
12
- );
13
-
14
- NotificationList.propTypes = {
15
- children: PropTypes.node,
16
- className: PropTypes.string
17
- };
18
- NotificationList.displayName = 'NotificationList';
19
-
20
- export default createComponent(styles, NotificationList);
File without changes