@lemonadejs/calendar 3.2.1 → 3.3.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.
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,32 +530,77 @@ if (! Modal && typeof (require) === 'function') {
510
530
  self.rangeValues = null;
511
531
  }
512
532
 
513
- const setValue = function(reset) {
514
- if (reset) {
515
- self.value = '';
516
- self.input.value = '';
517
- destroyRange();
533
+ const renderValue = function() {
534
+ let value = null;
535
+ if (self.range) {
536
+ if (Array.isArray(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
+ }
518
546
  } 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
- }
547
+ value = getDate();
548
+ if (self.numeric) {
549
+ value = dateToNum(value);
550
+ }
551
+ }
552
+ return value;
553
+ }
554
+
555
+ const updateValue = function(v) {
556
+ if (self.range) {
557
+ if (v) {
558
+ if (! Array.isArray(v)) {
559
+ v = v.split(',');
527
560
  }
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
- }
561
+ self.rangeValues = v;
562
+
563
+ if (v[0] && typeof(v[0]) === 'string' && v[0].indexOf('-')) {
564
+ self.rangeValues[0] = dateToNum(v[0]);
565
+ }
566
+ if (v[1] && typeof(v[1]) === 'string' && v[1].indexOf('-')) {
567
+ self.rangeValues[1] = dateToNum(v[1]);
536
568
  }
569
+
570
+ v = v[0];
537
571
  }
538
572
  }
573
+
574
+ let d;
575
+ if (v) {
576
+ v = isNumber(v) ? numToDate(v, true) : v;
577
+ d = new Date(v);
578
+ }
579
+ // if no date is defined
580
+ if (! isValidDate(d)) {
581
+ d = new Date();
582
+ }
583
+ // Update my index
584
+ self.cursor = {
585
+ y: d.getFullYear(),
586
+ m: d.getMonth(),
587
+ d: d.getDate(),
588
+ };
589
+ // Update the internal calendar date
590
+ setDate(d);
591
+ }
592
+
593
+ const applyValue = function(reset) {
594
+ if (reset) {
595
+ self.value = '';
596
+ destroyRange();
597
+ } else {
598
+ // Set the internal value
599
+ self.value = renderValue();
600
+ }
601
+ if (self.input) {
602
+ self.input.value = self.value;
603
+ }
539
604
  }
540
605
 
541
606
  /**
@@ -546,19 +611,24 @@ if (! Modal && typeof (require) === 'function') {
546
611
  self.select = function(e, item) {
547
612
  // Update cursor generic
548
613
  let value = setCursor(item);
549
- // Update range
550
- setRange(item);
551
614
  // Based where was the click
552
- if (! (self.view === 'days' && ! item.grey)) {
615
+ if (self.view !== 'days') {
553
616
  // Update the internal date
554
617
  setDate(value);
555
- }
556
- // Go back to the view of days
557
- if (self.view !== 'days') {
618
+ // Back to the days
558
619
  self.view = 'days';
559
620
  }
560
621
  }
561
622
 
623
+ self.selectRange = function(e, item) {
624
+ if (self.view === 'days' && self.range === true) {
625
+ // Update cursor generic
626
+ setCursor(item);
627
+ // Update range
628
+ setRange(item);
629
+ }
630
+ }
631
+
562
632
  /**
563
633
  * Next handler
564
634
  * @param {object?} e mouse event
@@ -598,6 +668,12 @@ if (! Modal && typeof (require) === 'function') {
598
668
  if (! (self.input && e.target.getAttribute('readonly') === null)) {
599
669
  self.content.focus();
600
670
  }
671
+
672
+ // Update the internal date values
673
+ updateValue(self.value);
674
+ // Populate components
675
+ self.hours = views.hours();
676
+ self.minutes = views.minutes();
601
677
  }
602
678
  }
603
679
 
@@ -608,16 +684,18 @@ if (! Modal && typeof (require) === 'function') {
608
684
  if (self.modal && self.modal.closed === false) {
609
685
  // Close modal
610
686
  self.modal.closed = true;
687
+ // Cancel range events
688
+ destroyRange();
611
689
  }
612
690
  }
613
691
 
614
692
  self.reset = function() {
615
- setValue(true);
693
+ applyValue(true);
616
694
  self.close();
617
695
  }
618
696
 
619
697
  self.update = function() {
620
- setValue();
698
+ applyValue();
621
699
  self.close();
622
700
  }
623
701
 
@@ -636,10 +714,20 @@ if (! Modal && typeof (require) === 'function') {
636
714
  * @returns {string}
637
715
  */
638
716
  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);
