@lemonadejs/modal 2.0.4 → 2.1.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Javascript Modal
1
+ # LemonadeJS Modal
2
2
 
3
3
  [Official website and documentation is here](https://lemonadejs.net/components/modal)
4
4
 
@@ -26,7 +26,7 @@ $ npm install @lemonadejs/modal
26
26
 
27
27
  ### CDN
28
28
 
29
- To use data grid via a CDN, include the following script tags in your HTML file:
29
+ To use modal via a CDN, include the following script tags in your HTML file:
30
30
 
31
31
  ```html
32
32
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
@@ -93,7 +93,9 @@ You can configure things such as position, size, and functionalities.
93
93
  | draggable? | boolean | Determines if the modal can be dragged |
94
94
  | resizable? | boolean | Determines if the modal can be resized |
95
95
  | closed? | boolean | Controls the open and close state of the modal |
96
- | closable? | boolean | Disables the ability to close the modal |
96
+ | closable? | boolean | Enables the close button |
97
+ | minimized? | boolean | Controls the minimized state of the modal |
98
+ | minimizable? | boolean | Enables the minimize button |
97
99
  | center? | boolean | Enables rendering the modal in the center of its parent container |
98
100
  | url? | string | The URL from which to fetch and render content |
99
101
 
package/dist/index.d.ts CHANGED
@@ -12,6 +12,8 @@ interface Modal {
12
12
  interface options {
13
13
  closed?: boolean;
14
14
  closable?: boolean;
15
+ minimized?: boolean;
16
+ minimizable?: boolean;
15
17
  resizable?: boolean;
16
18
  draggable?: boolean;
17
19
  center?: boolean;
@@ -25,6 +27,8 @@ interface options {
25
27
  interface instance {
26
28
  closed: boolean;
27
29
  closable: boolean;
30
+ minimized: boolean;
31
+ minimizable: boolean;
28
32
  resizable: boolean;
29
33
  draggable: boolean;
30
34
  center: boolean;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  if (! lemonade && typeof(require) === 'function') {
2
- var lemonade = require('lemonadejs');
2
+ var lemonade = require('../../../dist/lemonade');
3
3
  }
4
4
 
5
5
  ;(function (global, factory) {
@@ -7,182 +7,112 @@ if (! lemonade && typeof(require) === 'function') {
7
7
  typeof define === 'function' && define.amd ? define(factory) :
8
8
  global.Modal = factory();
9
9
  }(this, (function () {
10
+
11
+ // State of the resize and move modal
10
12
  let state = {};
11
- let editorAction;
13
+ // Internal controls of the action of resize and move
14
+ let controls = {};
12
15
  // Width of the border
13
16
  let cornerSize = 10;
14
17
 
15
- // Events
16
- const mouseDown = function(e) {
17
- let item = e.target.closest('.lm-modal');
18
- if (item !== null) {
19
- // Keep the tracking information
20
- let x;
21
- let y;
22
- let rect = item.getBoundingClientRect();
23
-
24
- if (e.changedTouches && e.changedTouches[0]) {
25
- x = e.changedTouches[0].clientX;
26
- y = e.changedTouches[0].clientY;
27
- } else {
28
- x = e.clientX;
29
- y = e.clientY;
30
- }
31
-
32
- if (item.self.closable === true && rect.width - (x - rect.left) < 40 && (y - rect.top) < 40) {
33
- item.self.closed = true;
34
- } else {
35
- editorAction = {
36
- e: item,
37
- x: x,
38
- y: y,
39
- w: rect.width,
40
- h: rect.height,
41
- d: item.style.cursor,
42
- resizing: !!item.style.cursor,
43
- actioned: false,
44
- s: item.self,
45
- }
46
-
47
- // Make sure width and height styling is OK
48
- if (!e.target.style.width) {
49
- item.style.width = rect.width + 'px';
50
- }
18
+ // Get the coordinates of the action
19
+ const getCoords = function(e) {
20
+ let x;
21
+ let y;
51
22
 
52
- if (!item.style.height) {
53
- item.style.height = rect.height + 'px';
54
- }
23
+ if (e.changedTouches && e.changedTouches[0]) {
24
+ x = e.changedTouches[0].clientX;
25
+ y = e.changedTouches[0].clientY;
26
+ } else {
27
+ x = e.clientX;
28
+ y = e.clientY;
29
+ }
55
30
 
56
- // Remove any selection from the page
57
- let s = window.getSelection();
58
- if (s.rangeCount) {
59
- for (let i = 0; i < s.rangeCount; i++) {
60
- s.removeRange(s.getRangeAt(i));
61
- }
62
- }
31
+ return [x,y];
32
+ }
63
33
 
64
- e.preventDefault();
65
- e.stopPropagation();
66
- }
34
+ // Get the button status
35
+ const getButton = function(e) {
36
+ e = e || window.event;
37
+ if (e.buttons) {
38
+ return e.buttons;
39
+ } else if (e.button) {
40
+ return e.button;
41
+ } else {
42
+ return e.which;
67
43
  }
68
44
  }
69
45
 
46
+ // Finalize any potential action
70
47
  const mouseUp = function(e) {
71
- if (editorAction && editorAction.e) {
72
- // Element
73
- if (editorAction.resizing) {
74
- let w = parseInt(editorAction.e.style.width);
75
- let h = parseInt(editorAction.e.style.height)
76
- editorAction.s.width = w;
77
- editorAction.s.height = h;
78
- } else {
79
- let t = parseInt(editorAction.e.style.top);
80
- let l = parseInt(editorAction.e.style.left)
81
- editorAction.s.top = t;
82
- editorAction.s.left = l;
83
- }
84
-
85
- if (typeof(editorAction.e.refresh) == 'function') {
86
- state.actioned = true;
87
- editorAction.e.refresh.call(editorAction.s);
88
- }
89
-
90
- editorAction.e.style.cursor = '';
48
+ // Finalize all actions
49
+ if (typeof(controls.action) === 'function') {
50
+ controls.action();
91
51
  }
92
-
93
- // Reset
52
+ // Reset controls
53
+ controls = {};
54
+ // Reset state controls
94
55
  state = {
95
56
  x: null,
96
57
  y: null,
97
58
  }
98
-
99
- editorAction = false;
100
59
  }
101
60
 
102
61
  const mouseMove = function(e) {
103
- if (editorAction) {
104
- let x = e.clientX || e.pageX;
105
- let y = e.clientY || e.pageY;
106
-
107
- // Action on going
108
- if (! editorAction.resizing && editorAction.s.draggable === true) {
109
- if (state && state.x == null && state.y == null) {
110
- state.x = x;
111
- state.y = y;
112
- }
113
-
114
- let dx = x - state.x;
115
- let dy = y - state.y;
116
- let top = editorAction.e.offsetTop + dy;
117
- let left = editorAction.e.offsetLeft + dx;
118
-
119
- // Update position
120
- editorAction.top = top
121
- editorAction.left = left
122
- editorAction.e.style.top = top + 'px';
123
- editorAction.e.style.left = left + 'px';
124
- editorAction.e.style.cursor = "move";
125
-
62
+ if (! getButton(e)) {
63
+ return false;
64
+ }
65
+ // Get mouse coordinates
66
+ let [x,y] = getCoords(e);
126
67
 
68
+ // Move modal
69
+ if (controls.type === 'move') {
70
+ if (state && state.x == null && state.y == null) {
127
71
  state.x = x;
128
72
  state.y = y;
129
- state.top = top
130
- state.left = left
131
-
132
- // Update element
133
- if (typeof(editorAction.e.refresh) == 'function') {
134
- state.actioned = true;
135
- editorAction.e.refresh.call(editorAction.s, 'position', top, left);
136
- }
137
- } else {
138
- let width = null;
139
- let height = null;
140
- let newHeight = null;
141
-
142
- if (editorAction.d === 'e-resize' || editorAction.d === 'ne-resize' || editorAction.d === 'se-resize') {
143
- // Update width
144
- width = editorAction.w + (x - editorAction.x);
145
- editorAction.e.style.width = width + 'px';
146
-
147
- // Update Height
148
- if (e.shiftKey) {
149
- newHeight = (x - editorAction.x) * (editorAction.h / editorAction.w);
150
- height = editorAction.h + newHeight;
151
- editorAction.e.style.height = height + 'px';
152
- } else {
153
- newHeight = false;
154
- }
155
- }
156
-
157
- if (! newHeight) {
158
- if (editorAction.d === 's-resize' || editorAction.d === 'se-resize' || editorAction.d === 'sw-resize') {
159
- height = editorAction.h + (y - editorAction.y);
160
- editorAction.e.style.height = height + 'px';
161
- }
162
- }
73
+ }
163
74
 
164
- // Update element
165
- if (typeof(editorAction.e.refresh) == 'function') {
166
- state.actioned = true;
167
- editorAction.e.refresh.call(editorAction.s, 'dimensions', width, height);
75
+ let dx = x - state.x;
76
+ let dy = y - state.y;
77
+ let top = controls.e.offsetTop + dy;
78
+ let left = controls.e.offsetLeft + dx;
79
+
80
+ // Update position
81
+ controls.top = top
82
+ controls.left = left
83
+ controls.e.style.top = top + 'px';
84
+ controls.e.style.left = left + 'px';
85
+ controls.e.style.cursor = "move";
86
+
87
+
88
+ state.x = x;
89
+ state.y = y;
90
+ state.top = top
91
+ state.left = left
92
+ } else if (controls.type === 'resize') {
93
+ let width = null;
94
+ let height = null;
95
+ let newHeight = null;
96
+
97
+ if (controls.d === 'e-resize' || controls.d === 'ne-resize' || controls.d === 'se-resize') {
98
+ // Update width
99
+ width = controls.w + (x - controls.x);
100
+ controls.e.style.width = width + 'px';
101
+
102
+ // Update Height
103
+ if (e.shiftKey) {
104
+ newHeight = (x - controls.x) * (controls.h / controls.w);
105
+ height = controls.h + newHeight;
106
+ controls.e.style.height = height + 'px';
107
+ } else {
108
+ newHeight = false;
168
109
  }
169
110
  }
170
- } else {
171
- let item = e.target.closest('.lm-modal');
172
- if (item !== null) {
173
- if (item.self && item.self.resizable === true) {
174
- let rect = item.getBoundingClientRect();
175
- if (rect.height - (e.clientY - rect.top) < cornerSize) {
176
- if (rect.width - (e.clientX - rect.left) < cornerSize) {
177
- item.style.cursor = 'se-resize';
178
- } else {
179
- item.style.cursor = 's-resize';
180
- }
181
- } else if (rect.width - (e.clientX - rect.left) < cornerSize) {
182
- item.style.cursor = 'e-resize';
183
- } else {
184
- item.style.cursor = '';
185
- }
111
+
112
+ if (! newHeight) {
113
+ if (controls.d === 's-resize' || controls.d === 'se-resize' || controls.d === 'sw-resize') {
114
+ height = controls.h + (y - controls.y);
115
+ controls.e.style.height = height + 'px';
186
116
  }
187
117
  }
188
118
  }
@@ -191,28 +121,18 @@ if (! lemonade && typeof(require) === 'function') {
191
121
  document.addEventListener('mouseup', mouseUp);
192
122
  document.addEventListener('mousemove', mouseMove);
193
123
 
194
- const Modal = function (template) {
195
- let self = this;
196
-
197
- // Default values
198
- if (typeof(self.title) === 'undefined') {
199
- self.title = '';
200
- }
201
- if (typeof(self.closed) === 'undefined') {
202
- self.closed = false;
203
- }
204
- if (typeof(self.closable) === 'undefined') {
205
- self.closable = false;
124
+ // Dispatcher
125
+ const Dispatch = function(type, option){
126
+ if (typeof this[type] === 'function') {
127
+ this[type](this, option)
206
128
  }
129
+ }
207
130
 
208
- // Dispatcher
209
- const Dispatch = (type, option) => {
210
- if (typeof self[type] === 'function') {
211
- self[type](self, option)
212
- }
213
- }
131
+ const Modal = function (template) {
132
+ let self = this;
214
133
 
215
- self.mousedown = mouseDown;
134
+ // Make sure keep the state as boolean
135
+ self.closed = !!self.closed;
216
136
 
217
137
  self.onload = function() {
218
138
  if (self.url) {
@@ -233,29 +153,115 @@ if (! lemonade && typeof(require) === 'function') {
233
153
  self.left = (window.innerWidth - self.width) / 2;
234
154
  }
235
155
 
236
- // Make sure the instance of the self is available via the DOM element
237
- self.el.self = self;
156
+ // Full screen
157
+ if (self.height > 260) {
158
+ self.el.classList.add('fullscreen');
159
+ }
238
160
 
239
- // Close
161
+ // Close and stop propagation
240
162
  document.addEventListener('keydown', (e) => {
241
163
  if (e.key === 'Escape' && self.closed === false) {
242
164
  self.closed = true;
165
+ e.preventDefault();
166
+ e.stopImmediatePropagation();
243
167
  }
244
168
  });
245
-
246
- // Full screen
247
- if (self.height > 260) {
248
- self.el.classList.add('fullscreen');
249
- }
250
169
  }
251
170
 
252
171
  self.onchange = function(property) {
253
172
  if (property === 'closed') {
254
- self.closed ? Dispatch('onclose') : Dispatch('onopen');
173
+ self.closed ? Dispatch.call(self,'onclose') : Dispatch.call(self,'onopen');
174
+ } else if (property === 'top' || property === 'left' || property === 'width' || property === 'height') {
175
+ self.el.style[property] = self[property] + 'px';
176
+ }
177
+ }
178
+
179
+ self.mousemove = function(e) {
180
+ if (getButton(e)) {
181
+ return;
182
+ }
183
+
184
+ // Root element of the component
185
+ let item = self.el;
186
+ // Get the position and dimensions
187
+ let rect = item.getBoundingClientRect();
188
+
189
+ controls = {
190
+ type: null,
191
+ e: item,
192
+ w: rect.width,
193
+ h: rect.height,
194
+ }
195
+
196
+ // When resizable
197
+ if (self.resizable === true) {
198
+ if (rect.height - (e.clientY - rect.top) < cornerSize) {
199
+ if (rect.width - (e.clientX - rect.left) < cornerSize) {
200
+ item.style.cursor = 'se-resize';
201
+ } else {
202
+ item.style.cursor = 's-resize';
203
+ }
204
+ } else if (rect.width - (e.clientX - rect.left) < cornerSize) {
205
+ item.style.cursor = 'e-resize';
206
+ } else {
207
+ item.style.cursor = '';
208
+ }
209
+
210
+ if (item.style.cursor) {
211
+ controls.type = 'resize';
212
+ controls.d = item.style.cursor;
213
+ } else {
214
+ controls.type = null;
215
+ controls.d = null;
216
+ }
217
+ }
218
+ }
219
+
220
+ self.mousedown = function(e) {
221
+ // Get mouse coordinates
222
+ let [x,y] = getCoords(e);
223
+ controls.x = x;
224
+ controls.y = y;
225
+ // Root element of the component
226
+ let item = self.el;
227
+ // Get the position and dimensions
228
+ let rect = item.getBoundingClientRect();
229
+ let corner = rect.width - (x - rect.left) < 40 && (y - rect.top) < 40;
230
+
231
+ if (self.closable === true && corner === true) {
232
+ self.closed = true;
233
+ } else if (self.minimizable === true && corner === true) {
234
+ self.minimized = ! item.lemon.self.minimized;
235
+ } else {
236
+ if (controls.type === 'resize') {
237
+ // This will be the callback when finalize the resize
238
+ controls.action = function() {
239
+ self.width = parseInt(item.style.width);
240
+ self.height = parseInt(item.style.height);
241
+ }
242
+ // Make sure the width and height is defined for the modal
243
+ if (!item.style.width) {
244
+ item.style.width = controls.w + 'px';
245
+ }
246
+ if (!item.style.height) {
247
+ item.style.height = controls.h + 'px';
248
+ }
249
+ } else {
250
+ // Modal is draggable by the title
251
+ if (self.draggable === true && self.title && y - rect.top < 40) {
252
+ // Action
253
+ controls.type = 'move';
254
+ // Callback
255
+ controls.action = function() {
256
+ self.top = parseInt(item.style.top);
257
+ self.left = parseInt(item.style.left);
258
+ }
259
+ }
260
+ }
255
261
  }
256
262
  }
257
263
 
258
- return `<div class="lm-modal" title="{{self.title}}" closed="{{self.closed}}" :closable="self.closable" style="width: {{self.width}}px; height: {{self.height}}px; top: {{self.top}}px; left: {{self.left}}px;" onmousedown="self.mousedown(e)" tabindex="-1">${template}</div>`
264
+ return `<div class="lm-modal" title="{{self.title}}" closed="{{self.closed}}" :closable="self.closable" :minimized="self.minimized" :minimizable="self.minimizable" :top="self.top" :left="self.left" :width="self.width" :height="self.height" onmousedown="self.mousedown(e)" onmousemove="self.mousemove(e)" tabindex="-1">${template}</div>`
259
265
  }
260
266
 
261
267
  lemonade.setComponents({ Modal: Modal });
package/dist/style.css CHANGED
@@ -10,6 +10,8 @@
10
10
  border: 1px solid #ccc;
11
11
  box-sizing: border-box;
12
12
  box-shadow: 0 0 4px 3px rgba(80,80,80,.1);
13
+ opacity: 1;
14
+ transition: opacity 0.5s ease;
13
15
  }
14
16
 
15
17
  @media only screen and (max-width : 800px) {
@@ -57,15 +59,27 @@
57
59
  line-height: 24px;
58
60
  }
59
61
 
62
+ .lm-modal::after {
63
+ font-family: 'Material Icons';
64
+ cursor: pointer;
65
+ }
66
+
60
67
  .lm-modal[closable="true"]::after {
61
68
  content: 'close';
62
- font-family: 'Material Icons';
63
69
  display: block;
64
70
  position: absolute;
65
71
  top: 10px;
66
72
  right: 10px;
67
73
  font-size: 24px;
68
- cursor: pointer;
74
+ }
75
+
76
+ .lm-modal[minimizable="true"]::after {
77
+ content: '\2500';
78
+ display: block;
79
+ position: absolute;
80
+ top: 10px;
81
+ right: 10px;
82
+ font-size: 24px;
69
83
  }
70
84
 
71
85
 
@@ -77,7 +91,26 @@
77
91
  display: none !important;
78
92
  }
79
93
 
94
+ .lm-modal[minimized="true"] {
95
+ bottom: 0;
96
+ min-height: 0px;
97
+ height: 45px !important;
98
+ }
99
+
100
+ .lm-modal[minimized="true"]::before {
101
+ height: 100%;
102
+ cursor: pointer;
103
+ }
104
+
105
+ .lm-modal[minimized="true"]::after {
106
+ content: '';
107
+ }
108
+
80
109
  @keyframes slide-bottom-in {
81
110
  0% { transform: translateY(100%); }
82
111
  100% { transform: translateY(0%); }
83
112
  }
113
+
114
+ .lm-modal.hide {
115
+ opacity: 0;
116
+ }
package/package.json CHANGED
@@ -13,8 +13,8 @@
13
13
  "modal js"
14
14
  ],
15
15
  "dependencies": {
16
- "lemonadejs": "^3.3.1"
16
+ "lemonadejs": "^3.3.2"
17
17
  },
18
18
  "main": "dist/index.js",
19
- "version": "2.0.4"
19
+ "version": "2.1.0"
20
20
  }
package/src/index.html ADDED
@@ -0,0 +1,20 @@
1
+ <script src="https://cdn.jsdelivr.net/npm/lemonadejs@3.3.1/dist/lemonade.min.js"></script>
2
+
3
+ <script type="text/javascript" src="../dist/index.js"></script>
4
+ <link rel="stylesheet" href="../dist/style.css" />
5
+
6
+ <div id="root">
7
+ <div>
8
+
9
+ </div>
10
+ </div>
11
+
12
+ <script>
13
+ const root = document.getElementById("root")
14
+
15
+ Modal(root, {
16
+ title: 'Nicolas Jesse',
17
+ minimizable: true,
18
+ height: 350,
19
+ })
20
+ </script>