kalendly 0.2.0 → 0.2.2
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 +192 -55
- package/dist/core/index.d.mts +2 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/index.d.mts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +229 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +229 -33
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +228 -32
- package/dist/index.umd.js.map +1 -1
- package/dist/styles/calendar.css +135 -27
- package/package.json +20 -34
package/dist/index.umd.js
CHANGED
|
@@ -438,6 +438,7 @@ var Kalendly = (() => {
|
|
|
438
438
|
};
|
|
439
439
|
|
|
440
440
|
// src/web-components/CalendarElement.ts
|
|
441
|
+
var isSameDay2 = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
441
442
|
var CalendarElement = class extends HTMLElement {
|
|
442
443
|
constructor() {
|
|
443
444
|
super(...arguments);
|
|
@@ -459,6 +460,13 @@ var Kalendly = (() => {
|
|
|
459
460
|
this._categoryColors = null;
|
|
460
461
|
this._renderEvent = null;
|
|
461
462
|
this._renderNoEvents = null;
|
|
463
|
+
// Selection state (availability mode — range)
|
|
464
|
+
this._rangeStart = null;
|
|
465
|
+
this._rangeEnd = null;
|
|
466
|
+
this._timeRangeDate = null;
|
|
467
|
+
this._timeRangeStart = null;
|
|
468
|
+
this._timeRangeEnd = null;
|
|
469
|
+
this._timeRangeComplete = false;
|
|
462
470
|
}
|
|
463
471
|
get events() {
|
|
464
472
|
return this._events;
|
|
@@ -487,6 +495,13 @@ var Kalendly = (() => {
|
|
|
487
495
|
this._renderNoEvents = val;
|
|
488
496
|
if (this.engine) this.render();
|
|
489
497
|
}
|
|
498
|
+
get loading() {
|
|
499
|
+
return this.hasAttribute("loading");
|
|
500
|
+
}
|
|
501
|
+
set loading(val) {
|
|
502
|
+
if (val) this.setAttribute("loading", "");
|
|
503
|
+
else this.removeAttribute("loading");
|
|
504
|
+
}
|
|
490
505
|
connectedCallback() {
|
|
491
506
|
this.classList.add("kalendly-calendar");
|
|
492
507
|
this.initEngine();
|
|
@@ -497,8 +512,20 @@ var Kalendly = (() => {
|
|
|
497
512
|
this.classList.remove("kalendly-calendar");
|
|
498
513
|
this.innerHTML = "";
|
|
499
514
|
}
|
|
500
|
-
attributeChangedCallback(
|
|
515
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
501
516
|
if (oldVal === newVal) return;
|
|
517
|
+
if (name === "loading") {
|
|
518
|
+
this.render();
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (name === "selectable" && newVal === null) {
|
|
522
|
+
this._rangeStart = null;
|
|
523
|
+
this._rangeEnd = null;
|
|
524
|
+
this._timeRangeDate = null;
|
|
525
|
+
this._timeRangeStart = null;
|
|
526
|
+
this._timeRangeEnd = null;
|
|
527
|
+
this._timeRangeComplete = false;
|
|
528
|
+
}
|
|
502
529
|
this.reinit();
|
|
503
530
|
}
|
|
504
531
|
get minYear() {
|
|
@@ -590,6 +617,8 @@ var Kalendly = (() => {
|
|
|
590
617
|
root.style.setProperty("--calendar-today-outline", t.todayOutline);
|
|
591
618
|
if (t.selectedBg)
|
|
592
619
|
root.style.setProperty("--calendar-selected-bg", t.selectedBg);
|
|
620
|
+
if (t.headerBg) root.style.setProperty("--calendar-header-bg", t.headerBg);
|
|
621
|
+
if (t.popupBg) root.style.setProperty("--calendar-popup-bg", t.popupBg);
|
|
593
622
|
if (t.eventIndicator)
|
|
594
623
|
root.style.setProperty("--calendar-event-indicator", t.eventIndicator);
|
|
595
624
|
}
|
|
@@ -600,6 +629,9 @@ var Kalendly = (() => {
|
|
|
600
629
|
const title = this.getAttribute("title");
|
|
601
630
|
const minYear = this.minYear;
|
|
602
631
|
const maxYear = this.maxYear;
|
|
632
|
+
const availabilityMode = this.getAttribute("availability-mode");
|
|
633
|
+
const selectable = this.hasAttribute("selectable");
|
|
634
|
+
const isLoading = this.loading;
|
|
603
635
|
const today = /* @__PURE__ */ new Date();
|
|
604
636
|
const todayMonth = today.getMonth();
|
|
605
637
|
const todayYear = today.getFullYear();
|
|
@@ -709,6 +741,37 @@ var Kalendly = (() => {
|
|
|
709
741
|
const defaultRenderNoEvents = () => '<div class="no-events-message">No events scheduled for this day.</div>';
|
|
710
742
|
const renderEvent = this._renderEvent || defaultRenderEvent;
|
|
711
743
|
const renderNoEvents = this._renderNoEvents || defaultRenderNoEvents;
|
|
744
|
+
const renderTimeGrid = (events, date) => {
|
|
745
|
+
const isHourBooked = (hour) => events.some((event) => {
|
|
746
|
+
if (!event.startTime || !event.endTime) return true;
|
|
747
|
+
const [startH] = event.startTime.split(":").map(Number);
|
|
748
|
+
const [endH] = event.endTime.split(":").map(Number);
|
|
749
|
+
return hour >= startH && hour < endH;
|
|
750
|
+
});
|
|
751
|
+
const slots = Array.from({ length: 24 }, (_, hour) => {
|
|
752
|
+
const startTime = `${String(hour).padStart(2, "0")}:00`;
|
|
753
|
+
const endTime = `${String(hour + 1).padStart(2, "0")}:00`;
|
|
754
|
+
const booked = isHourBooked(hour);
|
|
755
|
+
const inTimeRange = !booked && selectable && this._timeRangeStart !== null && this._timeRangeEnd !== null && isSameDay2(this._timeRangeDate, date) && startTime >= this._timeRangeStart && endTime <= this._timeRangeEnd;
|
|
756
|
+
const isRangeStart = inTimeRange && startTime === this._timeRangeStart;
|
|
757
|
+
const isRangeEnd = inTimeRange && endTime === this._timeRangeEnd;
|
|
758
|
+
const isInRange = inTimeRange && !isRangeStart && !isRangeEnd;
|
|
759
|
+
const slotClasses = [
|
|
760
|
+
"time-grid__slot",
|
|
761
|
+
booked ? "time-grid__slot--booked" : "time-grid__slot--free",
|
|
762
|
+
isRangeStart ? "time-grid__slot--range-start" : "",
|
|
763
|
+
isRangeEnd ? "time-grid__slot--range-end" : "",
|
|
764
|
+
isInRange ? "time-grid__slot--in-range" : ""
|
|
765
|
+
].filter(Boolean).join(" ");
|
|
766
|
+
const slotAttrs = !booked && selectable ? `data-action="select-slot" data-start-time="${startTime}" data-end-time="${endTime}" data-date="${date.toISOString()}"` : "";
|
|
767
|
+
return `
|
|
768
|
+
<div class="${slotClasses}" ${slotAttrs}>
|
|
769
|
+
<span class="time-grid__label">${startTime}</span>
|
|
770
|
+
<span class="time-grid__status">${booked ? "Booked" : "Available"}</span>
|
|
771
|
+
</div>`;
|
|
772
|
+
});
|
|
773
|
+
return `<div class="time-grid">${slots.join("")}</div>`;
|
|
774
|
+
};
|
|
712
775
|
const html = `
|
|
713
776
|
${title ? `
|
|
714
777
|
<div class="page--title">
|
|
@@ -798,30 +861,52 @@ var Kalendly = (() => {
|
|
|
798
861
|
</tr>
|
|
799
862
|
</thead>
|
|
800
863
|
<tbody data-calendar-body>
|
|
801
|
-
${
|
|
864
|
+
${isLoading ? Array.from(
|
|
865
|
+
{ length: 6 },
|
|
866
|
+
() => `<tr>${Array.from(
|
|
867
|
+
{ length: 7 },
|
|
868
|
+
() => `<td class="calendar--skeleton" aria-hidden="true"></td>`
|
|
869
|
+
).join("")}</tr>`
|
|
870
|
+
).join("") : viewModel.calendarDates.map(
|
|
802
871
|
(week) => `
|
|
803
|
-
|
|
804
|
-
|
|
872
|
+
<tr>
|
|
873
|
+
${week.map((calendarDate, dayIndex) => {
|
|
805
874
|
const classes = getCellClasses(calendarDate);
|
|
875
|
+
if (availabilityMode && calendarDate.isCurrentMonth) {
|
|
876
|
+
classes.push(
|
|
877
|
+
calendarDate.hasEvents ? "availability--booked" : "availability--free"
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
if (availabilityMode === "day" && selectable && calendarDate.isCurrentMonth) {
|
|
881
|
+
const d = calendarDate.date;
|
|
882
|
+
if (this._rangeStart && isSameDay2(d, this._rangeStart))
|
|
883
|
+
classes.push("availability--range-start");
|
|
884
|
+
if (this._rangeEnd && isSameDay2(d, this._rangeEnd))
|
|
885
|
+
classes.push("availability--range-end");
|
|
886
|
+
if (this._rangeStart && this._rangeEnd) {
|
|
887
|
+
if (d > this._rangeStart && d < this._rangeEnd)
|
|
888
|
+
classes.push("availability--in-range");
|
|
889
|
+
}
|
|
890
|
+
}
|
|
806
891
|
const dateString = calendarDate.date.toISOString();
|
|
807
892
|
return `
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
893
|
+
<td
|
|
894
|
+
class="${classes.join(" ")}"
|
|
895
|
+
data-date="${dateString}"
|
|
896
|
+
data-day-index="${dayIndex}"
|
|
897
|
+
data-clickable="true"
|
|
898
|
+
>
|
|
899
|
+
${calendarDate.date.getDate()}
|
|
900
|
+
</td>
|
|
901
|
+
`;
|
|
817
902
|
}).join("")}
|
|
818
|
-
|
|
819
|
-
|
|
903
|
+
</tr>
|
|
904
|
+
`
|
|
820
905
|
).join("")}
|
|
821
906
|
</tbody>
|
|
822
907
|
</table>
|
|
823
908
|
|
|
824
|
-
${viewModel.selectedDate ? `
|
|
909
|
+
${!isLoading && availabilityMode !== "day" && viewModel.selectedDate ? `
|
|
825
910
|
<div class="date-popup ${viewModel.popupPositionClass}">
|
|
826
911
|
<div class="popup-header">
|
|
827
912
|
<h2>${viewModel.scheduleDay}</h2>
|
|
@@ -835,7 +920,7 @@ var Kalendly = (() => {
|
|
|
835
920
|
` : ""}
|
|
836
921
|
|
|
837
922
|
<div class="events-container">
|
|
838
|
-
${viewModel.tasks.length > 0 ? viewModel.tasks.map((event) => renderEvent(event)).join("") : renderNoEvents()}
|
|
923
|
+
${availabilityMode === "time" ? renderTimeGrid(viewModel.tasks, viewModel.selectedDate) : viewModel.tasks.length > 0 ? viewModel.tasks.map((event) => renderEvent(event)).join("") : renderNoEvents()}
|
|
839
924
|
</div>
|
|
840
925
|
</div>
|
|
841
926
|
` : ""}
|
|
@@ -857,6 +942,59 @@ var Kalendly = (() => {
|
|
|
857
942
|
e.stopPropagation();
|
|
858
943
|
const date = new Date(cell.dataset.date);
|
|
859
944
|
const dayIndex = parseInt(cell.dataset.dayIndex || "0");
|
|
945
|
+
const availMode = this.getAttribute("availability-mode");
|
|
946
|
+
const isSelectable = this.hasAttribute("selectable");
|
|
947
|
+
if (availMode === "day" && isSelectable) {
|
|
948
|
+
const isBooked = cell.classList.contains("availability--booked");
|
|
949
|
+
if (!isBooked) {
|
|
950
|
+
let startDate;
|
|
951
|
+
let endDate;
|
|
952
|
+
if (this._rangeEnd !== null) {
|
|
953
|
+
this._rangeStart = date;
|
|
954
|
+
this._rangeEnd = null;
|
|
955
|
+
startDate = date;
|
|
956
|
+
endDate = date;
|
|
957
|
+
} else if (this._rangeStart === null) {
|
|
958
|
+
this._rangeStart = date;
|
|
959
|
+
startDate = date;
|
|
960
|
+
endDate = date;
|
|
961
|
+
} else {
|
|
962
|
+
const [s, e2] = this._rangeStart <= date ? [this._rangeStart, date] : [date, this._rangeStart];
|
|
963
|
+
const cursor = new Date(s);
|
|
964
|
+
cursor.setDate(cursor.getDate() + 1);
|
|
965
|
+
let blocked = false;
|
|
966
|
+
while (cursor < e2) {
|
|
967
|
+
if (this.engine.getEventsForDate(cursor).length > 0) {
|
|
968
|
+
blocked = true;
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
cursor.setDate(cursor.getDate() + 1);
|
|
972
|
+
}
|
|
973
|
+
if (blocked) {
|
|
974
|
+
this._rangeStart = date;
|
|
975
|
+
this._rangeEnd = null;
|
|
976
|
+
} else {
|
|
977
|
+
this._rangeStart = s;
|
|
978
|
+
this._rangeEnd = e2;
|
|
979
|
+
}
|
|
980
|
+
startDate = this._rangeStart;
|
|
981
|
+
endDate = this._rangeEnd ?? this._rangeStart;
|
|
982
|
+
}
|
|
983
|
+
this.dispatchEvent(
|
|
984
|
+
new CustomEvent("cal-availability-select", {
|
|
985
|
+
bubbles: true,
|
|
986
|
+
composed: true,
|
|
987
|
+
detail: { startDate, endDate }
|
|
988
|
+
})
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
if (availMode === "time") {
|
|
993
|
+
this._timeRangeDate = null;
|
|
994
|
+
this._timeRangeStart = null;
|
|
995
|
+
this._timeRangeEnd = null;
|
|
996
|
+
this._timeRangeComplete = false;
|
|
997
|
+
}
|
|
860
998
|
this.engine.handleDateClick(date, dayIndex);
|
|
861
999
|
this.dispatchEvent(
|
|
862
1000
|
new CustomEvent("cal-date-select", {
|
|
@@ -872,19 +1010,29 @@ var Kalendly = (() => {
|
|
|
872
1010
|
const action = actionEl.dataset.action;
|
|
873
1011
|
e.stopPropagation();
|
|
874
1012
|
switch (action) {
|
|
875
|
-
case "previous":
|
|
1013
|
+
case "previous": {
|
|
1014
|
+
const vm = this.engine.getViewModel();
|
|
1015
|
+
const tMonth = vm.currentMonth === 0 ? 11 : vm.currentMonth - 1;
|
|
1016
|
+
const tYear = vm.currentMonth === 0 ? vm.currentYear - 1 : vm.currentYear;
|
|
1017
|
+
this.dispatchMonthChange(tYear, tMonth);
|
|
876
1018
|
this.actions.previous();
|
|
877
|
-
this.dispatchMonthChange();
|
|
878
1019
|
break;
|
|
879
|
-
|
|
1020
|
+
}
|
|
1021
|
+
case "next": {
|
|
1022
|
+
const vm = this.engine.getViewModel();
|
|
1023
|
+
const tMonth = vm.currentMonth === 11 ? 0 : vm.currentMonth + 1;
|
|
1024
|
+
const tYear = vm.currentMonth === 11 ? vm.currentYear + 1 : vm.currentYear;
|
|
1025
|
+
this.dispatchMonthChange(tYear, tMonth);
|
|
880
1026
|
this.actions.next();
|
|
881
|
-
this.dispatchMonthChange();
|
|
882
1027
|
break;
|
|
883
|
-
|
|
1028
|
+
}
|
|
1029
|
+
case "today": {
|
|
1030
|
+
const t = /* @__PURE__ */ new Date();
|
|
1031
|
+
this.dispatchMonthChange(t.getFullYear(), t.getMonth());
|
|
884
1032
|
this.actions.goToToday();
|
|
885
1033
|
this.pickerOpen = false;
|
|
886
|
-
this.dispatchMonthChange();
|
|
887
1034
|
break;
|
|
1035
|
+
}
|
|
888
1036
|
case "toggle-picker":
|
|
889
1037
|
this.pickerOpen = !this.pickerOpen;
|
|
890
1038
|
if (this.pickerOpen) {
|
|
@@ -899,8 +1047,8 @@ var Kalendly = (() => {
|
|
|
899
1047
|
const newYear = vm.currentYear - 1;
|
|
900
1048
|
this.yearInput = String(newYear);
|
|
901
1049
|
this.updatePickerYear(newYear);
|
|
1050
|
+
this.dispatchMonthChange(newYear, vm.currentMonth);
|
|
902
1051
|
this.actions.jump(newYear, vm.currentMonth);
|
|
903
|
-
this.dispatchMonthChange();
|
|
904
1052
|
}
|
|
905
1053
|
break;
|
|
906
1054
|
}
|
|
@@ -910,21 +1058,60 @@ var Kalendly = (() => {
|
|
|
910
1058
|
const newYear = vm.currentYear + 1;
|
|
911
1059
|
this.yearInput = String(newYear);
|
|
912
1060
|
this.updatePickerYear(newYear);
|
|
1061
|
+
this.dispatchMonthChange(newYear, vm.currentMonth);
|
|
913
1062
|
this.actions.jump(newYear, vm.currentMonth);
|
|
914
|
-
this.dispatchMonthChange();
|
|
915
1063
|
}
|
|
916
1064
|
break;
|
|
917
1065
|
}
|
|
918
1066
|
case "select-month": {
|
|
919
1067
|
const month = parseInt(actionEl.dataset.month || "0", 10);
|
|
920
|
-
this.
|
|
1068
|
+
const year = this.engine.getViewModel().currentYear;
|
|
1069
|
+
this.dispatchMonthChange(year, month);
|
|
1070
|
+
this.actions.jump(year, month);
|
|
921
1071
|
this.pickerOpen = false;
|
|
922
|
-
this.dispatchMonthChange();
|
|
923
1072
|
break;
|
|
924
1073
|
}
|
|
925
1074
|
case "close-popup":
|
|
1075
|
+
this._timeRangeDate = null;
|
|
1076
|
+
this._timeRangeStart = null;
|
|
1077
|
+
this._timeRangeEnd = null;
|
|
1078
|
+
this._timeRangeComplete = false;
|
|
926
1079
|
this.engine.clearSelection();
|
|
927
1080
|
break;
|
|
1081
|
+
case "select-slot": {
|
|
1082
|
+
const slotStart = actionEl.dataset.startTime;
|
|
1083
|
+
const slotEnd = actionEl.dataset.endTime;
|
|
1084
|
+
const slotDate = new Date(actionEl.dataset.date);
|
|
1085
|
+
if (this._timeRangeComplete) {
|
|
1086
|
+
this._timeRangeDate = slotDate;
|
|
1087
|
+
this._timeRangeStart = slotStart;
|
|
1088
|
+
this._timeRangeEnd = slotEnd;
|
|
1089
|
+
this._timeRangeComplete = false;
|
|
1090
|
+
} else if (this._timeRangeStart === null) {
|
|
1091
|
+
this._timeRangeDate = slotDate;
|
|
1092
|
+
this._timeRangeStart = slotStart;
|
|
1093
|
+
this._timeRangeEnd = slotEnd;
|
|
1094
|
+
} else {
|
|
1095
|
+
const newStart = slotStart < this._timeRangeStart ? slotStart : this._timeRangeStart;
|
|
1096
|
+
const newEnd = slotEnd > this._timeRangeEnd ? slotEnd : this._timeRangeEnd;
|
|
1097
|
+
this._timeRangeStart = newStart;
|
|
1098
|
+
this._timeRangeEnd = newEnd;
|
|
1099
|
+
this._timeRangeComplete = true;
|
|
1100
|
+
}
|
|
1101
|
+
this.render();
|
|
1102
|
+
this.dispatchEvent(
|
|
1103
|
+
new CustomEvent("cal-availability-select", {
|
|
1104
|
+
bubbles: true,
|
|
1105
|
+
composed: true,
|
|
1106
|
+
detail: {
|
|
1107
|
+
date: this._timeRangeDate,
|
|
1108
|
+
startTime: this._timeRangeStart,
|
|
1109
|
+
endTime: this._timeRangeEnd
|
|
1110
|
+
}
|
|
1111
|
+
})
|
|
1112
|
+
);
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
928
1115
|
}
|
|
929
1116
|
};
|
|
930
1117
|
this.delegatedInputHandler = (e) => {
|
|
@@ -949,8 +1136,8 @@ var Kalendly = (() => {
|
|
|
949
1136
|
target.value = this.yearInput;
|
|
950
1137
|
target.classList.remove("invalid");
|
|
951
1138
|
} else if (year !== vm.currentYear) {
|
|
1139
|
+
this.dispatchMonthChange(year, vm.currentMonth);
|
|
952
1140
|
this.actions.jump(year, vm.currentMonth);
|
|
953
|
-
this.dispatchMonthChange();
|
|
954
1141
|
}
|
|
955
1142
|
};
|
|
956
1143
|
this.delegatedKeydownHandler = (e) => {
|
|
@@ -989,14 +1176,17 @@ var Kalendly = (() => {
|
|
|
989
1176
|
if (prevBtn) prevBtn.disabled = year <= this.minYear;
|
|
990
1177
|
if (nextBtn) nextBtn.disabled = year >= this.maxYear;
|
|
991
1178
|
}
|
|
992
|
-
dispatchMonthChange() {
|
|
1179
|
+
dispatchMonthChange(year, month) {
|
|
993
1180
|
if (!this.engine) return;
|
|
994
1181
|
const vm = this.engine.getViewModel();
|
|
995
1182
|
this.dispatchEvent(
|
|
996
1183
|
new CustomEvent("cal-month-change", {
|
|
997
1184
|
bubbles: true,
|
|
998
1185
|
composed: true,
|
|
999
|
-
detail: {
|
|
1186
|
+
detail: {
|
|
1187
|
+
year: year ?? vm.currentYear,
|
|
1188
|
+
month: month ?? vm.currentMonth
|
|
1189
|
+
}
|
|
1000
1190
|
})
|
|
1001
1191
|
);
|
|
1002
1192
|
}
|
|
@@ -1011,7 +1201,10 @@ var Kalendly = (() => {
|
|
|
1011
1201
|
return this.engine?.getViewModel().selectedDate ?? null;
|
|
1012
1202
|
}
|
|
1013
1203
|
goToDate(date) {
|
|
1014
|
-
|
|
1204
|
+
const year = date.getFullYear();
|
|
1205
|
+
const month = date.getMonth();
|
|
1206
|
+
this.dispatchMonthChange(year, month);
|
|
1207
|
+
this.actions?.jump(year, month);
|
|
1015
1208
|
}
|
|
1016
1209
|
getEngine() {
|
|
1017
1210
|
if (!this.engine)
|
|
@@ -1025,7 +1218,10 @@ var Kalendly = (() => {
|
|
|
1025
1218
|
"max-year",
|
|
1026
1219
|
"week-starts-on",
|
|
1027
1220
|
"title",
|
|
1028
|
-
"use-short-month-names"
|
|
1221
|
+
"use-short-month-names",
|
|
1222
|
+
"availability-mode",
|
|
1223
|
+
"selectable",
|
|
1224
|
+
"loading"
|
|
1029
1225
|
];
|
|
1030
1226
|
function defineCalendarElement(tagName = "kal-calendar") {
|
|
1031
1227
|
if (typeof customElements !== "undefined" && !customElements.get(tagName)) {
|