UNPKG

106 kBJavaScriptView Raw
1class _LicenseChecker {
2 constructor() {
3 this._licenseKey = '';
4 this._logOnSuccess = false;
5 this._success = false;
6 }
7 activateLicense(licenseKey, options = { logLicenseActivated: true }) {
8 this._licenseKey = licenseKey;
9 this._logOnSuccess = options.logLicenseActivated;
10 }
11 _checkLicense() {
12 if (this._success) {
13 return;
14 }
15 if (this._licenseKey) {
16 const parts = this._licenseKey.split('-');
17 if (parts.length !== 2) {
18 console.warn(`uiloos > license > invalid license key detected: ${this._licenseKey}, ${buy}`);
19 }
20 else {
21 const [_, type] = parts;
22 if (this._logOnSuccess) {
23 console.log(`uiloos > license > license activated, this license is for use with ${type} developers. We thank you for your support, you can disable this message if you want to. ${owner}`);
24 }
25 this._success = true;
26 }
27 }
28 else {
29 console.warn(`uiloos > license > you are using commercial software, ${buy}`);
30 }
31 }
32}
33let licenseChecker = new _LicenseChecker();
34const owner = 'If you are not the owner of this website please ignore this message.';
35const buy = `please purchase a license at https://www.uiloos.dev. ${owner}`;
36
37const common$3 = `uiloos > ActiveList >`;
38
39class ActiveListAutoPlayDurationError extends Error {
40 constructor() {
41 super(`${common$3} autoPlay > duration cannot be negative or zero`);
42 this.name = 'ActiveListAutoPlayDurationError';
43 }
44}
45
46class _AutoPlay {
47 constructor(activeList, config) {
48 this._autoPlayTimeoutId = null;
49 this._autoPlayStarted = new Date();
50 this._pauseStarted = null;
51 this._autoPlayCurrentDuration = 0;
52 this._config = null;
53 this._activeList = activeList;
54 this._config = config;
55 }
56 _setConfig(config) {
57 this._config = config;
58 }
59 _play(inform) {
60 this._cancelTimer();
61 if (!this._config || this._activeList.lastActivatedContent === null) {
62 return;
63 }
64 const duration = this._getDuration(this._config, this._activeList.lastActivatedContent);
65 if (duration <= 0) {
66 throw new ActiveListAutoPlayDurationError();
67 }
68 this._autoPlayCurrentDuration = duration;
69 if (this._pauseStarted === null) {
70 this._activeList.autoPlay.duration = duration;
71 }
72 else {
73 this._pauseStarted = null;
74 }
75 this._autoPlayStarted = new Date();
76 this._autoPlayTimeoutId = window.setTimeout(() => {
77 this._autoPlayTimeoutId = null;
78 this._activeList.activateNext({ isUserInteraction: false });
79 }, duration);
80 this._activeList.autoPlay.isPlaying = true;
81 if (inform) {
82 const event = {
83 type: 'AUTO_PLAY_PLAYING',
84 time: new Date(),
85 };
86 this._activeList._inform(event);
87 }
88 }
89 _pause() {
90 if (!this._activeList.autoPlay.isPlaying) {
91 return;
92 }
93 this._pauseStarted = new Date();
94 this._cancelTimer();
95 this._activeList.autoPlay.isPlaying = false;
96 const event = {
97 type: 'AUTO_PLAY_PAUSED',
98 time: new Date(),
99 };
100 this._activeList._inform(event);
101 }
102 _stop() {
103 if (!this._activeList.autoPlay.isPlaying && !this._pauseStarted) {
104 return;
105 }
106 this._cancelTimer();
107 this._pauseStarted = null;
108 this._activeList.autoPlay.isPlaying = false;
109 this._activeList.autoPlay.duration = 0;
110 this._activeList.autoPlay.hasBeenStoppedBefore = true;
111 const event = {
112 type: 'AUTO_PLAY_STOPPED',
113 time: new Date(),
114 };
115 this._activeList._inform(event);
116 }
117 _cancelTimer() {
118 if (this._autoPlayTimeoutId !== null) {
119 window.clearTimeout(this._autoPlayTimeoutId);
120 this._autoPlayTimeoutId = null;
121 }
122 }
123 _onDeactivation(activationOptions) {
124 if (this._activeList.lastActivatedContent === null) {
125 this._stop();
126 return;
127 }
128 if (!this._config) {
129 return;
130 }
131 if (this._shouldStopOnUserInteraction(activationOptions, this._config)) {
132 this._stop();
133 return;
134 }
135 }
136 onActiveIndexChanged(index, activationOptions) {
137 if (!this._config) {
138 return;
139 }
140 if (this._shouldStopOnUserInteraction(activationOptions, this._config)) {
141 this._stop();
142 }
143 else if (this._activeList.isCircular === false &&
144 index === this._activeList.getLastIndex()) {
145 this._stop();
146 }
147 else {
148 this._play(false);
149 }
150 }
151 _shouldStopOnUserInteraction(activationOptions, config) {
152 return !!(activationOptions &&
153 activationOptions.isUserInteraction !== false &&
154 config.stopsOnUserInteraction);
155 }
156 _getDuration(config, lastActivatedContent) {
157 if (this._pauseStarted) {
158 return (this._autoPlayCurrentDuration -
159 (this._pauseStarted.getTime() - this._autoPlayStarted.getTime()));
160 }
161 if (typeof config.duration === 'number') {
162 return config.duration;
163 }
164 else {
165 return config.duration({
166 index: lastActivatedContent.index,
167 content: lastActivatedContent,
168 value: lastActivatedContent.value,
169 activeList: this._activeList,
170 });
171 }
172 }
173}
174
175class ActiveListContent {
176 constructor(activeList, index, value) {
177 this.isActive = false;
178 this.hasBeenActiveBefore = false;
179 this.isFirst = false;
180 this.isLast = false;
181 this.hasNext = false;
182 this.hasPrevious = false;
183 this.isNext = false;
184 this.isPrevious = false;
185 this.activeList = activeList;
186 this.index = index;
187 this.value = value;
188 }
189 activate(activationOptions) {
190 this.activeList.activateByIndex(this.index, activationOptions);
191 }
192 deactivate(activationOptions) {
193 this.activeList.deactivateByIndex(this.index, activationOptions);
194 }
195 toggle(activationOptions) {
196 this.activeList.toggleByIndex(this.index, activationOptions);
197 }
198 remove() {
199 return this.activeList.removeByIndex(this.index);
200 }
201 swapWith(item) {
202 const itemIndex = this.activeList.getIndex(item);
203 this.swapWithByIndex(itemIndex);
204 }
205 swapWithByIndex(index) {
206 this.activeList.swapByIndex(this.index, index);
207 }
208 swapWithNext() {
209 const nextIndex = this.activeList._getBoundedNextIndex(this.index);
210 this.swapWithByIndex(nextIndex);
211 }
212 swapWithPrevious() {
213 const previousIndex = this.activeList._getBoundedPreviousIndex(this.index);
214 this.swapWithByIndex(previousIndex);
215 }
216 moveToIndex(to) {
217 this.activeList.moveByIndex(this.index, to);
218 }
219 moveToPredicate(predicate, options) {
220 this.activeList.moveByIndexByPredicate(this.index, predicate, options);
221 }
222 moveToFirst() {
223 this.activeList.moveByIndex(this.index, 0);
224 }
225 moveToLast() {
226 this.activeList.moveByIndex(this.index, this.activeList.getLastIndex());
227 }
228}
229
230class ActiveListCooldownDurationError extends Error {
231 constructor() {
232 super(`${common$3} cooldown > duration cannot be negative or zero`);
233 this.name = "ActiveListCooldownDurationError";
234 }
235}
236
237class _CooldownTimer {
238 constructor(activeList, cooldown) {
239 this._cooldownTimeoutId = null;
240 this._cooldown = undefined;
241 if (typeof cooldown === 'number') {
242 this._assertDuration(cooldown);
243 }
244 this._activeList = activeList;
245 this._cooldown = cooldown;
246 }
247 _isActive(activationOptions) {
248 if (activationOptions.isUserInteraction === false) {
249 return false;
250 }
251 return this._activeList.cooldown.isActive;
252 }
253 _setCooldown(activationOptions, content) {
254 if (activationOptions.isUserInteraction === false) {
255 return;
256 }
257 const duration = this._getDuration(activationOptions, content);
258 if (duration === -1) {
259 this._stopCooldown();
260 return;
261 }
262 this._activeList.cooldown.isActive = true;
263 this._activeList.cooldown.duration = duration;
264 this._cooldownTimeoutId = window.setTimeout(() => {
265 this._stopCooldown();
266 }, duration);
267 const event = {
268 type: 'COOLDOWN_STARTED',
269 time: new Date(),
270 };
271 this._activeList._inform(event);
272 }
273 _getDuration(activationOptions, content) {
274 let duration = -1;
275 if (activationOptions.cooldown !== undefined) {
276 duration = this._getDurationFromConfig(activationOptions.cooldown, content);
277 }
278 else if (this._cooldown !== undefined) {
279 duration = this._getDurationFromConfig(this._cooldown, content);
280 }
281 else {
282 return -1;
283 }
284 this._assertDuration(duration);
285 return duration;
286 }
287 _getDurationFromConfig(cooldownConfig, content) {
288 if (typeof cooldownConfig === 'number') {
289 return cooldownConfig;
290 }
291 else {
292 return cooldownConfig({
293 index: content.index,
294 content: content,
295 value: content.value,
296 activeList: this._activeList,
297 });
298 }
299 }
300 _assertDuration(cooldownValue) {
301 if (cooldownValue <= 0) {
302 throw new ActiveListCooldownDurationError();
303 }
304 }
305 _stopCooldown() {
306 if (this._cooldownTimeoutId) {
307 window.clearTimeout(this._cooldownTimeoutId);
308 }
309 if (!this._activeList.cooldown.isActive) {
310 return;
311 }
312 this._activeList.cooldown.isActive = false;
313 this._activeList.cooldown.duration = 0;
314 const event = {
315 type: 'COOLDOWN_ENDED',
316 time: new Date(),
317 };
318 this._activeList._inform(event);
319 }
320}
321
322class ActiveListActivationLimitReachedError extends Error {
323 constructor() {
324 super(`${common$3} activateByIndex > activation limit reached`);
325 this.name = 'ActiveListActivationLimitReachedError';
326 }
327}
328
329class ActiveListIndexOutOfBoundsError extends Error {
330 constructor(message) {
331 super(message);
332 this.name = "ActiveListIndexOutOfBoundsError";
333 }
334}
335function throwIndexOutOfBoundsError(method, indexName) {
336 throw new ActiveListIndexOutOfBoundsError(`${common$3} ${method} > "${indexName}" is out of bounds`);
337}
338
339class ActiveListItemNotFoundError extends Error {
340 constructor() {
341 super(`${common$3} getIndex > index cannot be found, item is not in contents array`);
342 this.name = 'ActiveListItemNotFoundError';
343 }
344}
345
346class _History {
347 constructor() {
348 this._events = [];
349 this._keepHistoryFor = 0;
350 }
351 _push(event) {
352 if (this._keepHistoryFor > 0) {
353 this._events.push(event);
354 if (this._events.length - 1 === this._keepHistoryFor) {
355 this._events.shift();
356 }
357 }
358 }
359 _setKeepHistoryFor(_keepHistoryFor = 0) {
360 this._keepHistoryFor = _keepHistoryFor;
361 }
362}
363
364class _Observer {
365 constructor() {
366 this._subscribers = [];
367 }
368 _subscribe(subscriber) {
369 this._subscribers.push(subscriber);
370 return () => {
371 this._unsubscribe(subscriber);
372 };
373 }
374 _unsubscribe(subscriber) {
375 this._subscribers = this._subscribers.filter((s) => subscriber !== s);
376 }
377 _clear() {
378 this._subscribers.length = 0;
379 }
380 _inform(observable, event) {
381 this._subscribers.forEach((subscriber) => subscriber(observable, event));
382 }
383}
384
385class ActiveList {
386 constructor(config = {}, subscriber) {
387 this._isInitializing = false;
388 this.contents = [];
389 this.maxActivationLimit = 1;
390 this.maxActivationLimitBehavior = 'circular';
391 this.active = [];
392 this.activeContents = [];
393 this.activeIndexes = [];
394 this.lastActivated = null;
395 this.lastActivatedContent = null;
396 this.lastActivatedIndex = -1;
397 this.lastDeactivated = null;
398 this.lastDeactivatedContent = null;
399 this.lastDeactivatedIndex = -1;
400 this.isCircular = false;
401 this.direction = 'right';
402 this.oppositeDirection = 'left';
403 this._history = new _History();
404 this.history = this._history._events;
405 this._observer = new _Observer();
406 this.hasActiveChangedAtLeastOnce = false;
407 this.cooldown = {
408 isActive: false,
409 duration: 0,
410 };
411 this.autoPlay = {
412 isPlaying: false,
413 duration: 0,
414 hasBeenStoppedBefore: false,
415 };
416 licenseChecker._checkLicense();
417 if (subscriber) {
418 this.subscribe(subscriber);
419 }
420 this.initialize(config);
421 }
422 subscribe(subscriber) {
423 return this._observer._subscribe(subscriber);
424 }
425 unsubscribe(subscriber) {
426 this._observer._unsubscribe(subscriber);
427 }
428 unsubscribeAll() {
429 this._observer._clear();
430 }
431 initialize(config) {
432 this._isInitializing = true;
433 this.maxActivationLimit =
434 config.maxActivationLimit !== undefined ? config.maxActivationLimit : 1;
435 this.maxActivationLimitBehavior = config.maxActivationLimitBehavior
436 ? config.maxActivationLimitBehavior
437 : 'circular';
438 this.isCircular = !!config.isCircular;
439 const contents = config.contents ? config.contents : [];
440 this.contents.length = 0;
441 contents.forEach((c, index) => {
442 this.contents[index] = this._initializeABrokenContent(c, index, contents);
443 });
444 this._directions = config.directions
445 ? config.directions
446 : { next: 'right', previous: 'left' };
447 this._history._events.length = 0;
448 this._history._setKeepHistoryFor(config.keepHistoryFor);
449 this._becameEmpty();
450 this._activationCooldownTimer = new _CooldownTimer(this, config.cooldown);
451 this.cooldown.isActive = false;
452 this.cooldown.duration = 0;
453 if (config.active !== undefined) {
454 if (Array.isArray(config.active)) {
455 config.active.forEach((active) => this.activate(active, { isUserInteraction: false }));
456 }
457 else {
458 this.activate(config.active, { isUserInteraction: false });
459 }
460 }
461 else if (config.activeIndexes !== undefined) {
462 if (Array.isArray(config.activeIndexes)) {
463 config.activeIndexes.forEach((index) => this.activateByIndex(index, {
464 isUserInteraction: false,
465 }));
466 }
467 else {
468 this.activateByIndex(config.activeIndexes, {
469 isUserInteraction: false,
470 });
471 }
472 }
473 this._emptyLastDeactivated();
474 this.hasActiveChangedAtLeastOnce = false;
475 this.direction = this._directions.next;
476 this.oppositeDirection = this._directions.previous;
477 this.autoPlay.isPlaying = false;
478 this.autoPlay.duration = 0;
479 this.autoPlay.hasBeenStoppedBefore = false;
480 this._autoPlay = new _AutoPlay(this, config.autoPlay ? config.autoPlay : null);
481 this._autoPlay._play(false);
482 this._isInitializing = false;
483 const event = {
484 type: 'INITIALIZED',
485 values: [...this.active],
486 indexes: [...this.activeIndexes],
487 time: new Date(),
488 };
489 this._inform(event);
490 }
491 _initializeABrokenContent(value, index, contents) {
492 const content = new ActiveListContent(this, index, value);
493 this._repairContent(content, index, contents);
494 return content;
495 }
496 activateByIndex(index, activationOptions = {
497 isUserInteraction: true,
498 cooldown: undefined,
499 }) {
500 const previousDeactivatedIndex = this.lastDeactivatedIndex;
501 const activatedContent = this._doActivateByIndex(index, activationOptions);
502 if (!activatedContent) {
503 return;
504 }
505 let deactivatedIndex = -1;
506 let deactivatedValue = null;
507 if (previousDeactivatedIndex !== this.lastDeactivatedIndex) {
508 deactivatedIndex = this.lastDeactivatedIndex;
509 deactivatedValue = this.lastDeactivated;
510 }
511 const event = {
512 type: 'ACTIVATED',
513 value: activatedContent.value,
514 index,
515 deactivatedIndex,
516 deactivatedValue,
517 time: new Date(),
518 };
519 this._inform(event);
520 this._activationCooldownTimer._setCooldown(activationOptions, this.lastActivatedContent);
521 }
522 _doActivateByIndex(index, activationOptions) {
523 if (this._checkIndex(index)) {
524 throwIndexOutOfBoundsError('activateByIndex', 'index');
525 }
526 if (this.activeIndexes.includes(index)) {
527 return null;
528 }
529 if (this._activationCooldownTimer._isActive(activationOptions)) {
530 return null;
531 }
532 const limitReached = this.maxActivationLimit === false
533 ? false
534 : this.maxActivationLimit === this.activeIndexes.length;
535 if (limitReached) {
536 if (this.maxActivationLimitBehavior === 'error') {
537 throw new ActiveListActivationLimitReachedError();
538 }
539 else if (this.maxActivationLimitBehavior === 'ignore') {
540 return null;
541 }
542 }
543 const nextIndex = this._getUnboundedNextIndex(index);
544 const previousIndex = this._getUnboundedPreviousIndex(index);
545 this.contents.forEach((content, i) => {
546 content.isActive = content.isActive ? content.isActive : index === i;
547 content.isNext = nextIndex === i;
548 content.isPrevious = previousIndex === i;
549 if (index === i) {
550 this.activeIndexes.push(i);
551 this.activeContents.push(content);
552 this.active.push(content.value);
553 if (limitReached) {
554 this.activeIndexes.shift();
555 this.active.shift();
556 const content = this.activeContents.shift();
557 if (content) {
558 this._deactivateContent(content);
559 }
560 }
561 this.direction = this._getDirectionWhenMovingToIndex(i);
562 this.oppositeDirection =
563 this.direction === this._directions.next
564 ? this._directions.previous
565 : this._directions.next;
566 this.lastActivated = content.value;
567 this.lastActivatedContent = content;
568 this.lastActivatedIndex = i;
569 content.hasBeenActiveBefore = true;
570 }
571 });
572 if (this._autoPlay) {
573 this._autoPlay.onActiveIndexChanged(index, activationOptions);
574 }
575 this.hasActiveChangedAtLeastOnce = true;
576 return this.lastActivatedContent;
577 }
578 activate(item, activationOptions) {
579 const index = this.getIndex(item);
580 this.activateByIndex(index, activationOptions);
581 }
582 activateByPredicate(predicate, activationOptions = {
583 isUserInteraction: true,
584 cooldown: undefined,
585 }) {
586 if (this._activationCooldownTimer._isActive(activationOptions)) {
587 return undefined;
588 }
589 const previousActiveIndexes = [...this.activeIndexes];
590 let lastActivated = null;
591 let error = null;
592 this._execPred(predicate, (index) => {
593 try {
594 const content = this._doActivateByIndex(index, activationOptions);
595 if (content) {
596 lastActivated = content;
597 }
598 }
599 catch (e) {
600 if (e instanceof ActiveListActivationLimitReachedError) {
601 error = e;
602 return true;
603 }
604 }
605 });
606 if (lastActivated) {
607 const values = [];
608 const indexes = [];
609 this.activeIndexes.forEach((current) => {
610 const isNewlyActivated = previousActiveIndexes.every((prev) => prev !== current);
611 if (isNewlyActivated) {
612 indexes.push(current);
613 values.push(this.contents[current].value);
614 }
615 });
616 const deactivatedValues = [];
617 const deactivatedIndexes = [];
618 if (this.maxActivationLimit !== false &&
619 this.maxActivationLimitBehavior === 'circular') {
620 previousActiveIndexes.forEach((prev) => {
621 const isNewlyDeactivated = this.activeIndexes.every((current) => prev !== current);
622 if (isNewlyDeactivated) {
623 deactivatedIndexes.push(prev);
624 deactivatedValues.push(this.contents[prev].value);
625 }
626 });
627 }
628 const event = {
629 type: 'ACTIVATED_MULTIPLE',
630 values,
631 indexes,
632 deactivatedIndexes,
633 deactivatedValues,
634 time: new Date(),
635 };
636 this._inform(event);
637 if (lastActivated) {
638 this._activationCooldownTimer._setCooldown(activationOptions, lastActivated);
639 }
640 }
641 if (error) {
642 throw error;
643 }
644 }
645 activateNext(activationOptions) {
646 if (this.isEmpty()) {
647 return;
648 }
649 const index = this._getBoundedNextIndex(this.lastActivatedIndex);
650 this.activateByIndex(index, activationOptions);
651 }
652 activatePrevious(activationOptions) {
653 if (this.isEmpty()) {
654 return;
655 }
656 const index = this._getBoundedPreviousIndex(this.lastActivatedIndex);
657 this.activateByIndex(index, activationOptions);
658 }
659 activateFirst(activationOptions) {
660 if (this.isEmpty()) {
661 return;
662 }
663 this.activateByIndex(0, activationOptions);
664 }
665 activateLast(activationOptions) {
666 if (this.isEmpty()) {
667 return;
668 }
669 this.activateByIndex(this.getLastIndex(), activationOptions);
670 }
671 deactivateByIndex(index, activationOptions = {
672 isUserInteraction: true,
673 cooldown: undefined,
674 }) {
675 const deactivatedContent = this._doDeactivateByIndex(index, activationOptions);
676 if (!deactivatedContent) {
677 return;
678 }
679 const event = {
680 type: 'DEACTIVATED',
681 value: this.contents[index].value,
682 index,
683 time: new Date(),
684 };
685 this._inform(event);
686 this._activationCooldownTimer._setCooldown(activationOptions, deactivatedContent);
687 }
688 _doDeactivateByIndex(index, activationOptions) {
689 if (this._checkIndex(index)) {
690 throwIndexOutOfBoundsError('deactivateByIndex', 'index');
691 }
692 const indexOfIndex = this.activeIndexes.indexOf(index);
693 if (indexOfIndex === -1) {
694 return null;
695 }
696 if (this._activationCooldownTimer._isActive(activationOptions)) {
697 return null;
698 }
699 const deactivatedContent = this.activeContents[indexOfIndex];
700 this._deactivateContent(deactivatedContent);
701 this.activeIndexes.splice(indexOfIndex, 1);
702 this.active.splice(indexOfIndex, 1);
703 this.activeContents.splice(indexOfIndex, 1);
704 if (this.activeIndexes.length === 0) {
705 this._emptyLastActives();
706 this.direction = this._directions.next;
707 }
708 else {
709 this._setLastActives();
710 this.direction = this._getDirectionWhenMovingToIndex(deactivatedContent.index);
711 this.oppositeDirection = this.direction;
712 this.direction =
713 this.direction === this._directions.next
714 ? this._directions.previous
715 : this._directions.next;
716 }
717 this._repairContents();
718 this.hasActiveChangedAtLeastOnce = true;
719 if (this._autoPlay) {
720 this._autoPlay._onDeactivation(activationOptions);
721 }
722 return deactivatedContent;
723 }
724 deactivate(item, activationOptions) {
725 const index = this.getIndex(item);
726 this.deactivateByIndex(index, activationOptions);
727 }
728 deactivateByPredicate(predicate, activationOptions = {
729 isUserInteraction: true,
730 cooldown: undefined,
731 }) {
732 if (this._activationCooldownTimer._isActive(activationOptions)) {
733 return undefined;
734 }
735 const deactivatedIndexes = [];
736 const deactivatedValues = [];
737 let lastRemoved = null;
738 this._execPred(predicate, (index) => {
739 const content = this._doDeactivateByIndex(index, activationOptions);
740 if (content) {
741 deactivatedIndexes.push(content.index);
742 deactivatedValues.push(content.value);
743 lastRemoved = content;
744 }
745 });
746 if (deactivatedIndexes.length === 0) {
747 return;
748 }
749 const event = {
750 type: 'DEACTIVATED_MULTIPLE',
751 values: deactivatedValues,
752 indexes: deactivatedIndexes,
753 time: new Date(),
754 };
755 this._inform(event);
756 if (lastRemoved) {
757 this._activationCooldownTimer._setCooldown(activationOptions, lastRemoved);
758 }
759 }
760 toggleByIndex(index, activationOptions) {
761 if (this._checkIndex(index)) {
762 throwIndexOutOfBoundsError('toggleByIndex', 'index');
763 }
764 if (this.contents[index].isActive) {
765 this.deactivateByIndex(index, activationOptions);
766 }
767 else {
768 this.activateByIndex(index, activationOptions);
769 }
770 }
771 toggle(item, activationOptions) {
772 const index = this.getIndex(item);
773 this.toggleByIndex(index, activationOptions);
774 }
775 play() {
776 this._autoPlay._play(true);
777 }
778 pause() {
779 this._autoPlay._pause();
780 }
781 stop() {
782 this._autoPlay._stop();
783 }
784 configureAutoPlay(autoPlayConfig) {
785 this._autoPlay._setConfig(autoPlayConfig);
786 if (autoPlayConfig) {
787 this._autoPlay._play(true);
788 }
789 else {
790 this._autoPlay._stop();
791 }
792 }
793 insertAtIndex(item, index) {
794 if (index < 0 || index > this.contents.length) {
795 throwIndexOutOfBoundsError('insertAtIndex', 'index');
796 }
797 const content = this._initializeABrokenContent(item, index, this.contents);
798 this.activeIndexes.forEach((i, aiIndex) => {
799 this.activeIndexes[aiIndex] = i >= index ? i + 1 : i;
800 });
801 this.contents.splice(index, 0, content);
802 if (index <= this.lastActivatedIndex) {
803 this.lastActivatedIndex += 1;
804 }
805 this._repairContents();
806 const event = {
807 type: 'INSERTED',
808 value: item,
809 index,
810 time: new Date(),
811 };
812 this._inform(event);
813 return content;
814 }
815 push(item) {
816 return this.insertAtIndex(item, this.contents.length);
817 }
818 unshift(item) {
819 return this.insertAtIndex(item, 0);
820 }
821 insertByPredicate(item, predicate, options = { mode: 'at' }) {
822 const mod = this._modeToMod(options.mode);
823 return this._execPred(predicate, (index) => {
824 const atIndex = Math.max(0, index + mod);
825 return this.insertAtIndex(item, atIndex);
826 });
827 }
828 removeByIndex(index) {
829 const value = this._doRemoveAtIndex(index);
830 const indexOfIndex = this.activeIndexes.indexOf(index);
831 if (indexOfIndex !== -1) {
832 this.activeIndexes.splice(indexOfIndex, 1);
833 this.active.splice(indexOfIndex, 1);
834 this.activeContents.splice(indexOfIndex, 1);
835 this.hasActiveChangedAtLeastOnce = true;
836 }
837 this.activeIndexes.map((i, aiIndex) => {
838 this.activeIndexes[aiIndex] = i >= index ? i - 1 : i;
839 });
840 if (this.isEmpty()) {
841 this._becameEmpty();
842 this._autoPlay._stop();
843 }
844 else {
845 this._setLastActives();
846 }
847 this._repairContents();
848 const event = {
849 type: 'REMOVED',
850 value,
851 index,
852 time: new Date(),
853 };
854 this._inform(event);
855 return value;
856 }
857 _doRemoveAtIndex(index) {
858 if (this._checkIndex(index)) {
859 throwIndexOutOfBoundsError('removeByIndex', 'index');
860 }
861 if (this.lastDeactivated && this.lastDeactivatedIndex === index) {
862 this._emptyLastDeactivated();
863 }
864 const value = this.contents[index].value;
865 this.contents.splice(index, 1);
866 return value;
867 }
868 remove(item) {
869 const index = this.getIndex(item);
870 return this.removeByIndex(index);
871 }
872 pop() {
873 if (this.isEmpty()) {
874 return undefined;
875 }
876 return this.removeByIndex(this.getLastIndex());
877 }
878 shift() {
879 if (this.isEmpty()) {
880 return undefined;
881 }
882 return this.removeByIndex(0);
883 }
884 removeByPredicate(predicate) {
885 if (this.isEmpty()) {
886 return [];
887 }
888 const removed = [];
889 this._execPred(predicate, (index) => {
890 const content = this.contents[index];
891 removed.push(content);
892 });
893 const removedIndexes = [];
894 removed.forEach((content, index) => {
895 const actualIndex = content.index - index;
896 this._doRemoveAtIndex(actualIndex);
897 removedIndexes.push(content.index);
898 });
899 if (this.isEmpty()) {
900 this._becameEmpty();
901 this._autoPlay._stop();
902 }
903 else {
904 removedIndexes.forEach((index) => {
905 const indexOfIndex = this.activeIndexes.indexOf(index);
906 if (indexOfIndex !== -1) {
907 this.activeIndexes.splice(indexOfIndex, 1);
908 this.active.splice(indexOfIndex, 1);
909 this.activeContents.splice(indexOfIndex, 1);
910 this.hasActiveChangedAtLeastOnce = true;
911 }
912 });
913 removedIndexes.forEach((removed) => {
914 this.activeIndexes.forEach((index, aiIndex) => {
915 this.activeIndexes[aiIndex] = index >= removed ? index - 1 : index;
916 });
917 });
918 this._setLastActives();
919 }
920 const removedValues = removed.map((r) => r.value);
921 if (removedIndexes.length > 0) {
922 this._repairContents();
923 const event = {
924 type: 'REMOVED_MULTIPLE',
925 indexes: [...removedIndexes],
926 values: [...removedValues],
927 time: new Date(),
928 };
929 this._inform(event);
930 }
931 return removedValues;
932 }
933 swapByIndex(a, b) {
934 if (this._checkIndex(a)) {
935 throwIndexOutOfBoundsError('swapByIndex', 'a');
936 }
937 if (this._checkIndex(b)) {
938 throwIndexOutOfBoundsError('swapByIndex', 'b');
939 }
940 if (a === b) {
941 return;
942 }
943 const itemA = this.contents[a];
944 const itemB = this.contents[b];
945 if (this.lastActivatedIndex === itemA.index) {
946 this.lastActivatedIndex = itemB.index;
947 }
948 else if (this.lastActivatedIndex === itemB.index) {
949 this.lastActivatedIndex = itemA.index;
950 }
951 const indexOfA = this.activeIndexes.indexOf(itemA.index);
952 const indexOfB = this.activeIndexes.indexOf(itemB.index);
953 if (indexOfA !== -1) {
954 this.activeIndexes[indexOfA] = itemB.index;
955 }
956 if (indexOfB !== -1) {
957 this.activeIndexes[indexOfB] = itemA.index;
958 }
959 itemA.index = b;
960 itemB.index = a;
961 this.contents[a] = itemB;
962 this.contents[b] = itemA;
963 this._repairContents();
964 const event = {
965 type: 'SWAPPED',
966 value: {
967 a: itemA.value,
968 b: itemB.value,
969 },
970 index: {
971 a,
972 b,
973 },
974 time: new Date(),
975 };
976 this._inform(event);
977 }
978 swap(a, b) {
979 const indexA = this.getIndex(a);
980 const indexB = this.getIndex(b);
981 this.swapByIndex(indexA, indexB);
982 }
983 moveByIndex(from, to) {
984 if (this._checkIndex(from)) {
985 throwIndexOutOfBoundsError('moveByIndex', 'from');
986 }
987 if (this._checkIndex(to)) {
988 throwIndexOutOfBoundsError('moveByIndex', 'to');
989 }
990 if (from === to) {
991 return;
992 }
993 const lastActivatedIndex = this.lastActivatedIndex;
994 if (lastActivatedIndex === from) {
995 this.lastActivatedIndex = to;
996 }
997 else if (to === lastActivatedIndex && from > lastActivatedIndex) {
998 this.lastActivatedIndex += 1;
999 }
1000 else if (to === lastActivatedIndex && from < lastActivatedIndex) {
1001 this.lastActivatedIndex -= 1;
1002 }
1003 else if (to > lastActivatedIndex && from < lastActivatedIndex) {
1004 this.lastActivatedIndex -= 1;
1005 }
1006 else if (to < lastActivatedIndex && from > lastActivatedIndex) {
1007 this.lastActivatedIndex += 1;
1008 }
1009 this.activeIndexes.forEach((index, aiIndex) => {
1010 if (index === from) {
1011 this.activeIndexes[aiIndex] = to;
1012 return;
1013 }
1014 if (index > from && index > to) {
1015 this.activeIndexes[aiIndex] = index;
1016 return;
1017 }
1018 if (index < from && index < to) {
1019 this.activeIndexes[aiIndex] = index;
1020 return;
1021 }
1022 this.activeIndexes[aiIndex] = from > to ? index + 1 : index - 1;
1023 });
1024 const fromItem = this.contents[from];
1025 this.contents.splice(from, 1);
1026 this.contents.splice(to, 0, fromItem);
1027 this._repairContents();
1028 const event = {
1029 type: 'MOVED',
1030 value: fromItem.value,
1031 index: {
1032 from,
1033 to,
1034 },
1035 time: new Date(),
1036 };
1037 this._inform(event);
1038 }
1039 move(item, to) {
1040 const from = this.getIndex(item);
1041 this.moveByIndex(from, to);
1042 }
1043 moveByIndexByPredicate(index, predicate, options = { mode: 'at' }) {
1044 const mod = this._modeToMod(options.mode);
1045 this._execPred(predicate, (i, length) => {
1046 const atIndex = Math.min(Math.max(0, i + mod), length - 1);
1047 this.moveByIndex(index, atIndex);
1048 return true;
1049 });
1050 }
1051 moveByPredicate(item, predicate, options) {
1052 const index = this.getIndex(item);
1053 this.moveByIndexByPredicate(index, predicate, options);
1054 }
1055 getIndex(item) {
1056 const contents = this.contents;
1057 const length = contents.length;
1058 for (let i = 0; i < length; i++) {
1059 if (contents[i].value === item) {
1060 return i;
1061 }
1062 }
1063 throw new ActiveListItemNotFoundError();
1064 }
1065 getLastIndex() {
1066 return this.contents.length - 1;
1067 }
1068 _getBoundedNextIndex(index) {
1069 let nextIndex = index + 1;
1070 if (nextIndex >= this.contents.length) {
1071 nextIndex = this.isCircular ? 0 : this.getLastIndex();
1072 }
1073 return nextIndex;
1074 }
1075 _getBoundedPreviousIndex(index) {
1076 let previousIndex = index - 1;
1077 if (previousIndex < 0) {
1078 previousIndex = this.isCircular ? this.getLastIndex() : 0;
1079 }
1080 return previousIndex;
1081 }
1082 _getUnboundedNextIndex(index) {
1083 const nextIndex = index + 1;
1084 if (this.isCircular && nextIndex === this.contents.length) {
1085 return 0;
1086 }
1087 return nextIndex;
1088 }
1089 _getUnboundedPreviousIndex(index) {
1090 const previousIndex = index - 1;
1091 if (this.isCircular && previousIndex < 0) {
1092 return this.getLastIndex();
1093 }
1094 return previousIndex;
1095 }
1096 isEmpty() {
1097 return this.contents.length === 0;
1098 }
1099 _getDirectionWhenMovingToIndex(next) {
1100 const lastActivatedIndex = this.lastActivatedIndex;
1101 if (this.isCircular) {
1102 if (this.lastActivatedIndex === -1) {
1103 return this._directions.next;
1104 }
1105 const lastActivatedLargerThanNext = this.lastActivatedIndex > next;
1106 const lastIndex = this.getLastIndex();
1107 const leftDistance = lastActivatedLargerThanNext
1108 ? this.lastActivatedIndex - next
1109 : lastIndex - next + this.lastActivatedIndex + 1;
1110 const rightDistance = lastActivatedLargerThanNext
1111 ? 1 + next + (lastIndex - this.lastActivatedIndex)
1112 : next - this.lastActivatedIndex;
1113 return leftDistance >= rightDistance
1114 ? this._directions.next
1115 : this._directions.previous;
1116 }
1117 else {
1118 return next >= lastActivatedIndex
1119 ? this._directions.next
1120 : this._directions.previous;
1121 }
1122 }
1123 _repairContents() {
1124 let nextIndex = null;
1125 let previousIndex = null;
1126 if (this.lastActivatedIndex !== -1) {
1127 nextIndex = this._getUnboundedNextIndex(this.lastActivatedIndex);
1128 previousIndex = this._getUnboundedPreviousIndex(this.lastActivatedIndex);
1129 }
1130 this.contents.forEach((content, index) => {
1131 content.index = index;
1132 content.isNext = nextIndex === index;
1133 content.isPrevious = previousIndex === index;
1134 this._repairContent(content, index, this.contents);
1135 });
1136 }
1137 _repairContent(content, index, contents) {
1138 content.isFirst = index === 0;
1139 content.isLast = index === contents.length - 1;
1140 if (this.isCircular) {
1141 content.hasNext = true;
1142 content.hasPrevious = true;
1143 }
1144 else {
1145 content.hasNext = index + 1 < contents.length;
1146 content.hasPrevious = index - 1 >= 0;
1147 }
1148 }
1149 _emptyLastActives() {
1150 this.lastActivatedIndex = -1;
1151 this.lastActivated = null;
1152 this.lastActivatedContent = null;
1153 }
1154 _emptyLastDeactivated() {
1155 this.lastDeactivatedIndex = -1;
1156 this.lastDeactivated = null;
1157 this.lastDeactivatedContent = null;
1158 }
1159 _becameEmpty() {
1160 this._emptyLastDeactivated();
1161 this._emptyLastActives();
1162 this.activeContents.length = 0;
1163 this.activeIndexes.length = 0;
1164 this.active.length = 0;
1165 this.hasActiveChangedAtLeastOnce = true;
1166 }
1167 _setLastActives() {
1168 if (this.activeIndexes.length === 0) {
1169 this._emptyLastActives();
1170 return;
1171 }
1172 const newLastActiveIndex = this.activeIndexes[this.activeIndexes.length - 1];
1173 const newLastActiveList = this.contents[newLastActiveIndex];
1174 this.lastActivated = newLastActiveList.value;
1175 this.lastActivatedContent = newLastActiveList;
1176 this.lastActivatedIndex = newLastActiveIndex;
1177 }
1178 _deactivateContent(content) {
1179 content.isActive = false;
1180 this.lastDeactivated = content.value;
1181 this.lastDeactivatedContent = content;
1182 this.lastDeactivatedIndex = content.index;
1183 }
1184 _execPred(predicate, action) {
1185 const contents = this.contents;
1186 const length = contents.length;
1187 for (let index = 0; index < length; index++) {
1188 const content = this.contents[index];
1189 const data = {
1190 index,
1191 content,
1192 value: content.value,
1193 activeList: this,
1194 };
1195 if (predicate(data)) {
1196 const result = action(index, length);
1197 if (result !== undefined) {
1198 return result;
1199 }
1200 }
1201 }
1202 return null;
1203 }
1204 _inform(event) {
1205 if (this._isInitializing) {
1206 return;
1207 }
1208 this._history._push(event);
1209 this._observer._inform(this, event);
1210 }
1211 _checkIndex(index) {
1212 return index < 0 || index >= this.contents.length;
1213 }
1214 _modeToMod(mode) {
1215 return mode === 'at' ? 0 : mode === 'after' ? 1 : -1;
1216 }
1217}
1218
1219function _callSubscriber(subscriberName, event, component, config) {
1220 const methodName = 'on' +
1221 event.type
1222 .toLowerCase()
1223 .split('_')
1224 .reduce((acc, word) => {
1225 const letters = word.split('');
1226 letters[0] = letters[0].toUpperCase();
1227 return acc + letters.join('');
1228 }, '');
1229 const method = config[methodName];
1230 if (!method) {
1231 if (config.debug) {
1232 console.warn(`uiloos > ${subscriberName} event '${event.type}' was fired but '${methodName}' method is not implemented, this might not be correct.`);
1233 }
1234 return;
1235 }
1236 method(event, component);
1237}
1238
1239function createActiveListSubscriber(config) {
1240 return (activeList, event) => {
1241 _callSubscriber('createActiveListSubscriber', event, activeList, config);
1242 };
1243}
1244
1245const common$2 = `uiloos > ViewChannel >`;
1246
1247class ViewChannelAutoDismissDurationError extends Error {
1248 constructor() {
1249 super(`${common$2} autoDismiss > duration cannot be negative or zero`);
1250 this.name = 'ViewChannelAutoDismissDurationError';
1251 }
1252}
1253
1254class _AutoDismiss {
1255 constructor(view, config) {
1256 this._autoDismissTimeoutId = null;
1257 this._autoDismissStarted = new Date();
1258 this._pauseStarted = null;
1259 this._autoDismissCurrentDuration = 0;
1260 this._config = null;
1261 this._view = view;
1262 this._config = config;
1263 }
1264 _play(inform) {
1265 if (this._view.autoDismiss.isPlaying) {
1266 return;
1267 }
1268 this._cancelTimer();
1269 if (!this._config) {
1270 return;
1271 }
1272 const duration = this._getDuration(this._config);
1273 if (duration <= 0) {
1274 throw new ViewChannelAutoDismissDurationError();
1275 }
1276 this._autoDismissCurrentDuration = duration;
1277 this._autoDismissStarted = new Date();
1278 if (this._pauseStarted === null) {
1279 this._view.autoDismiss.duration = duration;
1280 }
1281 const result = this._config.result;
1282 this._autoDismissTimeoutId = window.setTimeout(() => {
1283 if (this._view.isPresented) {
1284 this._view.autoDismiss.isPlaying = false;
1285 this._view.autoDismiss.duration = 0;
1286 this._view.viewChannel._doRemoveByIndex(this._view.index, result, 'AUTO_DISMISS');
1287 }
1288 this._autoDismissTimeoutId = null;
1289 }, duration);
1290 this._view.result.then(() => {
1291 this._cancelTimer();
1292 });
1293 this._view.autoDismiss.isPlaying = true;
1294 if (inform) {
1295 const event = {
1296 type: 'AUTO_DISMISS_PLAYING',
1297 view: this._view,
1298 index: this._view.index,
1299 time: new Date(),
1300 };
1301 this._view.viewChannel._inform(event);
1302 }
1303 }
1304 _pause() {
1305 if (!this._view.autoDismiss.isPlaying) {
1306 return;
1307 }
1308 this._pauseStarted = new Date();
1309 this._cancelTimer();
1310 this._view.autoDismiss.isPlaying = false;
1311 const event = {
1312 type: 'AUTO_DISMISS_PAUSED',
1313 view: this._view,
1314 index: this._view.index,
1315 time: new Date(),
1316 };
1317 this._view.viewChannel._inform(event);
1318 }
1319 _stop() {
1320 if (!this._view.autoDismiss.isPlaying && !this._pauseStarted) {
1321 return;
1322 }
1323 this._cancelTimer();
1324 this._pauseStarted = null;
1325 this._view.autoDismiss.isPlaying = false;
1326 this._view.autoDismiss.duration = 0;
1327 const event = {
1328 type: 'AUTO_DISMISS_STOPPED',
1329 view: this._view,
1330 index: this._view.index,
1331 time: new Date(),
1332 };
1333 this._view.viewChannel._inform(event);
1334 }
1335 _cancelTimer() {
1336 if (this._autoDismissTimeoutId !== null) {
1337 window.clearTimeout(this._autoDismissTimeoutId);
1338 this._autoDismissTimeoutId = null;
1339 }
1340 }
1341 _getDuration(config) {
1342 if (this._pauseStarted) {
1343 return (this._autoDismissCurrentDuration -
1344 (this._pauseStarted.getTime() - this._autoDismissStarted.getTime()));
1345 }
1346 return config.duration;
1347 }
1348}
1349
1350class ViewChannelView {
1351 constructor(viewChannel, index, data, priority, autoDismissConfig) {
1352 var _a;
1353 this.autoDismiss = {
1354 isPlaying: false,
1355 duration: 0,
1356 };
1357 this._resolve = null;
1358 this.isPresented = true;
1359 this.viewChannel = viewChannel;
1360 this.index = index;
1361 this.data = data;
1362 this.priority = priority;
1363 this.result = new Promise((resolve) => {
1364 this._resolve = resolve;
1365 });
1366 this._autoDismiss = new _AutoDismiss(this, autoDismissConfig);
1367 this._autoDismiss._play(false);
1368 this.autoDismiss.duration = (_a = autoDismissConfig === null || autoDismissConfig === void 0 ? void 0 : autoDismissConfig.duration) !== null && _a !== void 0 ? _a : 0;
1369 }
1370 dismiss(result) {
1371 this.viewChannel.dismiss(this, result);
1372 }
1373 play() {
1374 this._autoDismiss._play(true);
1375 }
1376 pause() {
1377 this._autoDismiss._pause();
1378 }
1379 stop() {
1380 this._autoDismiss._stop();
1381 }
1382 changeData(data) {
1383 this.viewChannel.changeData(this, data);
1384 }
1385}
1386
1387class ViewChannelIndexOutOfBoundsError extends Error {
1388 constructor(method) {
1389 super(`${common$2} ${method} > "index" is out of bounds`);
1390 this.name = 'ViewChannelIndexOutOfBoundsError';
1391 }
1392}
1393
1394class ViewChannelViewNotFoundError extends Error {
1395 constructor(method) {
1396 super(`${common$2} ${method} > "ViewChannelView" not found in views array`);
1397 this.name = 'ViewChannelViewNotFoundError';
1398 }
1399}
1400
1401class ViewChannel {
1402 constructor(config = {}, subscriber) {
1403 this.views = [];
1404 this._history = new _History();
1405 this.history = this._history._events;
1406 this._observer = new _Observer();
1407 licenseChecker._checkLicense();
1408 if (subscriber) {
1409 this.subscribe(subscriber);
1410 }
1411 this.initialize(config);
1412 }
1413 initialize(config) {
1414 this._history._events.length = 0;
1415 this._history._setKeepHistoryFor(config.keepHistoryFor);
1416 this._clearViews();
1417 const event = {
1418 type: 'INITIALIZED',
1419 time: new Date(),
1420 };
1421 this._inform(event);
1422 }
1423 subscribe(subscriber) {
1424 return this._observer._subscribe(subscriber);
1425 }
1426 unsubscribe(subscriber) {
1427 this._observer._unsubscribe(subscriber);
1428 }
1429 unsubscribeAll() {
1430 this._observer._clear();
1431 }
1432 present(viewConfig) {
1433 const priority = viewConfig.priority ? viewConfig.priority : 0;
1434 const priorityArray = Array.isArray(priority) ? priority : [priority];
1435 const index = this._getIndexForPriority(priorityArray);
1436 const view = new ViewChannelView(this, index, viewConfig.data, priorityArray, viewConfig.autoDismiss);
1437 this.views.splice(index, 0, view);
1438 this._repairIndexes();
1439 const event = {
1440 type: 'PRESENTED',
1441 view,
1442 index,
1443 time: new Date(),
1444 };
1445 this._inform(event);
1446 return view;
1447 }
1448 _doRemoveByIndex(index, result, reason) {
1449 if (index < 0 || index >= this.views.length) {
1450 throw new ViewChannelIndexOutOfBoundsError('dismissByIndex');
1451 }
1452 const view = this.views[index];
1453 this.views.splice(index, 1);
1454 this._repairIndexes();
1455 view.isPresented = false;
1456 view.autoDismiss.duration = 0;
1457 view.autoDismiss.isPlaying = false;
1458 view._resolve(result);
1459 const event = {
1460 type: 'DISMISSED',
1461 view,
1462 index,
1463 reason,
1464 time: new Date(),
1465 };
1466 this._inform(event);
1467 }
1468 dismissByIndex(index, result) {
1469 this._doRemoveByIndex(index, result, 'USER_INTERACTION');
1470 }
1471 dismiss(view, result) {
1472 if (!view.isPresented) {
1473 return;
1474 }
1475 const index = this.views.indexOf(view);
1476 if (index === -1) {
1477 throw new ViewChannelViewNotFoundError('dismiss');
1478 }
1479 this.dismissByIndex(index, result);
1480 }
1481 dismissAll(result) {
1482 if (this.views.length === 0) {
1483 return;
1484 }
1485 const indexes = [];
1486 const dismissedViews = [...this.views];
1487 this._clearViews();
1488 dismissedViews.forEach((view) => {
1489 view.isPresented = false;
1490 view._resolve(result);
1491 indexes.push(view.index);
1492 });
1493 const event = {
1494 type: 'DISMISSED_ALL',
1495 views: dismissedViews,
1496 indexes,
1497 time: new Date(),
1498 };
1499 this._inform(event);
1500 }
1501 changeDataByIndex(index, data) {
1502 if (index < 0 || index >= this.views.length) {
1503 throw new ViewChannelIndexOutOfBoundsError('changeDataByIndex');
1504 }
1505 const view = this.views[index];
1506 view.data = data;
1507 const event = {
1508 type: 'DATA_CHANGED',
1509 view: view,
1510 data,
1511 index: view.index,
1512 time: new Date(),
1513 };
1514 this._inform(event);
1515 }
1516 changeData(view, data) {
1517 const index = this.views.indexOf(view);
1518 if (index === -1) {
1519 throw new ViewChannelViewNotFoundError('changeData');
1520 }
1521 this.changeDataByIndex(index, data);
1522 }
1523 _getIndexForPriority(priority) {
1524 for (let view of this.views) {
1525 const largestArray = priority.length > view.priority.length ? priority : view.priority;
1526 for (let level = 0; level < largestArray.length; level++) {
1527 const inserted = this._getPriorityAtLevel(priority, level);
1528 const existing = this._getPriorityAtLevel(view.priority, level);
1529 if (inserted < existing) {
1530 return view.index;
1531 }
1532 }
1533 }
1534 return this.views.length;
1535 }
1536 _getPriorityAtLevel(priorityArray, level) {
1537 const priority = priorityArray[level];
1538 if (priority !== undefined) {
1539 return priority;
1540 }
1541 else {
1542 return 0;
1543 }
1544 }
1545 _repairIndexes() {
1546 this.views.forEach((view, index) => {
1547 view.index = index;
1548 });
1549 }
1550 _clearViews() {
1551 this.views.length = 0;
1552 }
1553 _inform(event) {
1554 this._history._push(event);
1555 this._observer._inform(this, event);
1556 }
1557}
1558
1559function createViewChannelSubscriber(config) {
1560 return (viewChannel, event) => {
1561 _callSubscriber('createViewChannelSubscriber', event, viewChannel, config);
1562 };
1563}
1564
1565class TypewriterCursor {
1566 constructor(typewriter, position, data, selection) {
1567 this.isBlinking = true;
1568 this._blinkTimeoutId = null;
1569 this._typewriter = typewriter;
1570 this.position = position;
1571 this.selection = selection;
1572 this.data = data;
1573 }
1574 _startBlink() {
1575 if (this.isBlinking) {
1576 return;
1577 }
1578 this._clearBlink();
1579 this._blinkTimeoutId = window.setTimeout(() => {
1580 this.isBlinking = true;
1581 const event = {
1582 type: 'BLINKING',
1583 time: new Date(),
1584 cursor: this,
1585 };
1586 this._typewriter._inform(event);
1587 }, this._typewriter.blinkAfter);
1588 }
1589 _clearBlink() {
1590 if (this._blinkTimeoutId) {
1591 window.clearTimeout(this._blinkTimeoutId);
1592 this._blinkTimeoutId = null;
1593 }
1594 }
1595}
1596
1597const name = 'Typewriter';
1598const common$1 = `uiloos > ${name} >`;
1599
1600class TypewriterBlinkAfterError extends Error {
1601 constructor() {
1602 super(`${common$1} blinkAfter cannot be negative or zero`);
1603 this.name = `${name}BlinkAfterError`;
1604 }
1605}
1606
1607class TypewriterDelayError extends Error {
1608 constructor() {
1609 super(`${common$1} delay cannot be negative or zero`);
1610 this.name = `${name}DelayError`;
1611 }
1612}
1613
1614class TypewriterRepeatError extends Error {
1615 constructor() {
1616 super(`${common$1} repeat cannot be negative or zero`);
1617 this.name = `${name}RepeatError`;
1618 }
1619}
1620
1621class TypewriterRepeatDelayError extends Error {
1622 constructor() {
1623 super(`${common$1} repeatDelay cannot be a negative number`);
1624 this.name = `${name}RepeatDelayError`;
1625 }
1626}
1627
1628class TypewriterCursorOutOfBoundsError extends Error {
1629 constructor() {
1630 super(`${common$1} cursor is out of bounds`);
1631 this.name = `${name}CursorOutOfBoundsError`;
1632 }
1633}
1634
1635class TypewriterCursorNotAtSelectionEdgeError extends Error {
1636 constructor() {
1637 super(`${common$1} cursor is not placed on edges of selection`);
1638 this.name = `${name}CursorNotAtSelectionEdgeError`;
1639 }
1640}
1641
1642class TypewriterCursorSelectionInvalidRangeError extends Error {
1643 constructor() {
1644 super(`${common$1} cursors selection has an invalid range: start is equal or larger than the end`);
1645 this.name = `${name}CursorSelectionInvalidRangeError`;
1646 }
1647}
1648
1649class TypewriterCursorSelectionOutOfBoundsError extends Error {
1650 constructor(name) {
1651 super(`${common$1} cursor selection ${name} is out of bounds`);
1652 this.name = `${name}InvalidCursorSelectionOutOfBoundsError`;
1653 }
1654}
1655
1656class TypewriterActionUnknownCursorError extends Error {
1657 constructor() {
1658 super(`${common$1} action uses an unknown cursor`);
1659 this.name = `${name}ActionUnknownCursorError`;
1660 }
1661}
1662
1663class Typewriter {
1664 constructor(config = {}, subscriber) {
1665 this.cursors = [];
1666 this._originalCursors = [];
1667 this.actions = [];
1668 this.lastPerformedAction = null;
1669 this.text = '';
1670 this._originalText = '';
1671 this.blinkAfter = 250;
1672 this.isPlaying = false;
1673 this._stopped = false;
1674 this.isFinished = false;
1675 this.repeat = false;
1676 this.repeatDelay = 0;
1677 this._repeated = 0;
1678 this.hasBeenStoppedBefore = false;
1679 this._index = 0;
1680 this._animationTimeoutId = null;
1681 this._tickStarted = new Date();
1682 this._pauseStarted = null;
1683 this._history = new _History();
1684 this.history = this._history._events;
1685 this._observer = new _Observer();
1686 licenseChecker._checkLicense();
1687 if (subscriber) {
1688 this.subscribe(subscriber);
1689 }
1690 this.initialize(config);
1691 }
1692 initialize(config) {
1693 this._clearAnimation();
1694 this.cursors.forEach((c) => {
1695 c._clearBlink();
1696 });
1697 this.actions.length = 0;
1698 this.cursors.length = 0;
1699 this._history._events.length = 0;
1700 this._history._setKeepHistoryFor(config.keepHistoryFor);
1701 this.text = config.text !== undefined ? config.text : '';
1702 this._originalText = this.text;
1703 const textLength = Array.from(this.text).length;
1704 this._originalCursors.length = 0;
1705 if (config.cursors) {
1706 config.cursors.forEach((cursor) => {
1707 const position = cursor.position;
1708 if (position < 0 || position > textLength) {
1709 throw new TypewriterCursorOutOfBoundsError();
1710 }
1711 const selection = cursor.selection;
1712 if (selection) {
1713 const { start, end } = selection;
1714 if (position !== start && position !== end) {
1715 throw new TypewriterCursorNotAtSelectionEdgeError();
1716 }
1717 if (start < 0 || start > textLength) {
1718 throw new TypewriterCursorSelectionOutOfBoundsError(_START);
1719 }
1720 if (end < 0 || end > textLength) {
1721 throw new TypewriterCursorSelectionOutOfBoundsError(_END);
1722 }
1723 if (start >= end) {
1724 throw new TypewriterCursorSelectionInvalidRangeError();
1725 }
1726 }
1727 this._originalCursors.push({
1728 position: cursor.position,
1729 data: cursor.data,
1730 selection: selection
1731 ? {
1732 start: selection.start,
1733 end: selection.end,
1734 }
1735 : undefined,
1736 });
1737 this.cursors.push(new TypewriterCursor(this, cursor.position, cursor.data ? cursor.data : undefined, selection));
1738 });
1739 }
1740 else {
1741 this.cursors.push(new TypewriterCursor(this, textLength, undefined, undefined));
1742 this._originalCursors.push({ data: undefined, position: textLength });
1743 }
1744 if (config.actions) {
1745 for (let i = 0; i < config.actions.length; i++) {
1746 const action = config.actions[i];
1747 if (action.delay <= 0) {
1748 throw new TypewriterDelayError();
1749 }
1750 if (this.cursors[action.cursor] === undefined) {
1751 throw new TypewriterActionUnknownCursorError();
1752 }
1753 this.actions.push(action);
1754 }
1755 }
1756 this._index = 0;
1757 this.isPlaying =
1758 (config.autoPlay === true || config.autoPlay === undefined) &&
1759 this.actions.length > 0;
1760 this.isFinished = false;
1761 this.blinkAfter = config.blinkAfter !== undefined ? config.blinkAfter : 250;
1762 if (this.blinkAfter <= 0) {
1763 throw new TypewriterBlinkAfterError();
1764 }
1765 this._repeated = 0;
1766 this.repeat = config.repeat !== undefined ? config.repeat : false;
1767 if (typeof this.repeat === 'number' && this.repeat <= 0) {
1768 throw new TypewriterRepeatError();
1769 }
1770 this.repeatDelay =
1771 config.repeatDelay !== undefined ? config.repeatDelay : 0;
1772 if (this.repeatDelay < 0) {
1773 throw new TypewriterRepeatDelayError();
1774 }
1775 this.hasBeenStoppedBefore = false;
1776 this._pauseStarted = null;
1777 if (this.isPlaying) {
1778 this._tick();
1779 }
1780 const event = {
1781 type: 'INITIALIZED',
1782 time: new Date(),
1783 };
1784 this._inform(event);
1785 }
1786 subscribe(subscriber) {
1787 return this._observer._subscribe(subscriber);
1788 }
1789 unsubscribe(subscriber) {
1790 this._observer._unsubscribe(subscriber);
1791 }
1792 unsubscribeAll() {
1793 this._observer._clear();
1794 }
1795 play() {
1796 if (this.isFinished || this._stopped) {
1797 this._init();
1798 this._stopped = false;
1799 this.hasBeenStoppedBefore = false;
1800 this._resetTandC();
1801 }
1802 else if (this.isPlaying || this.actions.length === 0) {
1803 return;
1804 }
1805 this.isPlaying = true;
1806 this._tick();
1807 const event = {
1808 type: 'PLAYING',
1809 time: new Date(),
1810 };
1811 this._inform(event);
1812 }
1813 pause() {
1814 if (!this.isPlaying) {
1815 return;
1816 }
1817 this._clearAnimation();
1818 this.isPlaying = false;
1819 this._pauseStarted = new Date();
1820 this.cursors.forEach((c) => c._startBlink());
1821 const event = {
1822 type: 'PAUSED',
1823 time: new Date(),
1824 };
1825 this._inform(event);
1826 }
1827 stop() {
1828 if (this.isFinished || (!this.isPlaying && !this._pauseStarted)) {
1829 return;
1830 }
1831 this._clearAnimation();
1832 this.isPlaying = false;
1833 this.hasBeenStoppedBefore = true;
1834 this._stopped = true;
1835 this._init();
1836 const event = {
1837 type: 'STOPPED',
1838 time: new Date(),
1839 };
1840 this._inform(event);
1841 }
1842 _init() {
1843 this.isFinished = false;
1844 this._index = 0;
1845 this._pauseStarted = null;
1846 this._repeated = 0;
1847 this.cursors.forEach((c) => (c.isBlinking = true));
1848 }
1849 _tick() {
1850 const action = this.actions[this._index];
1851 const cursor = this.cursors[action.cursor];
1852 let delay = action.delay;
1853 if (this._pauseStarted) {
1854 delay -= this._pauseStarted.getTime() - this._tickStarted.getTime();
1855 this._pauseStarted = null;
1856 }
1857 this._tickStarted = new Date();
1858 this._animationTimeoutId = window.setTimeout(() => {
1859 var _a, _b;
1860 const textArray = Array.from(this.text);
1861 cursor.isBlinking = false;
1862 cursor._startBlink();
1863 let noOp = false;
1864 if (action.type !== 'mouse') {
1865 if (action.text === '⎚') {
1866 if (this.text === '') {
1867 noOp = true;
1868 }
1869 else {
1870 this.text = '';
1871 this.cursors.forEach((c) => {
1872 c.position = 0;
1873 c.selection = undefined;
1874 });
1875 }
1876 }
1877 else if (action.text === '←') {
1878 noOp = this._actionLorR(cursor, -1, ((_a = cursor.selection) === null || _a === void 0 ? void 0 : _a.start) || 0, 0);
1879 }
1880 else if (action.text === '→') {
1881 noOp = this._actionLorR(cursor, 1, ((_b = cursor.selection) === null || _b === void 0 ? void 0 : _b.end) || 0, textArray.length);
1882 }
1883 else if (action.text === '⇧←') {
1884 noOp = this._actionSLorR(cursor, -1, _START, 0);
1885 }
1886 else if (action.text === '⇧→') {
1887 noOp = this._actionSLorR(cursor, 1, _END, textArray.length);
1888 }
1889 else if (action.text === '⌫') {
1890 const removed = {
1891 start: -1,
1892 end: -1,
1893 no: -1,
1894 };
1895 if (cursor.selection) {
1896 const start = cursor.selection.start;
1897 const end = cursor.selection.end;
1898 const no = end - start;
1899 textArray.splice(cursor.selection.start, no);
1900 this.text = textArray.join('');
1901 removed.start = start;
1902 removed.end = end;
1903 removed.no = no;
1904 }
1905 else {
1906 const position = cursor.position;
1907 if (position !== 0) {
1908 textArray.splice(position - 1, 1);
1909 this.text = textArray.join('');
1910 removed.start = position - 1;
1911 removed.end = position;
1912 removed.no = 1;
1913 }
1914 else {
1915 noOp = true;
1916 }
1917 }
1918 cursor.selection = undefined;
1919 if (!noOp) {
1920 this.cursors.forEach((c) => {
1921 const hasOverlap = this._overlap(c.selection, removed) > 0;
1922 if (c.position > removed.start) {
1923 if (c.selection &&
1924 hasOverlap &&
1925 removed.start < c.selection.start &&
1926 c.position < removed.end) {
1927 c.position = removed.start;
1928 }
1929 else {
1930 c.position -= removed.no;
1931 }
1932 }
1933 const selection = c.selection;
1934 if (selection) {
1935 if (hasOverlap) {
1936 const overlap = this._overlap(selection, removed);
1937 if (selection.start <= removed.start) {
1938 selection.end -= overlap;
1939 }
1940 else {
1941 selection.start -= overlap;
1942 selection.end -= removed.no;
1943 }
1944 if (selection.start === selection.end) {
1945 c.selection = undefined;
1946 }
1947 }
1948 else if (removed.start <= selection.start &&
1949 removed.end <= selection.start) {
1950 selection.start -= removed.no;
1951 selection.end -= removed.no;
1952 }
1953 }
1954 });
1955 }
1956 }
1957 else {
1958 const text = Array.from(action.text);
1959 if (cursor.selection) {
1960 const start = cursor.selection.start;
1961 const end = cursor.selection.end;
1962 const no = end - start;
1963 textArray.splice(cursor.selection.start, no);
1964 cursor.position = start;
1965 const removed = {
1966 start,
1967 end,
1968 no,
1969 };
1970 textArray.splice(cursor.position, 0, ...text);
1971 this.text = textArray.join('');
1972 this.cursors.forEach((c) => {
1973 if (cursor === c) {
1974 return;
1975 }
1976 const removedNo = removed.no - text.length;
1977 const selection = c.selection;
1978 if (selection) {
1979 if (selection.start >= removed.start &&
1980 selection.end <= removed.end) {
1981 c.selection = undefined;
1982 c.position = removed.start;
1983 }
1984 else {
1985 const hasOverlap = this._overlap(selection, removed) > 0;
1986 if (hasOverlap) {
1987 const isPosStart = selection.start === c.position;
1988 const overlap = this._overlap(selection, removed);
1989 if (selection.start > removed.start) {
1990 selection.start -= removed.no - overlap;
1991 selection.start = Math.max(0, selection.start);
1992 }
1993 if (selection.end === removed.end) {
1994 selection.end -= removed.no;
1995 }
1996 else if (selection.end === removed.end - 1) {
1997 selection.end -= removed.no - 1;
1998 }
1999 else if (selection.end !== removed.start) {
2000 selection.end -= removed.no - text.length;
2001 }
2002 c.position = isPosStart ? selection.start : selection.end;
2003 }
2004 else if (removed.start <= selection.start &&
2005 removed.end <= selection.start) {
2006 const isPosStart = selection.start === c.position;
2007 const leftMost = Math.min(selection.start, selection.end);
2008 if (removed.end === leftMost) {
2009 selection.start = removed.start;
2010 }
2011 else {
2012 selection.start -= removedNo;
2013 }
2014 selection.end -= removedNo;
2015 selection.start = Math.max(0, selection.start);
2016 c.position = isPosStart ? selection.start : selection.end;
2017 }
2018 }
2019 }
2020 else {
2021 if (c.position >= removed.start && c.position <= removed.end) {
2022 c.position = removed.start;
2023 }
2024 else if (c.position > removed.end) {
2025 c.position -= removedNo;
2026 }
2027 }
2028 });
2029 cursor.position += text.length;
2030 }
2031 else {
2032 textArray.splice(cursor.position, 0, ...text);
2033 this.text = textArray.join('');
2034 this.cursors.forEach((c) => {
2035 if (cursor === c) {
2036 return;
2037 }
2038 const selection = c.selection;
2039 if (selection) {
2040 if (cursor.position < selection.start) {
2041 selection.start += text.length;
2042 selection.end += text.length;
2043 }
2044 else if (cursor.position < selection.end) {
2045 selection.end += text.length;
2046 }
2047 }
2048 if (cursor.position < c.position) {
2049 c.position += text.length;
2050 }
2051 });
2052 cursor.position += text.length;
2053 }
2054 cursor.selection = undefined;
2055 }
2056 }
2057 else {
2058 const position = Math.min(textArray.length, Math.max(0, action.position));
2059 if (cursor.position === position &&
2060 this._same(cursor.selection, action.selection)) {
2061 noOp = true;
2062 }
2063 else {
2064 cursor.position = position;
2065 if (action.selection) {
2066 cursor.selection = {
2067 start: action.selection.start,
2068 end: action.selection.end,
2069 };
2070 }
2071 else {
2072 cursor.selection = undefined;
2073 }
2074 }
2075 }
2076 this._index += 1;
2077 if (this._index >= this.actions.length) {
2078 if (this.repeat === false || this.repeat === this._repeated + 1) {
2079 this.isFinished = true;
2080 this.isPlaying = false;
2081 const event = {
2082 type: 'FINISHED',
2083 action,
2084 time: new Date(),
2085 cursor,
2086 };
2087 this.lastPerformedAction = action;
2088 this._inform(event);
2089 }
2090 else {
2091 this._repeated += 1;
2092 this._change(noOp, action, cursor);
2093 this._animationTimeoutId = window.setTimeout(() => {
2094 this._index = 0;
2095 this._resetTandC();
2096 this.cursors.forEach((c) => {
2097 c._clearBlink();
2098 c.isBlinking = true;
2099 });
2100 const event = {
2101 type: 'REPEATING',
2102 time: new Date(),
2103 cursor,
2104 };
2105 this._inform(event);
2106 this._tick();
2107 }, this.repeatDelay);
2108 }
2109 }
2110 else {
2111 this._change(noOp, action, cursor);
2112 this._tick();
2113 }
2114 }, delay);
2115 }
2116 _clearAnimation() {
2117 if (this._animationTimeoutId) {
2118 window.clearTimeout(this._animationTimeoutId);
2119 this._animationTimeoutId = null;
2120 return;
2121 }
2122 }
2123 _resetTandC() {
2124 this.text = this._originalText;
2125 this._originalCursors.forEach((copy, index) => {
2126 const cursor = this.cursors[index];
2127 cursor.data = copy.data ? copy.data : undefined;
2128 cursor.position = copy.position;
2129 const selection = copy.selection;
2130 if (selection) {
2131 cursor.selection = {
2132 start: selection.start,
2133 end: selection.end,
2134 };
2135 }
2136 else {
2137 cursor.selection = undefined;
2138 }
2139 });
2140 }
2141 _overlap(s, r) {
2142 if (!s) {
2143 return 0;
2144 }
2145 return Math.min(s.end, r.end) - Math.max(s.start, r.start);
2146 }
2147 _same(a, b) {
2148 if (a === b) {
2149 return true;
2150 }
2151 if (a && b) {
2152 return a.start === b.start && a.end === b.end;
2153 }
2154 else {
2155 return false;
2156 }
2157 }
2158 _actionLorR(cursor, mod, select, stop) {
2159 if (cursor.position === stop) {
2160 if (cursor.selection === undefined) {
2161 return true;
2162 }
2163 }
2164 else {
2165 if (cursor.selection) {
2166 cursor.position = select;
2167 }
2168 else {
2169 cursor.position += mod;
2170 }
2171 }
2172 cursor.selection = undefined;
2173 return false;
2174 }
2175 _actionSLorR(cursor, mod, which, stop) {
2176 if (cursor.position === stop) {
2177 return true;
2178 }
2179 else {
2180 cursor.position += mod;
2181 const selection = cursor.selection;
2182 if (selection) {
2183 selection[which] += mod;
2184 }
2185 else {
2186 const selection = { start: -1, end: -1 };
2187 selection[which === _START ? _END : _START] = cursor.position - mod;
2188 selection[which] = cursor.position;
2189 cursor.selection = selection;
2190 }
2191 }
2192 return false;
2193 }
2194 _change(noOp, action, cursor) {
2195 if (noOp) {
2196 return;
2197 }
2198 const event = {
2199 type: 'CHANGED',
2200 action,
2201 time: new Date(),
2202 cursor,
2203 };
2204 this.lastPerformedAction = action;
2205 this._inform(event);
2206 }
2207 _inform(event) {
2208 this._history._push(event);
2209 this._observer._inform(this, event);
2210 }
2211 *[Symbol.iterator]() {
2212 const text = Array.from(this.text);
2213 const cursorMap = {};
2214 this.cursors.forEach((c) => {
2215 const pos = c.position;
2216 if (cursorMap[pos]) {
2217 cursorMap[pos].push(c);
2218 }
2219 else {
2220 cursorMap[pos] = [c];
2221 }
2222 });
2223 for (let i = 0; i < text.length; i++) {
2224 const cursors = cursorMap[i];
2225 yield {
2226 position: i,
2227 cursors: cursors ? cursors : [],
2228 character: text[i],
2229 selected: this.cursors.filter((c) => c.selection && i >= c.selection.start && i < c.selection.end),
2230 };
2231 }
2232 const finalCursors = cursorMap[text.length];
2233 if (finalCursors) {
2234 yield {
2235 position: text.length,
2236 character: '',
2237 cursors: finalCursors,
2238 selected: [],
2239 };
2240 }
2241 }
2242}
2243const _START = 'start';
2244const _END = 'end';
2245
2246function createTypewriterSubscriber(config) {
2247 return (typewriter, event) => {
2248 _callSubscriber('createTypewriterSubscriber', event, typewriter, config);
2249 };
2250}
2251
2252const typewriterActionTypeBackspace = '⌫';
2253
2254function typewriterFromSentences(config, subscriber) {
2255 const delay = config.delay === undefined ? 50 : config.delay;
2256 const sentenceDelay = config.sentenceDelay === undefined ? 2000 : config.sentenceDelay;
2257 const actions = [];
2258 let text = config.text ? Array.from(config.text) : [];
2259 let firstSentence = true;
2260 for (let sentence of config.sentences) {
2261 const sentenceArray = Array.from(sentence);
2262 let charsInCommonFromStart = 0;
2263 for (let i = 0; i < text.length; i++) {
2264 const fromChar = text[i];
2265 const toChar = sentenceArray[i];
2266 if (toChar === fromChar) {
2267 charsInCommonFromStart += 1;
2268 }
2269 else {
2270 break;
2271 }
2272 }
2273 const backspaces = text.length - charsInCommonFromStart;
2274 text = text.slice(0, text.length - backspaces);
2275 for (let i = 0; i < backspaces; i++) {
2276 const actualDelay = !firstSentence && i === 0 ? sentenceDelay : delay;
2277 actions.push({
2278 type: _KEYBOARD,
2279 text: typewriterActionTypeBackspace,
2280 delay: actualDelay,
2281 cursor: 0,
2282 });
2283 }
2284 const missingChars = text.length > 0
2285 ? sentenceArray.slice(charsInCommonFromStart)
2286 : sentenceArray;
2287 for (const missingChar of missingChars) {
2288 actions.push({
2289 type: _KEYBOARD,
2290 text: missingChar,
2291 delay,
2292 cursor: 0,
2293 });
2294 }
2295 text = text.concat(missingChars);
2296 firstSentence = false;
2297 }
2298 return new Typewriter(Object.assign(Object.assign({ repeatDelay: sentenceDelay }, config), { actions }), subscriber);
2299}
2300const _KEYBOARD = 'keyboard';
2301
2302const DATE_GALLERY_MODES = [
2303 'day',
2304 'week',
2305 'month',
2306 'month-six-weeks',
2307 'month-pad-to-week',
2308 'year',
2309];
2310
2311class DateGalleryDate {
2312 constructor(dateGallery, date, events, isPadding, isSelected) {
2313 this.canBeSelected = true;
2314 this.dateGallery = dateGallery;
2315 this.date = date;
2316 this.events = events;
2317 this.isPadding = isPadding;
2318 this.isSelected = isSelected;
2319 this.isToday = dateGallery._sameDay(new Date(), date);
2320 this.hasEvents = events.length > 0;
2321 this.hasEventsWithOverlap = this.events.some(e => e.isOverlapping);
2322 if (dateGallery._canSelect) {
2323 this.canBeSelected = dateGallery._canSelect(this);
2324 }
2325 }
2326 select() {
2327 this.dateGallery.selectDate(this.date);
2328 }
2329 deselect() {
2330 this.dateGallery.deselectDate(this.date);
2331 }
2332 toggle() {
2333 this.dateGallery.toggleDateSelection(this.date);
2334 }
2335}
2336
2337function _hasOverlap(a, b) {
2338 const earlier = a.startDate < b.startDate ? a : b;
2339 const later = earlier === a ? b : a;
2340 const laterStart = later.startDate.getTime();
2341 const earlierStart = earlier.startDate.getTime();
2342 const earlierEnd = earlier.endDate.getTime();
2343 return laterStart >= earlierStart && laterStart < earlierEnd;
2344}
2345
2346class DateGalleryEvent {
2347 constructor(dateGallery, data, startDate, endDate) {
2348 this.overlappingEvents = [];
2349 this.isOverlapping = false;
2350 this.spansMultipleDays = false;
2351 this.dateGallery = dateGallery;
2352 this.data = data;
2353 this.startDate = startDate;
2354 this.endDate = endDate;
2355 }
2356 _recalculate() {
2357 this.overlappingEvents.length = 0;
2358 this.dateGallery.events.forEach((other) => {
2359 if (other === this) {
2360 return;
2361 }
2362 if (_hasOverlap(this, other)) {
2363 this.overlappingEvents.push(other);
2364 }
2365 });
2366 this.overlappingEvents.sort((a, b) => {
2367 return a.startDate.getTime() - b.startDate.getTime();
2368 });
2369 this.spansMultipleDays = !this.dateGallery._sameDay(this.startDate, this.endDate);
2370 this.isOverlapping = this.overlappingEvents.length > 0;
2371 }
2372 remove() {
2373 this.dateGallery.removeEvent(this);
2374 }
2375 move(range) {
2376 this.dateGallery.moveEvent(this, range);
2377 }
2378 changeData(data) {
2379 this.dateGallery.changeEventData(this, data);
2380 }
2381}
2382
2383const common = `uiloos > DateGallery >`;
2384
2385class DateGalleryEventInvalidRangeError extends Error {
2386 constructor() {
2387 super(`${common} invalid range, an events startDate lies after its endDate`);
2388 this.name = 'DateGalleryEventInvalidRangeError';
2389 }
2390}
2391
2392class DateGalleryEventNotFoundError extends Error {
2393 constructor(method) {
2394 super(`${common} ${method} > "DateGalleryEvent" not found in events array`);
2395 this.name = 'DateGalleryEventNotFoundError';
2396 }
2397}
2398
2399class DateGalleryFirstDayOfWeekError extends Error {
2400 constructor() {
2401 super(`${common} invalid firstDayOfWeek`);
2402 this.name = 'DateGalleryFirstDayOfWeekError';
2403 }
2404}
2405
2406class DateGalleryInvalidDateError extends Error {
2407 constructor(method, dateName) {
2408 super(`${common} ${method} > "${dateName}" is an or contains an invalid date`);
2409 this.name = 'DateGalleryInvalidDateError';
2410 }
2411}
2412
2413class DateGalleryModeError extends Error {
2414 constructor(mode) {
2415 super(`${common} unknown mode: "${mode}" provided`);
2416 this.name = 'DateGalleryModeError';
2417 }
2418}
2419
2420class DateGalleryNumberOfFramesError extends Error {
2421 constructor() {
2422 super(`${common} numberOfFrames cannot be negative or zero`);
2423 this.name = 'DateGalleryNumberOfFramesError';
2424 }
2425}
2426
2427class DateGallerySelectionLimitReachedError extends Error {
2428 constructor(method) {
2429 super(`${common} ${method} > selection limit reached`);
2430 this.name = 'DateGallerySelectionLimitReachedError';
2431 }
2432}
2433
2434class DateGallery {
2435 constructor(config = {}, subscriber) {
2436 this._isInitializing = false;
2437 this.isUTC = false;
2438 this.frames = [];
2439 this.firstFrame = {
2440 dates: [],
2441 events: [],
2442 anchorDate: new Date(),
2443 };
2444 this.numberOfFrames = 1;
2445 this.maxSelectionLimit = false;
2446 this.maxSelectionLimitBehavior = 'circular';
2447 this.selectedDates = [];
2448 this._canSelect = undefined;
2449 this.events = [];
2450 this.mode = 'month-six-weeks';
2451 this.firstDayOfWeek = 0;
2452 this._anchorDate = new Date();
2453 this._history = new _History();
2454 this.history = this._history._events;
2455 this._observer = new _Observer();
2456 licenseChecker._checkLicense();
2457 if (subscriber) {
2458 this.subscribe(subscriber);
2459 }
2460 this._doInitialize(config, 'constructor');
2461 }
2462 subscribe(subscriber) {
2463 return this._observer._subscribe(subscriber);
2464 }
2465 unsubscribe(subscriber) {
2466 this._observer._unsubscribe(subscriber);
2467 }
2468 unsubscribeAll() {
2469 this._observer._clear();
2470 }
2471 initialize(config) {
2472 this._doInitialize(config, 'initialize');
2473 }
2474 _doInitialize(config, method) {
2475 this._isInitializing = true;
2476 this.isUTC = config.isUTC !== undefined ? config.isUTC : false;
2477 this.mode = config.mode ? config.mode : 'month-six-weeks';
2478 this._checkMode(this.mode);
2479 this.firstDayOfWeek = config.firstDayOfWeek ? config.firstDayOfWeek : 0;
2480 if (this.firstDayOfWeek < 0 || this.firstDayOfWeek > 6) {
2481 throw new DateGalleryFirstDayOfWeekError();
2482 }
2483 this.numberOfFrames =
2484 config.numberOfFrames !== undefined ? config.numberOfFrames : 1;
2485 if (this.numberOfFrames <= 0) {
2486 throw new DateGalleryNumberOfFramesError();
2487 }
2488 this.maxSelectionLimit =
2489 config.maxSelectionLimit !== undefined ? config.maxSelectionLimit : false;
2490 this.maxSelectionLimitBehavior =
2491 config.maxSelectionLimitBehavior !== undefined
2492 ? config.maxSelectionLimitBehavior
2493 : 'circular';
2494 this._anchorDate = config.initialDate
2495 ? this._toDate(config.initialDate, method, 'initialDate')
2496 : new Date();
2497 this._toMidnight(this._anchorDate);
2498 this._dragAnchor();
2499 this.events.length = 0;
2500 this.selectedDates.length = 0;
2501 this._canSelect = config.canSelect;
2502 if (config.selectedDates) {
2503 config.selectedDates.forEach((s) => {
2504 this.selectDate(this._toDate(s, method, 'selectedDates'));
2505 });
2506 }
2507 if (config.events) {
2508 config.events.forEach((config) => {
2509 this._doAddEvent(config, method);
2510 });
2511 this.events.forEach((e) => {
2512 e._recalculate();
2513 });
2514 }
2515 this._buildFrames();
2516 this._history._events.length = 0;
2517 this._history._setKeepHistoryFor(config.keepHistoryFor);
2518 this._isInitializing = false;
2519 const event = {
2520 type: 'INITIALIZED',
2521 time: new Date(),
2522 };
2523 this._inform(event);
2524 }
2525 changeConfig(config) {
2526 if (config.initialDate === undefined &&
2527 config.mode === undefined &&
2528 config.numberOfFrames === undefined) {
2529 return;
2530 }
2531 let changed = false;
2532 let drag = false;
2533 const method = 'changeConfig';
2534 if (config.mode !== undefined) {
2535 this._checkMode(config.mode);
2536 if (this.mode !== config.mode) {
2537 this.mode = config.mode;
2538 changed = true;
2539 drag = true;
2540 }
2541 }
2542 if (config.initialDate !== undefined) {
2543 const date = this._toDate(config.initialDate, method, 'initialDate');
2544 this._toMidnight(date);
2545 if (!this._sameDay(date, this._anchorDate)) {
2546 this._anchorDate = date;
2547 changed = true;
2548 drag = true;
2549 }
2550 }
2551 if (config.numberOfFrames !== undefined) {
2552 if (config.numberOfFrames <= 0) {
2553 throw new DateGalleryNumberOfFramesError();
2554 }
2555 if (this.numberOfFrames !== config.numberOfFrames) {
2556 this.numberOfFrames = config.numberOfFrames;
2557 changed = true;
2558 }
2559 }
2560 if (changed) {
2561 if (drag) {
2562 this._dragAnchor();
2563 }
2564 this._buildFrames();
2565 const event = {
2566 type: 'CONFIG_CHANGED',
2567 mode: this.mode,
2568 anchorDate: new Date(this._anchorDate),
2569 numberOfFrames: this.numberOfFrames,
2570 frames: this.frames,
2571 time: new Date(),
2572 };
2573 this._inform(event);
2574 }
2575 }
2576 today() {
2577 this.changeConfig({
2578 initialDate: new Date(),
2579 });
2580 }
2581 _buildFrames(inform = false) {
2582 this.frames.length = 0;
2583 const anchorAtStart = this._anchorDate;
2584 for (let i = 0; i < this.numberOfFrames; i++) {
2585 if (i !== 0) {
2586 this._moveFrame(1);
2587 }
2588 const frame = {
2589 dates: [],
2590 events: [],
2591 anchorDate: new Date(this._anchorDate),
2592 };
2593 const anchor = new Date(this._anchorDate);
2594 if (this.mode === 'day') {
2595 frame.dates.push(this._makeDate(anchor));
2596 }
2597 else if (this.mode === 'week') {
2598 this._addNoDates(anchor, 7, frame);
2599 }
2600 else if (this.mode === 'year') {
2601 const year = this._getFullYear(anchor);
2602 const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
2603 this._addNoDates(anchor, isLeapYear ? 366 : 365, frame);
2604 }
2605 else if (this.mode === 'month') {
2606 const anchorMonth = this._getMonth(anchor);
2607 this._addMonth(anchor, anchorMonth, frame);
2608 }
2609 else if (this.mode === 'month-pad-to-week') {
2610 const date = this._firstDayOfWeek(anchor);
2611 const anchorMonth = this._getMonth(anchor);
2612 while (this._getMonth(date) !== anchorMonth) {
2613 this._pushDay(date, frame);
2614 }
2615 this._addMonth(date, anchorMonth, frame);
2616 while (this._getDay(date) !== this.firstDayOfWeek) {
2617 this._pushDay(date, frame);
2618 }
2619 }
2620 else if (this.mode === 'month-six-weeks') {
2621 const date = this._firstDayOfWeek(anchor);
2622 this._addNoDates(date, 42, frame);
2623 }
2624 this.frames.push(frame);
2625 const startDate = new Date(frame.dates[0].date);
2626 const endDate = new Date(frame.dates[frame.dates.length - 1].date);
2627 this._toMidnight(startDate);
2628 this._moveDateBy(endDate, 1);
2629 this._toMidnight(endDate);
2630 this.events.forEach((event) => {
2631 if (_hasOverlap({ startDate, endDate }, event)) {
2632 frame.events.push(event);
2633 }
2634 });
2635 }
2636 this._anchorDate = anchorAtStart;
2637 this.firstFrame = this.frames[0];
2638 if (inform) {
2639 const event = {
2640 type: 'FRAME_CHANGED',
2641 frames: this.frames,
2642 time: new Date(),
2643 };
2644 this._inform(event);
2645 }
2646 }
2647 next() {
2648 this._moveFrame(this.numberOfFrames);
2649 this._buildFrames(true);
2650 }
2651 previous() {
2652 this._moveFrame(-this.numberOfFrames);
2653 this._buildFrames(true);
2654 }
2655 _moveFrame(mod) {
2656 const date = new Date(this._anchorDate);
2657 if (this.mode === 'day') {
2658 this._moveDateBy(date, 1 * mod);
2659 }
2660 else if (this.mode === 'week') {
2661 this._moveDateBy(date, 7 * mod);
2662 }
2663 else if (this.mode === 'year') {
2664 if (this.isUTC) {
2665 date.setUTCFullYear(date.getUTCFullYear() + 1 * mod);
2666 }
2667 else {
2668 date.setFullYear(date.getFullYear() + 1 * mod);
2669 }
2670 }
2671 else {
2672 if (this.isUTC) {
2673 date.setUTCMonth(date.getUTCMonth() + 1 * mod);
2674 }
2675 else {
2676 date.setMonth(date.getMonth() + 1 * mod);
2677 }
2678 }
2679 this._anchorDate = date;
2680 }
2681 selectDate(date) {
2682 const method = 'selectDate';
2683 const _date = this._toDate(date, method, 'date');
2684 const [index] = this._indexOfDate(_date, method);
2685 if (index === -1) {
2686 this._doSelectDate(_date, method);
2687 }
2688 }
2689 _doSelectDate(date, method) {
2690 const deselectedDates = [];
2691 const midnight = this._pushSelectDate(date, method, deselectedDates);
2692 if (!midnight) {
2693 return;
2694 }
2695 this._buildFrames();
2696 let deselectedDate = deselectedDates[0];
2697 if (!deselectedDate) {
2698 deselectedDate = null;
2699 }
2700 const event = {
2701 type: 'DATE_SELECTED',
2702 date: new Date(midnight),
2703 deselectedDate,
2704 time: new Date(),
2705 };
2706 this._inform(event);
2707 }
2708 _pushSelectDate(date, method, deselectedDates) {
2709 const midnight = this._toDate(date, method, 'date');
2710 this._toMidnight(midnight);
2711 if (this._canSelect && !this._canSelect(this._makeDate(midnight))) {
2712 return null;
2713 }
2714 const limitReached = this.maxSelectionLimit === false
2715 ? false
2716 : this.maxSelectionLimit === this.selectedDates.length;
2717 if (limitReached) {
2718 if (this.maxSelectionLimitBehavior === 'error') {
2719 throw new DateGallerySelectionLimitReachedError(method);
2720 }
2721 else if (this.maxSelectionLimitBehavior === 'ignore') {
2722 return null;
2723 }
2724 else {
2725 const deselected = this.selectedDates.shift();
2726 if (deselected) {
2727 deselectedDates.push(deselected);
2728 }
2729 }
2730 }
2731 this.selectedDates.push(midnight);
2732 return midnight;
2733 }
2734 deselectDate(date) {
2735 const [index, _date] = this._indexOfDate(date, 'deselectDate');
2736 if (index === -1) {
2737 return;
2738 }
2739 this._doDeselectDate(index, _date);
2740 }
2741 _doDeselectDate(index, date) {
2742 this.selectedDates.splice(index, 1);
2743 this._buildFrames();
2744 const event = {
2745 type: 'DATE_DESELECTED',
2746 date,
2747 time: new Date(),
2748 };
2749 this._inform(event);
2750 }
2751 toggleDateSelection(date) {
2752 const [index, _date] = this._indexOfDate(date, 'toggleDateSelection');
2753 if (index === -1) {
2754 this._doSelectDate(_date, 'toggleDateSelection');
2755 }
2756 else {
2757 this._doDeselectDate(index, _date);
2758 }
2759 }
2760 _indexOfDate(date, method) {
2761 const _date = this._toDate(date, method, 'date');
2762 const index = this.selectedDates.findIndex((s) => {
2763 return this._sameDay(s, _date);
2764 });
2765 return [index, _date];
2766 }
2767 deselectAll() {
2768 if (this.selectedDates.length === 0) {
2769 return;
2770 }
2771 const dates = [...this.selectedDates];
2772 this.selectedDates.length = 0;
2773 this._buildFrames();
2774 const e = {
2775 type: 'DATE_DESELECTED_MULTIPLE',
2776 dates,
2777 time: new Date(),
2778 };
2779 this._inform(e);
2780 }
2781 selectRange(a, b) {
2782 const method = 'selectRange';
2783 const aDate = this._toDate(a, method, 'a');
2784 const bDate = this._toDate(b, method, 'b');
2785 const startDate = bDate.getTime() > aDate.getTime() ? aDate : bDate;
2786 const endDate = aDate === startDate ? bDate : aDate;
2787 this._toMidnight(startDate);
2788 this._moveDateBy(endDate, 1);
2789 this._toMidnight(endDate);
2790 const date = new Date(startDate);
2791 const oldSelected = [...this.selectedDates];
2792 const selectedCollector = [];
2793 const deselectedCollector = [];
2794 let error = null;
2795 try {
2796 while (!this._sameDay(date, endDate)) {
2797 const index = this.selectedDates.findIndex((s) => {
2798 return this._sameDay(s, date);
2799 });
2800 if (index === -1) {
2801 const midnight = this._pushSelectDate(date, method, deselectedCollector);
2802 if (midnight) {
2803 selectedCollector.push(midnight);
2804 }
2805 }
2806 this._moveDateBy(date, 1);
2807 }
2808 }
2809 catch (e) {
2810 if (e instanceof DateGallerySelectionLimitReachedError) {
2811 error = e;
2812 }
2813 }
2814 const reportedSelectedDates = selectedCollector.filter((selectedDate) => !deselectedCollector.includes(selectedDate));
2815 if (reportedSelectedDates.length === 0) {
2816 if (error) {
2817 throw error;
2818 }
2819 return;
2820 }
2821 const deselectedDates = oldSelected.filter((oldSelect) => !this.selectedDates.some((selectedDate) => this._sameDay(oldSelect, selectedDate)));
2822 this._buildFrames();
2823 const event = {
2824 type: 'DATE_SELECTED_MULTIPLE',
2825 dates: reportedSelectedDates.map((d) => new Date(d)),
2826 deselectedDates: deselectedDates.map((d) => new Date(d)),
2827 time: new Date(),
2828 };
2829 this._inform(event);
2830 if (error) {
2831 throw error;
2832 }
2833 }
2834 addEvent(event) {
2835 const addedEvent = this._doAddEvent(event, 'addEvent');
2836 this.events.forEach((e) => {
2837 e._recalculate();
2838 });
2839 this._buildFrames();
2840 const e = {
2841 type: 'EVENT_ADDED',
2842 event: addedEvent,
2843 time: new Date(),
2844 };
2845 this._inform(e);
2846 return addedEvent;
2847 }
2848 _doAddEvent(config, method) {
2849 const startDate = this._toDate(config.startDate, method, 'event.startDate');
2850 const endDate = this._toDate(config.endDate, method, 'event.endDate');
2851 if (startDate.getTime() > endDate.getTime()) {
2852 throw new DateGalleryEventInvalidRangeError();
2853 }
2854 const event = new DateGalleryEvent(this, config.data, startDate, endDate);
2855 this.events.push(event);
2856 this.events.sort((a, b) => {
2857 return a.startDate.getTime() - b.startDate.getTime();
2858 });
2859 return event;
2860 }
2861 removeEvent(event) {
2862 const index = this.events.indexOf(event);
2863 if (index === -1) {
2864 return event;
2865 }
2866 this.events.splice(index, 1);
2867 this.events.forEach((e) => {
2868 e._recalculate();
2869 });
2870 this._buildFrames();
2871 const e = {
2872 type: 'EVENT_REMOVED',
2873 event,
2874 time: new Date(),
2875 };
2876 this._inform(e);
2877 return event;
2878 }
2879 moveEvent(event, range) {
2880 const startDate = this._toDate(range.startDate, 'moveEvent', 'range.startDate');
2881 const endDate = this._toDate(range.endDate, 'moveEvent', 'range.endDate');
2882 if (startDate.getTime() > endDate.getTime()) {
2883 throw new DateGalleryEventInvalidRangeError();
2884 }
2885 if (startDate.getTime() === event.startDate.getTime() &&
2886 endDate.getTime() === event.endDate.getTime()) {
2887 return;
2888 }
2889 const index = this.events.indexOf(event);
2890 if (index === -1) {
2891 throw new DateGalleryEventNotFoundError('moveEvent');
2892 }
2893 event.startDate = startDate;
2894 event.endDate = endDate;
2895 this.events.sort((a, b) => {
2896 return a.startDate.getTime() - b.startDate.getTime();
2897 });
2898 this.events.forEach((e) => {
2899 e._recalculate();
2900 });
2901 this._buildFrames();
2902 const e = {
2903 type: 'EVENT_MOVED',
2904 event,
2905 time: new Date(),
2906 };
2907 this._inform(e);
2908 }
2909 changeEventData(event, data) {
2910 const index = this.events.indexOf(event);
2911 if (index === -1) {
2912 throw new DateGalleryEventNotFoundError('changeEventData');
2913 }
2914 event.data = data;
2915 const e = {
2916 type: 'EVENT_DATA_CHANGED',
2917 event,
2918 data,
2919 time: new Date(),
2920 };
2921 this._inform(e);
2922 }
2923 _dragAnchor() {
2924 if (this.mode === 'year') {
2925 if (this.isUTC) {
2926 this._anchorDate.setUTCDate(1);
2927 this._anchorDate.setUTCMonth(0);
2928 }
2929 else {
2930 this._anchorDate.setDate(1);
2931 this._anchorDate.setMonth(0);
2932 }
2933 }
2934 else if (this.mode === 'week') {
2935 this._anchorDate = this._firstDayOfWeek(this._anchorDate);
2936 }
2937 else if (this.mode.startsWith('month')) {
2938 if (this.isUTC) {
2939 this._anchorDate.setUTCDate(1);
2940 }
2941 else {
2942 this._anchorDate.setDate(1);
2943 }
2944 }
2945 }
2946 _inform(event) {
2947 if (this._isInitializing) {
2948 return;
2949 }
2950 this._history._push(event);
2951 this._observer._inform(this, event);
2952 }
2953 _toDate(date, method, dateName) {
2954 if (date instanceof Date) {
2955 this._checkDate(date, method, dateName);
2956 }
2957 const result = new Date(date);
2958 this._checkDate(result, method, dateName);
2959 return result;
2960 }
2961 _checkDate(date, method, dateName) {
2962 const isValid = Object.prototype.toString.call(date) === '[object Date]' &&
2963 !isNaN(date.valueOf());
2964 if (!isValid) {
2965 throw new DateGalleryInvalidDateError(method, dateName);
2966 }
2967 }
2968 _firstDayOfWeek(date) {
2969 const copy = new Date(date);
2970 while (this._getDay(copy) !== this.firstDayOfWeek) {
2971 this._moveDateBy(copy, -1);
2972 }
2973 return copy;
2974 }
2975 _addNoDates(date, amount, frame) {
2976 for (let i = 0; i < amount; i++) {
2977 this._pushDay(date, frame);
2978 }
2979 }
2980 _addMonth(date, month, frame) {
2981 while (this._getMonth(date) === month) {
2982 this._pushDay(date, frame);
2983 }
2984 }
2985 _pushDay(date, frame) {
2986 frame.dates.push(this._makeDate(date));
2987 this._moveDateBy(date, 1);
2988 }
2989 _makeDate(date) {
2990 const _date = new Date(date);
2991 this._toMidnight(_date);
2992 let isPadding = false;
2993 if (this.mode === 'month-pad-to-week' || this.mode === 'month-six-weeks') {
2994 const anchorMonth = this._getMonth(this._anchorDate);
2995 isPadding = this._getMonth(_date) !== anchorMonth;
2996 }
2997 return new DateGalleryDate(this, _date, this.events.filter((event) => {
2998 const time = _date.getTime();
2999 const startDate = new Date(event.startDate);
3000 const start = this._toMidnight(startDate);
3001 const endDate = new Date(event.endDate);
3002 this._moveDateBy(endDate, 1);
3003 const end = this._toMidnight(endDate);
3004 return time >= start && time < end;
3005 }), isPadding, this.selectedDates.some((selected) => {
3006 return this._sameDay(selected, _date);
3007 }));
3008 }
3009 isSameDay(a, b) {
3010 const method = 'isSameDay';
3011 return this._sameDay(this._toDate(a, method, 'a'), this._toDate(b, method, 'b'));
3012 }
3013 _sameDay(a, b) {
3014 return (this._getFullYear(a) === this._getFullYear(b) &&
3015 this._getMonth(a) === this._getMonth(b) &&
3016 this._getDate(a) === this._getDate(b));
3017 }
3018 _getFullYear(date) {
3019 return this.isUTC ? date.getUTCFullYear() : date.getFullYear();
3020 }
3021 _getMonth(date) {
3022 return this.isUTC ? date.getUTCMonth() : date.getMonth();
3023 }
3024 _getDate(date) {
3025 return this.isUTC ? date.getUTCDate() : date.getDate();
3026 }
3027 _getDay(date) {
3028 return this.isUTC ? date.getUTCDay() : date.getDay();
3029 }
3030 _checkMode(mode) {
3031 if (!DATE_GALLERY_MODES.includes(mode)) {
3032 throw new DateGalleryModeError(mode);
3033 }
3034 }
3035 _toMidnight(date) {
3036 if (this.isUTC) {
3037 return date.setUTCHours(0, 0, 0, 0);
3038 }
3039 else {
3040 return date.setHours(0, 0, 0, 0);
3041 }
3042 }
3043 _moveDateBy(date, mod) {
3044 if (this.isUTC) {
3045 date.setUTCDate(date.getUTCDate() + mod);
3046 }
3047 else {
3048 date.setDate(date.getDate() + mod);
3049 }
3050 }
3051}
3052
3053function createDateGallerySubscriber(config) {
3054 return (activeList, event) => {
3055 _callSubscriber('createDateGallerySubscriber', event, activeList, config);
3056 };
3057}
3058
3059export { ActiveList, ActiveListActivationLimitReachedError, ActiveListAutoPlayDurationError, ActiveListContent, ActiveListCooldownDurationError, ActiveListIndexOutOfBoundsError, ActiveListItemNotFoundError, DATE_GALLERY_MODES, DateGallery, DateGalleryDate, DateGalleryEvent, DateGalleryEventInvalidRangeError, DateGalleryEventNotFoundError, DateGalleryFirstDayOfWeekError, DateGalleryInvalidDateError, DateGalleryModeError, DateGalleryNumberOfFramesError, DateGallerySelectionLimitReachedError, Typewriter, TypewriterActionUnknownCursorError, TypewriterBlinkAfterError, TypewriterCursor, TypewriterCursorNotAtSelectionEdgeError, TypewriterCursorOutOfBoundsError, TypewriterCursorSelectionInvalidRangeError, TypewriterCursorSelectionOutOfBoundsError, TypewriterDelayError, TypewriterRepeatDelayError, TypewriterRepeatError, ViewChannel, ViewChannelAutoDismissDurationError, ViewChannelIndexOutOfBoundsError, ViewChannelView, ViewChannelViewNotFoundError, _LicenseChecker, createActiveListSubscriber, createDateGallerySubscriber, createTypewriterSubscriber, createViewChannelSubscriber, licenseChecker, typewriterFromSentences };
3060//# sourceMappingURL=index.js.map