@pacem/pacem-ui 1.0.0-abel
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/LICENSE +191 -0
- package/NOTICE +4 -0
- package/dist/browser/pacem-ui.js +6343 -0
- package/dist/browser/pacem-ui.js.map +1 -0
- package/dist/browser/pacem-ui.min.js +2 -0
- package/dist/browser/pacem-ui.min.js.map +1 -0
- package/dist/bundle/pacem-ui.min.mjs +168 -0
- package/dist/bundle/pacem-ui.mjs +6276 -0
- package/dist/bundle/pacem-ui.mjs.map +7 -0
- package/dist/esm/adapter.js +360 -0
- package/dist/esm/anchor.js +149 -0
- package/dist/esm/balloon.js +583 -0
- package/dist/esm/binder.js +678 -0
- package/dist/esm/blade.js +31 -0
- package/dist/esm/bottom-sheet.js +277 -0
- package/dist/esm/button.js +100 -0
- package/dist/esm/buttonset.js +41 -0
- package/dist/esm/calendar.js +662 -0
- package/dist/esm/collapse.js +72 -0
- package/dist/esm/dialog-abstractions.js +61 -0
- package/dist/esm/dialog.js +102 -0
- package/dist/esm/divider.js +48 -0
- package/dist/esm/icon.js +131 -0
- package/dist/esm/image.js +109 -0
- package/dist/esm/index-components-ui.js +41 -0
- package/dist/esm/index-components.js +1 -0
- package/dist/esm/index-iife.js +3 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/infinite-scroller.js +137 -0
- package/dist/esm/iterative.js +45 -0
- package/dist/esm/lightbox-abstractions.js +6 -0
- package/dist/esm/lightbox.js +203 -0
- package/dist/esm/loader.js +100 -0
- package/dist/esm/markdown-svc.js +235 -0
- package/dist/esm/markdown.js +35 -0
- package/dist/esm/marquee.js +87 -0
- package/dist/esm/media-query.js +85 -0
- package/dist/esm/menu.js +165 -0
- package/dist/esm/pager.js +111 -0
- package/dist/esm/picture.js +157 -0
- package/dist/esm/progressbar.js +54 -0
- package/dist/esm/sidebar.js +60 -0
- package/dist/esm/slideshow.js +27 -0
- package/dist/esm/social-twitter.js +39 -0
- package/dist/esm/sticky-header.js +113 -0
- package/dist/esm/tabs.js +187 -0
- package/dist/esm/ticker.js +78 -0
- package/dist/esm/toast.js +171 -0
- package/dist/esm/toc.js +171 -0
- package/dist/esm/tuner.js +200 -0
- package/dist/esm/types.js +7 -0
- package/dist/esm/vibration.js +33 -0
- package/dist/esm/view.js +206 -0
- package/dist/esm/window.js +181 -0
- package/package.json +38 -0
- package/typings/index.d.ts +1165 -0
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { P, PCSS, CustomElement, Watch, ViewChild, Utils, PropertyConverters, Components, CustomTypedEvent, PropertyChangeEvent, Defaults, CustomElementUtils, Debounce, PropertyChangeEventName } from '@pacem/pacem-core';
|
|
8
|
+
//namespace Pacem.Components.UI {
|
|
9
|
+
export var CalendarZoom;
|
|
10
|
+
(function (CalendarZoom) {
|
|
11
|
+
CalendarZoom["Month"] = "month";
|
|
12
|
+
CalendarZoom["Week"] = "week";
|
|
13
|
+
CalendarZoom["Day"] = "day";
|
|
14
|
+
})(CalendarZoom || (CalendarZoom = {}));
|
|
15
|
+
export class ViewDateChangeEvent extends CustomTypedEvent {
|
|
16
|
+
constructor(date) {
|
|
17
|
+
super('viewdatechange', date);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class DateSelectEvent extends CustomTypedEvent {
|
|
21
|
+
constructor(date) {
|
|
22
|
+
super('dateselect', date, { bubbles: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class TimeSelectEvent extends CustomTypedEvent {
|
|
26
|
+
constructor(date) {
|
|
27
|
+
super('timeselect', date, { bubbles: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const MSECS_PER_HOUR = 1000 * 60 * 60;
|
|
31
|
+
const MSECS_PER_DAY = MSECS_PER_HOUR * 24;
|
|
32
|
+
const DAY_HOURS = [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5,
|
|
33
|
+
12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 16.5, 17, 17.5, 18, 18.5, 19, 19.5, 20, 20.5, 21, 21.5, 22, 22.5, 23, 23.5];
|
|
34
|
+
let now = new Date();
|
|
35
|
+
const DUMMY_DATE = Utils.Dates.dateOnly(now).valueOf();
|
|
36
|
+
const DAYS_OF_WEEK = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
|
37
|
+
let PacemCalendarEventElement = class PacemCalendarEventElement extends Components.PacemItemElement {
|
|
38
|
+
propertyChangedCallback(name, old, val, first) {
|
|
39
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
40
|
+
cancelAnimationFrame(this._handle);
|
|
41
|
+
this._handle = requestAnimationFrame(() => {
|
|
42
|
+
let container = this.container;
|
|
43
|
+
if (!Utils.isNull(container)) {
|
|
44
|
+
// trigger propertychange for `items`
|
|
45
|
+
container.dispatchEvent(new PropertyChangeEvent({ propertyName: 'items', oldValue: container.items, currentValue: container.items }));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
__decorate([
|
|
51
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
52
|
+
], PacemCalendarEventElement.prototype, "start", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
55
|
+
], PacemCalendarEventElement.prototype, "end", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
Watch({ converter: PropertyConverters.String })
|
|
58
|
+
], PacemCalendarEventElement.prototype, "caption", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
Watch({ converter: PropertyConverters.Json })
|
|
61
|
+
], PacemCalendarEventElement.prototype, "place", void 0);
|
|
62
|
+
__decorate([
|
|
63
|
+
Watch({ converter: PropertyConverters.Boolean })
|
|
64
|
+
], PacemCalendarEventElement.prototype, "allDay", void 0);
|
|
65
|
+
PacemCalendarEventElement = __decorate([
|
|
66
|
+
CustomElement({
|
|
67
|
+
tagName: P + '-calendar-event'
|
|
68
|
+
})
|
|
69
|
+
], PacemCalendarEventElement);
|
|
70
|
+
export { PacemCalendarEventElement };
|
|
71
|
+
export class CalendarEventSelectEvent extends CustomTypedEvent {
|
|
72
|
+
constructor(args) {
|
|
73
|
+
super("eventselect", args, { bubbles: false, cancelable: true });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export class CalendarEventUnselectEvent extends CustomTypedEvent {
|
|
77
|
+
constructor(args) {
|
|
78
|
+
super("eventunselect", args, { bubbles: false, cancelable: true });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export class PacemCalendarBaseElement extends Components.PacemItemsContainerElement {
|
|
82
|
+
validate(item) {
|
|
83
|
+
return item instanceof PacemCalendarEventElement;
|
|
84
|
+
}
|
|
85
|
+
propertyChangedCallback(name, old, val, first) {
|
|
86
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
87
|
+
if (name === 'viewDate' || name === 'weekStart') {
|
|
88
|
+
this._synchronizeWeek();
|
|
89
|
+
}
|
|
90
|
+
switch (name) {
|
|
91
|
+
case 'viewDate':
|
|
92
|
+
this.dispatchEvent(new ViewDateChangeEvent(val));
|
|
93
|
+
Utils.removeClass(this, "viewdate-next viewdate-previous");
|
|
94
|
+
requestAnimationFrame(() => {
|
|
95
|
+
Utils.addClass(this, old > val ? "viewdate-previous" : "viewdate-next");
|
|
96
|
+
});
|
|
97
|
+
break;
|
|
98
|
+
case 'zoom':
|
|
99
|
+
Utils.removeClass(this, "viewdate-next viewdate-previous");
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// #region PROTECTED
|
|
104
|
+
oneventselect(el, evt) {
|
|
105
|
+
this.dispatchEvent(new CalendarEventSelectEvent({ element: el, event: evt }));
|
|
106
|
+
}
|
|
107
|
+
oneventunselect(el, evt) {
|
|
108
|
+
this.dispatchEvent(new CalendarEventUnselectEvent({ element: el, event: evt }));
|
|
109
|
+
}
|
|
110
|
+
getHeaderLabel(d, f) {
|
|
111
|
+
const options = f === CalendarZoom.Week ? { weekday: 'short', day: 'numeric', month: 'numeric' }
|
|
112
|
+
: (f === CalendarZoom.Day ? { weekday: 'long' } : /* fallback: month */ { weekday: 'short' });
|
|
113
|
+
return Utils.parseDate(d).toLocaleString(Utils.lang(this), options);
|
|
114
|
+
}
|
|
115
|
+
getDayLabel(d) {
|
|
116
|
+
const options = d.getDate() == 1 ? { month: 'short', day: 'numeric' } : { day: 'numeric' };
|
|
117
|
+
return Utils.parseDate(d).toLocaleString(Utils.lang(this), options);
|
|
118
|
+
}
|
|
119
|
+
getHourLabel(d) {
|
|
120
|
+
const options = { hour: 'numeric' /*, minute: 'numeric'*/ };
|
|
121
|
+
return Utils.parseDate(d).toLocaleString(Utils.lang(this), options);
|
|
122
|
+
}
|
|
123
|
+
getTimeLabel(d) {
|
|
124
|
+
const options = { hour: 'numeric', minute: 'numeric' };
|
|
125
|
+
return Utils.parseDate(d).toLocaleString(Utils.lang(this), options);
|
|
126
|
+
}
|
|
127
|
+
isNow(d, now) {
|
|
128
|
+
const d0 = Utils.parseDate(d), v = Utils.parseDate(now || new Date());
|
|
129
|
+
return d0.getHours() === v.getHours() && this.isToday(d, now);
|
|
130
|
+
}
|
|
131
|
+
isToday(d, now) {
|
|
132
|
+
return this.isDate(d, now || new Date());
|
|
133
|
+
}
|
|
134
|
+
isViewDay(d, vd = this.viewDate) {
|
|
135
|
+
return this.isDate(d, vd || this.viewDate || new Date());
|
|
136
|
+
}
|
|
137
|
+
isDate(expected, d) {
|
|
138
|
+
if (!Utils.Dates.isDate(d) || !Utils.Dates.isDate(expected)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const d0 = Utils.parseDate(expected), v = Utils.parseDate(d);
|
|
142
|
+
return d0.getDate() === v.getDate() && d0.getMonth() == v.getMonth() && d0.getFullYear() === v.getFullYear();
|
|
143
|
+
}
|
|
144
|
+
isViewWeek(d) {
|
|
145
|
+
const d0 = Utils.parseDate(d);
|
|
146
|
+
return this.week && this.week.find(d1 => d1.getDate() == d0.getDate() && d1.getMonth() == d0.getMonth() && d1.getDate() == d0.getDate());
|
|
147
|
+
}
|
|
148
|
+
isViewMonth(d) {
|
|
149
|
+
const d0 = Utils.parseDate(d), v = Utils.parseDate(this.viewDate || new Date());
|
|
150
|
+
return d0.getMonth() == v.getMonth() && d0.getFullYear() === v.getFullYear();
|
|
151
|
+
}
|
|
152
|
+
isTimeSlotDisabled(ranges, d, h) {
|
|
153
|
+
if (!Utils.isNullOrEmpty(ranges)) {
|
|
154
|
+
h = h || 0;
|
|
155
|
+
const slotDate = new Date(d.getFullYear(), d.getMonth(), d.getDate(), Math.floor(h), 60 * (h % 1)), tz = slotDate.getTimezoneOffset(), slot = slotDate.valueOf() - (tz * 60 * 1000);
|
|
156
|
+
for (let range of ranges) {
|
|
157
|
+
let from = Utils.Dates.parse(range.from), to = Utils.Dates.parse(range.to);
|
|
158
|
+
if ((!from || (from && from.valueOf() <= slot))
|
|
159
|
+
&& (!to || (to && to.valueOf() > slot))
|
|
160
|
+
&& (to || from)) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
// #endregion
|
|
168
|
+
// #region PRIVATE
|
|
169
|
+
_getWeekStart(day, weekstart) {
|
|
170
|
+
let dow = day.getDay(), v = day.valueOf();
|
|
171
|
+
const tget = (weekstart || 'm').toLowerCase().startsWith('m') ? 1 : 0;
|
|
172
|
+
if (dow === tget) {
|
|
173
|
+
return v;
|
|
174
|
+
}
|
|
175
|
+
if (dow === 0) {
|
|
176
|
+
// damn 0-indexed sunday, skip to the previous one
|
|
177
|
+
dow = 7;
|
|
178
|
+
}
|
|
179
|
+
return v + (tget - dow) * MSECS_PER_DAY;
|
|
180
|
+
}
|
|
181
|
+
_getDatasource(d, w = this.weekStart) {
|
|
182
|
+
let day = Utils.Dates.dateOnly(Utils.parseDate(d));
|
|
183
|
+
const ds = this.month;
|
|
184
|
+
let _d0 = ds && ds.length && ds[0] && ds[0].length && ds[0][0];
|
|
185
|
+
if (_d0 && _d0.getMonth() == day.getMonth() && _d0.getFullYear() == day.getFullYear()
|
|
186
|
+
&& ds.find(wk => !Utils.isNull(wk.find(dy => dy.valueOf() == day.valueOf())))) {
|
|
187
|
+
// return the "convenient" datasource
|
|
188
|
+
return ds;
|
|
189
|
+
}
|
|
190
|
+
//
|
|
191
|
+
// month
|
|
192
|
+
let d1 = new Date(day.getFullYear(), day.getMonth(), 1);
|
|
193
|
+
let date1 = this._getWeekStart(d1, w);
|
|
194
|
+
let month = [];
|
|
195
|
+
let week = [];
|
|
196
|
+
do {
|
|
197
|
+
let date = Utils.Dates.dateOnly(new Date(date1));
|
|
198
|
+
week.push(date);
|
|
199
|
+
if (week.length == 7) {
|
|
200
|
+
month.push(week.splice(0));
|
|
201
|
+
}
|
|
202
|
+
date1 = date.valueOf() + MSECS_PER_DAY + /* beware of day-light-saving occurrences */ MSECS_PER_HOUR;
|
|
203
|
+
} while (month.length < 6);
|
|
204
|
+
//
|
|
205
|
+
return this.month = month;
|
|
206
|
+
}
|
|
207
|
+
_synchronizeWeek() {
|
|
208
|
+
const viewDate = Utils.parseDate(this.viewDate);
|
|
209
|
+
const vd = new Date(viewDate.getFullYear(), viewDate.getMonth(), 1);
|
|
210
|
+
const ds = this._getDatasource(vd, this.weekStart);
|
|
211
|
+
const week = ds.filter((w, j) => w.some(d => d.getDate() == viewDate.getDate() && d.getMonth() == viewDate.getMonth() && d.getFullYear() == viewDate.getFullYear()))[0];
|
|
212
|
+
if (!(this.week && this.week.length) || this.week[0] !== week[0]) {
|
|
213
|
+
this.week = week;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
__decorate([
|
|
218
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
219
|
+
], PacemCalendarBaseElement.prototype, "viewDate", void 0);
|
|
220
|
+
__decorate([
|
|
221
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
222
|
+
], PacemCalendarBaseElement.prototype, "now", void 0);
|
|
223
|
+
__decorate([
|
|
224
|
+
Watch({ converter: PropertyConverters.String })
|
|
225
|
+
], PacemCalendarBaseElement.prototype, "zoom", void 0);
|
|
226
|
+
__decorate([
|
|
227
|
+
Watch({ converter: PropertyConverters.String })
|
|
228
|
+
], PacemCalendarBaseElement.prototype, "weekStart", void 0);
|
|
229
|
+
__decorate([
|
|
230
|
+
Watch({ converter: PropertyConverters.Eval })
|
|
231
|
+
], PacemCalendarBaseElement.prototype, "week", void 0);
|
|
232
|
+
__decorate([
|
|
233
|
+
Watch({ converter: PropertyConverters.Eval })
|
|
234
|
+
], PacemCalendarBaseElement.prototype, "month", void 0);
|
|
235
|
+
__decorate([
|
|
236
|
+
Watch({ converter: PropertyConverters.Eval })
|
|
237
|
+
], PacemCalendarBaseElement.prototype, "disabledRanges", void 0);
|
|
238
|
+
export class PacemCalendarWithEventsBaseElement extends PacemCalendarBaseElement {
|
|
239
|
+
constructor() {
|
|
240
|
+
super(...arguments);
|
|
241
|
+
this._datasource = [];
|
|
242
|
+
}
|
|
243
|
+
get datasource() {
|
|
244
|
+
return this._datasource;
|
|
245
|
+
}
|
|
246
|
+
_getSortedItems(items) {
|
|
247
|
+
return items.slice().sort((a, b) => {
|
|
248
|
+
const a_start = a.start.valueOf(), b_start = b.start.valueOf();
|
|
249
|
+
if (a_start != b_start) {
|
|
250
|
+
return a_start < b_start ? -1 : 1;
|
|
251
|
+
}
|
|
252
|
+
const a_end = a.end.valueOf(), b_end = b.end.valueOf(), a_span = a_end - a_start, b_span = b_end - b_start;
|
|
253
|
+
if (a_span != b_span) {
|
|
254
|
+
return a_span > b_span ? -1 : 1;
|
|
255
|
+
}
|
|
256
|
+
return 0;
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
propertyChangedCallback(name, old, val, first) {
|
|
260
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
261
|
+
switch (name) {
|
|
262
|
+
case 'month':
|
|
263
|
+
case 'week':
|
|
264
|
+
case 'items':
|
|
265
|
+
case 'zoom':
|
|
266
|
+
case 'viewDate':
|
|
267
|
+
cancelAnimationFrame(this._handle);
|
|
268
|
+
this._handle = requestAnimationFrame(() => {
|
|
269
|
+
let oldval = this._datasource;
|
|
270
|
+
let newval = this._datasource = this.buildDataSource(this._getSortedItems(this.items || []));
|
|
271
|
+
this.dispatchEvent(new PropertyChangeEvent({ propertyName: 'datasource', oldValue: oldval, currentValue: newval }));
|
|
272
|
+
});
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function getWeeklyEventDataItems(items, week) {
|
|
278
|
+
let lbound = week.length - 1, wstart = week[0].valueOf(), wend = week[lbound].valueOf();
|
|
279
|
+
return items.filter(evt => {
|
|
280
|
+
let startDate = Utils.Dates.dateOnly(evt.start);
|
|
281
|
+
let endDate = Utils.Dates.dateOnly(evt.end);
|
|
282
|
+
return startDate.valueOf() <= wend && endDate.valueOf() >= wstart;
|
|
283
|
+
}).map(evt => {
|
|
284
|
+
let startDate = Utils.Dates.dateOnly(evt.start), start = week.find(d => d.valueOf() == startDate.valueOf()), startIndex = week.indexOf(start);
|
|
285
|
+
let endDate = Utils.Dates.dateOnly(evt.end), end = week.find(d => d.valueOf() == endDate.valueOf()), endIndex = week.indexOf(end);
|
|
286
|
+
let ndx0 = startIndex == -1 ? 0 : startIndex, ndx1 = endIndex == -1 ? lbound : endIndex;
|
|
287
|
+
return {
|
|
288
|
+
start: evt.start, end: evt.end,
|
|
289
|
+
allDay: true,
|
|
290
|
+
// indexes
|
|
291
|
+
day: ndx0,
|
|
292
|
+
continuing: { start: startIndex == -1, end: endIndex == -1 },
|
|
293
|
+
// span (may be column- or row-)
|
|
294
|
+
span: ndx1 + 1 - ndx0,
|
|
295
|
+
caption: evt.caption,
|
|
296
|
+
event: evt
|
|
297
|
+
};
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
// #region AGENDA
|
|
301
|
+
function buildAgendaGrid() {
|
|
302
|
+
let grid = '';
|
|
303
|
+
for (let day = 0; day < 7; day++) {
|
|
304
|
+
if (day == 0) {
|
|
305
|
+
grid += `<div class="agenda-left all-day"></div>`;
|
|
306
|
+
}
|
|
307
|
+
grid += `<${P}-panel class="agenda-slot all-day day-${(day + 1)}" css-class="{{ {'viewday': :host.isViewDay(:host.week[${day}], :host.viewDate), 'today': :host.isToday(:host.week[${day}], :host.now)} }}"></${P}-panel>`;
|
|
308
|
+
}
|
|
309
|
+
for (let day = 0; day < 7; day++) {
|
|
310
|
+
for (let hour of DAY_HOURS) {
|
|
311
|
+
let whole = hour % 1 == 0;
|
|
312
|
+
let css = `hour-${whole ? 'whole' : 'half'}`;
|
|
313
|
+
if (day == 0 && whole) {
|
|
314
|
+
grid += `<${P}-text class="agenda-left ${css} hour-${hour * 2 + 1}"" text="{{ :host.getHourLabel(${DUMMY_DATE + hour * MSECS_PER_HOUR}) }}"></${P}-text>`;
|
|
315
|
+
}
|
|
316
|
+
grid += `<${P}-panel on-click=":host.time = Pacem.Utils.Dates.parse(:host.week[${day}].valueOf() + ${(hour * MSECS_PER_HOUR)})" disabled="{{ :host.isTimeSlotDisabled(:host.disabledRanges, :host.week[${day}], ${hour}) }}" class="agenda-slot ${css} day-${(day + 1)} hour-${hour * 2 + 1}" css-class="{{ {'viewday': :host.isViewDay(:host.week[${day}], :host.viewDate), 'today': :host.isToday(:host.week[${day}], :host.now)} }}"></${P}-panel>`;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return grid;
|
|
320
|
+
}
|
|
321
|
+
let PacemAgendaElement = class PacemAgendaElement extends PacemCalendarWithEventsBaseElement {
|
|
322
|
+
constructor() {
|
|
323
|
+
super(...arguments);
|
|
324
|
+
this._allDayDatasource = [];
|
|
325
|
+
}
|
|
326
|
+
buildDataSource(items) {
|
|
327
|
+
var week = this.week;
|
|
328
|
+
if (this.zoom === CalendarZoom.Day) {
|
|
329
|
+
week = [Utils.Dates.dateOnly(this.viewDate)];
|
|
330
|
+
}
|
|
331
|
+
let ds = [];
|
|
332
|
+
if (!Utils.isNull(week)) {
|
|
333
|
+
// alldays
|
|
334
|
+
this.dispatchEvent(new PropertyChangeEvent({
|
|
335
|
+
propertyName: 'allDayDatasource',
|
|
336
|
+
oldValue: this._allDayDatasource,
|
|
337
|
+
currentValue: this._allDayDatasource = getWeeklyEventDataItems(items.filter(evt => {
|
|
338
|
+
return (evt.end.valueOf() - evt.start.valueOf()) >= MSECS_PER_DAY;
|
|
339
|
+
}), week)
|
|
340
|
+
}));
|
|
341
|
+
// hourlies
|
|
342
|
+
for (let j = 0; j < week.length; j++) {
|
|
343
|
+
let day = week[j], dayValue = day.valueOf(),
|
|
344
|
+
// search for events in this week
|
|
345
|
+
dayItems = items.filter(evt => {
|
|
346
|
+
let startDate = Utils.Dates.dateOnly(evt.start);
|
|
347
|
+
let endDate = Utils.Dates.dateOnly(evt.end);
|
|
348
|
+
return startDate.valueOf() <= dayValue && endDate.valueOf() >= dayValue;
|
|
349
|
+
}).map(evt => {
|
|
350
|
+
let evtStart = evt.start.valueOf(), evtEnd = evt.end.valueOf();
|
|
351
|
+
let retval = {
|
|
352
|
+
allDay: evt.allDay || (evtEnd - evtStart) >= MSECS_PER_DAY,
|
|
353
|
+
continuing: { start: evtStart < dayValue, end: evtEnd > (dayValue + MSECS_PER_DAY) },
|
|
354
|
+
caption: evt.caption,
|
|
355
|
+
hour: 0,
|
|
356
|
+
span: DAY_HOURS.length - 1,
|
|
357
|
+
offset: { start: "0", end: "0" },
|
|
358
|
+
event: evt
|
|
359
|
+
};
|
|
360
|
+
let startHour = evt.start.getHours() + evt.start.getMinutes() / 60, startIndex = retval.continuing.start ? 0 : Math.floor(startHour * 2), endHour = evt.end.getHours() + evt.end.getMinutes() / 60, endIndex = -1 + (retval.continuing.end ? DAY_HOURS.length : Math.ceil(endHour * 2));
|
|
361
|
+
let endNdx = endIndex + 1, end = endNdx >= DAY_HOURS.length ? 24 : DAY_HOURS[endNdx];
|
|
362
|
+
let fullSpan = end - DAY_HOURS[startIndex];
|
|
363
|
+
retval.hour = startIndex;
|
|
364
|
+
retval.span = 1 + endIndex - startIndex;
|
|
365
|
+
// offsets
|
|
366
|
+
if (!retval.continuing.start) {
|
|
367
|
+
// compute correct start offset
|
|
368
|
+
retval.offset.start = (((startHour - DAY_HOURS[startIndex]) / fullSpan) * 100) + "%";
|
|
369
|
+
}
|
|
370
|
+
if (!retval.continuing.end) {
|
|
371
|
+
// compute correct end offset
|
|
372
|
+
retval.offset.end = (((end - endHour) / fullSpan) * 100) + "%";
|
|
373
|
+
}
|
|
374
|
+
return retval;
|
|
375
|
+
});
|
|
376
|
+
//
|
|
377
|
+
ds.push(dayItems);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return ds;
|
|
381
|
+
}
|
|
382
|
+
get allDayDatasource() {
|
|
383
|
+
return this._allDayDatasource;
|
|
384
|
+
}
|
|
385
|
+
propertyChangedCallback(name, old, val, first) {
|
|
386
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
387
|
+
const clock = this._clock;
|
|
388
|
+
if (name === 'time') {
|
|
389
|
+
this.dispatchEvent(new TimeSelectEvent(val));
|
|
390
|
+
}
|
|
391
|
+
else if (!Utils.isNull(clock)) {
|
|
392
|
+
if (name === 'now') {
|
|
393
|
+
clock.now = val;
|
|
394
|
+
clock.className = `hour-${val.getHours()} minute-${val.getMinutes()}`;
|
|
395
|
+
}
|
|
396
|
+
if (name === 'now' || name === 'zoom' || name === 'viewDate') {
|
|
397
|
+
const d = this.now, z = this.zoom;
|
|
398
|
+
const showClock = d && z && ((this.isViewDay(d) && z === CalendarZoom.Day)
|
|
399
|
+
|| (this.isViewWeek(d) && z === CalendarZoom.Week));
|
|
400
|
+
clock.hidden = !showClock;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
__decorate([
|
|
406
|
+
ViewChild(P + '-clock')
|
|
407
|
+
], PacemAgendaElement.prototype, "_clock", void 0);
|
|
408
|
+
__decorate([
|
|
409
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
410
|
+
], PacemAgendaElement.prototype, "time", void 0);
|
|
411
|
+
PacemAgendaElement = __decorate([
|
|
412
|
+
CustomElement({
|
|
413
|
+
tagName: P + '-agenda', shadow: Defaults.USE_SHADOW_ROOT,
|
|
414
|
+
template: `<${P}-repeater class="${PCSS}-agenda agenda-grid" datasource="{{ :host.datasource }}">${buildAgendaGrid()}<${P}-clock hidden></${P}-clock>
|
|
415
|
+
<template>
|
|
416
|
+
<${P}-repeater class="agenda-day" datasource="{{ ^item }}">
|
|
417
|
+
<template>
|
|
418
|
+
<${P}-panel class="agenda-event-wrapper"
|
|
419
|
+
css-class="{{ ['hour-start-'+ (^item.hour + 1), 'hour-end-'+ (^item.hour + ^item.span +1), 'day-start-'+ (!^item.continuing.start), 'day-end-'+ (!^item.continuing.end)] }}">
|
|
420
|
+
<${P}-panel class="agenda-event" css="{{ {'top': ^item.offset.start, 'bottom': ^item.offset.end} }}" tab-order="{{ (^^index + 1) * 1000 + (^item.hour + 1) * 100 + ^index }}"
|
|
421
|
+
on-focus=":host.oneventselect($this, ^item.event)" on-blur=":host.oneventunselect($this, ^item.event)">
|
|
422
|
+
<${P}-span class="event-caption" text="{{ ^item.caption }}"></${P}-span>
|
|
423
|
+
</${P}-panel>
|
|
424
|
+
</${P}-panel>
|
|
425
|
+
</template>
|
|
426
|
+
</${P}-repeater>
|
|
427
|
+
</template>
|
|
428
|
+
<${P}-repeater class="agenda-allday" datasource="{{ :host.allDayDatasource }}">
|
|
429
|
+
<template>
|
|
430
|
+
<${P}-panel class="agenda-event" tab-order="{{ (^index + 1) * 500 + (^item.day + 1) * 50 + ^index }}" css-class="{{ ['day-start-'+ (^item.day + 1), 'day-end-'+ (^item.day + ^item.span + 1)] }}"
|
|
431
|
+
on-focus=":host.oneventselect($this, ^item.event)" on-blur=":host.oneventunselect($this, ^item.event)">
|
|
432
|
+
<${P}-text class="event-caption" text="{{ ^item.caption }}"></${P}-text>
|
|
433
|
+
</${P}-panel>
|
|
434
|
+
</template>
|
|
435
|
+
</${P}-repeater>
|
|
436
|
+
</${P}-repeater><${P}-content></${P}-content>`
|
|
437
|
+
})
|
|
438
|
+
], PacemAgendaElement);
|
|
439
|
+
export { PacemAgendaElement };
|
|
440
|
+
// #endregion
|
|
441
|
+
// #region CALENDAR
|
|
442
|
+
function buildCalendarGrid() {
|
|
443
|
+
let grid = '';
|
|
444
|
+
for (let week = 0; week < 6; week++) {
|
|
445
|
+
for (let day = 0; day < 7; day++) {
|
|
446
|
+
let css = `class="calendar-day week-${week + 1} day-${day + 1}"`;
|
|
447
|
+
grid += `<${P}-panel disabled="{{ :host.isTimeSlotDisabled(:host.disabledRanges, :host.month[${week}][${day}]) }}" on-click=":host._setDate(:host.month[${week}][${day}])" ${css} css-class="{{ {'viewmonth': :host.isViewMonth(:host.month[${week}][${day}]), 'viewday': :host.isViewDay(:host.month[${week}][${day}], :host.viewDate), 'today': :host.isToday(:host.month[${week}][${day}], :host.now), 'selected-date': :host.isDate(:host.month[${week}][${day}], :host.date)} }}"><${P}-span culture="{{ :host.culture }}" class="text-ellipsed" text="{{ :host.getDayLabel(:host.month[${week}][${day}], :host._formatVersion) }}"></${P}-span></${P}-panel>`;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return grid;
|
|
451
|
+
}
|
|
452
|
+
let PacemCalendarElement = class PacemCalendarElement extends PacemCalendarWithEventsBaseElement {
|
|
453
|
+
buildDataSource(items) {
|
|
454
|
+
const month = this.month;
|
|
455
|
+
let ds = [];
|
|
456
|
+
if (!Utils.isNull(month)) {
|
|
457
|
+
for (let j = 0; j < month.length; j++) {
|
|
458
|
+
let week = month[j],
|
|
459
|
+
// search for events in this week
|
|
460
|
+
weekItems = getWeeklyEventDataItems(items, week);
|
|
461
|
+
//
|
|
462
|
+
ds.push(weekItems);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return ds;
|
|
466
|
+
}
|
|
467
|
+
propertyChangedCallback(name, old, val, first) {
|
|
468
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
469
|
+
switch (name) {
|
|
470
|
+
//case 'date':
|
|
471
|
+
// this.dispatchEvent(new DateSelectEvent(val));
|
|
472
|
+
// break;
|
|
473
|
+
case 'dayLabelFormatter':
|
|
474
|
+
this._formatVersion = Date.now();
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
_setDate(d) {
|
|
479
|
+
if (d?.valueOf() !== this.date?.valueOf()) {
|
|
480
|
+
this.date = d;
|
|
481
|
+
this.dispatchEvent(new DateSelectEvent(d));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
getDayLabel(d, _ = this._formatVersion) {
|
|
485
|
+
const labeler = this.dayLabelFormatter;
|
|
486
|
+
if (typeof labeler === 'function') {
|
|
487
|
+
return labeler(d);
|
|
488
|
+
}
|
|
489
|
+
return super.getDayLabel(d);
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
__decorate([
|
|
493
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
494
|
+
], PacemCalendarElement.prototype, "date", void 0);
|
|
495
|
+
__decorate([
|
|
496
|
+
Watch({ emit: false })
|
|
497
|
+
], PacemCalendarElement.prototype, "dayLabelFormatter", void 0);
|
|
498
|
+
__decorate([
|
|
499
|
+
Watch()
|
|
500
|
+
], PacemCalendarElement.prototype, "_formatVersion", void 0);
|
|
501
|
+
PacemCalendarElement = __decorate([
|
|
502
|
+
CustomElement({
|
|
503
|
+
tagName: P + '-calendar', shadow: Defaults.USE_SHADOW_ROOT,
|
|
504
|
+
template: `<${P}-repeater class="${PCSS}-calendar calendar-grid" datasource="{{ :host.datasource }}">${buildCalendarGrid()}
|
|
505
|
+
<template>
|
|
506
|
+
<${P}-repeater class="calendar-week" datasource="{{ ^item }}">
|
|
507
|
+
<template>
|
|
508
|
+
<${P}-panel class="calendar-event" tab-order="{{ (^^index + 1) * 1000 + (^item.day + 1) * 100 + ^index }}"
|
|
509
|
+
on-focus=":host.oneventselect($this, ^item.event)" on-blur=":host.oneventunselect($this, ^item.event)"
|
|
510
|
+
css-class="{{ ['day-start-'+ (^item.day + 1), 'day-end-'+ (^item.day + ^item.span + 1)] }}">
|
|
511
|
+
<${P}-span class="event-startdate" culture="{{ :host.culture }}" hide="{{ ^item.continuing.start }}" text="{{ :host.getTimeLabel(^item.event.start) }}"></${P}-span>
|
|
512
|
+
<${P}-span class="event-caption" text="{{ ^item.caption }}"></${P}-span>
|
|
513
|
+
</${P}-panel>
|
|
514
|
+
</template>
|
|
515
|
+
</${P}-repeater>
|
|
516
|
+
</template>
|
|
517
|
+
</${P}-repeater><${P}-content></${P}-content>`
|
|
518
|
+
})
|
|
519
|
+
], PacemCalendarElement);
|
|
520
|
+
export { PacemCalendarElement };
|
|
521
|
+
// #endregion
|
|
522
|
+
// #region CLOCK (to be worked on: many possibilities ahead)
|
|
523
|
+
let PacemClockElement = class PacemClockElement extends Components.PacemElement {
|
|
524
|
+
};
|
|
525
|
+
__decorate([
|
|
526
|
+
Watch({ converter: PropertyConverters.Datetime })
|
|
527
|
+
], PacemClockElement.prototype, "now", void 0);
|
|
528
|
+
PacemClockElement = __decorate([
|
|
529
|
+
CustomElement({ tagName: P + '-clock' })
|
|
530
|
+
], PacemClockElement);
|
|
531
|
+
export { PacemClockElement };
|
|
532
|
+
// #endregion
|
|
533
|
+
// #region SCHEDULE
|
|
534
|
+
function buildCalendarHeader() {
|
|
535
|
+
let header = '';
|
|
536
|
+
for (let day = 0; day < 7; day++) {
|
|
537
|
+
header += `<${P}-span culture="{{ :host.culture }}" css-class="{{ {'viewday': :host.isViewDay(:host.week[${day}], :host.viewDate)} }}" class="schedule-heading day-${day + 1} text-ellipsed" text="{{ :host.getHeaderLabel(:host.week[${day}], :host.zoom) }}"></${P}-span>`;
|
|
538
|
+
}
|
|
539
|
+
const id = "dock_" + Utils.uniqueCode();
|
|
540
|
+
return `<div class="schedule-header schedule-grid"><div class="heading-left"></div>${header}</div>`;
|
|
541
|
+
}
|
|
542
|
+
let PacemScheduleElement = class PacemScheduleElement extends PacemCalendarBaseElement {
|
|
543
|
+
viewActivatedCallback() {
|
|
544
|
+
super.viewActivatedCallback();
|
|
545
|
+
this._calendar.addEventListener('dateselect', this.emitHandler, false);
|
|
546
|
+
this._agenda.addEventListener('timeselect', this.emitHandler, false);
|
|
547
|
+
// bootstrap
|
|
548
|
+
this.now = new Date();
|
|
549
|
+
}
|
|
550
|
+
disconnectedCallback() {
|
|
551
|
+
if (this._calendar) {
|
|
552
|
+
this._calendar.removeEventListener('dateselect', this.emitHandler, false);
|
|
553
|
+
this._agenda.removeEventListener('timeselect', this.emitHandler, false);
|
|
554
|
+
}
|
|
555
|
+
super.disconnectedCallback();
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
__decorate([
|
|
559
|
+
ViewChild(P + '-calendar')
|
|
560
|
+
], PacemScheduleElement.prototype, "_calendar", void 0);
|
|
561
|
+
__decorate([
|
|
562
|
+
ViewChild(P + '-agenda')
|
|
563
|
+
], PacemScheduleElement.prototype, "_agenda", void 0);
|
|
564
|
+
PacemScheduleElement = __decorate([
|
|
565
|
+
CustomElement({
|
|
566
|
+
tagName: P + '-schedule', shadow: Defaults.USE_SHADOW_ROOT,
|
|
567
|
+
template: `<${P}-panel class="${PCSS}-schedule" css-class="{{ ['schedule-'+ (:host.zoom || '${CalendarZoom.Month}')] }}">
|
|
568
|
+
<${P}-timer interval="10000" on-tick=":host.now = Pacem.Utils.parseDate(Date.now())"></${P}-timer>
|
|
569
|
+
${buildCalendarHeader()}
|
|
570
|
+
<${P}-agenda disabled-ranges="{{ :host.disabledRanges }}" on-eventselect=":host.handle($event)" on-eventunselect=":host.handle($event)" now="{{ :host.now }}" culture="{{ :host.culture }}" view-date="{{ :host.viewDate }}" zoom="{{ :host.zoom }}" week-start="{{ :host.weekStart }}" items="{{ :host.items }}"></${P}-agenda>
|
|
571
|
+
<${P}-calendar disabled-ranges="{{ :host.disabledRanges }}" on-eventselect=":host.handle($event)" on-eventunselect=":host.handle($event)" now="{{ :host.now }}" culture="{{ :host.culture }}" view-date="{{ :host.viewDate }}" zoom="{{ :host.zoom }}" week-start="{{ :host.weekStart }}" items="{{ :host.items }}"></${P}-calendar>
|
|
572
|
+
<${P}-content></${P}-content>
|
|
573
|
+
</${P}-panel>`
|
|
574
|
+
})
|
|
575
|
+
], PacemScheduleElement);
|
|
576
|
+
export { PacemScheduleElement };
|
|
577
|
+
// #endregion
|
|
578
|
+
// #region RULES
|
|
579
|
+
export class PacemCalendarRuleBaseElement extends HTMLElement {
|
|
580
|
+
constructor() {
|
|
581
|
+
super(...arguments);
|
|
582
|
+
this._disabledRanges = [];
|
|
583
|
+
}
|
|
584
|
+
viewActivatedCallback() {
|
|
585
|
+
if (!Utils.isNull(this._target = CustomElementUtils.findAncestor(this, node => node instanceof PacemCalendarBaseElement))) {
|
|
586
|
+
this.refreshDisabledRanges();
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
throw `Missing ancestor calendar element for ${this.constructor.name}.`;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
disconnectedCallback() {
|
|
593
|
+
this._target = undefined;
|
|
594
|
+
}
|
|
595
|
+
get target() {
|
|
596
|
+
return this._target;
|
|
597
|
+
}
|
|
598
|
+
refreshDisabledRanges() {
|
|
599
|
+
if (Utils.isNullOrEmpty(this._target)) {
|
|
600
|
+
// TODO: throw
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
let actualRanges = this._target.disabledRanges || [];
|
|
604
|
+
// cleanup old ones
|
|
605
|
+
for (let range of this._disabledRanges) {
|
|
606
|
+
let ndx = actualRanges.indexOf(range);
|
|
607
|
+
if (ndx >= 0) {
|
|
608
|
+
actualRanges.splice(ndx, 1);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
// add new ones
|
|
612
|
+
this._disabledRanges = this.computeDisabledRanges() || [];
|
|
613
|
+
for (let range of this._disabledRanges) {
|
|
614
|
+
actualRanges.push(range);
|
|
615
|
+
}
|
|
616
|
+
this._target.disabledRanges = actualRanges;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
__decorate([
|
|
620
|
+
Debounce(true)
|
|
621
|
+
], PacemCalendarRuleBaseElement.prototype, "refreshDisabledRanges", null);
|
|
622
|
+
let PacemCalendarDayOfWeekRuleElement = class PacemCalendarDayOfWeekRuleElement extends PacemCalendarRuleBaseElement {
|
|
623
|
+
constructor() {
|
|
624
|
+
super(...arguments);
|
|
625
|
+
this._daysOfWeek = [];
|
|
626
|
+
this._calendarChangeHandler = (evt) => {
|
|
627
|
+
if (evt.detail.propertyName == 'month') {
|
|
628
|
+
this.refreshDisabledRanges();
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
viewActivatedCallback() {
|
|
633
|
+
super.viewActivatedCallback();
|
|
634
|
+
this.target.addEventListener(PropertyChangeEventName, this._calendarChangeHandler, false);
|
|
635
|
+
}
|
|
636
|
+
propertyChangedCallback(name, old, val, first) {
|
|
637
|
+
if (name === 'days') {
|
|
638
|
+
this._daysOfWeek = (val || []).map(i => DAYS_OF_WEEK.indexOf(i)).filter(i => i >= 0);
|
|
639
|
+
this.refreshDisabledRanges();
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
computeDisabledRanges() {
|
|
643
|
+
let retval = [];
|
|
644
|
+
for (let week of this.target.month) {
|
|
645
|
+
for (let day of week) {
|
|
646
|
+
if (this._daysOfWeek.indexOf(day.getDay()) == -1) {
|
|
647
|
+
let from = Utils.Dates.dateOnly(day), to = Utils.Dates.dateOnly(new Date(from.valueOf() + MSECS_PER_DAY + /* get rid of daylight saving switches */ MSECS_PER_HOUR));
|
|
648
|
+
retval.push({ from: from, to: to });
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return retval;
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
__decorate([
|
|
656
|
+
Watch({ emit: false, converter: PropertyConverters.StringArray })
|
|
657
|
+
], PacemCalendarDayOfWeekRuleElement.prototype, "days", void 0);
|
|
658
|
+
PacemCalendarDayOfWeekRuleElement = __decorate([
|
|
659
|
+
CustomElement({ tagName: P + '-calendar-daysofweek-rule' })
|
|
660
|
+
], PacemCalendarDayOfWeekRuleElement);
|
|
661
|
+
export { PacemCalendarDayOfWeekRuleElement };
|
|
662
|
+
// #endregion
|