@lemonadejs/calendar 3.0.1 → 3.0.3

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
@@ -60,6 +60,7 @@ You can configure things such as calendar starting date, calendar events, and cu
60
60
  | range | array | Defines a restricted range of selectable dates within the calendar. Example: ['2023-06-20', '2023-06-25']. |
61
61
  | closed | boolean | Control when the calendar modal is open or closed. |
62
62
  | time | boolean | Enables time selection into the calendar. |
63
+ | type | string | |
63
64
 
64
65
  ### Calendar Events
65
66
 
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Official Type definitions for LemonadeJS plugins
3
+ * https://lemonadejs.net
4
+ * Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5
+ */
6
+
7
+ interface Calendar {
8
+ (): any
9
+ [key: string]: any
10
+ }
11
+
12
+ interface options {
13
+ range?: boolean;
14
+ type?: 'default' | 'inline';
15
+ value?: number | string;
16
+ numeric?: boolean;
17
+ input?: HTMLElement;
18
+ }
19
+
20
+ interface instance {
21
+
22
+ }
23
+
24
+ export declare function Calendar(el: HTMLElement, options?: options): instance;
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ if (! lemonade && typeof (require) === 'function') {
10
10
  }
11
11
 
12
12
  if (! Modal && typeof (require) === 'function') {
13
- var Modal = require('../../modal/dist/index');
13
+ var Modal = require('@lemonadejs/modal');
14
14
  }
15
15
 
