@woosmap/ui 3.120.0 → 3.121.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@woosmap/ui",
3
- "version": "3.120.0",
3
+ "version": "3.121.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/WebGeoServices/ui.git"
@@ -6,6 +6,7 @@ import Animate, { AnimatePresence } from '../Animate/Animate';
6
6
  import Button from '../Button/Button';
7
7
  import withClickOutside from '../withClickOutside/withClickOutside';
8
8
  import { tr } from '../utils/locale';
9
+ import Icon from '../Icon/Icon';
9
10
 
10
11
  class Modal extends Component {
11
12
  constructor(props) {
@@ -13,6 +14,7 @@ class Modal extends Component {
13
14
  const { defaultIsOpen } = this.props;
14
15
  this.state = { open: defaultIsOpen, isLoading: false };
15
16
  this.modalRef = React.createRef();
17
+ this.clickOutsideRef = null;
16
18
  }
17
19
 
18
20
  componentDidMount() {
@@ -72,6 +74,11 @@ class Modal extends Component {
72
74
  }
73
75
  };
74
76
 
77
+ displayCloseButton = () => {
78
+ const { isFull, disableCloseOutside, displayCloseButtonOutside } = this.props;
79
+ return !isFull && !disableCloseOutside && displayCloseButtonOutside;
80
+ };
81
+
75
82
  renderFooter = () => {
76
83
  const { footer, labelValidate, errorLabel, validateCb, validateBtnProps, mainButtonType, testId } = this.props;
77
84
  const { isLoading } = this.state;
@@ -107,10 +114,19 @@ class Modal extends Component {
107
114
  return <div className="modal__footer">{footer}</div>;
108
115
  };
109
116
 
117
+ getRef = () => {
118
+ if (this.displayCloseButton()) {
119
+ this.clickOutsideRef = this.modalRef;
120
+ } else {
121
+ this.clickOutsideRef = null;
122
+ }
123
+ return this.modalRef;
124
+ };
125
+
110
126
  render() {
111
127
  const { open } = this.state;
112
128
 
113
- const { title, children, className, isFull, header, disableCloseOutside, testId } = this.props;
129
+ const { title, children, className, isFull, header, testId } = this.props;
114
130
  const tit = open && title;
115
131
  return ReactDOM.createPortal(
116
132
  <AnimatePresence>
@@ -122,19 +138,13 @@ class Modal extends Component {
122
138
  data-testid={testId}
123
139
  >
124
140
  <Animate className="modal__wrapper">
125
- <div ref={this.modalRef} className="modal__content">
126
- <div className="modal__header">
127
- {header || <h1 className="title">{tit}</h1>}
128
- {!disableCloseOutside && (
129
- <Button
130
- testId={`${testId}-close-button`}
131
- className="modal__close"
132
- icon="close"
133
- type="link-flex"
134
- onClick={this.close}
135
- />
136
- )}
141
+ {this.displayCloseButton() && (
142
+ <div className="modal__close--outside">
143
+ <Icon size={30} icon="close" />
137
144
  </div>
145
+ )}
146
+ <div ref={this.getRef()} className="modal__content">
147
+ <div className="modal__header">{header || <h1 className="title">{tit}</h1>}</div>
138
148
  <div className="modal__body">{children}</div>
139
149
  {this.renderFooter()}
140
150
  </div>
@@ -164,6 +174,7 @@ Modal.defaultProps = {
164
174
  mainButtonType: 'primary',
165
175
  testId: 'modal',
166
176
  closesWithEscape: false,
177
+ displayCloseButtonOutside: false,
167
178
  };
168
179
 
169
180
  Modal.propTypes = {
@@ -184,6 +195,7 @@ Modal.propTypes = {
184
195
  mainButtonType: PropTypes.string,
185
196
  testId: PropTypes.string,
186
197
  closesWithEscape: PropTypes.bool,
198
+ displayCloseButtonOutside: PropTypes.bool,
187
199
  };
188
200
 
189
201
  export default withClickOutside(Modal, '.ignore-click-outside-modal');
@@ -12,11 +12,13 @@ export default Story;
12
12
 
13
13
  const Template = () => {
14
14
  const modalRef = React.createRef();
15
+
15
16
  function open() {
16
17
  if (modalRef.current) {
17
18
  modalRef.current.open();
18
19
  }
19
20
  }
21
+
20
22
  function validate() {
21
23
  if (modalRef.current) {
22
24
  setTimeout(() => {
@@ -24,6 +26,7 @@ const Template = () => {
24
26
  }, 2000);
25
27
  }
26
28
  }
29
+
27
30
  return (
28
31
  <div style={{ paddingLeft: '50px' }}>
29
32
  <Button onClick={open} label="Open modal" />
@@ -84,9 +87,25 @@ const TemplateEscapeModal = () => {
84
87
  return (
85
88
  <div style={{ paddingLeft: '50px' }}>
86
89
  <Button onClick={() => modalRef.current.open()} label="Open modal" />
87
- <Modal ref={modalRef} closesWithEscape title="My modal" />
90
+ <Modal ref={modalRef} closesWithEscape title="My modal">
91
+ content
92
+ </Modal>
88
93
  </div>
89
94
  );
90
95
  };
91
96
  export const ModalEscape = TemplateEscapeModal.bind({});
92
97
  Default.args = {};
98
+
99
+ const TemplateClickOutsideModal = () => {
100
+ const modalRef = React.createRef();
101
+ return (
102
+ <div style={{ paddingLeft: '50px' }}>
103
+ <Button onClick={() => modalRef.current.open()} label="Open modal" />
104
+ <Modal ref={modalRef} displayCloseButtonOutside title="My modal">
105
+ content
106
+ </Modal>
107
+ </div>
108
+ );
109
+ };
110
+ export const ModalClickOutside = TemplateClickOutsideModal.bind({});
111
+ Default.args = {};
@@ -37,6 +37,14 @@
37
37
  overflow-y auto
38
38
  .modal--full &
39
39
  padding 0
40
+ &__close
41
+ &--outside
42
+ position fixed
43
+ top 2rem
44
+ right 2rem
45
+ cursor pointer
46
+ .icon
47
+ fill $light
40
48
  &__footer
41
49
  &__header
42
50
  padding 1.8rem 2.4rem
@@ -17,25 +17,6 @@ it('renders a Modal component ', () => {
17
17
  expect(modal).toHaveClass('modal');
18
18
  });
19
19
 
20
- it('is hidden after clicking close', () => {
21
- const modalRef = React.createRef();
22
- render(<Modal ref={modalRef}>content</Modal>);
23
- act(() => {
24
- modalRef.current.open();
25
- });
26
- const modal = screen.getByTestId('modal');
27
- expect(modal).toHaveClass('modal');
28
-
29
- const close = screen.getByTestId('modal-close-button');
30
- userEvent.click(close);
31
- try {
32
- screen.getByTestId('modal');
33
- expect('Modal displayed').toBeFalsy();
34
- } catch (e) {
35
- // nothink
36
- }
37
- });
38
-
39
20
  it('is hidden after clicking cancel', () => {
40
21
  const modalRef = React.createRef();
41
22
  render(
@@ -88,3 +69,22 @@ it('is closing after escaping if it is set to be closed with it', () => {
88
69
  fireEvent.keyDown(document, { keyCode: 27 });
89
70
  expect(closeCb).toHaveBeenCalled();
90
71
  });
72
+
73
+ it('is closing after click outside if it is set to bet closed with it', () => {
74
+ const modalRef = React.createRef();
75
+ const closeCb = jest.fn();
76
+ render(
77
+ <Modal ref={modalRef} displayCloseButtonOutside closeCb={closeCb}>
78
+ content
79
+ </Modal>
80
+ );
81
+ act(() => {
82
+ modalRef.current.open();
83
+ });
84
+ expect(closeCb).not.toHaveBeenCalled();
85
+ fireEvent.mouseDown(screen.getByText('content'));
86
+ fireEvent.mouseDown(screen.getByText('Validate'));
87
+ expect(closeCb).not.toHaveBeenCalled();
88
+ fireEvent.mouseDown(screen.queryByTestId('icon-close'));
89
+ expect(closeCb).toHaveBeenCalled();
90
+ });