717
+ return self.value;
718
+ }
719
+
720
+ self.setValue = function(v) {
721
+ // Destroy range
722
+ destroyRange();
723
+ // Update the internal controllers
724
+ updateValue(v);
725
+ // Update value
726
+ self.value = v;
727
+ // Update input
728
+ if (self.input) {
729
+ self.input.value = self.value;
730
+ }
643
731
  }
644
732
 
645
733
  self.onchange = function(prop) {
@@ -649,11 +737,10 @@ if (! Modal && typeof (require) === 'function') {
649
737
  self.options = views[self.view].call(self, date);
650
738
  }
651
739
  } else if (prop === 'value') {
652
- // TODO: onchange only when the component value really changes
653
- if (typeof(onchange) === 'function') {
740
+ if (typeof (onchange) === 'function') {
654
741
  onchange(self, self.value);
655
742
  }
656
- if (typeof(self.onupdate) === 'function') {
743
+ if (typeof (self.onupdate) === 'function') {
657
744
  self.onupdate(self, self.value);
658
745
  }
659
746
  } else if (prop === 'options') {
@@ -662,27 +749,12 @@ if (! Modal && typeof (require) === 'function') {
662
749
  }
663
750
 
664
751
  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
- };
752
+ // Update the internal date values
753
+ updateValue(self.value);
679
754
  // Populate components
680
755
  self.hours = views.hours();
681
756
  self.minutes = views.minutes();
682
757
 
683
- // Update the internal calendar date
684
- setDate(d);
685
-
686
758
  if (self.type !== "inline") {
687
759
  // Create modal instance
688
760
  self.modal = {
@@ -728,6 +800,7 @@ if (! Modal && typeof (require) === 'function') {
728
800
  // Current view
729
801
  let view = self.view;
730
802
  // Select
803
+ self.selectRange(e, self.options[self.cursor.index]);
731
804
  self.select(e, self.options[self.cursor.index]);
732
805
  // If is range do something different
733
806
  if (view === 'days' && ! self.range) {
@@ -772,8 +845,8 @@ if (! Modal && typeof (require) === 'function') {
772
845
  });
773
846
  }
774
847
 
775
- return `<div class="lm-calendar">
776
- <div class="lm-calendar-options">
848
+ return `<div class="lm-calendar" :value="self.value">
849
+ <div class="lm-calendar-options">
777
850
  <button onclick="self.reset">Reset</button>
778
851
  <button onclick="self.update">Done</button>
779
852
  </div>
@@ -781,16 +854,16 @@ if (! Modal && typeof (require) === 'function') {
781
854
  <div class="lm-calendar-header">
782
855
  <div>
783
856
  <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>
857
+ <div class="lm-calendar-navigation"><button type="button" class="material-icons lm-ripple" onclick="self.prev" tabindex="0">arrow_drop_up</button> <button type="button" class="material-icons lm-ripple" onclick="self.next" tabindex="0">arrow_drop_down</button></div>
785
858
  </div>
786
859
  <div class="lm-calendar-weekdays" :loop="self.weekdays"><div>{{self.title}}</div></div>
787
860
  </div>
788
861
  <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>
862
+ <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" onmousedown="self.parent.selectRange">{{self.title}}</div>
790
863
  </div>
791
864
  <div class="lm-calendar-footer">
792
865
  <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>
866
+ <div><input type="button" value="Update" onclick="self.update" class="lm-ripple"></div>
794
867
  </div>
795
868
  </div>
796
869
  </div>`
package/dist/style.css CHANGED
@@ -1,3 +1,13 @@
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
+ position: relative;
9
+ }
10
+
1
11
  .lm-calendar .lm-modal {
2
12
  min-width: initial;
3
13
  min-height: initial;
@@ -10,7 +20,7 @@
10
20
  .lm-modal > div > .lm-calendar-options {
11
21
  display: flex;
12
22
  justify-content: space-between;
13
- border-bottom: 1px solid #ddd;
23
+ border-bottom: 1px solid var(--lm-border-color, #ccc);
14
24
  }
15
25
 
16
26
  .lm-modal > div > .lm-calendar-options button {
@@ -43,22 +53,22 @@
43
53
  }
44
54
 
45
55
  .lm-calendar-header .lm-calendar-labels > button {
46
- font-size: 1.2em;
56
+ font-size: 1.3em;
47
57
  border: 0;
48
- padding: 2px;
49
- margin: 2px;
50
- background-color: #fff;
58
+ padding: 4px;
59
+ background-color: transparent;
51
60
  }
52
61
 
53
62
  .lm-calendar-navigation button {
54
63
  cursor: pointer;
55
- padding: 5px;
64
+ padding: 8px;
56
65
  border: 0;
57
66
  border-radius: 24px;
58
67
  }
59
68
 
60
69
  .lm-calendar-navigation i:hover {
61
- background-color: #eee;
70
+ background-color: var(--lm-background-color-hover, #ebebeb);
71
+ color: #000;
62
72
  }
63
73
 
64
74
  .lm-calendar-weekdays {
@@ -107,6 +117,7 @@
107
117
  .lm-calendar-container[data-view="months"] .lm-calendar-content {
108
118
  grid-template-columns: repeat(4, 1fr);
109
119
  }
120
+
110
121
  .lm-calendar-container[data-view="years"] .lm-calendar-content {
111
122
  grid-template-columns: repeat(4, 1fr);
112
123
  }
@@ -132,6 +143,7 @@
132
143
  .lm-calendar-content > div[data-selected="true"] {
133
144
  font-weight: bold;
134
145
  background-color: #eee;
146
+ color: #000;
135
147
  }
136
148
 
137
149
  .lm-calendar-content:focus > div[data-selected="true"] {
@@ -141,6 +153,7 @@
141
153
 
142
154
  .lm-calendar-content > div:hover {
143
155
  background-color: #eee;
156
+ color: #000;
144
157
  }
145
158
 
146
159
  .lm-calendar-content > div[data-range="true"] {
@@ -149,7 +162,8 @@
149
162
 
150
163
  .lm-calendar-content > div[data-start="true"],
151
164
  .lm-calendar-content > div[data-end="true"] {
152
- background-color: #78D350;
165
+ background-color: var(--lm-main-color, #2196f3);
166
+ color: initial;
153
167
  }
154
168
 
155
169
  .lm-calendar-content > div[data-range="true"]::before {
@@ -159,7 +173,7 @@
159
173
  right: 0;
160
174
  top: 8px;
161
175
  bottom: 8px;
162
- background-color: #78D35050;
176
+ background-color: var(--lm-main-color-alpha, #2196f3);
163
177
  }
164
178
 
165
179
  .lm-calendar-content > div[data-start="true"]::before {
@@ -179,7 +193,7 @@
179
193
  margin: 0 10px 0 10px;
180
194
  padding: 8px 0 8px 0;
181
195
  line-height: 34px;
182
- border-top: 1px solid #eee;
196
+ border-top: 1px solid var(--lm-border-color, #ccc);
183
197
  }
184
198
 
185
199
  .lm-calendar-footer select {
@@ -191,20 +205,16 @@
191
205
  margin: 2px;
192
206
  border-radius: 32px;
193
207
  font-size: 1.1em;
208
+ width: initial;
194
209
  }
195
210
 
196
211
  .lm-calendar-footer select:focus {
197
212
  background-color: #eee;
198
213
  }
199
214
 
200
- .lm-calendar-footer select:hover {
201
- background-color: #eee;
202
- }
203
-
204
215
  .lm-calendar-footer input {
205
216
  border: transparent;
206
217
  padding: 8px;
207
- background-color: #eee;
208
218
  width: 100%;
209
219
  cursor: pointer;
210
220
  }
@@ -212,20 +222,40 @@
212
222
  .lm-calendar-input {
213
223
  padding-right: 24px !important;
214
224
  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;
225
+ 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
226
  }
217
227
 
218
- .ripple {
228
+ .lm-ripple {
219
229
  background-position: center;
220
230
  transition: background 0.8s;
221
231
  }
222
232
 
223
- .ripple:hover {
224
- background: #E0E0E0 radial-gradient(circle, transparent 1%, #E0E0E0 1%) center/15000%;
233
+ .lm-ripple:hover {
234
+ background: var(--lm-background-color-hover, #ebebeb) radial-gradient(circle, transparent 1%, var(--lm-background-color-hover, #ebebeb) 1%) center/15000%;
225
235
  }
226
236
 
227
- .ripple:active {
228
- background-color: #E0E0E0;
237
+ .lm-ripple:active {
238
+ background-color: var(--lm-background-color-active, #e8e8e8);
229
239
  background-size: 100%;
230
240
  transition: background 0s;
231
- }
241
+ }
242
+
243
+ .lm-dark-mode .lm-calendar-weekdays {
244
+ color: #aaa;
245
+ }
246
+
247
+ .lm-dark-mode .lm-calendar-labels > button {
248
+ background-color: initial;
249
+ }
250
+
251
+ .lm-dark-mode .lm-calendar-content:focus > div[data-selected="true"] {
252
+ outline-color: white;
253
+ }
254
+
255
+ .lm-dark-mode .lm-calendar-content > div[data-grey="true"] {
256
+ color: var(--lm-font-grayout, #777);
257
+ }
258
+
259
+ .lm-dark-mode .lm-calendar-footer select:focus {
260
+ background-color: #3a3a45;
261
+ }
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.2",
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.1"
23
23
  }