16
16
  ; (function (global, factory) {
@@ -30,6 +30,10 @@ if (! Modal && typeof (require) === 'function') {
30
30
  const excelLeapYearBug = Date.UTC(1900, 1, 29);
31
31
  const millisecondsPerDay = 86400000;
32
32
 
33
+ function isValidDate(d) {
34
+ return d instanceof Date && !isNaN(d.getTime());
35
+ }
36
+
33
37
  /**
34
38
  * Date to number
35
39
  */
@@ -46,7 +50,11 @@ if (! Modal && typeof (require) === 'function') {
46
50
  return jsDateInMilliseconds / millisecondsPerDay;
47
51
  }
48
52
 
49
- const numToDate = function (excelSerialNumber) {
53
+ const numToDate = function (excelSerialNumber, asString) {
54
+ if (! excelSerialNumber) {
55
+ return '';
56
+ }
57
+
50
58
  let jsDateInMilliseconds = excelInitialTime + excelSerialNumber * millisecondsPerDay;
51
59
  if (jsDateInMilliseconds >= excelLeapYearBug) {
52
60
  jsDateInMilliseconds -= millisecondsPerDay;
@@ -54,7 +62,7 @@ if (! Modal && typeof (require) === 'function') {
54
62
 
55
63
  const d = new Date(jsDateInMilliseconds);
56
64
 
57
- return [
65
+ let arr = [
58
66
  d.getUTCFullYear(),
59
67
  Two(d.getUTCMonth() + 1),
60
68
  Two(d.getUTCDate()),
@@ -62,6 +70,16 @@ if (! Modal && typeof (require) === 'function') {
62
70
  Two(d.getUTCMinutes()),
63
71
  Two(d.getUTCSeconds()),
64
72
  ];
73
+
74
+ if (asString) {
75
+ return arrayToStringDate(arr);
76
+ } else {
77
+ return arr;
78
+ }
79
+ }
80
+
81
+ const arrayToStringDate = function(arr) {
82
+ return [arr[0],Two(arr[1]),Two(arr[2])].join('-');
65
83
  }
66
84
 
67
85
  /**
@@ -154,19 +172,19 @@ if (! Modal && typeof (require) === 'function') {
154
172
  }
155
173
 
156
174
  // Select range
157
- if (this.type === 'range' && this.range) {
175
+ if (this.range && this.rangeValues) {
158
176
  // Mark the start and end points
159
- if (this.range[0] === item.number) {
177
+ if (this.rangeValues[0] === item.number) {
160
178
  item.range = true;
161
179
  item.start = true;
162
180
  }
163
- if (this.range[1] === item.number) {
181
+ if (this.rangeValues[1] === item.number) {
164
182
  item.range = true;
165
183
  item.end = true;
166
184
  }
167
185
  // Re-recreate teh range
168
- if (this.range[0] && this.range[1]) {
169
- if (this.range[0] <= item.number && this.range[1] >= item.number) {
186
+ if (this.rangeValues[0] && this.rangeValues[1]) {
187
+ if (this.rangeValues[0] <= item.number && this.rangeValues[1] >= item.number) {
170
188
  item.range = true;
171
189
  }
172
190
  }
@@ -245,7 +263,7 @@ if (! Modal && typeof (require) === 'function') {
245
263
  // Transform in two digits
246
264
  const Two = function(value) {
247
265
  value = '' + value;
248
- if (value.length == 1) {
266
+ if (value.length === 1) {
249
267
  value = '0' + value;
250
268
  }
251
269
  return value;
@@ -264,7 +282,7 @@ if (! Modal && typeof (require) === 'function') {
264
282
  let date = new Date();
265
283
 
266
284
  // Range
267
- self.range = null;
285
+ self.rangeValues = null;
268
286
 
269
287
  /**
270
288
  * Update the internal date
@@ -424,7 +442,7 @@ if (! Modal && typeof (require) === 'function') {
424
442
  if (self.modal) {
425
443
  if (!(e.relatedTarget && self.modal.el.contains(e.relatedTarget))) {
426
444
  if (self.modal.closed === false) {
427
- // self.modal.closed = true
445
+ self.modal.closed = true
428
446
  }
429
447
  }
430
448
  }
@@ -435,23 +453,23 @@ if (! Modal && typeof (require) === 'function') {
435
453
  * @param s
436
454
  */
437
455
  const setRange = function(s) {
438
- if (self.view === 'days' && self.type === 'range') {
456
+ if (self.view === 'days' && self.range) {
439
457
  let d = self.getValue();
440
458
  // Date to number
441
459
  let number = dateToNum(d);
442
460
  // Start a new range
443
- if (self.range && (self.range[0] > number || self.range[1])) {
461
+ if (self.rangeValues && (self.rangeValues[0] > number || self.rangeValues[1])) {
444
462
  destroyRange();
445
463
  }
446
464
  // Range
447
465
  s.range = true;
448
466
  // Update range
449
- if (! self.range) {
467
+ if (! self.rangeValues) {
450
468
  s.start = true;
451
- self.range = [number, null];
469
+ self.rangeValues = [number, null];
452
470
  } else {
453
471
  s.end = true;
454
- self.range[1] = number;
472
+ self.rangeValues[1] = number;
455
473
  }
456
474
  }
457
475
  }
@@ -461,9 +479,9 @@ if (! Modal && typeof (require) === 'function') {
461
479
  * @param s
462
480
  */
463
481
  const updateRange = function(s) {
464
- if (self.type === 'range' && self.view === 'days' && self.range) {
482
+ if (self.range && self.view === 'days' && self.rangeValues) {
465
483
  // Creating a range
466
- if (self.range[0] && ! self.range[1]) {
484
+ if (self.rangeValues[0] && ! self.rangeValues[1]) {
467
485
  let number = s.number;
468
486
  if (number) {
469
487
  // Update range properties
@@ -471,7 +489,7 @@ if (! Modal && typeof (require) === 'function') {
471
489
  // Item number
472
490
  let v = self.options[i].number;
473
491
  // Update property condition
474
- self.options[i].range = v >= self.range[0] && v <= number;
492
+ self.options[i].range = v >= self.rangeValues[0] && v <= number;
475
493
  }
476
494
  }
477
495
  }
@@ -487,14 +505,43 @@ if (! Modal && typeof (require) === 'function') {
487
505
  self.options[i].start = false;
488
506
  self.options[i].end = false;
489
507
  }
490
- self.range = null;
508
+ self.rangeValues = null;
509
+ }
510
+
511
+ const setValue = function(reset) {
512
+ if (reset) {
513
+ self.value = '';
514
+ self.input.value = '';
515
+ destroyRange();
516
+ } else {
517
+ if (self.range) {
518
+ self.value = self.rangeValues[0];
519
+ if (self.input) {
520
+ if (self.numeric) {
521
+ self.input.value = self.rangeValues;
522
+ } else {
523
+ self.input.value = [numToDate(self.rangeValues[0], true), numToDate(self.rangeValues[1], true)];
524
+ }
525
+ }
526
+ } else {
527
+ self.value = self.getValue();
528
+ if (self.input) {
529
+ if (self.numeric) {
530
+ self.input.value = dateToNum(self.value);
531
+ } else {
532
+ self.input.value = self.value;
533
+ }
534
+ }
535
+ }
536
+ }
491
537
  }
492
538
 
493
539
  /**
494
540
  * Select an item with the enter or mouse
541
+ * @param {object} e - mouse event
495
542
  * @param {object} item - selected cell
496
543
  */
497
- self.select = function(item) {
544
+ self.select = function(e, item) {
498
545
  // Update cursor generic
499
546
  let value = setCursor(item);
500
547
  // Update range
@@ -512,10 +559,10 @@ if (! Modal && typeof (require) === 'function') {
512
559
 
513
560
  /**
514
561
  * Next handler
515
- * @param {object} e mouse event
562
+ * @param {object?} e mouse event
516
563
  */
517
564
  self.next = function(e) {
518
- if (! e) {
565
+ if (! e || e.type === 'click') {
519
566
  // Icon click
520
567
  move(1);
521
568
  } else {
@@ -526,10 +573,10 @@ if (! Modal && typeof (require) === 'function') {
526
573
 
527
574
  /**
528
575
  * Next handler
529
- * @param {object} e mouse event
576
+ * @param {object?} e mouse event
530
577
  */
531
578
  self.prev = function(e) {
532
- if (! e) {
579
+ if (! e || e.type === 'click') {
533
580
  // Icon click
534
581
  move(-1);
535
582
  } else {
@@ -541,11 +588,14 @@ if (! Modal && typeof (require) === 'function') {
541
588
  /**
542
589
  * Open the modal
543
590
  */
544
- self.open = function() {
545
- if (self.modal) {
591
+ self.open = function(e) {
592
+ if (self.modal && self.modal.closed) {
593
+ // Open modal
546
594
  self.modal.closed = false;
547
- // Set the focus
548
- self.content.focus();
595
+ // Set the focus on the content to use the keyboard
596
+ if (! (self.input && e.target.getAttribute('readonly') === null)) {
597
+ self.content.focus();
598
+ }
549
599
  }
550
600
  }
551
601
 
@@ -554,10 +604,31 @@ if (! Modal && typeof (require) === 'function') {
554
604
  */
555
605
  self.close = function() {
556
606
  if (self.modal && self.modal.closed === false) {
607
+ // Close modal
557
608
  self.modal.closed = true;
558
609
  }
559
610
  }
560
611
 
612
+ self.reset = function() {
613
+ setValue(true);
614
+ self.close();
615
+ }
616
+
617
+ self.update = function() {
618
+ setValue();
619
+ self.close();
620
+ }
621
+
622
+ /**
623
+ * Change the view
624
+ */
625
+ self.setView = function() {
626
+ let v = this.getAttribute('data-view');
627
+ if (v) {
628
+ self.view = v;
629
+ }
630
+ }
631
+
561
632
  /**
562
633
  * Get value from cursor
563
634
  * @returns {string}
@@ -588,7 +659,9 @@ if (! Modal && typeof (require) === 'function') {
588
659
  let d;
589
660
  if (self.value) {
590
661
  d = new Date(self.value);
591
- } else {
662
+ }
663
+ // if no date is defined
664
+ if (! isValidDate(d)) {
592
665
  d = new Date();
593
666
  }
594
667
  // Update my index
@@ -609,7 +682,7 @@ if (! Modal && typeof (require) === 'function') {
609
682
  self.modal = {
610
683
  width: 300,
611
684
  closed: true,
612
- 'auto-close': true,
685
+ focus: false,
613
686
  };
614
687
  // Generate modal
615
688
  Modal(self.el, self.modal);
@@ -621,11 +694,18 @@ if (! Modal && typeof (require) === 'function') {
621
694
  self.input.addEventListener('focus', self.open);
622
695
  self.input.addEventListener('click', self.open);
623
696
  self.input.addEventListener('blur', blur);
697
+
698
+ // Retrieve the value
699
+ if (self.value) {
700
+ self.input.value = self.value;
701
+ } else if (self.input.value) {
702
+ self.value = self.input.value;
703
+ }
624
704
  }
625
705
 
626
706
  /**
627
707
  * Handler keyboard
628
- * @param e
708
+ * @param {object} e - event
629
709
  */
630
710
  self.content.addEventListener('keydown', function(e){
631
711
  if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
@@ -633,18 +713,20 @@ if (! Modal && typeof (require) === 'function') {
633
713
  } else if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
634
714
  self.next(e);
635
715
  } else if (e.key === 'Enter') {
716
+ // Current view
717
+ let view = self.view;
636
718
  // Select
637
- self.select(self.options[self.cursor.index]);
638
- // If is range do something different
639
- if (self.type !== 'range') {
640
- self.value = self.getValue();
641
- self.close();
719
+ self.select(e, self.options[self.cursor.index]);
720
+ // If is range do something diferent
721
+ if (view === 'days' && ! self.range) {
722
+ self.update();
642
723
  }
643
724
  }
644
725
  });
645
726
 
646
727
  /**
647
728
  * Mouse wheel handler
729
+ * @param {object} e - mouse event
648
730
  */
649
731
  self.content.addEventListener('wheel', function(e){
650
732
  if (e.deltaY < 0) {
@@ -656,34 +738,41 @@ if (! Modal && typeof (require) === 'function') {
656
738
 
657
739
  /**
658
740
  * Range handler
659
- * @param e
741
+ * @param {object} e - mouse event
660
742
  */
661
743
  self.content.addEventListener('mouseover', function(e){
662
744
  if (e.target.lemon) {
663
745
  updateRange(e.target.lemon.self);
664
746
  }
665
747
  });
748
+
749
+ // Create event for focus out
750
+ self.el.addEventListener("focusout", (e) => {
751
+ if (e.relatedTarget !== self.input && ! self.el.contains(e.relatedTarget)) {
752
+ self.close();
753
+ }
754
+ });
666
755
  }
667
756
 
668
757
  return `<div class="lm-calendar">
669
758
  <div class="lm-calendar-options">
670
- <button onclick="self.value = ''; self.close();">Reset</button>
671
- <button onclick="self.value = self.getValue(); self.close();">Done</button>
759
+ <button onclick="self.reset">Reset</button>
760
+ <button onclick="self.update">Done</button>
672
761
  </div>
673
762
  <div class="lm-calendar-container" data-view="{{self.view}}">
674
763
  <div class="lm-calendar-header">
675
764
  <div>
676
- <div class="lm-calendar-labels"><div onclick="self.view = 'months'">{{self.month}}</div> <div onclick="self.view = 'years'">{{self.year}}</div></div>
677
- <div class="lm-calendar-navigation"><i class="material-icons ripple" onclick="self.prev()" tabindex="0">arrow_drop_up</i> <i class="material-icons ripple" onclick="self.next()" tabindex="0">arrow_drop_down</i></div>
765
+ <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>
766
+ <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>
678
767
  </div>
679
768
  <div class="lm-calendar-weekdays" :loop="self.weekdays"><div>{{self.title}}</div></div>
680
769
  </div>
681
770
  <div class="lm-calendar-content" :loop="self.options" tabindex="0" :ref="self.content">
682
- <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)">{{self.title}}</div>
771
+ <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>
683
772
  </div>
684
773
  <div class="lm-calendar-footer">
685
774
  <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>
686
- <div><input type="button" value="Update" onclick="self.value = self.getValue(); self.close();" class="ripple"></div>
775
+ <div><input type="button" value="Update" onclick="self.update" class="ripple"></div>
687
776
  </div>
688
777
  </div>
689
778
  </div>`
package/dist/react.js ADDED
@@ -0,0 +1,31 @@
1
+ // @ts-nocheck
2
+ import React, { useRef, useEffect } from "react";
3
+ import Component from './index';
4
+
5
+ import "./style.css";
6
+ import "@lemonadejs/modal/dist/style.css"
7
+
8
+ // @ts-ignore
9
+ const Calendar = React.forwardRef((props, mainReference) => {
10
+ // Dom element
11
+ const Ref = useRef(null);
12
+
13
+ // Get the properties for the spreadsheet
14
+ let options = { ...props };
15
+
16
+ useEffect(() => {
17
+ // @ts-ignore
18
+ if (! Ref.current.innerHTML) {
19
+ mainReference.current = Component(Ref.current, options);
20
+ }
21
+ }, []);
22
+
23
+ let prop = {
24
+ ref: Ref,
25
+ style: { height: '100%', width: '100%' }
26
+ };
27
+
28
+ return React.createElement("div", prop);
29
+ })
30
+
31
+ export default Calendar;
package/dist/style.css CHANGED
@@ -19,6 +19,7 @@
19
19
  text-transform: uppercase;
20
20
  cursor: pointer;
21
21
  padding: 15px;
22
+ font-weight: bold;
22
23
  }
23
24
 
24
25
  .lm-calendar-header {
@@ -35,23 +36,24 @@
35
36
  }
36
37
 
37
38
  .lm-calendar-header .lm-calendar-labels {
38
- font-size: 1.4em;
39
39
  display: flex;
40
40
  flex: 1;
41
41
  cursor: pointer;
42
42
  padding-left: 5px;
43
43
  }
44
44
 
45
- .lm-calendar-header .lm-calendar-labels > div {
45
+ .lm-calendar-header .lm-calendar-labels > button {
46
+ font-size: 1.2em;
47
+ border: 0;
48
+ padding: 2px;
46
49
  margin: 2px;
50
+ background-color: #fff;
47
51
  }
48
52
 
49
- .lm-calendar-navigation {
53
+ .lm-calendar-navigation button {
50
54
  cursor: pointer;
51
- }
52
-
53
- .lm-calendar-navigation i {
54
55
  padding: 5px;
56
+ border: 0;
55
57
  border-radius: 24px;
56
58
  }
57
59
 
package/dist/vue.js ADDED
@@ -0,0 +1,32 @@
1
+ import { h, getCurrentInstance } from 'vue';
2
+ import component from "./index";
3
+
4
+ import "./style.css";
5
+ import "@lemonadejs/modal/dist/style.css"
6
+
7
+ export const Calendar = {
8
+ inheritAttrs: false,
9
+ mounted() {
10
+ const { attrs } = getCurrentInstance();
11
+
12
+ let options = {
13
+ ...attrs
14
+ };
15
+
16
+ this.el = this.$refs.container;
17
+
18
+ this.current = component(this.$refs.container, options);
19
+ },
20
+ setup() {
21
+ let containerProps = {
22
+ ref: 'container',
23
+ style: {
24
+ width: '100%',
25
+ height: '100%',
26
+ }
27
+ };
28
+ return () => h('div', containerProps);
29
+ }
30
+ }
31
+
32
+ export default Calendar;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lemonadejs/calendar",
3
3
  "title": "LemonadeJS calendar",
4
- "description": "LemonadeJS Calendar Component.",
4
+ "description": "LemonadeJS reactive JavaScript calendar plugin",
5
5
  "author": {
6
6
  "name": "Contact <contact@lemonadejs.net>",
7
7
  "url": "https://lemonadejs.net"
@@ -13,12 +13,11 @@
13
13
  "library",
14
14
  "javascript plugins"
15
15
  ],
16
- "scripts": {
17
- "build": "webpack --config webpack.config.js"
18
- },
19
16
  "dependencies": {
20
- "lemonadejs": "^3.3.2"
17
+ "lemonadejs": "^4.0.1",
18
+ "@lemonadejs/modal": "^2.3.3"
21
19
  },
22
20
  "main": "dist/index.js",
23
- "version": "3.0.1"
21
+ "types": "dist/index.d.ts",
22
+ "version": "3.0.3"
24
23
  }
package/dist/index.html DELETED
@@ -1,11 +0,0 @@
1
- <html>
2
- <script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
3
- <script src="./index.js"></script>
4
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/calendar/dist/style.min.css" />
5
- <div id='root'></div>
6
-
7
- <script>
8
- console.log(Calendar)
9
- Calendar(document.getElementById('root'), {});
10
- </script>
11
- </html>