@woosmap/ui 2.44.0 → 2.48.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/package.json +1 -1
- package/src/components/Button/Button.js +1 -1
- package/src/components/Dropdown/Dropdown.js +77 -3
- package/src/components/Dropdown/Dropdown.stories.js +29 -0
- package/src/components/Dropdown/Dropdown.styl +3 -0
- package/src/components/Icon/Icon.js +6 -0
- package/src/components/Modal/Modal.js +24 -0
- package/src/components/Modal/Modal.stories.js +12 -0
- package/src/components/Modal/Modal.test.js +18 -2
- package/src/icons/social-facebook.svg +1 -0
- package/src/icons/social-linkedin.svg +1 -0
- package/src/icons/social-twitter.svg +1 -0
- package/src/styles/commons/base.styl +6 -6
package/package.json
CHANGED
|
@@ -104,7 +104,7 @@ Button.propTypes = {
|
|
|
104
104
|
]),
|
|
105
105
|
isLoading: PropTypes.bool,
|
|
106
106
|
active: PropTypes.bool,
|
|
107
|
-
label: PropTypes.string,
|
|
107
|
+
label: PropTypes.oneOfType(PropTypes.string, PropTypes.node),
|
|
108
108
|
icon: PropTypes.string,
|
|
109
109
|
iconSize: PropTypes.number,
|
|
110
110
|
className: PropTypes.string,
|
|
@@ -45,9 +45,20 @@ class DropdownMenu extends Component {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
render() {
|
|
48
|
-
const { direction, children, closeCb, testId, ...rest } = this.props;
|
|
48
|
+
const { direction, children, closeCb, testId, isSection, ...rest } = this.props;
|
|
49
49
|
const childrenWithProps = mapChildrenWithProps(children, this.childrenRefs, closeCb);
|
|
50
|
-
|
|
50
|
+
if (isSection) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
role="menu"
|
|
54
|
+
className={cl('dropdown__menu', direction, 'dropdown__menu--section')}
|
|
55
|
+
data-testid={testId}
|
|
56
|
+
{...rest}
|
|
57
|
+
>
|
|
58
|
+
{childrenWithProps}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
51
62
|
return (
|
|
52
63
|
<ul role="menu" className={cl('dropdown__menu', direction)} data-testid={testId} {...rest}>
|
|
53
64
|
{childrenWithProps}
|
|
@@ -60,15 +71,50 @@ DropdownMenu.defaultProps = {
|
|
|
60
71
|
direction: 'sw',
|
|
61
72
|
closeCb: null,
|
|
62
73
|
testId: 'dropdown-menu',
|
|
74
|
+
isSection: false,
|
|
63
75
|
};
|
|
64
76
|
|
|
65
77
|
DropdownMenu.propTypes = {
|
|
66
78
|
children: PropTypes.node.isRequired,
|
|
67
79
|
closeCb: PropTypes.func,
|
|
68
80
|
testId: PropTypes.string,
|
|
81
|
+
isSection: PropTypes.bool,
|
|
69
82
|
direction: PropTypes.oneOf(['ne', 'e', 'se', 's', 'sw', 'w']),
|
|
70
83
|
};
|
|
71
84
|
|
|
85
|
+
class DropdownMenuSection extends Component {
|
|
86
|
+
constructor(props) {
|
|
87
|
+
super(props);
|
|
88
|
+
this.childrenRefs = {};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
close = () => {
|
|
92
|
+
closeChildren(this.childrenRefs);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
render() {
|
|
96
|
+
const { title, children, closeCb, ...rest } = this.props;
|
|
97
|
+
const childrenWithProps = mapChildrenWithProps(children, this.childrenRefs, closeCb);
|
|
98
|
+
return (
|
|
99
|
+
<div className="dropdown__menu__section">
|
|
100
|
+
{title && <div className="dropdown__menu__section__title">{title}</div>}
|
|
101
|
+
<ul {...rest}>{childrenWithProps}</ul>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
DropdownMenuSection.defaultProps = {
|
|
108
|
+
title: null,
|
|
109
|
+
closeCb: null,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
DropdownMenuSection.propTypes = {
|
|
113
|
+
children: PropTypes.node.isRequired,
|
|
114
|
+
title: PropTypes.string,
|
|
115
|
+
closeCb: PropTypes.func,
|
|
116
|
+
};
|
|
117
|
+
|
|
72
118
|
class DropdownSeparator extends Component {
|
|
73
119
|
render() {
|
|
74
120
|
const { testId } = this.props;
|
|
@@ -243,6 +289,28 @@ class Dropdown extends Component {
|
|
|
243
289
|
this.setOpen(false);
|
|
244
290
|
};
|
|
245
291
|
|
|
292
|
+
onMouseEnter = () => {
|
|
293
|
+
const { openOnMouseEnter } = this.props;
|
|
294
|
+
if (openOnMouseEnter) {
|
|
295
|
+
if (this.mouseLeaveTimeout) {
|
|
296
|
+
clearTimeout(this.mouseLeaveTimeout);
|
|
297
|
+
}
|
|
298
|
+
this.setOpen(true);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
onMouseLeave = () => {
|
|
303
|
+
const { openOnMouseEnter } = this.props;
|
|
304
|
+
if (openOnMouseEnter) {
|
|
305
|
+
if (this.mouseLeaveTimeout) {
|
|
306
|
+
clearTimeout(this.mouseLeaveTimeout);
|
|
307
|
+
}
|
|
308
|
+
this.mouseLeaveTimeout = setTimeout(() => {
|
|
309
|
+
this.setOpen(false);
|
|
310
|
+
}, 500);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
246
314
|
onClick = (e) => {
|
|
247
315
|
const { onClick } = this.props;
|
|
248
316
|
const { open } = this.state;
|
|
@@ -273,6 +341,7 @@ class Dropdown extends Component {
|
|
|
273
341
|
closeCb,
|
|
274
342
|
disableCloseOutside,
|
|
275
343
|
testId,
|
|
344
|
+
openOnMouseEnter,
|
|
276
345
|
...rest
|
|
277
346
|
} = this.props;
|
|
278
347
|
const { open } = this.state;
|
|
@@ -283,6 +352,8 @@ class Dropdown extends Component {
|
|
|
283
352
|
ref={this.clickOutsideRef}
|
|
284
353
|
className={cl('dropdown', { open }, `dropdown--${size}`, className)}
|
|
285
354
|
{...rest}
|
|
355
|
+
onMouseEnter={this.onMouseEnter}
|
|
356
|
+
onMouseLeave={this.onMouseLeave}
|
|
286
357
|
>
|
|
287
358
|
<Button
|
|
288
359
|
disabled={disabled}
|
|
@@ -311,6 +382,7 @@ Dropdown.defaultProps = {
|
|
|
311
382
|
label: null,
|
|
312
383
|
className: null,
|
|
313
384
|
closeCb: null,
|
|
385
|
+
openOnMouseEnter: false,
|
|
314
386
|
btnFace: 'link-flex',
|
|
315
387
|
btnFaceIcon: 'caret-bottom',
|
|
316
388
|
btnFaceIconSize: 24,
|
|
@@ -323,7 +395,8 @@ Dropdown.propTypes = {
|
|
|
323
395
|
onDoubleClick: PropTypes.func,
|
|
324
396
|
disabled: PropTypes.bool,
|
|
325
397
|
disableCloseOutside: PropTypes.bool,
|
|
326
|
-
|
|
398
|
+
openOnMouseEnter: PropTypes.bool,
|
|
399
|
+
label: PropTypes.oneOfType(PropTypes.string, PropTypes.node),
|
|
327
400
|
testId: PropTypes.string,
|
|
328
401
|
children: PropTypes.node.isRequired,
|
|
329
402
|
className: PropTypes.string,
|
|
@@ -336,6 +409,7 @@ Dropdown.propTypes = {
|
|
|
336
409
|
|
|
337
410
|
export default Object.assign(withClickOutside(Dropdown, '.popover__content'), {
|
|
338
411
|
Menu: DropdownMenu,
|
|
412
|
+
MenuSection: DropdownMenuSection,
|
|
339
413
|
Item: DropdownItem,
|
|
340
414
|
ButtonItem: DropdownButtonItem,
|
|
341
415
|
ConfirmButtonItem: DropdownConfirmButtonItem,
|
|
@@ -52,3 +52,32 @@ const Template = () => (
|
|
|
52
52
|
);
|
|
53
53
|
export const Default = Template.bind({});
|
|
54
54
|
Default.args = {};
|
|
55
|
+
|
|
56
|
+
const MultiMenuTemplate = () => (
|
|
57
|
+
<div className="mbi" id="menuid">
|
|
58
|
+
<Dropdown btnFace="link" btnFaceIcon="clock" label="My dropdown" openOnMouseEnter>
|
|
59
|
+
<Dropdown.Menu isSection direction="se">
|
|
60
|
+
<Dropdown.MenuSection title="Section title">
|
|
61
|
+
<Dropdown.ButtonItem btnIcon="delete" isImportant btnLabel="Delete" />
|
|
62
|
+
<Dropdown.ConfirmButtonItem
|
|
63
|
+
btnIcon="delete"
|
|
64
|
+
isImportant
|
|
65
|
+
btnLabel="Delete confirm"
|
|
66
|
+
onConfirm={() => null}
|
|
67
|
+
/>
|
|
68
|
+
</Dropdown.MenuSection>
|
|
69
|
+
<Dropdown.MenuSection title="Section title 2">
|
|
70
|
+
<Dropdown.ButtonItem btnIcon="delete" isImportant btnLabel="Delete" />
|
|
71
|
+
<Dropdown.ConfirmButtonItem
|
|
72
|
+
btnIcon="delete"
|
|
73
|
+
isImportant
|
|
74
|
+
btnLabel="Delete confirm"
|
|
75
|
+
onConfirm={() => null}
|
|
76
|
+
/>
|
|
77
|
+
</Dropdown.MenuSection>
|
|
78
|
+
</Dropdown.Menu>
|
|
79
|
+
</Dropdown>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
export const MultiMenuTemplateDropdown = MultiMenuTemplate.bind({});
|
|
83
|
+
MultiMenuTemplateDropdown.args = {};
|
|
@@ -114,6 +114,9 @@ import { ReactComponent as Localities } from '../../icons/localities.svg';
|
|
|
114
114
|
import { ReactComponent as Map } from '../../icons/map.svg';
|
|
115
115
|
import { ReactComponent as Merchant } from '../../icons/merchant.svg';
|
|
116
116
|
import { ReactComponent as Traffic } from '../../icons/traffic.svg';
|
|
117
|
+
import { ReactComponent as SocialFacebook } from '../../icons/social-facebook.svg';
|
|
118
|
+
import { ReactComponent as SocialLinkedin } from '../../icons/social-linkedin.svg';
|
|
119
|
+
import { ReactComponent as SocialTwitter } from '../../icons/social-twitter.svg';
|
|
117
120
|
|
|
118
121
|
const Icons = {
|
|
119
122
|
access: Access,
|
|
@@ -229,6 +232,9 @@ const Icons = {
|
|
|
229
232
|
maps: Map,
|
|
230
233
|
merchant: Merchant,
|
|
231
234
|
traffic: Traffic,
|
|
235
|
+
'social-facebook': SocialFacebook,
|
|
236
|
+
'social-linkedin': SocialLinkedin,
|
|
237
|
+
'social-twitter': SocialTwitter,
|
|
232
238
|
};
|
|
233
239
|
|
|
234
240
|
class Icon extends Component {
|
|
@@ -15,6 +15,10 @@ class Modal extends Component {
|
|
|
15
15
|
this.modalRef = React.createRef();
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
componentDidMount() {
|
|
19
|
+
this.handleEscFunction('add');
|
|
20
|
+
}
|
|
21
|
+
|
|
18
22
|
componentDidUpdate() {
|
|
19
23
|
const { isLoading } = this.state;
|
|
20
24
|
const { hasErrors } = this.props;
|
|
@@ -23,6 +27,10 @@ class Modal extends Component {
|
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
componentWillUnmount() {
|
|
31
|
+
this.handleEscFunction();
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
handleClickOutside = () => {
|
|
27
35
|
this.close();
|
|
28
36
|
};
|
|
@@ -31,6 +39,20 @@ class Modal extends Component {
|
|
|
31
39
|
this.setState({ isLoading: loading });
|
|
32
40
|
}
|
|
33
41
|
|
|
42
|
+
handleEscFunction = (key) => {
|
|
43
|
+
const { closesWithEscape } = this.props;
|
|
44
|
+
if (closesWithEscape) {
|
|
45
|
+
if (key === 'add') document.addEventListener('keydown', this.escFunction, false);
|
|
46
|
+
else document.removeEventListener('keydown', this.escFunction, false);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
escFunction = (event) => {
|
|
51
|
+
if (event.keyCode === 27) {
|
|
52
|
+
this.close();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
34
56
|
open = () => {
|
|
35
57
|
this.setState({ open: true });
|
|
36
58
|
};
|
|
@@ -141,6 +163,7 @@ Modal.defaultProps = {
|
|
|
141
163
|
validateBtnProps: {},
|
|
142
164
|
mainButtonType: 'primary',
|
|
143
165
|
testId: 'modal',
|
|
166
|
+
closesWithEscape: false,
|
|
144
167
|
};
|
|
145
168
|
|
|
146
169
|
Modal.propTypes = {
|
|
@@ -160,6 +183,7 @@ Modal.propTypes = {
|
|
|
160
183
|
validateBtnProps: PropTypes.object,
|
|
161
184
|
mainButtonType: PropTypes.string,
|
|
162
185
|
testId: PropTypes.string,
|
|
186
|
+
closesWithEscape: PropTypes.bool,
|
|
163
187
|
};
|
|
164
188
|
|
|
165
189
|
export default withClickOutside(Modal, '.ignore-click-outside-modal');
|
|
@@ -78,3 +78,15 @@ const TemplateConfirmationModal = () => {
|
|
|
78
78
|
};
|
|
79
79
|
export const ModalConfirmation = TemplateConfirmationModal.bind({});
|
|
80
80
|
Default.args = {};
|
|
81
|
+
|
|
82
|
+
const TemplateEscapeModal = () => {
|
|
83
|
+
const modalRef = React.createRef();
|
|
84
|
+
return (
|
|
85
|
+
<div style={{ paddingLeft: '50px' }}>
|
|
86
|
+
<Button onClick={() => modalRef.current.open()} label="Open modal" />
|
|
87
|
+
<Modal ref={modalRef} closesWithEscape title="My modal" />
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
export const ModalEscape = TemplateEscapeModal.bind({});
|
|
92
|
+
Default.args = {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
3
|
import '@testing-library/jest-dom/extend-expect';
|
|
4
4
|
import { act } from 'react-dom/test-utils';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
@@ -56,7 +56,7 @@ it('is hidden after clicking cancel', () => {
|
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
it('is hidden after clicking
|
|
59
|
+
it('is hidden after clicking validate', () => {
|
|
60
60
|
const modalRef = React.createRef();
|
|
61
61
|
const validateCb = jest.fn();
|
|
62
62
|
render(
|
|
@@ -72,3 +72,19 @@ it('is hidden after clicking cancel', () => {
|
|
|
72
72
|
userEvent.click(validate);
|
|
73
73
|
expect(validateCb.mock.calls.length).toBe(1);
|
|
74
74
|
});
|
|
75
|
+
|
|
76
|
+
it('is closing after escaping if it is set to be closed with it', () => {
|
|
77
|
+
const modalRef = React.createRef();
|
|
78
|
+
const closeCb = jest.fn();
|
|
79
|
+
render(
|
|
80
|
+
<Modal ref={modalRef} closesWithEscape closeCb={closeCb}>
|
|
81
|
+
content
|
|
82
|
+
</Modal>
|
|
83
|
+
);
|
|
84
|
+
act(() => {
|
|
85
|
+
modalRef.current.open();
|
|
86
|
+
});
|
|
87
|
+
expect(closeCb).not.toHaveBeenCalled();
|
|
88
|
+
fireEvent.keyDown(document, { keyCode: 27 });
|
|
89
|
+
expect(closeCb).toHaveBeenCalled();
|
|
90
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.426 1.66H4.661a3 3 0 0 0-3 3v14.766a3 3 0 0 0 3 3H12.7v-8.095H10v-3.1h2.7V8.93a3.76 3.76 0 0 1 3.37-4.113 3.823 3.823 0 0 1 .642-.009 18.532 18.532 0 0 1 2.413.124v2.779H17.46c-1.3 0-1.53.607-1.53 1.516v2h3.075l-.4 3.1h-2.676v8.1h3.5a3 3 0 0 0 3-3V4.66a3 3 0 0 0-3.003-3Z" fill-rule="evenodd"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.426 1.66H4.661a3 3 0 0 0-3 3v14.766a3 3 0 0 0 3 3h14.765a3 3 0 0 0 3-3V4.66a3 3 0 0 0-3-3ZM7.8 19.281H4.721V9.409H7.8ZM6.26 8.072h-.012a1.778 1.778 0 0 1-1.761-1.793v-.006a1.786 1.786 0 1 1 1.772 1.8Zm9.961 11.21v-4.8c0-1.144-.028-2.62-1.6-2.62-1.6 0-1.834 1.255-1.834 2.537v4.88H9.726v-9.87h2.935v1.349h.032a3.225 3.225 0 0 1 2.9-1.586c3.115 0 3.68 2.04 3.68 4.7l.007 5.41Z" fill-rule="evenodd"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.066 5.136a8.972 8.972 0 0 1-2.61.715 4.552 4.552 0 0 0 2-2.511 9.083 9.083 0 0 1-2.884 1.1 4.545 4.545 0 0 0-7.741 4.142 12.9 12.9 0 0 1-9.357-4.744A4.544 4.544 0 0 0 3.879 9.9a4.542 4.542 0 0 1-2.058-.567v.057a4.542 4.542 0 0 0 3.642 4.453 4.519 4.519 0 0 1-1.2.159 4.441 4.441 0 0 1-.853-.08 4.549 4.549 0 0 0 4.241 3.153 9.112 9.112 0 0 1-5.639 1.944 9.559 9.559 0 0 1-1.082-.062A12.88 12.88 0 0 0 7.892 21 12.832 12.832 0 0 0 20.814 8.254v-.179c0-.2 0-.393-.014-.588a9.2 9.2 0 0 0 2.267-2.348Z"/></svg>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
html
|
|
2
|
-
font-size
|
|
3
|
-
width
|
|
4
|
-
height
|
|
5
|
-
-moz-text-size-adjust
|
|
6
|
-
-webkit-text-size-adjust
|
|
7
|
-
-ms-text-size-adjust
|
|
2
|
+
font-size 62.5%
|
|
3
|
+
width 100%
|
|
4
|
+
height 100%
|
|
5
|
+
-moz-text-size-adjust 100%
|
|
6
|
+
-webkit-text-size-adjust 100%
|
|
7
|
+
-ms-text-size-adjust 100%
|
|
8
8
|
|
|
9
9
|
body
|
|
10
10
|
width 100%
|