@lemonadejs/calendar 3.2.1 → 3.3.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
@@ -84,5 +84,5 @@ The LemonadeJS [Reactive JavaScript Calendar](https://lemonadejs.net) is release
84
84
 
85
85
  ## Other Tools
86
86
 
87
- - [jSuites JavaScript Calendar](https://jsuites.net/docs/javascript-calendar)
88
- - [Jspreadsheet](https://jspreadsheet.com/)
87
+ - [jSuites Plugins - JavaScript Calendar](https://jsuites.net/docs/javascript-calendar)
88
+ - [Jspreadsheet - JavaScript Spreadsheet](https://jspreadsheet.com/)
package/dist/index.js CHANGED
@@ -78,6 +78,13 @@ if (! Modal && typeof (require) === 'function') {
78
78
  }
79
79
  }
80
80
 
81
+ const isNumber = function (num) {
82
+ if (typeof(num) === 'string') {
83
+ num = num.trim();
84
+ }
85
+ return !isNaN(num) && num !== null && num !== '';
86
+ }
87
+
81
88
  const arrayToStringDate = function(arr) {
82
89
  return [arr[0],Two(arr[1]),Two(arr[2])].join('-');
83
90
  }
@@ -162,15 +169,16 @@ if (! Modal && typeof (require) === 'function') {
162
169
  if (data && data[d]) {
163
170
  item.data = data[d];
164
171
  }
165
- // Select cursor
166
- if (this.cursor.y === year && this.cursor.m === month && this.cursor.d === day) {
167
- // Select item
168
- item.selected = true;
169
- // Cursor
170
- this.cursor.index = result.length - 1;
171
- }
172
172
  }
173
-
173
+ // Month
174
+ let m = tmp.getMonth();
175
+ // Select cursor
176
+ if (this.cursor.y === year && this.cursor.m === m && this.cursor.d === day) {
177
+ // Select item
178
+ item.selected = true;
179
+ // Cursor
180
+ this.cursor.index = result.length - 1;
181
+ }
174
182
  // Select range
175
183
  if (this.range && this.rangeValues) {
176
184
  // Mark the start and end points
@@ -315,6 +323,13 @@ if (! Modal && typeof (require) === 'function') {
315
323
  }
316
324
  }
317
325
 
326
+ const getDate = function() {
327
+ let v = [ self.cursor.y, self.cursor.m, self.cursor.d ];
328
+ let d = new Date(Date.UTC(...v));
329
+ // Update the headers of the calendar
330
+ return d.toISOString().substring(0, 10);
331
+ }
332
+
318
333
  /**
319
334
  * Set the internal cursor
320
335
  * @param {object} s
@@ -341,6 +356,11 @@ if (! Modal && typeof (require) === 'function') {
341
356
  // New cursor
342
357
  self.cursor.index = self.options.indexOf(s);
343
358
  }
359
+
360
+ if (typeof (self.onupdate) === 'function') {
361
+ self.onupdate(self, renderValue());
362
+ }
363
+
344
364
  return d;
345
365
  }
346
366
 
@@ -456,11 +476,11 @@ if (! Modal && typeof (require) === 'function') {
456
476
  */
457
477
  const setRange = function(s) {
458
478
  if (self.view === 'days' && self.range) {
459
- let d = self.getValue();
479
+ let d = getDate();
460
480
  // Date to number
461
481
  let number = dateToNum(d);
462
482
  // Start a new range
463
- if (self.rangeValues && (self.rangeValues[0] > number || self.rangeValues[1])) {
483
+ if (self.rangeValues && (self.rangeValues[0] >= number || self.rangeValues[1])) {
464
484
  destroyRange();
465
485
  }
466
486
  // Range
@@ -491,7 +511,7 @@ if (! Modal && typeof (require) === 'function') {
491
511
  // Item number
492
512
  let v = self.options[i].number;
493
513
  // Update property condition
494
- self.options[i].range = v > self.rangeValues[0] && v <= number;
514
+ self.options[i].range = v >= self.rangeValues[0] && v <= number;
495
515
  }
496
516
  }
497
517
  }
@@ -510,31 +530,58 @@ if (! Modal && typeof (require) === 'function') {
510
530
  self.rangeValues = null;
511
531
  }
512
532
 
513
- const setValue = function(reset) {
533
+ const renderValue = function() {
534
+ let value = null;
535
+ if (self.range) {
536
+ if (self.rangeValues) {
537
+ if (self.numeric) {
538
+ value = self.rangeValues;
539
+ } else {
540
+ value = [
541
+ numToDate(self.rangeValues[0], true),
542
+ numToDate(self.rangeValues[1], true)
543
+ ];
544
+ }
545
+ }
546
+ } else {
547
+ value = getDate();
548
+ if (self.numeric) {
549
+ value = dateToNum(value);
550
+ }
551
+ }
552
+ return value;
553
+ }
554
+
555
+ const updateValue = function(v) {
556
+ let d;
557
+ if (v) {
558
+ v = isNumber(v) ? numToDate(v, true) : v;
559
+ d = new Date(v);
560
+ }
561
+ // if no date is defined
562
+ if (! isValidDate(d)) {
563
+ d = new Date();
564
+ }
565
+ // Update my index
566
+ self.cursor = {
567
+ y: d.getFullYear(),
568
+ m: d.getMonth(),
569
+ d: d.getDate(),
570
+ };
571
+ // Update the internal calendar date
572
+ setDate(d);
573
+ }
574
+
575
+ const applyValue = function(reset) {
514
576
  if (reset) {
515
577
  self.value = '';
516
- self.input.value = '';
517
578
  destroyRange();
518
579
  } else {
519
- if (self.range) {
520
- self.value = self.rangeValues[0];
521
- if (self.input) {
522
- if (self.numeric) {
523
- self.input.value = self.rangeValues;
524
- } else {
525
- self.input.value = [numToDate(self.rangeValues[0], true), numToDate(self.rangeValues[1], true)];
526
- }
527
- }
528
- } else {
529
- self.value = self.getValue();
530
- if (self.input) {
531
- if (self.numeric) {
532
- self.input.value = dateToNum(self.value);
533
- } else {
534
- self.input.value = self.value;
535
- }
536
- }
537
- }
580
+ // Set the internal value
581
+ self.value = renderValue();
582
+ }
583
+ if (self.input) {
584
+ self.input.value = self.value;
538
585
  }
539
586
  }
540
587
 
@@ -549,12 +596,10 @@ if (! Modal && typeof (require) === 'function') {
549
596
  // Update range
550
597
  setRange(item);
551
598
  // Based where was the click
552
- if (! (self.view === 'days' && ! item.grey)) {
599
+ if (self.view !== 'days') {
553
600
  // Update the internal date
554
601
  setDate(value);
555
- }
556
- // Go back to the view of days
557
- if (self.view !== 'days') {
602
+ // Change back to right view
558
603
  self.view = 'days';
559
604
  }
560
605
  }
@@ -564,7 +609,7 @@ if (! Modal && typeof (require) === 'function') {
564
609
  * @param {object?} e mouse event
565
610
  */
566
611
  self.next = function(e) {
567
- if (! e || e.type === 'click') {
612
+ if (! e || e.type === 'mousedown') {
568
613
  // Icon click
569
614
  move(1);
570
615
  } else {
@@ -578,7 +623,7 @@ if (! Modal && typeof (require) === 'function') {
578
623
  * @param {object?} e mouse event
579
624
  */
580
625
  self.prev = function(e) {
581
- if (! e || e.type === 'click') {
626
+ if (! e || e.type === 'mousedown') {
582
627
  // Icon click
583
628
  move(-1);
584
629
  } else {
@@ -612,12 +657,12 @@ if (! Modal && typeof (require) === 'function') {
612
657
  }
613
658
 
614
659
  self.reset = function() {
615
- setValue(true);
660
+ applyValue(true);
616
661
  self.close();
617
662
  }
618
663
 
619
664
  self.update = function() {
620
- setValue();
665
+ applyValue();
621
666
  self.close();
622
667
  }
623
668
 
@@ -636,10 +681,20 @@ if (! Modal && typeof (require) === 'function') {
636
681
  * @returns {string}
637
682
  */
638
683
  self.getValue = function() {
639
- let v = [ self.cursor.y, self.cursor.m, self.cursor.d ];
640
- let d = new Date(Date.UTC(...v));
641
- // Update the headers of the calendar
642
- return d.toISOString().substring(0,10);
684
+ return self.value;
685
+ }
686
+
687
+ self.setValue = function(v) {
688
+ // Destroy range
689
+ destroyRange();
690
+ // Update the internal controllers
691
+ updateValue(v);
692
+ // Update value
693
+ self.value = v;
694
+ // Update input
695
+ if (self.input) {
696
+ self.input.value = self.value;
697
+ }
643
698
  }
644
699
 
645
700
  self.onchange = function(prop) {
@@ -649,11 +704,10 @@ if (! Modal && typeof (require) === 'function') {
649
704
  self.options = views[self.view].call(self, date);
650
705
  }
651
706
  } else if (prop === 'value') {
652
- // TODO: onchange only when the component value really changes
653
- if (typeof(onchange) === 'function') {
707
+ if (typeof (onchange) === 'function') {
654
708
  onchange(self, self.value);
655
709
  }
656
- if (typeof(self.onupdate) === 'function') {
710
+ if (typeof (self.onupdate) === 'function') {
657
711
  self.onupdate(self, self.value);
658
712
  }
659
713
  } else if (prop === 'options') {
@@ -662,27 +716,12 @@ if (! Modal && typeof (require) === 'function') {
662
716
  }
663
717
 
664
718
  self.onload = function() {
665
- let d;
666
- if (self.value) {
667
- d = new Date(self.value);
668
- }
669
- // if no date is defined
670
- if (! isValidDate(d)) {
671
- d = new Date();
672
- }
673
- // Update my index
674
- self.cursor = {
675
- y: d.getFullYear(),
676
- m: d.getMonth(),
677
- d: d.getDate(),
678
- };
719
+ // Update the internal date values
720
+ updateValue(self.value);
679
721
  // Populate components
680
722
  self.hours = views.hours();
681
723
  self.minutes = views.minutes();
682
724
 
683
- // Update the internal calendar date
684
- setDate(d);
685
-
686
725
  if (self.type !== "inline") {
687
726
  // Create modal instance
688
727
  self.modal = {
@@ -772,7 +811,7 @@ if (! Modal && typeof (require) === 'function') {
772
811
  });
773
812
  }
774
813
 
775
- return `<div class="lm-calendar">
814
+ return `<div class="lm-calendar" :value="self.value">
776
815
  <div class="lm-calendar-options">
777
816
  <button onclick="self.reset">Reset</button>
778
817
  <button onclick="self.update">Done</button>
@@ -780,17 +819,17 @@ if (! Modal && typeof (require) === 'function') {
780
819
  <div class="lm-calendar-container" data-view="{{self.view}}">
781
820
  <div class="lm-calendar-header">
782
821
  <div>
783
- <div class="lm-calendar-labels"><button onclick="self.setView" data-view="months">{{self.month}}</button> <button onclick="self.setView" data-view="years">{{self.year}}</button></div>
784
- <div class="lm-calendar-navigation"><button type="button" class="material-icons ripple" onclick="self.prev" tabindex="0">arrow_drop_up</button> <button type="button" class="material-icons ripple" onclick="self.next" tabindex="0">arrow_drop_down</button></div>
822
+ <div class="lm-calendar-labels"><button onmousedown="self.setView" data-view="months">{{self.month}}</button> <button onmousedown="self.setView" data-view="years">{{self.year}}</button></div>
823
+ <div class="lm-calendar-navigation"><button type="button" class="material-icons lm-ripple" onmousedown="self.prev" tabindex="0">arrow_drop_up</button> <button type="button" class="material-icons lm-ripple" onmousedown="self.next" tabindex="0">arrow_drop_down</button></div>
785
824
  </div>
786
825
  <div class="lm-calendar-weekdays" :loop="self.weekdays"><div>{{self.title}}</div></div>
787
826
  </div>
788
827
  <div class="lm-calendar-content" :loop="self.options" tabindex="0" :ref="self.content">
789
- <div data-start="{{self.start}}" data-end="{{self.end}}" data-range="{{self.range}}" data-event="{{self.data}}" data-grey="{{self.grey}}" data-bold="{{self.bold}}" data-selected="{{self.selected}}" onclick="self.parent.select">{{self.title}}</div>
828
+ <div data-start="{{self.start}}" data-end="{{self.end}}" data-range="{{self.range}}" data-event="{{self.data}}" data-grey="{{self.grey}}" data-bold="{{self.bold}}" data-selected="{{self.selected}}" onmousedown="self.parent.select">{{self.title}}</div>
790
829
  </div>
791
830
  <div class="lm-calendar-footer">
792
831
  <div><select :loop="self.hours"><option value="{{self.value}}">{{self.title}}</option></select>:<select :loop="self.minutes"><option value="{{self.value}}">{{self.title}}</option></select></div>
793
- <div><input type="button" value="Update" onclick="self.update" class="ripple"></div>
832
+ <div><input type="button" value="Update" onclick="self.update" class="lm-ripple"></div>
794
833
  </div>
795
834
  </div>
796
835
  </div>`
package/dist/style.css CHANGED
@@ -1,3 +1,12 @@
1
+ .lm-calendar {
2
+ user-select: none;
3
+ -moz-user-select: none;
4
+ -webkit-user-drag: none;
5
+ -webkit-touch-callout: none;
6
+ -webkit-user-select: none;
7
+ -ms-user-select: none;
8
+ }
9
+
1
10
  .lm-calendar .lm-modal {
2
11
  min-width: initial;
3
12
  min-height: initial;
@@ -43,16 +52,15 @@
43
52
  }
44
53
 
45
54
  .lm-calendar-header .lm-calendar-labels > button {
46
- font-size: 1.2em;
55
+ font-size: 1.3em;
47
56
  border: 0;
48
- padding: 2px;
49
- margin: 2px;
57
+ padding: 4px;
50
58
  background-color: #fff;
51
59
  }
52
60
 
53
61
  .lm-calendar-navigation button {
54
62
  cursor: pointer;
55
- padding: 5px;
63
+ padding: 8px;
56
64
  border: 0;
57
65
  border-radius: 24px;
58
66
  }
@@ -150,6 +158,7 @@
150
158
  .lm-calendar-content > div[data-start="true"],
151
159
  .lm-calendar-content > div[data-end="true"] {
152
160
  background-color: #78D350;
161
+ color: initial;
153
162
  }
154
163
 
155
164
  .lm-calendar-content > div[data-range="true"]::before {
@@ -191,20 +200,16 @@
191
200
  margin: 2px;
192
201
  border-radius: 32px;
193
202
  font-size: 1.1em;
203
+ width: initial;
194
204
  }
195
205
 
196
206
  .lm-calendar-footer select:focus {
197
207
  background-color: #eee;
198
208
  }
199
209
 
200
- .lm-calendar-footer select:hover {
201
- background-color: #eee;
202
- }
203
-
204
210
  .lm-calendar-footer input {
205
211
  border: transparent;
206
212
  padding: 8px;
207
- background-color: #eee;
208
213
  width: 100%;
209
214
  cursor: pointer;
210
215
  }
@@ -212,20 +217,57 @@
212
217
  .lm-calendar-input {
213
218
  padding-right: 24px !important;
214
219
  box-sizing: border-box;
215
- background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z"/></svg>') top 50% right 0 no-repeat, content-box;
220
+ background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z" fill="gray" /></svg>') top 50% right 1px no-repeat;
216
221
  }
217
222
 
218
- .ripple {
223
+ .lm-ripple {
219
224
  background-position: center;
220
225
  transition: background 0.8s;
221
226
  }
222
227
 
223
- .ripple:hover {
228
+ .lm-ripple:hover {
224
229
  background: #E0E0E0 radial-gradient(circle, transparent 1%, #E0E0E0 1%) center/15000%;
225
230
  }
226
231
 
227
- .ripple:active {
232
+ .lm-ripple:active {
228
233
  background-color: #E0E0E0;
229
234
  background-size: 100%;
230
235
  transition: background 0s;
231
- }
236
+ }
237
+
238
+ .lm-dark-mode .lm-ripple:hover {
239
+ background-color: #888;
240
+ }
241
+
242
+ .lm-dark-mode .lm-ripple:active {
243
+ background-color: #888;
244
+ }
245
+
246
+ .lm-dark-mode .lm-calendar-weekdays {
247
+ color: #aaa;
248
+ }
249
+
250
+ .lm-dark-mode .lm-calendar-labels > button {
251
+ background-color: initial;
252
+ }
253
+
254
+ .lm-dark-mode .lm-calendar-content > div[data-selected="true"] {
255
+ background-color: #444;
256
+ }
257
+
258
+ .lm-dark-mode .lm-calendar-content:focus > div[data-selected="true"] {
259
+ outline-color: white;
260
+ }
261
+
262
+ .lm-dark-mode .lm-calendar-content > div[data-grey="true"] {
263
+ color: #777;
264
+ }
265
+
266
+ .lm-dark-mode .lm-calendar-content > div:hover {
267
+ color: white;
268
+ background-color: #333;
269
+ }
270
+
271
+ .lm-dark-mode .lm-calendar-footer select:focus {
272
+ background-color: #3a3a45;
273
+ }
package/package.json CHANGED
@@ -14,10 +14,10 @@
14
14
  "javascript plugins"
15
15
  ],
16
16
  "dependencies": {
17
- "lemonadejs": "^4.1.1",
18
- "@lemonadejs/modal": "^2.7.2"
17
+ "lemonadejs": "^4.2.1",
18
+ "@lemonadejs/modal": "^2.8.0"
19
19
  },
20
20
  "main": "dist/index.js",
21
21
  "types": "dist/index.d.ts",
22
- "version": "3.2.1"
22
+ "version": "3.3.0"
23
23
  }