Socket
Socket
Sign inDemoInstall

timeline

Package Overview
Dependencies
0
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.2.2 to 3.3.0

__tests__/order-events.test.OLD.ts

2

__tests__/utils.dates.format.test.ts

@@ -20,3 +20,3 @@ import { formatDate, Granularity } from '../src/utils/dates'

test('DAY', () => {
expect(formatDate(Date.UTC(1900, 0), "DAY")).toBe('Mon, 1st Jan 1900')
expect(formatDate(Date.UTC(1900, 0), Granularity.DAY)).toBe('Mon, 1st Jan 1900')
expect(formatDate(Date.UTC(1900, 11, 2), Granularity.DAY)).toBe('Sun, 2nd Dec 1900')

@@ -23,0 +23,0 @@ expect(formatDate(Date.UTC(1900, 11, 3), Granularity.DAY)).toBe('Mon, 3rd Dec 1900')

@@ -7,2 +7,3 @@ import { Milliseconds } from "./constants";

import EventsBand from "./models/band/events";
import Popup from './views/popup';
export declare type Multiplier = .25 | .5 | 1 | 2 | 4 | 8 | 16;

@@ -24,3 +25,3 @@ export declare class Animator {

registerModel(model: Band<MinimapBandConfig | EventsBandConfig>): void;
registerView(view: Canvas | Debug): void;
registerView(view: Canvas | Debug | Popup): void;
private adjustMinimapBands;

@@ -27,0 +28,0 @@ animate: (timestamp: number) => void;

@@ -5,2 +5,3 @@ "use strict";

const constants_1 = require("./constants");
const event_bus_1 = require("./event-bus");
var Direction;

@@ -51,3 +52,3 @@ (function (Direction) {

this.adjustMinimapBands();
document.dispatchEvent(new CustomEvent(constants_1.ZOOM_DONE));
event_bus_1.default.dispatch(constants_1.EventType.ZoomDone);
this.stop();

@@ -94,3 +95,3 @@ }

this.elapsedTimeTotal = 0;
document.dispatchEvent(new CustomEvent(constants_1.CENTER_CHANGE_DONE));
event_bus_1.default.dispatch(constants_1.EventType.CenterChange);
}

@@ -151,2 +152,3 @@ accelerate() {

playForward() {
event_bus_1.default.dispatch(constants_1.EventType.Play);
this.direction = Direction.Forward;

@@ -156,2 +158,3 @@ this.nextFrame();

playBackward() {
event_bus_1.default.dispatch(constants_1.EventType.Play);
this.direction = Direction.Backward;

@@ -161,2 +164,3 @@ this.nextFrame();

stop() {
event_bus_1.default.dispatch(constants_1.EventType.Pause);
this.direction = Direction.Stop;

@@ -163,0 +167,0 @@ this.activeBand = null;

@@ -6,9 +6,8 @@ import { Animator } from './animator';

export default class Api {
private onChange;
protected views: View[];
animator: Animator;
constructor(onChange: OnChangeFunction);
private handleChange;
constructor();
on(eventName: string, func: any): void;
protected resize: () => void;
reload(): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const animator_1 = require("./animator");
const props_1 = require("./models/props");
const constants_1 = require("./constants");
const props_1 = require("./models/props");
class Api {
constructor(onChange) {
this.onChange = onChange;
constructor() {
this.animator = animator_1.default;
this.handleChange = () => {
this.onChange(props_1.default);
};
this.resize = () => {

@@ -29,5 +25,22 @@ props_1.default.resize();

});
if (this.onChange != null && typeof this.onChange === 'function') {
document.addEventListener(constants_1.CENTER_CHANGE_DONE, this.handleChange);
document.addEventListener(constants_1.ZOOM_DONE, this.handleChange);
}
on(eventName, func) {
const nameMap = {
centerchange: constants_1.EventType.CenterChange,
pause: constants_1.EventType.Pause,
play: constants_1.EventType.Play,
scrolldone: constants_1.EventType.ScrollDone,
select: constants_1.EventType.Select,
zoomdone: constants_1.EventType.ZoomDone,
};
if (Object.keys(nameMap).indexOf(eventName) > -1) {
const eventType = nameMap[eventName];
let realFunc;
if (eventType === constants_1.EventType.CenterChange)
realFunc = () => func(props_1.default);
else if (eventType === constants_1.EventType.Select)
realFunc = (ev) => func(ev.detail);
else
realFunc = func;
document.addEventListener(eventType, realFunc);
}

@@ -34,0 +47,0 @@ }

import { RawEv3nt } from "./models/event";
export declare const EVENT_HEIGHT = 14;
export declare const EVENT_ROW_HEIGHT = 16;
export declare const DATE_BAR_HEIGHT = 16;
export declare const RULER_LABELS_HEIGHT = 60;
export declare const CENTER_CHANGE_DONE = "CENTER_CHANGE_DONE";
export declare const ZOOM_DONE = "ZOOM_DONE";
export declare const SCROLL_DONE = "SCROLL_DONE";
export declare const IMAGE_SIZES: number[];
export declare const EVENT_HEIGHT = 16;
export declare const LETTER_WIDTH: number;
export declare const FONT_SIZE: number;
export declare const ROW_SPACING: number;
export declare const EVENT_ROW_HEIGHT: number;
export declare const DATE_BAR_HEIGHT: number;
export declare const IMAGE_BOUNDING_BOX: number;
export declare const IMAGE_BORDER_SIZE: number;
export declare const IMAGE_SIZE: number;
export declare enum EventType {
CenterChange = "CenterChange",
ZoomDone = "ZoomDone",
ScrollDone = "ScrollDone",
Pause = "Pause",
Play = "Play",
Select = "Select"
}
export declare const PIXELS_PER_LETTER = 8;
export declare const DEFAULT_IMAGE_PATH = "/images";
export declare type Milliseconds = number;

@@ -11,0 +23,0 @@ export declare type Grid = [Milliseconds, Milliseconds][][];

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EVENT_HEIGHT = 14;
exports.EVENT_ROW_HEIGHT = 16;
exports.IMAGE_SIZES = [16, 32, 64, 128, 256];
exports.EVENT_HEIGHT = 16;
exports.LETTER_WIDTH = Math.round(exports.EVENT_HEIGHT * .1875 + 3.5);
exports.FONT_SIZE = Math.round(exports.EVENT_HEIGHT * .3125 + 6);
exports.ROW_SPACING = Math.round(exports.EVENT_HEIGHT / 3);
exports.EVENT_ROW_HEIGHT = exports.EVENT_HEIGHT + exports.ROW_SPACING;
exports.DATE_BAR_HEIGHT = exports.EVENT_ROW_HEIGHT;
exports.RULER_LABELS_HEIGHT = 60;
exports.CENTER_CHANGE_DONE = 'CENTER_CHANGE_DONE';
exports.ZOOM_DONE = 'ZOOM_DONE';
exports.SCROLL_DONE = 'SCROLL_DONE';
exports.IMAGE_BOUNDING_BOX = (exports.EVENT_ROW_HEIGHT * 2) - exports.ROW_SPACING * 2;
exports.IMAGE_BORDER_SIZE = Math.round(exports.ROW_SPACING / 2);
exports.IMAGE_SIZE = exports.IMAGE_SIZES.reduce((prev, curr) => Math.abs(curr - exports.IMAGE_BOUNDING_BOX) < Math.abs(prev - exports.IMAGE_BOUNDING_BOX) ? curr : prev);
var EventType;
(function (EventType) {
EventType["CenterChange"] = "CenterChange";
EventType["ZoomDone"] = "ZoomDone";
EventType["ScrollDone"] = "ScrollDone";
EventType["Pause"] = "Pause";
EventType["Play"] = "Play";
EventType["Select"] = "Select";
})(EventType = exports.EventType || (exports.EventType = {}));
exports.PIXELS_PER_LETTER = 8;
exports.DEFAULT_IMAGE_PATH = '/images';
class RawSegment {

@@ -12,0 +25,0 @@ }

@@ -0,4 +1,6 @@

import { EventType } from './constants';
export declare type Target = Document | Window | HTMLElement;
export declare class EventBus {
private eventsListeners;
dispatch(eventType: EventType, payload?: any): void;
register(type: string, listener: EventListenerOrEventListenerObject, target?: Target): void;

@@ -5,0 +7,0 @@ flush(): void;

@@ -7,2 +7,8 @@ "use strict";

}
dispatch(eventType, payload) {
const event = (payload != null) ?
new CustomEvent(eventType, { detail: payload }) :
new CustomEvent(eventType);
document.dispatchEvent(event);
}
register(type, listener, target = document) {

@@ -9,0 +15,0 @@ target.addEventListener(type, listener);

import { Props } from './models/props';
import Config from './models/config/index';
import { calcPixelsPerMillisecond } from './utils';
import { OrderedEvents, orderEvents } from './utils/events.worker';
import Api, { OnChangeFunction } from './api';
import { OrderedTimeline, orderEvents } from './utils/events.worker';
import Api from './api';
import MinimapBand from './models/band/minimap';
import EventsBand from './models/band/events';
import { formatDate } from './utils/dates';
import { RawEv3nt } from './models/event';
export { Config as TimelineConfig, Props as TimelineProps, EventsBand, MinimapBand, OrderedEvents, calcPixelsPerMillisecond, formatDate, orderEvents, RawEv3nt };
export declare type OnSelectFunction = (e: RawEv3nt) => void;
import { Ev3ntLocation, RawEv3nt, Ev3nt, Voyage } from './models/event';
import { EventType } from './constants';
export { Config as TimelineConfig, Ev3nt, Ev3ntLocation, EventsBand, EventType, MinimapBand, OrderedTimeline, Props as TimelineProps, RawEv3nt, calcPixelsPerMillisecond, formatDate, orderEvents, Voyage, };
export declare type OnSelectFunction = (e: Ev3nt, band: EventsBand, props: Props) => void;
export default class Timeline extends Api {
protected config: Config;
private onSelect?;
private wrapper;
constructor(config: Config, onChange?: OnChangeFunction, onSelect?: OnSelectFunction);
private popup;
constructor(config: Config);
hidePopup(): void;
showPopup(event: Ev3nt): void;
private render;

@@ -18,0 +20,0 @@ private renderLabels;

@@ -12,3 +12,3 @@ "use strict";

const events_worker_1 = require("./utils/events.worker");
exports.OrderedEvents = events_worker_1.OrderedEvents;
exports.OrderedTimeline = events_worker_1.OrderedTimeline;
exports.orderEvents = events_worker_1.orderEvents;

@@ -19,2 +19,3 @@ const api_1 = require("./api");

const label_1 = require("./views/label");
const popup_1 = require("./views/popup");
const minimap_1 = require("./models/band/minimap");

@@ -27,9 +28,12 @@ exports.MinimapBand = minimap_1.default;

const event_1 = require("./models/event");
exports.Ev3ntLocation = event_1.Ev3ntLocation;
exports.RawEv3nt = event_1.RawEv3nt;
exports.Ev3nt = event_1.Ev3nt;
exports.Voyage = event_1.Voyage;
const band_2 = require("./models/band");
const constants_1 = require("./constants");
exports.EventType = constants_1.EventType;
class Timeline extends api_1.default {
constructor(config, onChange, onSelect) {
super(onChange);
this.config = config;
this.onSelect = onSelect;
constructor(config) {
super();
this.appendToWrapper = (child) => {

@@ -43,5 +47,12 @@ let children = child.render();

config.rootElement.appendChild(this.render());
this.popup = new popup_1.default(this.wrapper);
const debouncedResize = utils_1.debounce(this.resize, 600);
window.addEventListener('resize', debouncedResize);
}
hidePopup() {
this.popup.hide();
}
showPopup(event) {
this.popup.show(event);
}
render() {

@@ -58,3 +69,3 @@ this.wrapper = create_element_1.default('div', 'wrapper', [

.map(band => band.type === band_2.BandType.EventsBand ?
new events_1.default(band, this.onSelect) :
new events_1.default(band) :
new band_1.default(band));

@@ -61,0 +72,0 @@ this.views.push(new canvas_1.default());

import Band, { BandType } from '.';
import { EventsBandConfig } from '../config';
import { Pixels } from '../../constants';
import { RawEv3nt } from '../event';
import { Ev3nt } from '../event';
import { OrderedBand } from '../../utils/events.worker';
export default class EventsBand extends Band<EventsBandConfig> {

@@ -10,15 +11,15 @@ type: BandType;

private highestVisibleRow;
events: RawEv3nt[];
events: Ev3nt[];
rowCount: number;
visibleEvents: RawEv3nt[];
visibleEvents: Ev3nt[];
private _offsetY;
offsetY: number;
constructor(config: EventsBandConfig);
init(): void;
init(orderedBand: OrderedBand): void;
private getColor;
private updateEvents;
update(): void;
getEventByCoordinates(x: Pixels, y: Pixels): RawEv3nt;
getEventByCoordinates(x: Pixels, y: Pixels): Ev3nt;
zoomIn(): void;
zoomOut(): void;
}

@@ -8,5 +8,3 @@ "use strict";

const props_1 = require("../props");
const events_worker_1 = require("../../utils/events.worker");
const dates_1 = require("../../utils/dates");
const utils_1 = require("../../utils");
class EventsBand extends _1.default {

@@ -37,10 +35,6 @@ constructor(config) {

}
init() {
init(orderedBand) {
super.init();
const pixelsPerMillisecond = utils_1.calcPixelsPerMillisecond(props_1.default.viewportWidth, this.config.zoomLevel || 0, props_1.default.time);
const orderedEvents = this.config.orderedEvents == null ?
events_worker_1.orderEvents(this.config.events, pixelsPerMillisecond) :
this.config.orderedEvents;
this.events = orderedEvents.events;
this.rowCount = orderedEvents.row_count;
this.events = orderedBand.events;
this.rowCount = orderedBand.rowCount;
this.height = constants_1.EVENT_ROW_HEIGHT * this.rowCount;

@@ -82,3 +76,36 @@ this.offsetY = 0;

event.width = 1;
event.padding = Math.round((event.space) * this.pixelsPerMillisecond);
event.uncertain_from_width = 0;
if (event.dmin != null) {
let uncertain_from_to;
if (event.d != null) {
uncertain_from_to = event.d;
}
else if (event.ed != null) {
uncertain_from_to = event.ed;
}
else if (event.dmax != null) {
uncertain_from_to = event.dmin + (event.dmax - event.dmin) / 2;
}
else {
throw Error(['updateEvents', 'Width uncertain from is not definable', JSON.stringify(event)].join('\n'));
}
event.uncertain_from_width = (uncertain_from_to - event.dmin) * this.pixelsPerMillisecond;
}
event.uncertain_to_width = 0;
if (event.dmax != null) {
let uncertain_to_from;
if (event.ed != null) {
uncertain_to_from = event.ed;
}
else if (event.d != null) {
uncertain_to_from = event.d;
}
else if (event.dmin != null) {
uncertain_to_from = event.dmin + (event.dmax - event.dmin) / 2;
}
else {
throw Error(['updateEvents', 'Width uncertain to is not definable', JSON.stringify(event)].join('\n'));
}
event.uncertain_to_width = (event.dmax - uncertain_to_from) * this.pixelsPerMillisecond;
}
event.top = this.top + this.availableHeight - ((event.row + 1) * constants_1.EVENT_ROW_HEIGHT) + this.offsetY;

@@ -98,3 +125,3 @@ event.color = this.getColor(event.from, event.to);

const event = this.events.find(e => {
if (!(e.from < timestamp && e.from + e.time + e.space > timestamp) ||
if (!(e.from < timestamp && e.screenTo > timestamp) ||
(e.row < this.lowestVisibleRow || e.row > this.highestVisibleRow))

@@ -101,0 +128,0 @@ return false;

import { Granularity } from '../../utils/dates';
import { Pixels, Milliseconds, Ratio } from '../../constants';
import { BandConfig } from '../config';
import { OrderedBand } from '../../utils/events.worker';
export declare enum BandType {

@@ -33,3 +34,3 @@ EventsBand = 0,

private setHorizontalProps;
init(): void;
init(_orderedBand?: OrderedBand): void;
resize(): void;

@@ -36,0 +37,0 @@ update(): void;

@@ -40,2 +40,4 @@ "use strict";

this.availableHeight = this.visibleHeight - constants_1.DATE_BAR_HEIGHT;
if (this.availableHeight / this.visibleHeight < .666)
this.availableHeight = this.visibleHeight * .666;
this.visibleRowsCount = Math.floor(this.availableHeight / constants_1.EVENT_ROW_HEIGHT) - 1;

@@ -49,3 +51,3 @@ this.top = Math.round(this.config.topOffsetRatio * props_1.default.viewportHeight);

}
init() {
init(_orderedBand) {
this.zoomLevel = this.config.zoomLevel;

@@ -52,0 +54,0 @@ this.setVerticalProps();

@@ -56,11 +56,14 @@ "use strict";

continue;
const x = this.positionAtTimestamp(event.from);
const y = this.maxRowCount - ((event.row + 2) * this.eventHeight);
const eventWidth = Math.round(event.time * this.pixelsPerMillisecond);
const eventLeft = this.positionAtTimestamp(event.date_min != null ? event.date_min : event.date);
const y = this.maxRowCount - ((event.row + 1) * this.eventHeight);
const width = eventWidth < 1 ? 1 : eventWidth;
this.nextCtx.rect(eventLeft, y, width, this.eventHeight);
this.nextCtx.fillStyle = `rgb(190, 190, 190)`;
this.nextCtx.fillRect(x, y, width, this.eventHeight);
if (event.img) {
this.nextCtx.fillStyle = `rgb(240, 240, 240)`;
this.nextCtx.fillRect(x, y - this.eventHeight * 2, this.eventHeight * 2, this.eventHeight * 2);
}
}
});
this.nextCtx.fillStyle = `rgb(190, 190, 190)`;
this.nextCtx.fill();
}

@@ -67,0 +70,0 @@ updateNextCanvas() {

import { Ratio } from "../../constants";
import { OrderedEvents } from "../../utils/events.worker";
import { RawEv3nt } from "../event";
import { OrderedTimeline } from "../../utils/events.worker";
import { RawEv3nt, Ev3nt } from "../event";
import MinimapBand from "../band/minimap";

@@ -22,9 +22,11 @@ import EventsBand from "../band/events";

label?: string;
orderedEvents?: OrderedEvents;
orderedEvents?: OrderedTimeline;
}
export default class Config {
bands: (EventsBand | MinimapBand)[];
center?: number;
controlBand: EventsBand;
bands: (EventsBand | MinimapBand)[];
controlBand?: EventsBand;
imagePath?: string;
parent?: Ev3nt;
rootElement: HTMLElement;
}
import { Milliseconds, Pixels } from '../constants';
import { Granularity } from '../utils/dates';
export declare enum ImageFileType {
NONE = "none",
JPG = "jpg",
SVG = "svg",
GIF = "gif",
PNG = "png"
}
declare class Point {
type: "Point";
coordinates: [number, number];
}
export declare class Ev3ntLocation {
coor: Point;
coor4326?: [number, number];
dmin?: Milliseconds;
dmin_g?: Granularity;
d?: Milliseconds;
d_g?: Granularity;
ed?: Milliseconds;
ed_g?: Granularity;
dmax?: Milliseconds;
dmax_g?: Granularity;
}
export declare class Voyage {
d: Milliseconds;
ed: Milliseconds;
route: string;
sp?: Point;
ep?: Point;
}
export declare class RawEv3nt {
date: Milliseconds;
date_granularity?: Granularity;
date_min?: Milliseconds;
date_min_granularity?: Granularity;
description?: string;
end_date?: Milliseconds;
end_date_granularity?: Granularity;
end_date_max?: Milliseconds;
end_date_max_granularity?: Granularity;
id?: string;
label?: string;
row?: number;
wikidata_identifier?: string;
class: string[];
d: Milliseconds;
d_g: Granularity;
dmax: Milliseconds;
dmax_g: Granularity;
dmin: Milliseconds;
dmin_g: Granularity;
dsc: string;
ed: Milliseconds;
ed_g: Granularity;
id: string;
img: ImageFileType;
lbl: string;
locs: Ev3ntLocation[];
voyages: Voyage[];
wid: string;
}
export declare class Ev3nt extends RawEv3nt {
from: Milliseconds;
to: Milliseconds;
tags: string[];
locations: any[];
screenTo: Milliseconds;
time?: Milliseconds;
space?: Milliseconds;
row: number;
left?: Pixels;
padding?: Pixels;
top?: Pixels;
width?: Pixels;
uncertain_from_width?: Pixels;
uncertain_to_width?: Pixels;
color?: string;
image?: HTMLImageElement;
constructor(event: RawEv3nt, pixelsPerMillisecond?: Pixels);
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../constants");
var ImageFileType;
(function (ImageFileType) {
ImageFileType["NONE"] = "none";
ImageFileType["JPG"] = "jpg";
ImageFileType["SVG"] = "svg";
ImageFileType["GIF"] = "gif";
ImageFileType["PNG"] = "png";
})(ImageFileType = exports.ImageFileType || (exports.ImageFileType = {}));
class Point {
}
class Ev3ntLocation {
}
exports.Ev3ntLocation = Ev3ntLocation;
class Voyage {
}
exports.Voyage = Voyage;
class RawEv3nt {
constructor() {
this.date_granularity = "DAY";
}
exports.RawEv3nt = RawEv3nt;
class Ev3nt extends RawEv3nt {
constructor(event, pixelsPerMillisecond) {
super();
for (const key in event) {
if (event[key] != null)
this[key] = event[key];
}
if (this.lbl == null)
this.lbl = 'NO LABEL';
if (this.id == null)
this.id = 'id_' + crypto.getRandomValues(new Uint8Array(4)).join('_');
this.from = this.dmin || this.d;
this.to = this.dmax || this.ed;
if (this.to == null)
this.to = this.from;
this.time = this.to - this.from;
if (pixelsPerMillisecond != null) {
const paddingRight = Math.round(constants_1.EVENT_HEIGHT * 2 / pixelsPerMillisecond);
let space = ((this.lbl.length * constants_1.PIXELS_PER_LETTER) / pixelsPerMillisecond) + paddingRight;
space = space > this.time ? space - this.time : 0;
this.screenTo = Math.round(this.from + this.time + space);
}
}
}
exports.RawEv3nt = RawEv3nt;
exports.Ev3nt = Ev3nt;

@@ -5,4 +5,6 @@ import { Milliseconds, Pixels } from "../constants";

import EventsBand from "./band/events";
import { RawEv3nt } from './event';
export declare class Props {
private readonly defaultCenterRatio;
parent: RawEv3nt;
bands: (EventsBand | MinimapBand)[];

@@ -12,2 +14,3 @@ eventsBands: EventsBand[];

controlBand: EventsBand;
imagePath: string;
from: Milliseconds;

@@ -23,3 +26,2 @@ time: Milliseconds;

dimensions: HTMLElement;
private centerChangeDone;
init(config: Config): void;

@@ -26,0 +28,0 @@ resize(): void;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../constants");
const utils_1 = require("../utils");
const band_1 = require("./band");
const __1 = require("..");
const event_bus_1 = require("../event-bus");
function onEventsBand(band) {

@@ -15,5 +16,2 @@ return band.type === band_1.BandType.EventsBand;

this.defaultCenterRatio = .5;
this.centerChangeDone = utils_1.debounce(() => {
document.dispatchEvent(new CustomEvent(constants_1.CENTER_CHANGE_DONE));
}, 300);
}

@@ -30,3 +28,3 @@ get center() { return this._center; }

this._center = n;
this.centerChangeDone();
event_bus_1.default.dispatch(constants_1.EventType.CenterChange);
}

@@ -42,21 +40,5 @@ set dimensions(rootElement) {

console.error('[init] No rootElement found');
this.imagePath = config.imagePath != null ? config.imagePath : constants_1.DEFAULT_IMAGE_PATH;
this.rootElement = config.rootElement;
this.dimensions = this.rootElement;
const [froms, tos] = config.bands.reduce((prev, curr) => {
if (curr.type === band_1.BandType.MinimapBand)
return prev;
const band = curr;
const events = band.config.orderedEvents == null ? band.config.events : band.config.orderedEvents.events;
prev[0].push(events[0].date_min || events[0].date);
prev[1].push(events.reduce((prev2, curr2) => {
return Math.max(prev2, curr2.end_date || -Infinity, curr2.end_date_max || -Infinity);
}, -Infinity));
return prev;
}, [[], []]);
this.from = Math.min(...froms);
this.to = Math.max(...tos);
this.time = this.to - this.from;
this.center = (config.center != null) ?
config.center :
this.from + (this.defaultCenterRatio * this.time);
this.bands = config.bands;

@@ -66,3 +48,26 @@ this.eventsBands = this.bands.filter(onEventsBand);

this.controlBand = config.controlBand != null ? config.controlBand : this.eventsBands[0];
for (const band of this.bands) {
const t0 = performance.now();
const options = {
bands: this.eventsBands
.map(band => ({
events: band.config.events,
zoomLevel: band.config.zoomLevel
})),
parent: config.parent,
viewportWidth: this.viewportWidth
};
const orderResult = __1.orderEvents(options);
this.parent = orderResult.parent;
this.from = orderResult.from;
this.to = orderResult.to;
this.time = orderResult.time;
const t1 = performance.now();
console.log('Performance: ', `${t1 - t0}ms\n[from] ${new Date(this.from).toUTCString()}\n[ to ] ${new Date(this.to).toUTCString()}`);
this.center = (config.center != null) ?
config.center :
this.from + (this.defaultCenterRatio * this.time);
for (const [index, band] of this.eventsBands.entries()) {
band.init(orderResult.bands[index]);
}
for (const band of this.minimapBands) {
band.init();

@@ -69,0 +74,0 @@ }

@@ -14,3 +14,3 @@ import { Milliseconds } from "../constants";

WEEK = "WEEK",
MONTH = "MONHT",
MONTH = "MONTH",
YEAR = "YEAR",

@@ -28,3 +28,3 @@ YEAR_5 = "YEAR_5",

export declare function subsequentDate(granularity: Granularity): ((date: Milliseconds) => Milliseconds);
export declare function byDate(a: RawEv3nt, b: RawEv3nt): 1 | 0 | -1;
export declare function byDate(a: RawEv3nt, b: RawEv3nt): 0 | 1 | -1;
export declare const labelBody: (d: number, granularity: Granularity) => string;

@@ -33,3 +33,3 @@ "use strict";

label = `${formatMonth(date)} ${label}`;
if (granularity === "MONHT")
if (granularity === "MONTH")
return label;

@@ -72,3 +72,3 @@ label = `${formatDateNumber(date)} ${label}`;

if (pixelsPerMillisecond > 2.2e-8)
return "MONHT";
return "MONTH";
if (pixelsPerMillisecond > 2.2e-9)

@@ -82,3 +82,3 @@ return "YEAR";

return "DECADE_5";
if (pixelsPerMillisecond > 1e-11)
if (pixelsPerMillisecond > 1.5e-11)
return "CENTURY";

@@ -136,3 +136,3 @@ if (pixelsPerMillisecond > 5e-12)

}
if (granularity === "MONHT") {
if (granularity === "MONTH") {
return (d) => {

@@ -186,4 +186,4 @@ const date = new Date(d);

function byDate(a, b) {
const aFrom = a.date_min != null ? a.date_min : a.date;
const bFrom = b.date_min != null ? b.date_min : b.date;
const aFrom = a.dmin != null ? a.dmin : a.d;
const bFrom = b.dmin != null ? b.dmin : b.d;
if (aFrom < bFrom)

@@ -193,4 +193,4 @@ return -1;

return 1;
const aTo = a.end_date_max != null ? a.end_date_max : a.end_date;
const bTo = b.end_date_max != null ? b.end_date_max : b.end_date;
const aTo = a.dmax != null ? a.dmax : a.ed;
const bTo = b.dmax != null ? b.dmax : b.ed;
if (aTo < bTo)

@@ -214,3 +214,3 @@ return -1;

return date.getUTCFullYear().toString();
if (granularity === "MONHT")
if (granularity === "MONTH")
return formatMonth(date);

@@ -217,0 +217,0 @@ if (granularity === "WEEK")

@@ -1,7 +0,26 @@

import { Milliseconds } from "../constants";
import { RawEv3nt } from "../models/event";
export declare class OrderedEvents {
import { Milliseconds, Pixels } from "../constants";
import { Ev3nt, RawEv3nt } from "../models/event";
interface InputBand {
events: RawEv3nt[];
row_count: number;
zoomLevel: number;
}
export declare function orderEvents(events: RawEv3nt[], pixelsPerMillisecond: Milliseconds): OrderedEvents;
export interface OrderedBand {
events: Ev3nt[];
pixelsPerMillisecond?: Pixels;
rowCount: number;
zoomLevel: number;
}
interface Options {
parent?: RawEv3nt;
bands: InputBand[];
viewportWidth: Pixels;
}
export declare class OrderedTimeline {
bands: OrderedBand[];
from: Milliseconds;
parent: Ev3nt;
time: Milliseconds;
to: Milliseconds;
}
export declare function orderEvents(options: Options): OrderedTimeline;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../constants");
class OrderedEvents {
constructor() {
this.events = [];
this.row_count = 0;
const event_1 = require("../models/event");
const index_1 = require("./index");
class OrderedTimeline {
}
exports.OrderedTimeline = OrderedTimeline;
function orderEvents(options) {
if (options.bands == null || !options.bands.length)
return new OrderedTimeline();
let from = options.bands.reduce((prev, curr) => {
const firstEvent = curr.events[0];
return Math.min(prev, firstEvent.dmin || Infinity, firstEvent.d || Infinity);
}, Infinity);
let to = options.bands.reduce((prev, curr) => {
const highest = curr.events.reduce((prev2, curr2) => {
return Math.max(prev2, curr2.d || -Infinity, curr2.ed || -Infinity, curr2.dmax || -Infinity);
}, -Infinity);
return Math.max(highest, prev);
}, -Infinity);
let parent;
if (options.parent != null) {
parent = new event_1.Ev3nt(options.parent);
from = Math.min(from, parent.dmin || Infinity, parent.d || Infinity);
to = Math.max(to, parent.ed || -Infinity, parent.dmax || -Infinity);
}
}
exports.OrderedEvents = OrderedEvents;
const pixelsPerLetter = 8;
function orderEvents(events, pixelsPerMillisecond) {
if (!events.length)
return new OrderedEvents();
let rowCount = 0;
const grid = [];
const paddingRight = constants_1.EVENT_HEIGHT * 2 / pixelsPerMillisecond;
const addRow = (event) => {
let row;
if (event.label == null)
event.label = 'NO LABEL';
event.from = event.date_min || event.date;
event.to = event.end_date_max || event.end_date;
if (event.to == null)
event.to = event.from;
event.time = event.to == null ? 0 : event.to - event.from;
event.space = 0;
if (!event.time) {
if (event.label == null)
event.label = 'NO LABEL';
event.space = ((event.label.length * pixelsPerLetter) / pixelsPerMillisecond) + paddingRight;
const time = to - from;
function processBand(band) {
const pixelsPerMillisecond = index_1.calcPixelsPerMillisecond(options.viewportWidth, band.zoomLevel, time);
const rows = [-Infinity];
const imageSize = Math.round(constants_1.EVENT_ROW_HEIGHT * 2 / pixelsPerMillisecond);
function rowHasSpace(row, imageFrom) {
return (rows[row + 1] == null || rows[row + 1] < imageFrom) && (rows[row + 2] == null || rows[row + 2] < imageFrom);
}
let rowIterator = 0;
while (row == null && rowIterator < grid.length) {
let cellIterator = 0;
let hasSpace = true;
while (hasSpace && cellIterator < grid[rowIterator].length) {
if (event.to < grid[rowIterator][cellIterator][0])
break;
hasSpace = event.from > grid[rowIterator][cellIterator][1];
cellIterator++;
function addRow(rawEvent) {
const event = new event_1.Ev3nt(rawEvent, pixelsPerMillisecond);
let row;
if (event.img) {
const imageFrom = event.time ? event.from : event.from - imageSize / 2;
const imageTo = event.time ? event.from + imageSize : event.from + imageSize / 2;
row = rows.findIndex(r => imageFrom > r);
if (row > -1) {
let hasSpace = false;
while (!hasSpace) {
hasSpace = rowHasSpace(row, imageFrom);
if (hasSpace)
break;
row = rows.findIndex((r, i) => i > row && imageFrom > r);
if (row === -1)
hasSpace = true;
}
}
if (row === -1) {
row = rows.push(event.screenTo) - 1;
rows.push(imageTo);
rows.push(imageTo);
}
else {
rows[row] = event.screenTo;
rows[row + 1] = imageTo;
rows[row + 2] = imageTo;
}
}
if (hasSpace) {
grid[rowIterator].push([event.from, event.from + event.time + event.space]);
row = rowIterator;
else {
row = rows.findIndex(r => event.from > r);
if (row === -1) {
row = rows.push(event.screenTo) - 1;
}
else {
rows[row] = event.screenTo;
}
}
rowIterator++;
event.row = row;
return event;
}
if (row == null)
row = grid.push([[event.from, event.from + event.time + event.space]]) - 1;
if (row > rowCount)
rowCount = row;
event.row = row;
return event;
};
events = events.map(addRow);
return {
events: band.events.map(addRow),
zoomLevel: band.zoomLevel,
pixelsPerMillisecond,
rowCount: rows.length,
};
}
return {
events,
row_count: grid.length
bands: options.bands.map(processBand),
from,
parent,
time,
to,
};
}
exports.orderEvents = orderEvents;

@@ -1,2 +0,2 @@

import { RawEv3nt } from "../models/event";
import { Ev3nt } from "../models/event";
import { Milliseconds, Ratio, Pixels } from "../constants";

@@ -8,2 +8,2 @@ export declare const debounce: (func: Function, wait: number) => () => void;

export declare function calcPixelsPerMillisecond(viewportWidth: Pixels, zoomLevel: number, totalTime: Milliseconds): number;
export declare function logEvent(event: RawEv3nt, ...rest: string[]): void;
export declare function logEvent(event: Ev3nt, ...rest: string[]): void;

@@ -37,7 +37,7 @@ "use strict";

const d = new Date(ts);
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
return d.toUTCString();
}
function logEvent(event, ...rest) {
console.log(event.label, event, event.left, formatDate(event.from), formatDate(event.to), rest);
console.log(event.lbl, event, formatDate(event.from), formatDate(event.to), rest);
}
exports.logEvent = logEvent;
import BandView from './index';
import EventsBand from '../../models/band/events';
import { OnSelectFunction } from '../../index';
export default class EventsBandView extends BandView {
band: EventsBand;
private select;
constructor(band: EventsBand, select: OnSelectFunction);
constructor(band: EventsBand);
render(): HTMLElement;

@@ -9,0 +7,0 @@ private onWheel;

@@ -5,8 +5,7 @@ "use strict";

const event_bus_1 = require("../../event-bus");
const utils_1 = require("../../utils");
const constants_1 = require("../../constants");
class EventsBandView extends index_1.default {
constructor(band, select) {
constructor(band) {
super(band);
this.band = band;
this.select = select;
this.onWheel = (ev) => {

@@ -24,6 +23,3 @@ if (Math.abs(ev.deltaX) === 0 && ev.deltaY !== 0) {

const event = this.band.getEventByCoordinates(ev.clientX, ev.clientY);
if (event && this.select) {
this.select(event);
utils_1.logEvent(event);
}
event_bus_1.default.dispatch(constants_1.EventType.Select, event);
};

@@ -30,0 +26,0 @@ }

@@ -71,3 +71,3 @@ "use strict";

if (this.lastDragInterval > 200 || significantDrag) {
document.dispatchEvent(new CustomEvent(constants_1.SCROLL_DONE));
event_bus_1.default.dispatch(constants_1.EventType.ScrollDone);
}

@@ -74,0 +74,0 @@ }

@@ -9,2 +9,6 @@ import View from '../index';

constructor();
private updateImages;
private onImgLoad;
private drawImage;
private onAnimationDone;
render(): HTMLCanvasElement[];

@@ -11,0 +15,0 @@ resize(): void;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const create_element_1 = require("../../utils/create-element");

@@ -8,18 +9,72 @@ const props_1 = require("../../models/props");

const rulers_1 = require("./rulers");
const band_1 = require("../../models/band");
const event_bus_1 = require("../../event-bus");
class Canvas {
constructor() {
this.indicatorsDrawn = false;
this.onImgLoad = (event) => {
const callback = (ev) => {
event.image.removeEventListener('load', callback);
event.image.removeEventListener('error', callback);
if (ev.type === 'error') {
event.image = null;
return;
}
if (event.image.width > event.image.height) {
event.image.height = Math.round(event.image.height * (constants_1.IMAGE_BOUNDING_BOX / event.image.width));
event.image.width = constants_1.IMAGE_BOUNDING_BOX;
}
else {
event.image.width = Math.round(event.image.width * (constants_1.IMAGE_BOUNDING_BOX / event.image.height));
event.image.height = constants_1.IMAGE_BOUNDING_BOX;
}
this.drawImage(event);
};
return callback;
};
this.onAnimationDone = () => {
};
this.update = () => {
props_1.default.bands
.forEach(band => {
if (band.type === band_1.BandType.EventsBand)
this.drawEventsBand(band);
else
this.drawMinimapBand(band);
});
for (const band of props_1.default.eventsBands) {
this.drawEventsBand(band);
}
for (const band of props_1.default.minimapBands) {
this.drawMinimapBand(band);
}
this.drawIndicators();
this.updateImages();
};
animator_1.default.registerView(this);
event_bus_1.default.register(constants_1.EventType.ZoomDone, this.onAnimationDone);
event_bus_1.default.register(constants_1.EventType.ScrollDone, this.onAnimationDone);
}
updateImages() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
for (const band of props_1.default.eventsBands) {
for (const event of band.visibleEvents) {
if (event.img == null)
continue;
if (event.image == null) {
const path = `${props_1.default.imagePath}/${event.wid}__${constants_1.IMAGE_SIZE}.${event.img}`;
event.image = new Image();
const onImgLoad = this.onImgLoad(event);
event.image.addEventListener('load', onImgLoad);
event.image.addEventListener('error', onImgLoad);
event.image.src = path;
}
else {
this.drawImage(event);
}
}
}
});
}
drawImage(event) {
if (event.image == null || !event.image.complete || !event.image.naturalWidth)
return;
const x = event.time ? event.left : event.left - (event.image.width / 2) - constants_1.IMAGE_BORDER_SIZE;
const y = event.top - event.image.height;
this.ctx.fillStyle = event.color;
this.ctx.fillRect(x, y - constants_1.IMAGE_BORDER_SIZE * 2, event.image.width + constants_1.IMAGE_BORDER_SIZE * 2, event.image.height + constants_1.IMAGE_BORDER_SIZE * 2);
this.ctx.drawImage(event.image, x + constants_1.IMAGE_BORDER_SIZE, y - constants_1.IMAGE_BORDER_SIZE, event.image.width, event.image.height);
}
render() {

@@ -63,4 +118,25 @@ this.canvas = create_element_1.default('canvas', 'main', [

else {
let left = event.left;
let width = event.width;
if (event.uncertain_from_width > 1) {
const gradient = this.ctx.createLinearGradient(event.left, 0, event.left + event.uncertain_from_width, 0);
gradient.addColorStop(0, 'white');
gradient.addColorStop(1, event.color);
this.ctx.fillStyle = gradient;
this.ctx.fillRect(event.left, event.top, event.uncertain_from_width, constants_1.EVENT_HEIGHT);
left = event.left + event.uncertain_from_width;
width -= event.uncertain_from_width;
}
if (event.uncertain_to_width > 1) {
width -= event.uncertain_to_width;
const gradientLeft = left + width;
const gradientWidth = gradientLeft + event.uncertain_to_width;
const gradient = this.ctx.createLinearGradient(gradientLeft, 0, gradientWidth, 0);
gradient.addColorStop(0, event.color);
gradient.addColorStop(1, 'white');
this.ctx.fillStyle = gradient;
this.ctx.fillRect(gradientLeft, event.top, event.uncertain_to_width, constants_1.EVENT_HEIGHT);
}
this.ctx.fillStyle = event.color;
this.ctx.fillRect(event.left, event.top, event.width, constants_1.EVENT_HEIGHT);
this.ctx.fillRect(left, event.top, width, constants_1.EVENT_HEIGHT);
}

@@ -71,16 +147,13 @@ }

drawEventsText(band) {
this.ctx.font = '11px sans-serif';
this.ctx.font = `${constants_1.FONT_SIZE}px sans-serif`;
this.ctx.fillStyle = `rgb(40, 40, 40)`;
for (const event of band.visibleEvents) {
let eventWidth = event.time === 0 ? event.padding : event.width;
let eventLeft = event.left;
if (event.left < 0 && event.time !== 0) {
eventWidth = event.width + event.left;
eventLeft = 0;
eventLeft = -event.uncertain_from_width;
}
let eventLabelLength = event.label.length * constants_1.PIXELS_PER_LETTER;
if (eventLabelLength <= eventWidth) {
const paddingLeft = event.time ? 3 : 8;
this.ctx.fillText(event.label, eventLeft + paddingLeft, event.top + constants_1.EVENT_HEIGHT - 3);
}
const paddingLeft = event.time ? constants_1.FONT_SIZE / 3 : constants_1.FONT_SIZE / 1.2;
const x = eventLeft + paddingLeft + event.uncertain_from_width;
const y = event.top + constants_1.FONT_SIZE + ((constants_1.EVENT_HEIGHT - constants_1.FONT_SIZE) / 2) - 2;
this.ctx.fillText(event.lbl, Math.round(x), Math.round(y));
}

@@ -109,3 +182,3 @@ }

this.indicatorsCtx.rect(rightIndicatorLeftX, indicatorTOP, props_1.default.viewportWidth, band.visibleHeight);
this.indicatorsCtx.rect(leftIndicatorRightX, indicatorTOP + band.visibleHeight - constants_1.DATE_BAR_HEIGHT, rightIndicatorLeftX - leftIndicatorRightX, constants_1.DATE_BAR_HEIGHT);
this.indicatorsCtx.rect(leftIndicatorRightX, indicatorTOP + band.availableHeight, rightIndicatorLeftX - leftIndicatorRightX, band.visibleHeight - band.availableHeight);
}

@@ -112,0 +185,0 @@ this.indicatorsCtx.fillStyle = `rgba(0, 0, 0, .04)`;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const props_1 = require("../../models/props");
const constants_1 = require("../../constants");
const dates_1 = require("../../utils/dates");
const smallFont = "11px sans-serif";
const bigFont = "13px sans-serif";
function isSpecialRuler(date, band) {

@@ -39,3 +38,3 @@ if (band.granularity === "CENTURY" && new Date(date).getUTCFullYear() % 1000 === 0)

ctx.beginPath();
ctx.font = smallFont;
ctx.font = `${constants_1.FONT_SIZE}px sans-serif`;
ctx.fillStyle = `rgb(205, 205, 205)`;

@@ -48,3 +47,3 @@ for (const date of normalRulerDates) {

ctx.beginPath();
ctx.font = bigFont;
ctx.font = `${constants_1.FONT_SIZE * 1.2}px sans-serif`;
ctx.fillStyle = `rgb(120, 120, 120)`;

@@ -51,0 +50,0 @@ for (const date of specialRulerDates) {

@@ -1,1 +0,16 @@

!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Timeline=e():t.Timeline=e()}(this,function(){return function(t){var e={};function i(s){if(e[s])return e[s].exports;var n=e[s]={i:s,l:!1,exports:{}};return t[s].call(n.exports,n,n.exports,i),n.l=!0,n.exports}return i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)i.d(s,n,function(e){return t[e]}.bind(null,n));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="/dist/",i(i.s=11)}([function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(1),n=i(3),o=i(2);function r(t){return t.type===o.BandType.EventsBand}function a(t){return t.type===o.BandType.MinimapBand}class l{constructor(){this.defaultCenterRatio=.5,this.centerChangeDone=n.debounce(()=>{document.dispatchEvent(new CustomEvent(s.CENTER_CHANGE_DONE))},300)}get center(){return this._center}set center(t){this._center===this.from&&t<this.from||this._center===this.to&&t>this.to||(t<this.from?this._center=this.from:t>this.to?this._center=this.to:this._center=t,this.centerChangeDone())}set dimensions(t){const e=getComputedStyle(t);this.viewportHeight=parseInt(e.getPropertyValue("height"),10),this.viewportOffset=t.getBoundingClientRect().top,this.viewportWidth=parseInt(e.getPropertyValue("width"),10)}init(t){null==t.rootElement&&console.error("[init] No rootElement found"),this.rootElement=t.rootElement,this.dimensions=this.rootElement;const[e,i]=t.bands.reduce((t,e)=>{if(e.type===o.BandType.MinimapBand)return t;const i=e,s=null==i.config.orderedEvents?i.config.events:i.config.orderedEvents.events;return t[0].push(s[0].date_min||s[0].date),t[1].push(s.reduce((t,e)=>Math.max(t,e.end_date||-1/0,e.end_date_max||-1/0),-1/0)),t},[[],[]]);this.from=Math.min(...e),this.to=Math.max(...i),this.time=this.to-this.from,this.center=null!=t.center?t.center:this.from+this.defaultCenterRatio*this.time,this.bands=t.bands,this.eventsBands=this.bands.filter(r),this.minimapBands=this.bands.filter(a),this.controlBand=null!=t.controlBand?t.controlBand:this.eventsBands[0];for(const t of this.bands)t.init()}resize(){this.dimensions=this.rootElement}}e.Props=l,e.default=new l},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EVENT_HEIGHT=14,e.EVENT_ROW_HEIGHT=16,e.DATE_BAR_HEIGHT=e.EVENT_ROW_HEIGHT,e.RULER_LABELS_HEIGHT=60,e.CENTER_CHANGE_DONE="CENTER_CHANGE_DONE",e.ZOOM_DONE="ZOOM_DONE",e.SCROLL_DONE="SCROLL_DONE",e.PIXELS_PER_LETTER=8;e.RawSegment=class{},e.colors=["rgba(211,84,0","rgba(219,10,91","rgba(31,58,147","rgba(0,128,0"].map(t=>(e=1)=>`${t},${e})`)},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(6),n=i(0),o=i(1),r=i(3),a=i(4);!function(t){t[t.EventsBand=0]="EventsBand",t[t.MinimapBand=1]="MinimapBand"}(e.BandType||(e.BandType={}));e.default=class{constructor(t){this.config=t,this.defaultZoomLevel=0}get offsetX(){return this._offsetX}set offsetX(t){this.prevOffsetX=this.offsetX||t,this._offsetX=t}get zoomLevel(){return this._zoomLevel}set zoomLevel(t){t<0&&(t=0),this.visibleRatio=r.visibleRatio(t),this.width=Math.round(n.default.viewportWidth/this.visibleRatio),this.pixelsPerMillisecond=this.width/n.default.time,this.time=this.visibleRatio*n.default.time,this.granularity=s.getGranularity(this.pixelsPerMillisecond),this.nextDate=s.subsequentDate(this.granularity),this.prevZoomLevel=this.zoomLevel||t,this._zoomLevel=t,this.setHorizontalProps()}setVerticalProps(){this.visibleHeight=Math.round(this.config.heightRatio*n.default.viewportHeight),this.availableHeight=this.visibleHeight-o.DATE_BAR_HEIGHT,this.visibleRowsCount=Math.floor(this.availableHeight/o.EVENT_ROW_HEIGHT)-1,this.top=Math.round(this.config.topOffsetRatio*n.default.viewportHeight)}setHorizontalProps(){this.from=n.default.center-this.time/2,this.to=n.default.center+this.time/2,this.offsetX=(n.default.from-this.from)*this.pixelsPerMillisecond}init(){this.zoomLevel=this.config.zoomLevel,this.setVerticalProps(),a.default.registerModel(this)}resize(){this.zoomLevel=this.zoomLevel,this.setVerticalProps()}update(){this.setHorizontalProps()}updateConfig(t){Object.keys(t).forEach(e=>{this.config.hasOwnProperty(e)&&(this.config[e]=t[e])})}positionAtTimestamp(t){return Math.round((t-this.from)*this.pixelsPerMillisecond)}timestampAtProportion(t){return n.default.from+n.default.time*t}timestampAtPosition(t){return this.from+t/this.pixelsPerMillisecond}}},function(t,e,i){"use strict";function s(t){return Math.pow(2,-1*t)}function n(t){if(null==t)return null;const e=new Date(t);return`${e.getFullYear()}-${e.getMonth()+1}-${e.getDate()}`}Object.defineProperty(e,"__esModule",{value:!0}),e.debounce=((t,e)=>{let i;return()=>{clearTimeout(i),i=setTimeout(t,e)}}),e.visibleRatio=s,e.createRange=function(t){return Array.apply(null,{length:t}).map(Number.call,Number)},e.selectRandom=function(t,e){const i=[];for(;i.length<e;){const s=t[Math.floor(Math.random()*t.length)];(-1===i.indexOf(s)||t.length<e)&&i.push(s)}return i},e.calcPixelsPerMillisecond=function(t,e,i){return t/s(e)/i},e.logEvent=function(t,...e){console.log(t.label,t,t.left,n(t.from),n(t.to),e)}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(0),n=i(1);var o;!function(t){t[t.Backward=-1]="Backward",t[t.Stop=0]="Stop",t[t.Forward=1]="Forward"}(o||(o={}));class r{constructor(){this.elapsedTimeThreshold=2e3,this.goToDuration=300,this.zoomToDuration=300,this.multipliers=[.25,.5,1,2,4,8,16],this.multiplier=1,this.direction=o.Stop,this.elapsedTimeTotal=0,this.models=[],this.views=[],this.animate=(t=>{const e=null==this.prevTimestamp?0:t-this.prevTimestamp;if(e>0||null==this.prevTimestamp){if(null==this.centerMarker&&null==this.zoomMarker)s.default.center+=s.default.controlBand.time/480*this.multiplier*this.direction;else if(null!=this.centerMarker){const t=this.goToDuration-this.elapsedTimeTotal,i=Math.abs(this.centerMarker-s.default.center)/(t/e);t<e?(s.default.center=this.centerMarker,this.stop()):s.default.center=s.default.center+i*this.direction}else if(null!=this.zoomMarker){const t=this.zoomToDuration-this.elapsedTimeTotal,i=(this.zoomMarker-this.activeBand.zoomLevel)/(t/e);if(t<e)this.activeBand.zoomLevel=this.zoomMarker,s.default.eventsBands.forEach(t=>{t===this.activeBand?this.activeBand.zoomLevel=this.zoomMarker:t.zoomLevel=this.zoomMarker+(t.config.zoomLevel-this.activeBand.config.zoomLevel)}),this.adjustMinimapBands(),document.dispatchEvent(new CustomEvent(n.ZOOM_DONE)),this.stop();else{for(const t of s.default.eventsBands)t.zoomLevel=t.zoomLevel+i;this.adjustMinimapBands()}}this.models.forEach(t=>t.update()),this.views.forEach(t=>t.update())}this.elapsedTimeTotal+=e,this.elapsedTimeTotal>this.elapsedTimeThreshold&&this.resetElapsedTimeTotal(),(this.isPlaying()||null!=this.zoomMarker)&&(s.default.center>=s.default.from&&s.default.center<=s.default.to||null!=this.centerMarker||null!=this.zoomMarker?(this.prevTimestamp=t,requestAnimationFrame(this.animate)):this.stop())})}registerModel(t){this.models.push(t)}registerView(t){this.views.push(t)}adjustMinimapBands(){s.default.minimapBands.forEach(t=>{this.activeBand.zoomLevel<t.config.zoomLevel&&(t.zoomLevel=this.activeBand.zoomLevel)})}resetElapsedTimeTotal(){this.elapsedTimeTotal=0,document.dispatchEvent(new CustomEvent(n.CENTER_CHANGE_DONE))}accelerate(){const t=this.multipliers.indexOf(this.multiplier);return t===this.multipliers.length-1?this.multipliers[this.multipliers.length-1]:(this.multiplier=this.multipliers[t+1],this.multiplier)}decelerate(){const t=this.multipliers.indexOf(this.multiplier);return 0===t?this.multipliers[0]:(this.multiplier=this.multipliers[t-1],this.multiplier)}goTo(t){this.centerMarker=t,t>s.default.center?this.playForward():this.playBackward()}zoomTo(t,e){null==this.zoomMarker&&(e<0&&(e=0),t!==this.activeBand&&(this.stop(),this.activeBand=t),this.activeBand.zoomLevel!==e&&(this.zoomMarker=e,this.nextFrame()))}speed(t){const e=parseFloat(t);-1!==this.multipliers.indexOf(e)&&(this.multiplier=e)}isPlaying(){return this.direction!==o.Stop}isPlayingForward(){return this.direction===o.Forward}isPlayingBackward(){return this.direction===o.Backward}nextFrame(){requestAnimationFrame(this.animate)}playForward(){this.direction=o.Forward,this.nextFrame()}playBackward(){this.direction=o.Backward,this.nextFrame()}stop(){this.direction=o.Stop,this.activeBand=null,this.centerMarker=null,this.zoomMarker=null,this.prevTimestamp=null,this.elapsedTimeTotal=0}toggle(){this.isPlaying()?this.stop():this.nextFrame()}}e.Animator=r,e.default=new r},function(t,e,i){"use strict";let s;if(Object.defineProperty(e,"__esModule",{value:!0}),e.createSvg=((t,e,i={})=>{const s=document.createElementNS("http://www.w3.org/2000/svg",t);return null!=e&&s.setAttribute("style",e.join(";").concat(";")),Object.keys(i).forEach(t=>s.setAttribute(t,i[t])),s}),"undefined"!=typeof window){const t=document.createElement("style");document.head.appendChild(t),s=t.sheet}const n={};e.default=function(t,e,i,o){if(!e)return document.createElement(t);let r;return n.hasOwnProperty(e)?r=n[e].cloneNode(!1):((r=document.createElement(t)).classList.add(e),i&&s.insertRule(`.${e} { ${i.join(";").concat(";")} }`),n[e]=r.cloneNode(!1)),o&&r.setAttribute("style",o.join(";").concat(";")),r}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],n=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function o(t){return n[t.getUTCMonth()]}function r(t){const e=t.getUTCDate();return`${s[t.getUTCDay()]}, ${e}${function(t){return["st","nd","rd"][((t+90)%100-10)%10-1]||"th"}(e)}`}function a(t){return t.getUTCHours().toString().padStart(2,"0")}function l(t){return t.getUTCMinutes().toString().padStart(2,"0")}function h(t){return t.getUTCSeconds().toString().padStart(2,"0")}function d(t){return t.getUTCMilliseconds().toString().padStart(3,"0")}function u(t){return"YEAR"===t||"YEAR_5"===t||"DECADE"===t||"DECADE_5"===t||"CENTURY"===t||"CENTURY_5"===t||"MILLENIUM"===t}e.formatDate=((t,e)=>{if(null==t)return"∞";const i=new Date(t);let s=i.getUTCFullYear().toString();return u(e)?s:(s=`${o(i)} ${s}`,"MONHT"===e?s:(s=`${r(i)} ${s}`,"DAY"===e?s:(s=`${s} at ${a(i)}:`,"HOUR"===e?`${s}00`:(s=`${s}${l(i)}`,"MINUTE"===e?s:(s=`${s}:${h(i)}`,"SECOND"===e?s:`${s}.${d(i)}`)))))}),e.getGranularity=(t=>t>58?"MILLISECOND":t>12?"MILLISECOND_10":t>2.3?"MILLISECOND_50":t>1.5?"MILLISECOND_100":t>.4?"MILLISECOND_500":t>.00112?"SECOND":t>112e-6?"MINUTE":t>112e-7?"HOUR":t>8e-7?"DAY":t>2.6e-7?"WEEK":t>2.2e-8?"MONHT":t>2.2e-9?"YEAR":t>3.3e-10?"YEAR_5":t>1.6e-10?"DECADE":t>8e-11?"DECADE_5":t>1e-11?"CENTURY":t>5e-12?"CENTURY_5":"MILLENIUM"),e.getStep=(t=>{if("YEAR"===t)return 1;if("YEAR_5"===t)return 5;if("DECADE"===t)return 10;if("DECADE_5"===t)return 50;if("CENTURY"===t)return 100;if("CENTURY_5"===t)return 500;if("MILLENIUM"===t)return 1e3;if("MILLISECOND"===t)return 1;if("MILLISECOND_10"===t)return 10;if("MILLISECOND_50"===t)return 50;if("MILLISECOND_100"===t)return 100;if("MILLISECOND_500"===t)return 500;throw new RangeError("[getStep] Only steps with a granularity greater than 'year' calculated")}),e.subsequentDate=function(t){return u(t)?i=>{let s=new Date(i),n=s.getUTCFullYear()+1;if("YEAR"!==t){const i=e.getStep(t);for(;n%i!=0;)n+=1}return n>-1&&n<100?(s.setUTCFullYear(n),s.getTime()):Date.UTC(n,0,1)}:"MONHT"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth()+1,1)}:"WEEK"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()+7)}:"DAY"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()+1)}:"HOUR"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours()+1)}:"MINUTE"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes()+1)}:"SECOND"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds()+1)}:"MILLISECOND"===t.slice(0,"MILLISECOND".length)?i=>{const s=e.getStep(t),n=new Date(i);let o=n.getUTCMilliseconds()+1;return s>1&&(o=o+s-o%s),Date.UTC(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),n.getUTCHours(),n.getUTCMinutes(),n.getUTCSeconds(),o)}:void 0},e.byDate=function(t,e){const i=null!=t.date_min?t.date_min:t.date,s=null!=e.date_min?e.date_min:e.date;if(i<s)return-1;if(i>s)return 1;const n=null!=t.end_date_max?t.end_date_max:t.end_date,o=null!=e.end_date_max?e.end_date_max:e.end_date;return n<o?-1:n>o?1:0};e.labelBody=((t,e)=>{const i=new Date(t);return u(e)?i.getUTCFullYear().toString():"MONHT"===e?o(i):"WEEK"===e?`${o(i)}, week ${(t=>{const e=new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate())),i=e.getUTCDay()||7;e.setUTCDate(e.getUTCDate()+4-i);const s=new Date(Date.UTC(e.getUTCFullYear(),0,1));return Math.ceil(((e.getTime()-s.getTime())/864e5+1)/7)})(i)}`:"DAY"===e?`${r(i)} ${o(i)}`:"HOUR"===e?`${a(i)}:00`:"MINUTE"===e?`${a(i)}:${l(i)}`:"SECOND"===e?`${a(i)}:${l(i)}:${h(i)}`:"MILLISECOND"===e.slice(0,"MILLISECOND".length)?`${a(i)}:${l(i)}:${h(i)}.${d(i)}`:void 0})},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.DomainConfig=class{};class s{constructor(){this.heightRatio=1,this.rulers=!0,this.rulerLabels=!0,this.topOffsetRatio=0,this.zoomLevel=0}}e.BandConfig=s;e.MinimapBandConfig=class extends s{constructor(){super(...arguments),this.indicatorFor=0,this.targets=[]}};e.EventsBandConfig=class extends s{};e.default=class{}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(2),n=i(0),o=i(5),r=i(9),a=i(4),l=i(1);e.default=class{constructor(t){this.band=t,this.onMouseDown=(t=>{document.addEventListener("mouseup",this.onMouseUp),this.dragStartTime=Date.now(),this.dragStartPosition=[t.clientX,t.clientY],this.dragOffsetX=t.clientX,this.dragOffsetY=t.clientY}),this.onMouseMove=(t=>{if(null==this.dragOffsetX)return;const e=t.clientY-this.dragOffsetY,i=t.clientX-this.dragOffsetX;if(this.band.type===s.BandType.EventsBand){const t=this.band;(0!==t.offsetY||Math.abs(e)>Math.abs(i)&&Math.abs(e)>5)&&(t.offsetY=e)}const o=i/this.band.pixelsPerMillisecond;n.default.center-=o,a.default.nextFrame(),this.dragOffsetX=t.clientX,this.dragOffsetY=t.clientY}),this.onMouseUp=(t=>{this.lastDragInterval=Date.now()-this.dragStartTime,this.dispatchScrollDoneEvent(t),this.dragOffsetX=null,this.dragOffsetY=null,document.removeEventListener("mouseup",this.onMouseUp)}),this.onDblClick=(t=>{const e=this.band.timestampAtPosition(t.clientX);a.default.goTo(e)})}render(){return this.rootElement=o.default("div","band-wrap",["position: absolute","z-index: 2"],[`height: ${this.band.visibleHeight}px`,`top: ${this.band.top}px`,`width: ${n.default.viewportWidth}px`]),r.default.register("mousedown",this.onMouseDown,this.rootElement),r.default.register("mousemove",this.onMouseMove,this.rootElement),r.default.register("dblclick",this.onDblClick,this.rootElement),this.rootElement}dispatchScrollDoneEvent(t){const e=[this.dragStartPosition[0]-t.clientX,this.dragStartPosition[1]-t.clientY].map(Math.abs).some(t=>t>5);(this.lastDragInterval>200||e)&&document.dispatchEvent(new CustomEvent(l.SCROLL_DONE))}resize(){this.rootElement.style.cssText=`height: ${this.band.visibleHeight}px; top: ${this.band.top}px; width: ${n.default.viewportWidth}px;`}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class s{constructor(){this.eventsListeners=[]}register(t,e,i=document){i.addEventListener(t,e),this.eventsListeners.push([t,e,i])}flush(){this.eventsListeners.forEach(t=>{const[e,i,s]=t;s.removeEventListener(e,i)}),this.eventsListeners=[]}}e.EventBus=s,e.default=new s},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(1);class n{constructor(){this.events=[],this.row_count=0}}e.OrderedEvents=n;const o=8;e.orderEvents=function(t,e){if(!t.length)return new n;let i=0;const r=[],a=2*s.EVENT_HEIGHT/e;return{events:t=t.map(t=>{let s;null==t.label&&(t.label="NO LABEL"),t.from=t.date_min||t.date,t.to=t.end_date_max||t.end_date,null==t.to&&(t.to=t.from),t.time=null==t.to?0:t.to-t.from,t.space=0,t.time||(null==t.label&&(t.label="NO LABEL"),t.space=t.label.length*o/e+a);let n=0;for(;null==s&&n<r.length;){let e=0,i=!0;for(;i&&e<r[n].length&&!(t.to<r[n][e][0]);)i=t.from>r[n][e][1],e++;i&&(r[n].push([t.from,t.from+t.time+t.space]),s=n),n++}return null==s&&(s=r.push([[t.from,t.from+t.time+t.space]])-1),s>i&&(i=s),t.row=s,t}),row_count:r.length}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(0);e.TimelineProps=s.Props;const n=i(7);e.TimelineConfig=n.default;const o=i(8),r=i(5),a=i(3);e.calcPixelsPerMillisecond=a.calcPixelsPerMillisecond;const l=i(10);e.OrderedEvents=l.OrderedEvents,e.orderEvents=l.orderEvents;const h=i(12),d=i(13),u=i(14),c=i(16),f=i(17);e.MinimapBand=f.default;const p=i(18);e.EventsBand=p.default;const m=i(6);e.formatDate=m.formatDate;const v=i(19);e.RawEv3nt=v.RawEv3nt;const g=i(2);e.default=class extends h.default{constructor(t,e,i){super(e),this.config=t,this.onSelect=i,this.appendToWrapper=(t=>{let e=t.render();Array.isArray(e)||(e=[e]),e.forEach(t=>this.wrapper.appendChild(t))}),s.default.init(t),t.rootElement.appendChild(this.render());const n=a.debounce(this.resize,600);window.addEventListener("resize",n)}render(){this.wrapper=r.default("div","wrapper",["box-sizing: border-box","height: 100%","overflow: hidden","position: relative","user-select: none","width: 100%"]),this.views=s.default.bands.map(t=>t.type===g.BandType.EventsBand?new d.default(t,this.onSelect):new o.default(t)),this.views.push(new u.default),this.views.forEach(this.appendToWrapper),this.renderLabels();const t=r.default("div","red-line",["background-color: rgb(126, 0, 0)","bottom: 0","left: calc(50% - 1px)","position: absolute","top: 0","width: 2px","z-index: 4"]);return this.wrapper.appendChild(t),this.wrapper}renderLabels(){s.default.bands.filter(t=>t.type===g.BandType.EventsBand&&null!=t.config.label).map(t=>new c.default(t)).forEach(this.appendToWrapper)}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(4),n=i(1),o=i(0);e.default=class{constructor(t){this.onChange=t,this.animator=s.default,this.handleChange=(()=>{this.onChange(o.default)}),this.resize=(()=>{o.default.resize();for(const t of o.default.bands)t.resize();for(const t of this.views)t.resize();this.animator.nextFrame()}),document.addEventListener("keydown",t=>{189===t.keyCode&&o.default.controlBand.zoomOut(),187===t.keyCode&&o.default.controlBand.zoomIn()}),null!=this.onChange&&"function"==typeof this.onChange&&(document.addEventListener(n.CENTER_CHANGE_DONE,this.handleChange),document.addEventListener(n.ZOOM_DONE,this.handleChange))}reload(){this.resize()}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(8),n=i(9),o=i(3);e.default=class extends s.default{constructor(t,e){super(t),this.band=t,this.select=e,this.onWheel=(t=>{0===Math.abs(t.deltaX)&&0!==t.deltaY&&(t.deltaY<0&&this.zoomOut(),t.deltaY>0&&this.zoomIn())}),this.onClick=(t=>{if(this.lastDragInterval>175)return;const e=this.band.getEventByCoordinates(t.clientX,t.clientY);e&&this.select&&(this.select(e),o.logEvent(e))})}render(){const t=super.render();return n.default.register("click",this.onClick,this.rootElement),n.default.register("wheel",this.onWheel,this.rootElement),t}zoomIn(){this.band.zoomIn()}zoomOut(){this.band.zoomOut()}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(5),n=i(0),o=i(1),r=i(4),a=i(15),l=i(2);e.default=class{constructor(){this.indicatorsDrawn=!1,this.update=(()=>{n.default.bands.forEach(t=>{t.type===l.BandType.EventsBand?this.drawEventsBand(t):this.drawMinimapBand(t)}),this.drawIndicators()}),r.default.registerView(this)}render(){return this.canvas=s.default("canvas","main",["position: absolute"]),this.canvas.width=n.default.viewportWidth,this.canvas.height=n.default.viewportHeight,this.ctx=this.canvas.getContext("2d"),this.indicatorsCanvas=s.default("canvas","indicators",["position: absolute"],["z-index: 1"]),this.indicatorsCanvas.width=n.default.viewportWidth,this.indicatorsCanvas.height=n.default.viewportHeight,this.indicatorsCtx=this.indicatorsCanvas.getContext("2d"),this.update(),[this.canvas,this.indicatorsCanvas]}resize(){this.indicatorsCanvas.width=n.default.viewportWidth,this.indicatorsCanvas.height=n.default.viewportHeight,this.canvas.width=n.default.viewportWidth,this.canvas.height=n.default.viewportHeight,this.indicatorsDrawn=!1}clear(t){this.ctx.clearRect(0,t.top,this.canvas.width,t.visibleHeight)}drawEventsBand(t){this.clear(t),a.default(this.ctx,t);for(const e of t.visibleEvents)e.time?(this.ctx.fillStyle=e.color,this.ctx.fillRect(e.left,e.top,e.width,o.EVENT_HEIGHT)):(this.ctx.moveTo(e.left,e.top+o.EVENT_HEIGHT/2),this.ctx.beginPath(),this.ctx.arc(e.left,e.top+o.EVENT_HEIGHT/2,o.EVENT_HEIGHT/3,0,2*Math.PI),this.ctx.fillStyle=e.color,this.ctx.fill());this.drawEventsText(t)}drawEventsText(t){this.ctx.font="11px sans-serif",this.ctx.fillStyle="rgb(40, 40, 40)";for(const e of t.visibleEvents){let t=0===e.time?e.padding:e.width,i=e.left;if(e.left<0&&0!==e.time&&(t=e.width+e.left,i=0),e.label.length*o.PIXELS_PER_LETTER<=t){const t=e.time?3:8;this.ctx.fillText(e.label,i+t,e.top+o.EVENT_HEIGHT-3)}}}drawMinimapBand(t){if(t.isDrawn&&t.prevOffsetX===t.offsetX&&t.prevZoomLevel===t.zoomLevel)return;this.clear(t),a.default(this.ctx,t);const e=t.draw();this.ctx.drawImage(e,0,t.top,n.default.viewportWidth,t.availableHeight),t.isDrawn=!0}drawIndicators(){if(!this.indicatorsDrawn||!n.default.eventsBands.every(t=>t.prevZoomLevel===t.zoomLevel)){this.indicatorsCtx.clearRect(0,0,n.default.viewportWidth,n.default.viewportHeight),this.indicatorsCtx.beginPath();for(const t of n.default.minimapBands){const e=n.default.eventsBands[t.config.indicatorFor],i=Math.round(t.config.topOffsetRatio*n.default.viewportHeight),s=t.positionAtTimestamp(e.from);this.indicatorsCtx.rect(0,i,s,t.visibleHeight);const r=t.positionAtTimestamp(e.to);this.indicatorsCtx.rect(r,i,n.default.viewportWidth,t.visibleHeight),this.indicatorsCtx.rect(s,i+t.visibleHeight-o.DATE_BAR_HEIGHT,r-s,o.DATE_BAR_HEIGHT)}this.indicatorsCtx.fillStyle="rgba(0, 0, 0, .04)",this.indicatorsCtx.fill(),this.indicatorsCtx.closePath(),this.indicatorsDrawn=!0}}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(0),n=i(6),o="11px sans-serif",r="13px sans-serif";function a(t,e){return"CENTURY"===e.granularity&&new Date(t).getUTCFullYear()%1e3==0||("YEAR_5"===e.granularity&&new Date(t).getUTCFullYear()%50==0||"YEAR"===e.granularity&&new Date(t).getUTCFullYear()%5==0)}function l(t,e,i,s,o){const r=e.positionAtTimestamp(i);t.moveTo(r,s),t.lineTo(r,o),e.config.rulerLabels&&t.fillText(n.labelBody(i,e.granularity),r+3,o-3)}e.default=function(t,e){if(!e.config.rulers)return;let i=e.nextDate(e.from);const n=e.config.topOffsetRatio*s.default.viewportHeight,h=e.config.heightRatio*s.default.viewportHeight,d=[],u=[];for(;i<e.to;)a(i,e)?u.push(i):d.push(i),i=e.nextDate(i);t.beginPath(),t.font=o,t.fillStyle="rgb(205, 205, 205)";for(const i of d)l(t,e,i,n,n+h);t.strokeStyle="rgb(235, 235, 235)",t.stroke(),t.beginPath(),t.font=r,t.fillStyle="rgb(120, 120, 120)";for(const i of u)l(t,e,i,n,n+h);t.strokeStyle="rgb(150, 150, 150)",t.stroke()}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(5);e.default=class{constructor(t){this.band=t}render(){const t=s.default("div","events-label-wrapper",["border-top: 1px solid #CCC","pointer-events: none","position: absolute","width: 100%","z-index: 3"],[`top: ${100*this.band.config.topOffsetRatio}%`]),e=s.default("div","events-label",["background: white","border-bottom-right-radius: 4px","box-shadow: 1px 2px 4px #AAA","color: #444","display: inline-block","font-family: sans-serif","font-size: .8em","padding: 4px 8px"]);return e.innerText=this.band.config.label,t.appendChild(e),t}resize(){}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(2),n=i(7),o=i(0),r=i(5);e.default=class extends s.default{constructor(t){super(function(t){const e=Object.assign({},new n.MinimapBandConfig,t);return e.targets.length||e.targets.push(0),e}(t)),this.type=s.BandType.MinimapBand,this.canvas=r.default("canvas"),this.ctx=this.canvas.getContext("2d"),this.nextCanvas=r.default("canvas"),this.nextCtx=this.nextCanvas.getContext("2d"),this.isDrawn=!1}init(){super.init(),this.maxRowCount=this.config.targets.reduce((t,e)=>{const{rowCount:i}=o.default.eventsBands[e];return Math.max(t,i)},0);const t=this.availableHeight/this.maxRowCount;this.eventHeight=t<1?1:Math.floor(t),this.canvas.width=o.default.viewportWidth,this.canvas.height=this.maxRowCount*this.eventHeight,this.nextCanvas.width=this.canvas.width,this.nextCanvas.height=this.canvas.height}resize(){super.resize(),this.isDrawn=!1}draw(){return this.isDrawn?this.updateNextCanvas():this.drawEvents(),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.drawImage(this.nextCanvas,0,0),this.canvas}drawEvents(t=this.from,e=this.to){this.nextCtx.beginPath(),this.config.targets.forEach(i=>{const s=o.default.eventsBands[i];for(const i of s.events){if(i.from>e||i.to<t)continue;const s=Math.round(i.time*this.pixelsPerMillisecond),n=this.positionAtTimestamp(null!=i.date_min?i.date_min:i.date),o=this.maxRowCount-(i.row+1)*this.eventHeight,r=s<1?1:s;this.nextCtx.rect(n,o,r,this.eventHeight)}}),this.nextCtx.fillStyle="rgb(190, 190, 190)",this.nextCtx.fill()}updateNextCanvas(){const t=Math.round(this.offsetX-this.prevOffsetX);if(0===t)return this.canvas;let e,i;this.nextCtx.clearRect(0,0,this.nextCanvas.width,this.nextCanvas.height),this.nextCtx.drawImage(this.canvas,t,0),t<0?(e=this.timestampAtPosition(o.default.viewportWidth+t),i=this.to):(e=this.from,i=this.timestampAtPosition(t)),this.drawEvents(e,i)}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const s=i(2),n=i(7),o=i(4),r=i(1),a=i(0),l=i(10),h=i(6),d=i(3);e.default=class extends s.default{constructor(t){super(Object.assign({},new n.EventsBandConfig,t)),this.type=s.BandType.EventsBand,this.events=[],this.rowCount=0,this.visibleEvents=[],this._offsetY=0,null!=this.config.events&&this.config.events.sort(h.byDate)}get offsetY(){return this._offsetY}set offsetY(t){this._offsetY+=t,this._offsetY<0&&(this._offsetY=0);const e=this.height>this.availableHeight?this.height-this.availableHeight+r.EVENT_ROW_HEIGHT:0;this._offsetY>e&&(this._offsetY=e);const i=this._offsetY/r.EVENT_ROW_HEIGHT;this.lowestVisibleRow=Math.ceil(i),this.highestVisibleRow=this.lowestVisibleRow+this.visibleRowsCount}init(){super.init();const t=d.calcPixelsPerMillisecond(a.default.viewportWidth,this.config.zoomLevel||0,a.default.time),e=null==this.config.orderedEvents?l.orderEvents(this.config.events,t):this.config.orderedEvents;this.events=e.events,this.rowCount=e.row_count,this.height=r.EVENT_ROW_HEIGHT*this.rowCount,this.offsetY=0,this.updateEvents()}getColor(t,e){const i=[49,220,215];let s;if(a.default.center>e)s=a.default.center-e;else{if(!(a.default.center<t))return`rgb(${i.join(", ")})`;s=t-a.default.center}const n=s/(this.time/2),o=a.default.center>e?[253,231,37]:[204,104,232];return`rgb(${i.map((t,e)=>t+(o[e]-t)*n).join(", ")})`}updateEvents(){this.visibleEvents=this.events.filter(t=>!(t.from>this.to||t.to<this.from)&&t.row>=this.lowestVisibleRow&&t.row<=this.highestVisibleRow).map(t=>(t.left=this.positionAtTimestamp(t.from),t.width=Math.round(t.time*this.pixelsPerMillisecond),t.time&&t.width<1&&(t.width=1),t.padding=Math.round(t.space*this.pixelsPerMillisecond),t.top=this.top+this.availableHeight-(t.row+1)*r.EVENT_ROW_HEIGHT+this.offsetY,t.color=this.getColor(t.from,t.to),t))}update(){super.update(),this.updateEvents()}getEventByCoordinates(t,e){const i=this.timestampAtPosition(t),s=a.default.viewportOffset+this.top+this.availableHeight+this.offsetY,n=Math.floor((s-e)/r.EVENT_ROW_HEIGHT);return this.events.find(t=>!(!(t.from<i&&t.from+t.time+t.space>i)||t.row<this.lowestVisibleRow||t.row>this.highestVisibleRow)&&t.row===n)}zoomIn(){o.default.zoomTo(this,this.zoomLevel+1)}zoomOut(){o.default.zoomTo(this,this.zoomLevel-1)}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.RawEv3nt=class{constructor(){this.date_granularity="DAY"}}}])});
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Timeline=e():t.Timeline=e()}(this,function(){return function(t){var e={};function i(n){if(e[n])return e[n].exports;var s=e[n]={i:n,l:!1,exports:{}};return t[n].call(s.exports,s,s.exports,i),s.l=!0,s.exports}return i.m=t,i.c=e,i.d=function(t,e,n){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var s in t)i.d(n,s,function(e){return t[e]}.bind(null,s));return n},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="/dist/",i(i.s=9)}([function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IMAGE_SIZES=[16,32,64,128,256],e.EVENT_HEIGHT=16,e.LETTER_WIDTH=Math.round(.1875*e.EVENT_HEIGHT+3.5),e.FONT_SIZE=Math.round(.3125*e.EVENT_HEIGHT+6),e.ROW_SPACING=Math.round(e.EVENT_HEIGHT/3),e.EVENT_ROW_HEIGHT=e.EVENT_HEIGHT+e.ROW_SPACING,e.DATE_BAR_HEIGHT=e.EVENT_ROW_HEIGHT,e.IMAGE_BOUNDING_BOX=2*e.EVENT_ROW_HEIGHT-2*e.ROW_SPACING,e.IMAGE_BORDER_SIZE=Math.round(e.ROW_SPACING/2),e.IMAGE_SIZE=e.IMAGE_SIZES.reduce((t,i)=>Math.abs(i-e.IMAGE_BOUNDING_BOX)<Math.abs(t-e.IMAGE_BOUNDING_BOX)?i:t),function(t){t.CenterChange="CenterChange",t.ZoomDone="ZoomDone",t.ScrollDone="ScrollDone",t.Pause="Pause",t.Play="Play",t.Select="Select"}(e.EventType||(e.EventType={})),e.PIXELS_PER_LETTER=8,e.DEFAULT_IMAGE_PATH="/images";e.RawSegment=class{},e.colors=["rgba(211,84,0","rgba(219,10,91","rgba(31,58,147","rgba(0,128,0"].map(t=>(e=1)=>`${t},${e})`)},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(0),s=i(4),o=i(9),r=i(6);function a(t){return t.type===s.BandType.EventsBand}function l(t){return t.type===s.BandType.MinimapBand}class h{constructor(){this.defaultCenterRatio=.5}get center(){return this._center}set center(t){this._center===this.from&&t<this.from||this._center===this.to&&t>this.to||(t<this.from?this._center=this.from:t>this.to?this._center=this.to:this._center=t,r.default.dispatch(n.EventType.CenterChange))}set dimensions(t){const e=getComputedStyle(t);this.viewportHeight=parseInt(e.getPropertyValue("height"),10),this.viewportOffset=t.getBoundingClientRect().top,this.viewportWidth=parseInt(e.getPropertyValue("width"),10)}init(t){null==t.rootElement&&console.error("[init] No rootElement found"),this.imagePath=null!=t.imagePath?t.imagePath:n.DEFAULT_IMAGE_PATH,this.rootElement=t.rootElement,this.dimensions=this.rootElement,this.bands=t.bands,this.eventsBands=this.bands.filter(a),this.minimapBands=this.bands.filter(l),this.controlBand=null!=t.controlBand?t.controlBand:this.eventsBands[0];const e=performance.now(),i={bands:this.eventsBands.map(t=>({events:t.config.events,zoomLevel:t.config.zoomLevel})),parent:t.parent,viewportWidth:this.viewportWidth},s=o.orderEvents(i);this.parent=s.parent,this.from=s.from,this.to=s.to,this.time=s.time;const r=performance.now();console.log("Performance: ",`${r-e}ms\n[from] ${new Date(this.from).toUTCString()}\n[ to ] ${new Date(this.to).toUTCString()}`),this.center=null!=t.center?t.center:this.from+this.defaultCenterRatio*this.time;for(const[t,e]of this.eventsBands.entries())e.init(s.bands[t]);for(const t of this.minimapBands)t.init()}resize(){this.dimensions=this.rootElement}}e.Props=h,e.default=new h},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(1),s=i(0),o=i(6);var r;!function(t){t[t.Backward=-1]="Backward",t[t.Stop=0]="Stop",t[t.Forward=1]="Forward"}(r||(r={}));class a{constructor(){this.elapsedTimeThreshold=2e3,this.goToDuration=300,this.zoomToDuration=300,this.multipliers=[.25,.5,1,2,4,8,16],this.multiplier=1,this.direction=r.Stop,this.elapsedTimeTotal=0,this.models=[],this.views=[],this.animate=(t=>{const e=null==this.prevTimestamp?0:t-this.prevTimestamp;if(e>0||null==this.prevTimestamp){if(null==this.centerMarker&&null==this.zoomMarker)n.default.center+=n.default.controlBand.time/480*this.multiplier*this.direction;else if(null!=this.centerMarker){const t=this.goToDuration-this.elapsedTimeTotal,i=Math.abs(this.centerMarker-n.default.center)/(t/e);t<e?(n.default.center=this.centerMarker,this.stop()):n.default.center=n.default.center+i*this.direction}else if(null!=this.zoomMarker){const t=this.zoomToDuration-this.elapsedTimeTotal,i=(this.zoomMarker-this.activeBand.zoomLevel)/(t/e);if(t<e)this.activeBand.zoomLevel=this.zoomMarker,n.default.eventsBands.forEach(t=>{t===this.activeBand?this.activeBand.zoomLevel=this.zoomMarker:t.zoomLevel=this.zoomMarker+(t.config.zoomLevel-this.activeBand.config.zoomLevel)}),this.adjustMinimapBands(),o.default.dispatch(s.EventType.ZoomDone),this.stop();else{for(const t of n.default.eventsBands)t.zoomLevel=t.zoomLevel+i;this.adjustMinimapBands()}}this.models.forEach(t=>t.update()),this.views.forEach(t=>t.update())}this.elapsedTimeTotal+=e,this.elapsedTimeTotal>this.elapsedTimeThreshold&&this.resetElapsedTimeTotal(),(this.isPlaying()||null!=this.zoomMarker)&&(n.default.center>=n.default.from&&n.default.center<=n.default.to||null!=this.centerMarker||null!=this.zoomMarker?(this.prevTimestamp=t,requestAnimationFrame(this.animate)):this.stop())})}registerModel(t){this.models.push(t)}registerView(t){this.views.push(t)}adjustMinimapBands(){n.default.minimapBands.forEach(t=>{this.activeBand.zoomLevel<t.config.zoomLevel&&(t.zoomLevel=this.activeBand.zoomLevel)})}resetElapsedTimeTotal(){this.elapsedTimeTotal=0,o.default.dispatch(s.EventType.CenterChange)}accelerate(){const t=this.multipliers.indexOf(this.multiplier);return t===this.multipliers.length-1?this.multipliers[this.multipliers.length-1]:(this.multiplier=this.multipliers[t+1],this.multiplier)}decelerate(){const t=this.multipliers.indexOf(this.multiplier);return 0===t?this.multipliers[0]:(this.multiplier=this.multipliers[t-1],this.multiplier)}goTo(t){this.centerMarker=t,t>n.default.center?this.playForward():this.playBackward()}zoomTo(t,e){null==this.zoomMarker&&(e<0&&(e=0),t!==this.activeBand&&(this.stop(),this.activeBand=t),this.activeBand.zoomLevel!==e&&(this.zoomMarker=e,this.nextFrame()))}speed(t){const e=parseFloat(t);-1!==this.multipliers.indexOf(e)&&(this.multiplier=e)}isPlaying(){return this.direction!==r.Stop}isPlayingForward(){return this.direction===r.Forward}isPlayingBackward(){return this.direction===r.Backward}nextFrame(){requestAnimationFrame(this.animate)}playForward(){o.default.dispatch(s.EventType.Play),this.direction=r.Forward,this.nextFrame()}playBackward(){o.default.dispatch(s.EventType.Play),this.direction=r.Backward,this.nextFrame()}stop(){o.default.dispatch(s.EventType.Pause),this.direction=r.Stop,this.activeBand=null,this.centerMarker=null,this.zoomMarker=null,this.prevTimestamp=null,this.elapsedTimeTotal=0}toggle(){this.isPlaying()?this.stop():this.nextFrame()}}e.Animator=a,e.default=new a},function(t,e,i){"use strict";let n;if(Object.defineProperty(e,"__esModule",{value:!0}),e.createSvg=((t,e,i={})=>{const n=document.createElementNS("http://www.w3.org/2000/svg",t);return null!=e&&n.setAttribute("style",e.join(";").concat(";")),Object.keys(i).forEach(t=>n.setAttribute(t,i[t])),n}),"undefined"!=typeof window){const t=document.createElement("style");document.head.appendChild(t),n=t.sheet}const s={};e.default=function(t,e,i,o){if(!e)return document.createElement(t);let r;return s.hasOwnProperty(e)?r=s[e].cloneNode(!1):((r=document.createElement(t)).classList.add(e),i&&n.insertRule(`.${e} { ${i.join(";").concat(";")} }`),s[e]=r.cloneNode(!1)),o&&r.setAttribute("style",o.join(";").concat(";")),r}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(5),s=i(1),o=i(0),r=i(7),a=i(2);!function(t){t[t.EventsBand=0]="EventsBand",t[t.MinimapBand=1]="MinimapBand"}(e.BandType||(e.BandType={}));e.default=class{constructor(t){this.config=t,this.defaultZoomLevel=0}get offsetX(){return this._offsetX}set offsetX(t){this.prevOffsetX=this.offsetX||t,this._offsetX=t}get zoomLevel(){return this._zoomLevel}set zoomLevel(t){t<0&&(t=0),this.visibleRatio=r.visibleRatio(t),this.width=Math.round(s.default.viewportWidth/this.visibleRatio),this.pixelsPerMillisecond=this.width/s.default.time,this.time=this.visibleRatio*s.default.time,this.granularity=n.getGranularity(this.pixelsPerMillisecond),this.nextDate=n.subsequentDate(this.granularity),this.prevZoomLevel=this.zoomLevel||t,this._zoomLevel=t,this.setHorizontalProps()}setVerticalProps(){this.visibleHeight=Math.round(this.config.heightRatio*s.default.viewportHeight),this.availableHeight=this.visibleHeight-o.DATE_BAR_HEIGHT,this.availableHeight/this.visibleHeight<.666&&(this.availableHeight=.666*this.visibleHeight),this.visibleRowsCount=Math.floor(this.availableHeight/o.EVENT_ROW_HEIGHT)-1,this.top=Math.round(this.config.topOffsetRatio*s.default.viewportHeight)}setHorizontalProps(){this.from=s.default.center-this.time/2,this.to=s.default.center+this.time/2,this.offsetX=(s.default.from-this.from)*this.pixelsPerMillisecond}init(t){this.zoomLevel=this.config.zoomLevel,this.setVerticalProps(),a.default.registerModel(this)}resize(){this.zoomLevel=this.zoomLevel,this.setVerticalProps()}update(){this.setHorizontalProps()}updateConfig(t){Object.keys(t).forEach(e=>{this.config.hasOwnProperty(e)&&(this.config[e]=t[e])})}positionAtTimestamp(t){return Math.round((t-this.from)*this.pixelsPerMillisecond)}timestampAtProportion(t){return s.default.from+s.default.time*t}timestampAtPosition(t){return this.from+t/this.pixelsPerMillisecond}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],s=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function o(t){return s[t.getUTCMonth()]}function r(t){const e=t.getUTCDate();return`${n[t.getUTCDay()]}, ${e}${function(t){return["st","nd","rd"][((t+90)%100-10)%10-1]||"th"}(e)}`}function a(t){return t.getUTCHours().toString().padStart(2,"0")}function l(t){return t.getUTCMinutes().toString().padStart(2,"0")}function h(t){return t.getUTCSeconds().toString().padStart(2,"0")}function u(t){return t.getUTCMilliseconds().toString().padStart(3,"0")}function d(t){return"YEAR"===t||"YEAR_5"===t||"DECADE"===t||"DECADE_5"===t||"CENTURY"===t||"CENTURY_5"===t||"MILLENIUM"===t}e.formatDate=((t,e)=>{if(null==t)return"∞";const i=new Date(t);let n=i.getUTCFullYear().toString();return d(e)?n:(n=`${o(i)} ${n}`,"MONTH"===e?n:(n=`${r(i)} ${n}`,"DAY"===e?n:(n=`${n} at ${a(i)}:`,"HOUR"===e?`${n}00`:(n=`${n}${l(i)}`,"MINUTE"===e?n:(n=`${n}:${h(i)}`,"SECOND"===e?n:`${n}.${u(i)}`)))))}),e.getGranularity=(t=>t>58?"MILLISECOND":t>12?"MILLISECOND_10":t>2.3?"MILLISECOND_50":t>1.5?"MILLISECOND_100":t>.4?"MILLISECOND_500":t>.00112?"SECOND":t>112e-6?"MINUTE":t>112e-7?"HOUR":t>8e-7?"DAY":t>2.6e-7?"WEEK":t>2.2e-8?"MONTH":t>2.2e-9?"YEAR":t>3.3e-10?"YEAR_5":t>1.6e-10?"DECADE":t>8e-11?"DECADE_5":t>1.5e-11?"CENTURY":t>5e-12?"CENTURY_5":"MILLENIUM"),e.getStep=(t=>{if("YEAR"===t)return 1;if("YEAR_5"===t)return 5;if("DECADE"===t)return 10;if("DECADE_5"===t)return 50;if("CENTURY"===t)return 100;if("CENTURY_5"===t)return 500;if("MILLENIUM"===t)return 1e3;if("MILLISECOND"===t)return 1;if("MILLISECOND_10"===t)return 10;if("MILLISECOND_50"===t)return 50;if("MILLISECOND_100"===t)return 100;if("MILLISECOND_500"===t)return 500;throw new RangeError("[getStep] Only steps with a granularity greater than 'year' calculated")}),e.subsequentDate=function(t){return d(t)?i=>{let n=new Date(i),s=n.getUTCFullYear()+1;if("YEAR"!==t){const i=e.getStep(t);for(;s%i!=0;)s+=1}return s>-1&&s<100?(n.setUTCFullYear(s),n.getTime()):Date.UTC(s,0,1)}:"MONTH"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth()+1,1)}:"WEEK"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()+7)}:"DAY"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()+1)}:"HOUR"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours()+1)}:"MINUTE"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes()+1)}:"SECOND"===t?t=>{const e=new Date(t);return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds()+1)}:"MILLISECOND"===t.slice(0,"MILLISECOND".length)?i=>{const n=e.getStep(t),s=new Date(i);let o=s.getUTCMilliseconds()+1;return n>1&&(o=o+n-o%n),Date.UTC(s.getUTCFullYear(),s.getUTCMonth(),s.getUTCDate(),s.getUTCHours(),s.getUTCMinutes(),s.getUTCSeconds(),o)}:void 0},e.byDate=function(t,e){const i=null!=t.dmin?t.dmin:t.d,n=null!=e.dmin?e.dmin:e.d;if(i<n)return-1;if(i>n)return 1;const s=null!=t.dmax?t.dmax:t.ed,o=null!=e.dmax?e.dmax:e.ed;return s<o?-1:s>o?1:0};e.labelBody=((t,e)=>{const i=new Date(t);return d(e)?i.getUTCFullYear().toString():"MONTH"===e?o(i):"WEEK"===e?`${o(i)}, week ${(t=>{const e=new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate())),i=e.getUTCDay()||7;e.setUTCDate(e.getUTCDate()+4-i);const n=new Date(Date.UTC(e.getUTCFullYear(),0,1));return Math.ceil(((e.getTime()-n.getTime())/864e5+1)/7)})(i)}`:"DAY"===e?`${r(i)} ${o(i)}`:"HOUR"===e?`${a(i)}:00`:"MINUTE"===e?`${a(i)}:${l(i)}`:"SECOND"===e?`${a(i)}:${l(i)}:${h(i)}`:"MILLISECOND"===e.slice(0,"MILLISECOND".length)?`${a(i)}:${l(i)}:${h(i)}.${u(i)}`:void 0})},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class n{constructor(){this.eventsListeners=[]}dispatch(t,e){const i=null!=e?new CustomEvent(t,{detail:e}):new CustomEvent(t);document.dispatchEvent(i)}register(t,e,i=document){i.addEventListener(t,e),this.eventsListeners.push([t,e,i])}flush(){this.eventsListeners.forEach(t=>{const[e,i,n]=t;n.removeEventListener(e,i)}),this.eventsListeners=[]}}e.EventBus=n,e.default=new n},function(t,e,i){"use strict";function n(t){return Math.pow(2,-1*t)}function s(t){if(null==t)return null;return new Date(t).toUTCString()}Object.defineProperty(e,"__esModule",{value:!0}),e.debounce=((t,e)=>{let i;return()=>{clearTimeout(i),i=setTimeout(t,e)}}),e.visibleRatio=n,e.createRange=function(t){return Array.apply(null,{length:t}).map(Number.call,Number)},e.selectRandom=function(t,e){const i=[];for(;i.length<e;){const n=t[Math.floor(Math.random()*t.length)];(-1===i.indexOf(n)||t.length<e)&&i.push(n)}return i},e.calcPixelsPerMillisecond=function(t,e,i){return t/n(e)/i},e.logEvent=function(t,...e){console.log(t.lbl,t,s(t.from),s(t.to),e)}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.DomainConfig=class{};class n{constructor(){this.heightRatio=1,this.rulers=!0,this.rulerLabels=!0,this.topOffsetRatio=0,this.zoomLevel=0}}e.BandConfig=n;e.MinimapBandConfig=class extends n{constructor(){super(...arguments),this.indicatorFor=0,this.targets=[]}};e.EventsBandConfig=class extends n{};e.default=class{}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(1);e.TimelineProps=n.Props;const s=i(8);e.TimelineConfig=s.default;const o=i(10),r=i(3),a=i(7);e.calcPixelsPerMillisecond=a.calcPixelsPerMillisecond;const l=i(12);e.OrderedTimeline=l.OrderedTimeline,e.orderEvents=l.orderEvents;const h=i(13),u=i(14),d=i(15),c=i(18),f=i(19),p=i(20);e.MinimapBand=p.default;const m=i(21);e.EventsBand=m.default;const v=i(5);e.formatDate=v.formatDate;const g=i(11);e.Ev3ntLocation=g.Ev3ntLocation,e.RawEv3nt=g.RawEv3nt,e.Ev3nt=g.Ev3nt,e.Voyage=g.Voyage;const E=i(4),w=i(0);e.EventType=w.EventType;e.default=class extends h.default{constructor(t){super(),this.appendToWrapper=(t=>{let e=t.render();Array.isArray(e)||(e=[e]),e.forEach(t=>this.wrapper.appendChild(t))}),n.default.init(t),t.rootElement.appendChild(this.render()),this.popup=new f.default(this.wrapper);const e=a.debounce(this.resize,600);window.addEventListener("resize",e)}hidePopup(){this.popup.hide()}showPopup(t){this.popup.show(t)}render(){this.wrapper=r.default("div","wrapper",["box-sizing: border-box","height: 100%","overflow: hidden","position: relative","user-select: none","width: 100%"]),this.views=n.default.bands.map(t=>t.type===E.BandType.EventsBand?new u.default(t):new o.default(t)),this.views.push(new d.default),this.views.forEach(this.appendToWrapper),this.renderLabels();const t=r.default("div","red-line",["background-color: rgb(126, 0, 0)","bottom: 0","left: calc(50% - 1px)","position: absolute","top: 0","width: 2px","z-index: 4"]);return this.wrapper.appendChild(t),this.wrapper}renderLabels(){n.default.bands.filter(t=>t.type===E.BandType.EventsBand&&null!=t.config.label).map(t=>new c.default(t)).forEach(this.appendToWrapper)}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(4),s=i(1),o=i(3),r=i(6),a=i(2),l=i(0);e.default=class{constructor(t){this.band=t,this.onMouseDown=(t=>{document.addEventListener("mouseup",this.onMouseUp),this.dragStartTime=Date.now(),this.dragStartPosition=[t.clientX,t.clientY],this.dragOffsetX=t.clientX,this.dragOffsetY=t.clientY}),this.onMouseMove=(t=>{if(null==this.dragOffsetX)return;const e=t.clientY-this.dragOffsetY,i=t.clientX-this.dragOffsetX;if(this.band.type===n.BandType.EventsBand){const t=this.band;(0!==t.offsetY||Math.abs(e)>Math.abs(i)&&Math.abs(e)>5)&&(t.offsetY=e)}const o=i/this.band.pixelsPerMillisecond;s.default.center-=o,a.default.nextFrame(),this.dragOffsetX=t.clientX,this.dragOffsetY=t.clientY}),this.onMouseUp=(t=>{this.lastDragInterval=Date.now()-this.dragStartTime,this.dispatchScrollDoneEvent(t),this.dragOffsetX=null,this.dragOffsetY=null,document.removeEventListener("mouseup",this.onMouseUp)}),this.onDblClick=(t=>{const e=this.band.timestampAtPosition(t.clientX);a.default.goTo(e)})}render(){return this.rootElement=o.default("div","band-wrap",["position: absolute","z-index: 2"],[`height: ${this.band.visibleHeight}px`,`top: ${this.band.top}px`,`width: ${s.default.viewportWidth}px`]),r.default.register("mousedown",this.onMouseDown,this.rootElement),r.default.register("mousemove",this.onMouseMove,this.rootElement),r.default.register("dblclick",this.onDblClick,this.rootElement),this.rootElement}dispatchScrollDoneEvent(t){const e=[this.dragStartPosition[0]-t.clientX,this.dragStartPosition[1]-t.clientY].map(Math.abs).some(t=>t>5);(this.lastDragInterval>200||e)&&r.default.dispatch(l.EventType.ScrollDone)}resize(){this.rootElement.style.cssText=`height: ${this.band.visibleHeight}px; top: ${this.band.top}px; width: ${s.default.viewportWidth}px;`}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(0);!function(t){t.NONE="none",t.JPG="jpg",t.SVG="svg",t.GIF="gif",t.PNG="png"}(e.ImageFileType||(e.ImageFileType={}));e.Ev3ntLocation=class{};e.Voyage=class{};class s{}e.RawEv3nt=s;e.Ev3nt=class extends s{constructor(t,e){super();for(const e in t)null!=t[e]&&(this[e]=t[e]);if(null==this.lbl&&(this.lbl="NO LABEL"),null==this.id&&(this.id="id_"+crypto.getRandomValues(new Uint8Array(4)).join("_")),this.from=this.dmin||this.d,this.to=this.dmax||this.ed,null==this.to&&(this.to=this.from),this.time=this.to-this.from,null!=e){const t=Math.round(2*n.EVENT_HEIGHT/e);let i=this.lbl.length*n.PIXELS_PER_LETTER/e+t;i=i>this.time?i-this.time:0,this.screenTo=Math.round(this.from+this.time+i)}}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(0),s=i(11),o=i(7);class r{}e.OrderedTimeline=r,e.orderEvents=function(t){if(null==t.bands||!t.bands.length)return new r;let e,i=t.bands.reduce((t,e)=>{const i=e.events[0];return Math.min(t,i.dmin||1/0,i.d||1/0)},1/0),a=t.bands.reduce((t,e)=>{const i=e.events.reduce((t,e)=>Math.max(t,e.d||-1/0,e.ed||-1/0,e.dmax||-1/0),-1/0);return Math.max(i,t)},-1/0);null!=t.parent&&(e=new s.Ev3nt(t.parent),i=Math.min(i,e.dmin||1/0,e.d||1/0),a=Math.max(a,e.ed||-1/0,e.dmax||-1/0));const l=a-i;return{bands:t.bands.map(function(e){const i=o.calcPixelsPerMillisecond(t.viewportWidth,e.zoomLevel,l),r=[-1/0],a=Math.round(2*n.EVENT_ROW_HEIGHT/i);function h(t,e){return(null==r[t+1]||r[t+1]<e)&&(null==r[t+2]||r[t+2]<e)}return{events:e.events.map(function(t){const e=new s.Ev3nt(t,i);let n;if(e.img){const t=e.time?e.from:e.from-a/2,i=e.time?e.from+a:e.from+a/2;if((n=r.findIndex(e=>t>e))>-1){let e=!1;for(;!e&&!(e=h(n,t));)-1===(n=r.findIndex((e,i)=>i>n&&t>e))&&(e=!0)}-1===n?(n=r.push(e.screenTo)-1,r.push(i),r.push(i)):(r[n]=e.screenTo,r[n+1]=i,r[n+2]=i)}else-1===(n=r.findIndex(t=>e.from>t))?n=r.push(e.screenTo)-1:r[n]=e.screenTo;return e.row=n,e}),zoomLevel:e.zoomLevel,pixelsPerMillisecond:i,rowCount:r.length}}),from:i,parent:e,time:l,to:a}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(2),s=i(1),o=i(0);e.default=class{constructor(){this.animator=n.default,this.resize=(()=>{s.default.resize();for(const t of s.default.bands)t.resize();for(const t of this.views)t.resize();this.animator.nextFrame()}),document.addEventListener("keydown",t=>{189===t.keyCode&&s.default.controlBand.zoomOut(),187===t.keyCode&&s.default.controlBand.zoomIn()})}on(t,e){const i={centerchange:o.EventType.CenterChange,pause:o.EventType.Pause,play:o.EventType.Play,scrolldone:o.EventType.ScrollDone,select:o.EventType.Select,zoomdone:o.EventType.ZoomDone};if(Object.keys(i).indexOf(t)>-1){const n=i[t];let r;r=n===o.EventType.CenterChange?()=>e(s.default):n===o.EventType.Select?t=>e(t.detail):e,document.addEventListener(n,r)}}reload(){this.resize()}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(10),s=i(6),o=i(0);e.default=class extends n.default{constructor(t){super(t),this.band=t,this.onWheel=(t=>{0===Math.abs(t.deltaX)&&0!==t.deltaY&&(t.deltaY<0&&this.zoomOut(),t.deltaY>0&&this.zoomIn())}),this.onClick=(t=>{if(this.lastDragInterval>175)return;const e=this.band.getEventByCoordinates(t.clientX,t.clientY);s.default.dispatch(o.EventType.Select,e)})}render(){const t=super.render();return s.default.register("click",this.onClick,this.rootElement),s.default.register("wheel",this.onWheel,this.rootElement),t}zoomIn(){this.band.zoomIn()}zoomOut(){this.band.zoomOut()}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(16),s=i(3),o=i(1),r=i(0),a=i(2),l=i(17),h=i(6);e.default=class{constructor(){this.indicatorsDrawn=!1,this.onImgLoad=(t=>{const e=i=>{t.image.removeEventListener("load",e),t.image.removeEventListener("error",e),"error"!==i.type?(t.image.width>t.image.height?(t.image.height=Math.round(t.image.height*(r.IMAGE_BOUNDING_BOX/t.image.width)),t.image.width=r.IMAGE_BOUNDING_BOX):(t.image.width=Math.round(t.image.width*(r.IMAGE_BOUNDING_BOX/t.image.height)),t.image.height=r.IMAGE_BOUNDING_BOX),this.drawImage(t)):t.image=null};return e}),this.onAnimationDone=(()=>{}),this.update=(()=>{for(const t of o.default.eventsBands)this.drawEventsBand(t);for(const t of o.default.minimapBands)this.drawMinimapBand(t);this.drawIndicators(),this.updateImages()}),a.default.registerView(this),h.default.register(r.EventType.ZoomDone,this.onAnimationDone),h.default.register(r.EventType.ScrollDone,this.onAnimationDone)}updateImages(){return n.__awaiter(this,void 0,void 0,function*(){for(const t of o.default.eventsBands)for(const e of t.visibleEvents)if(null!=e.img)if(null==e.image){const t=`${o.default.imagePath}/${e.wid}__${r.IMAGE_SIZE}.${e.img}`;e.image=new Image;const i=this.onImgLoad(e);e.image.addEventListener("load",i),e.image.addEventListener("error",i),e.image.src=t}else this.drawImage(e)})}drawImage(t){if(null==t.image||!t.image.complete||!t.image.naturalWidth)return;const e=t.time?t.left:t.left-t.image.width/2-r.IMAGE_BORDER_SIZE,i=t.top-t.image.height;this.ctx.fillStyle=t.color,this.ctx.fillRect(e,i-2*r.IMAGE_BORDER_SIZE,t.image.width+2*r.IMAGE_BORDER_SIZE,t.image.height+2*r.IMAGE_BORDER_SIZE),this.ctx.drawImage(t.image,e+r.IMAGE_BORDER_SIZE,i-r.IMAGE_BORDER_SIZE,t.image.width,t.image.height)}render(){return this.canvas=s.default("canvas","main",["position: absolute"]),this.canvas.width=o.default.viewportWidth,this.canvas.height=o.default.viewportHeight,this.ctx=this.canvas.getContext("2d"),this.indicatorsCanvas=s.default("canvas","indicators",["position: absolute"],["z-index: 1"]),this.indicatorsCanvas.width=o.default.viewportWidth,this.indicatorsCanvas.height=o.default.viewportHeight,this.indicatorsCtx=this.indicatorsCanvas.getContext("2d"),this.update(),[this.canvas,this.indicatorsCanvas]}resize(){this.indicatorsCanvas.width=o.default.viewportWidth,this.indicatorsCanvas.height=o.default.viewportHeight,this.canvas.width=o.default.viewportWidth,this.canvas.height=o.default.viewportHeight,this.indicatorsDrawn=!1}clear(t){this.ctx.clearRect(0,t.top,this.canvas.width,t.visibleHeight)}drawEventsBand(t){this.clear(t),l.default(this.ctx,t);for(const e of t.visibleEvents)if(e.time){let t=e.left,i=e.width;if(e.uncertain_from_width>1){const n=this.ctx.createLinearGradient(e.left,0,e.left+e.uncertain_from_width,0);n.addColorStop(0,"white"),n.addColorStop(1,e.color),this.ctx.fillStyle=n,this.ctx.fillRect(e.left,e.top,e.uncertain_from_width,r.EVENT_HEIGHT),t=e.left+e.uncertain_from_width,i-=e.uncertain_from_width}if(e.uncertain_to_width>1){const n=t+(i-=e.uncertain_to_width),s=n+e.uncertain_to_width,o=this.ctx.createLinearGradient(n,0,s,0);o.addColorStop(0,e.color),o.addColorStop(1,"white"),this.ctx.fillStyle=o,this.ctx.fillRect(n,e.top,e.uncertain_to_width,r.EVENT_HEIGHT)}this.ctx.fillStyle=e.color,this.ctx.fillRect(t,e.top,i,r.EVENT_HEIGHT)}else this.ctx.moveTo(e.left,e.top+r.EVENT_HEIGHT/2),this.ctx.beginPath(),this.ctx.arc(e.left,e.top+r.EVENT_HEIGHT/2,r.EVENT_HEIGHT/3,0,2*Math.PI),this.ctx.fillStyle=e.color,this.ctx.fill();this.drawEventsText(t)}drawEventsText(t){this.ctx.font=`${r.FONT_SIZE}px sans-serif`,this.ctx.fillStyle="rgb(40, 40, 40)";for(const e of t.visibleEvents){let t=e.left;e.left<0&&0!==e.time&&(t=-e.uncertain_from_width);const i=t+(e.time?r.FONT_SIZE/3:r.FONT_SIZE/1.2)+e.uncertain_from_width,n=e.top+r.FONT_SIZE+(r.EVENT_HEIGHT-r.FONT_SIZE)/2-2;this.ctx.fillText(e.lbl,Math.round(i),Math.round(n))}}drawMinimapBand(t){if(t.isDrawn&&t.prevOffsetX===t.offsetX&&t.prevZoomLevel===t.zoomLevel)return;this.clear(t),l.default(this.ctx,t);const e=t.draw();this.ctx.drawImage(e,0,t.top,o.default.viewportWidth,t.availableHeight),t.isDrawn=!0}drawIndicators(){if(!this.indicatorsDrawn||!o.default.eventsBands.every(t=>t.prevZoomLevel===t.zoomLevel)){this.indicatorsCtx.clearRect(0,0,o.default.viewportWidth,o.default.viewportHeight),this.indicatorsCtx.beginPath();for(const t of o.default.minimapBands){const e=o.default.eventsBands[t.config.indicatorFor],i=Math.round(t.config.topOffsetRatio*o.default.viewportHeight),n=t.positionAtTimestamp(e.from);this.indicatorsCtx.rect(0,i,n,t.visibleHeight);const s=t.positionAtTimestamp(e.to);this.indicatorsCtx.rect(s,i,o.default.viewportWidth,t.visibleHeight),this.indicatorsCtx.rect(n,i+t.availableHeight,s-n,t.visibleHeight-t.availableHeight)}this.indicatorsCtx.fillStyle="rgba(0, 0, 0, .04)",this.indicatorsCtx.fill(),this.indicatorsCtx.closePath(),this.indicatorsDrawn=!0}}}},function(t,e,i){"use strict";i.r(e),i.d(e,"__extends",function(){return s}),i.d(e,"__assign",function(){return o}),i.d(e,"__rest",function(){return r}),i.d(e,"__decorate",function(){return a}),i.d(e,"__param",function(){return l}),i.d(e,"__metadata",function(){return h}),i.d(e,"__awaiter",function(){return u}),i.d(e,"__generator",function(){return d}),i.d(e,"__exportStar",function(){return c}),i.d(e,"__values",function(){return f}),i.d(e,"__read",function(){return p}),i.d(e,"__spread",function(){return m}),i.d(e,"__await",function(){return v}),i.d(e,"__asyncGenerator",function(){return g}),i.d(e,"__asyncDelegator",function(){return E}),i.d(e,"__asyncValues",function(){return w}),i.d(e,"__makeTemplateObject",function(){return _}),i.d(e,"__importStar",function(){return T}),i.d(e,"__importDefault",function(){return b});
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var n=function(t,e){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i])})(t,e)};function s(t,e){function i(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(i.prototype=e.prototype,new i)}var o=function(){return(o=Object.assign||function(t){for(var e,i=1,n=arguments.length;i<n;i++)for(var s in e=arguments[i])Object.prototype.hasOwnProperty.call(e,s)&&(t[s]=e[s]);return t}).apply(this,arguments)};function r(t,e){var i={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&e.indexOf(n)<0&&(i[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(n=Object.getOwnPropertySymbols(t);s<n.length;s++)e.indexOf(n[s])<0&&(i[n[s]]=t[n[s]])}return i}function a(t,e,i,n){var s,o=arguments.length,r=o<3?e:null===n?n=Object.getOwnPropertyDescriptor(e,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,i,n);else for(var a=t.length-1;a>=0;a--)(s=t[a])&&(r=(o<3?s(r):o>3?s(e,i,r):s(e,i))||r);return o>3&&r&&Object.defineProperty(e,i,r),r}function l(t,e){return function(i,n){e(i,n,t)}}function h(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)}function u(t,e,i,n){return new(i||(i=Promise))(function(s,o){function r(t){try{l(n.next(t))}catch(t){o(t)}}function a(t){try{l(n.throw(t))}catch(t){o(t)}}function l(t){t.done?s(t.value):new i(function(e){e(t.value)}).then(r,a)}l((n=n.apply(t,e||[])).next())})}function d(t,e){var i,n,s,o,r={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(i)throw new TypeError("Generator is already executing.");for(;r;)try{if(i=1,n&&(s=2&o[0]?n.return:o[0]?n.throw||((s=n.return)&&s.call(n),0):n.next)&&!(s=s.call(n,o[1])).done)return s;switch(n=0,s&&(o=[2&o[0],s.value]),o[0]){case 0:case 1:s=o;break;case 4:return r.label++,{value:o[1],done:!1};case 5:r.label++,n=o[1],o=[0];continue;case 7:o=r.ops.pop(),r.trys.pop();continue;default:if(!(s=(s=r.trys).length>0&&s[s.length-1])&&(6===o[0]||2===o[0])){r=0;continue}if(3===o[0]&&(!s||o[1]>s[0]&&o[1]<s[3])){r.label=o[1];break}if(6===o[0]&&r.label<s[1]){r.label=s[1],s=o;break}if(s&&r.label<s[2]){r.label=s[2],r.ops.push(o);break}s[2]&&r.ops.pop(),r.trys.pop();continue}o=e.call(t,r)}catch(t){o=[6,t],n=0}finally{i=s=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}function c(t,e){for(var i in t)e.hasOwnProperty(i)||(e[i]=t[i])}function f(t){var e="function"==typeof Symbol&&t[Symbol.iterator],i=0;return e?e.call(t):{next:function(){return t&&i>=t.length&&(t=void 0),{value:t&&t[i++],done:!t}}}}function p(t,e){var i="function"==typeof Symbol&&t[Symbol.iterator];if(!i)return t;var n,s,o=i.call(t),r=[];try{for(;(void 0===e||e-- >0)&&!(n=o.next()).done;)r.push(n.value)}catch(t){s={error:t}}finally{try{n&&!n.done&&(i=o.return)&&i.call(o)}finally{if(s)throw s.error}}return r}function m(){for(var t=[],e=0;e<arguments.length;e++)t=t.concat(p(arguments[e]));return t}function v(t){return this instanceof v?(this.v=t,this):new v(t)}function g(t,e,i){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n,s=i.apply(t,e||[]),o=[];return n={},r("next"),r("throw"),r("return"),n[Symbol.asyncIterator]=function(){return this},n;function r(t){s[t]&&(n[t]=function(e){return new Promise(function(i,n){o.push([t,e,i,n])>1||a(t,e)})})}function a(t,e){try{!function(t){t.value instanceof v?Promise.resolve(t.value.v).then(l,h):u(o[0][2],t)}(s[t](e))}catch(t){u(o[0][3],t)}}function l(t){a("next",t)}function h(t){a("throw",t)}function u(t,e){t(e),o.shift(),o.length&&a(o[0][0],o[0][1])}}function E(t){var e,i;return e={},n("next"),n("throw",function(t){throw t}),n("return"),e[Symbol.iterator]=function(){return this},e;function n(n,s){e[n]=t[n]?function(e){return(i=!i)?{value:v(t[n](e)),done:"return"===n}:s?s(e):e}:s}}function w(t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e,i=t[Symbol.asyncIterator];return i?i.call(t):(t=f(t),e={},n("next"),n("throw"),n("return"),e[Symbol.asyncIterator]=function(){return this},e);function n(i){e[i]=t[i]&&function(e){return new Promise(function(n,s){(function(t,e,i,n){Promise.resolve(n).then(function(e){t({value:e,done:i})},e)})(n,s,(e=t[i](e)).done,e.value)})}}}function _(t,e){return Object.defineProperty?Object.defineProperty(t,"raw",{value:e}):t.raw=e,t}function T(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var i in t)Object.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e.default=t,e}function b(t){return t&&t.__esModule?t:{default:t}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(1),s=i(0),o=i(5);function r(t,e){return"CENTURY"===e.granularity&&new Date(t).getUTCFullYear()%1e3==0||("YEAR_5"===e.granularity&&new Date(t).getUTCFullYear()%50==0||"YEAR"===e.granularity&&new Date(t).getUTCFullYear()%5==0)}function a(t,e,i,n,s){const r=e.positionAtTimestamp(i);t.moveTo(r,n),t.lineTo(r,s),e.config.rulerLabels&&t.fillText(o.labelBody(i,e.granularity),r+3,s-3)}e.default=function(t,e){if(!e.config.rulers)return;let i=e.nextDate(e.from);const o=e.config.topOffsetRatio*n.default.viewportHeight,l=e.config.heightRatio*n.default.viewportHeight,h=[],u=[];for(;i<e.to;)r(i,e)?u.push(i):h.push(i),i=e.nextDate(i);t.beginPath(),t.font=`${s.FONT_SIZE}px sans-serif`,t.fillStyle="rgb(205, 205, 205)";for(const i of h)a(t,e,i,o,o+l);t.strokeStyle="rgb(235, 235, 235)",t.stroke(),t.beginPath(),t.font=`${1.2*s.FONT_SIZE}px sans-serif`,t.fillStyle="rgb(120, 120, 120)";for(const i of u)a(t,e,i,o,o+l);t.strokeStyle="rgb(150, 150, 150)",t.stroke()}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(3);e.default=class{constructor(t){this.band=t}render(){const t=n.default("div","events-label-wrapper",["border-top: 1px solid #CCC","pointer-events: none","position: absolute","width: 100%","z-index: 3"],[`top: ${100*this.band.config.topOffsetRatio}%`]),e=n.default("div","events-label",["background: white","border-bottom-right-radius: 4px","box-shadow: 1px 2px 4px #AAA","color: #444","display: inline-block","font-family: sans-serif","font-size: .8em","padding: 4px 8px"]);return e.innerText=this.band.config.label,t.appendChild(e),t}resize(){}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(3),s=i(1),o=i(0),r=i(5),a=i(2),l=14;e.default=class{constructor(t){this.rootElement=t,this.update=(()=>{this.event&&this.setPosition()}),this.loadImage=(()=>{this.el.querySelector("img").removeEventListener("load",this.loadImage),this.setWidth(),this.setPosition()}),this.el=n.default("div"),this.el.id="popup",this.el.style.position="absolute",this.el.style.zIndex="10",this.hide(),this.rootElement.appendChild(this.el),this.el.addEventListener("click",t=>{t.target.matches("#popup-close")&&this.hide()}),a.default.registerView(this)}hide(){this.event=null,this.el.style.width="auto",this.el.style.visibility="hidden",this.el.classList.remove("bottom")}setWidth(){const t=this.el.getBoundingClientRect();this.el.style.width=`${t.width}px`}setPosition(){const t=this.el.getBoundingClientRect();if(this.event.left+this.event.width<l||this.event.left>s.default.viewportWidth-l)return void(this.el.style.visibility="hidden");let e=this.event.left+this.event.width/2-t.width/2;e<l&&(e=l),e+t.width>s.default.viewportWidth-l&&(e=s.default.viewportWidth-t.width-l),this.el.style.left=`${e}px`;let i=this.event.top+o.EVENT_HEIGHT+l;i+t.height>s.default.viewportHeight-l&&(i=this.event.top-t.height-l,this.el.classList.add("bottom")),this.el.style.top=`${i}px`,this.el.style.visibility="visible"}show(t){this.hide(),this.event=t,this.el.innerHTML=function(t){return`\n\t\t<img alt="noimage" src="" />\n\t\t<div class="metadata">\n\t\t\t<h2 class="label">${t.lbl}</h2>\n\t\t\t<div class="description">${t.dsc||""}</div>\n\t\t\t<br />\n\t\t\t<br />\n\t\t\t<div class="from">${r.formatDate(t.from,t.dmin_g||t.d_g)}</div>\n\t\t\t${t.time?`<div class="to">${r.formatDate(t.to,t.dmax_g||t.ed_g)}</div>`:""}\n\t\t</div>\n\t\t<div id="popup-close">✖</div>\n\t`}(t),this.el.querySelector(".label").style.color=t.color;const e=this.el.querySelector("img");t.img?(e.setAttribute("alt",`Image of ${t.lbl}`),e.addEventListener("load",this.loadImage),e.src=t.image.src.replace("32","128")):(e.src=null,e.setAttribute("alt","noimage"),this.setWidth(),this.setPosition())}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(4),s=i(8),o=i(1),r=i(3);e.default=class extends n.default{constructor(t){super(function(t){const e=Object.assign({},new s.MinimapBandConfig,t);return e.targets.length||e.targets.push(0),e}(t)),this.type=n.BandType.MinimapBand,this.canvas=r.default("canvas"),this.ctx=this.canvas.getContext("2d"),this.nextCanvas=r.default("canvas"),this.nextCtx=this.nextCanvas.getContext("2d"),this.isDrawn=!1}init(){super.init(),this.maxRowCount=this.config.targets.reduce((t,e)=>{const{rowCount:i}=o.default.eventsBands[e];return Math.max(t,i)},0);const t=this.availableHeight/this.maxRowCount;this.eventHeight=t<1?1:Math.floor(t),this.canvas.width=o.default.viewportWidth,this.canvas.height=this.maxRowCount*this.eventHeight,this.nextCanvas.width=this.canvas.width,this.nextCanvas.height=this.canvas.height}resize(){super.resize(),this.isDrawn=!1}draw(){return this.isDrawn?this.updateNextCanvas():this.drawEvents(),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.drawImage(this.nextCanvas,0,0),this.canvas}drawEvents(t=this.from,e=this.to){this.nextCtx.beginPath(),this.config.targets.forEach(i=>{const n=o.default.eventsBands[i];for(const i of n.events){if(i.from>e||i.to<t)continue;const n=this.positionAtTimestamp(i.from),s=this.maxRowCount-(i.row+2)*this.eventHeight,o=Math.round(i.time*this.pixelsPerMillisecond),r=o<1?1:o;this.nextCtx.fillStyle="rgb(190, 190, 190)",this.nextCtx.fillRect(n,s,r,this.eventHeight),i.img&&(this.nextCtx.fillStyle="rgb(240, 240, 240)",this.nextCtx.fillRect(n,s-2*this.eventHeight,2*this.eventHeight,2*this.eventHeight))}})}updateNextCanvas(){const t=Math.round(this.offsetX-this.prevOffsetX);if(0===t)return this.canvas;let e,i;this.nextCtx.clearRect(0,0,this.nextCanvas.width,this.nextCanvas.height),this.nextCtx.drawImage(this.canvas,t,0),t<0?(e=this.timestampAtPosition(o.default.viewportWidth+t),i=this.to):(e=this.from,i=this.timestampAtPosition(t)),this.drawEvents(e,i)}}},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const n=i(4),s=i(8),o=i(2),r=i(0),a=i(1),l=i(5);e.default=class extends n.default{constructor(t){super(Object.assign({},new s.EventsBandConfig,t)),this.type=n.BandType.EventsBand,this.events=[],this.rowCount=0,this.visibleEvents=[],this._offsetY=0,null!=this.config.events&&this.config.events.sort(l.byDate)}get offsetY(){return this._offsetY}set offsetY(t){this._offsetY+=t,this._offsetY<0&&(this._offsetY=0);const e=this.height>this.availableHeight?this.height-this.availableHeight+r.EVENT_ROW_HEIGHT:0;this._offsetY>e&&(this._offsetY=e);const i=this._offsetY/r.EVENT_ROW_HEIGHT;this.lowestVisibleRow=Math.ceil(i),this.highestVisibleRow=this.lowestVisibleRow+this.visibleRowsCount}init(t){super.init(),this.events=t.events,this.rowCount=t.rowCount,this.height=r.EVENT_ROW_HEIGHT*this.rowCount,this.offsetY=0,this.updateEvents()}getColor(t,e){const i=[49,220,215];let n;if(a.default.center>e)n=a.default.center-e;else{if(!(a.default.center<t))return`rgb(${i.join(", ")})`;n=t-a.default.center}const s=n/(this.time/2),o=a.default.center>e?[253,231,37]:[204,104,232];return`rgb(${i.map((t,e)=>t+(o[e]-t)*s).join(", ")})`}updateEvents(){this.visibleEvents=this.events.filter(t=>!(t.from>this.to||t.to<this.from)&&t.row>=this.lowestVisibleRow&&t.row<=this.highestVisibleRow).map(t=>{if(t.left=this.positionAtTimestamp(t.from),t.width=Math.round(t.time*this.pixelsPerMillisecond),t.time&&t.width<1&&(t.width=1),t.uncertain_from_width=0,null!=t.dmin){let e;if(null!=t.d)e=t.d;else if(null!=t.ed)e=t.ed;else{if(null==t.dmax)throw Error(["updateEvents","Width uncertain from is not definable",JSON.stringify(t)].join("\n"));e=t.dmin+(t.dmax-t.dmin)/2}t.uncertain_from_width=(e-t.dmin)*this.pixelsPerMillisecond}if(t.uncertain_to_width=0,null!=t.dmax){let e;if(null!=t.ed)e=t.ed;else if(null!=t.d)e=t.d;else{if(null==t.dmin)throw Error(["updateEvents","Width uncertain to is not definable",JSON.stringify(t)].join("\n"));e=t.dmin+(t.dmax-t.dmin)/2}t.uncertain_to_width=(t.dmax-e)*this.pixelsPerMillisecond}return t.top=this.top+this.availableHeight-(t.row+1)*r.EVENT_ROW_HEIGHT+this.offsetY,t.color=this.getColor(t.from,t.to),t})}update(){super.update(),this.updateEvents()}getEventByCoordinates(t,e){const i=this.timestampAtPosition(t),n=a.default.viewportOffset+this.top+this.availableHeight+this.offsetY,s=Math.floor((n-e)/r.EVENT_ROW_HEIGHT);return this.events.find(t=>!(!(t.from<i&&t.screenTo>i)||t.row<this.lowestVisibleRow||t.row>this.highestVisibleRow)&&t.row===s)}zoomIn(){o.default.zoomTo(this,this.zoomLevel+1)}zoomOut(){o.default.zoomTo(this,this.zoomLevel-1)}}}])});

@@ -19,3 +19,4 @@ [

"label": "Vasco da Gama",
"date": -16094073600000,
"date_min": -16094073600000,
"date": -15809990400000,
"end_date": -14043542400000

@@ -22,0 +23,0 @@ },

[
{
"label": "Plato",
"date": -75673612800000,
"end_date": -73085932800000
"lbl": "Plato",
"dmin": -75673612800000,
"d": -75484224000001,
"ed": -73149004800000,
"dmax": -73085846400001
},
{
"label": "Confucius",
"date": -79555046400000,
"end_date": -77251536000000
"lbl": "Confucius",
"d": -79555046400000,
"ed": -77251536000000
},
{
"label": "Aristotle",
"date": -74285078400000,
"end_date": -72297014400000
"lbl": "Aristotle",
"d": -74285078400000,
"ed": -72297014400000
},
{
"label": "Alexander the Great",
"date": -73384099200000,
"end_date": -72346089600000
"lbl": "Alexander the Great",
"d": -73384099200000,
"ed": -72346089600000
},
{
"label": "Socrates",
"date": -76998988800000,
"end_date": -74726928000000
"lbl": "Socrates",
"d": -76998988800000,
"ed": -74726928000000
},
{
"label": "Cicero",
"date": -65512022400000,
"end_date": -63494755200000
"lbl": "Cicero",
"d": -65512022400000,
"ed": -63494755200000
},
{
"label": "Augustine of Hippo",
"date": -50968742400000,
"end_date": -48577017600000
"lbl": "Augustine of Hippo",
"d": -50968742400000,
"ed": -48577017600000
},
{
"label": "Thomas Aquinas",
"date": -23509872000000,
"end_date": -21957955200000
"lbl": "Thomas Aquinas",
"dmin": -23509872000000,
"d": -23478336000001,
"ed": -21957955200000
},
{
"label": "Ibn Khaldun",
"date": -20120659200000,
"end_date": -17791660800000
"lbl": "Ibn Khaldun",
"d": -20120659200000,
"ed": -17791660800000
},
{
"label": "Avicenna",
"date": -31221158400000,
"end_date": -29427840000000
"lbl": "Avicenna",
"d": -31221158400000,
"ed": -29427840000000
},
{
"label": "Magna Carta",
"date": -23811235200000
"lbl": "Magna Carta",
"d": -23811235200000
},
{
"label": "Niccolò Machiavelli",
"date": -15799449600000,
"end_date": -13965004800000
"lbl": "Niccolò Machiavelli",
"d": -15799449600000,
"ed": -13965004800000
},
{
"label": "Jean-Jacques Rousseau",
"date": -8126265600000,
"end_date": -6043161600000
"lbl": "Jean-Jacques Rousseau",
"d": -8126265600000,
"ed": -6043161600000
},
{
"label": "Thomas Hobbes",
"date": -12046579200000,
"end_date": -9153907200000
"lbl": "Thomas Hobbes",
"d": -12046579200000,
"ed": -9153907200000
},
{
"label": "John Locke",
"date": -10645430400000,
"end_date": -8368185600000
"lbl": "John Locke",
"d": -10645430400000,
"ed": -8368185600000
},
{
"label": "Montesquieu",
"date": -8865936000000,
"end_date": -6781276800000
"lbl": "Montesquieu",
"d": -8865936000000,
"ed": -6781276800000
},
{
"label": "Voltaire",
"date": -8681644800000,
"end_date": -6046012800000
"lbl": "Voltaire",
"d": -8681644800000,
"ed": -6046012800000
},
{
"label": "Karl Marx",
"date": -4785955200000,
"end_date": -2739225600000
"lbl": "Karl Marx",
"d": -4785955200000,
"ed": -2739225600000,
"img": "jpg",
"wid": "Q9061"
},
{
"label": "Friedrich Engels",
"date": -4704912000000,
"end_date": -2348092800000
"lbl": "Friedrich Engels",
"d": -4704912000000,
"ed": -2348092800000
},
{
"label": "John Rawls",
"date": -1541894400000,
"end_date": 1038096000000
"lbl": "John Rawls",
"d": -1541894400000,
"ed": 1038096000000,
"img": "jpg",
"wid": "Q172544"
},
{
"label": "Jeremy Bentham",
"date": -7001769600000,
"end_date": -4341340800000
"lbl": "Jeremy Bentham",
"d": -7001769600000,
"ed": -4341340800000
},
{
"label": "Michel Foucault",
"date": -1363737600000,
"end_date": 456969600000
"lbl": "Michel Foucault",
"d": -1363737600000,
"ed": 456969600000,
"img": "jpg",
"wid": "Q44272"
},
{
"label": "David Hume",
"date": -8162380800000,
"end_date": -6101568000000
"lbl": "David Hume",
"d": -8162380800000,
"ed": -6101568000000
},
{
"label": "Thomas Jefferson",
"date": -7154611200000,
"end_date": -4528310400000
"lbl": "Thomas Jefferson",
"d": -7154611200000,
"ed": -4528310400000
},
{
"label": "Immanuel Kant",
"date": -7753363200000,
"end_date": -5234889600000
"lbl": "Immanuel Kant",
"d": -7753363200000,
"ed": -5234889600000,
"img": "jpg",
"wid": "Q9312"
},
{
"label": "Peter Kropotkin",
"date": -4009737600000,
"end_date": -1543017600000
"lbl": "Peter Kropotkin",
"d": -4009737600000,
"ed": -1543017600000,
"img": "jpg",
"wid": "Q5752"
},
{
"label": "John Stuart Mill",
"date": -5163350400000,
"end_date": -3050006400000
"lbl": "John Stuart Mill",
"d": -5163350400000,
"ed": -3050006400000
}
]
{
"name": "timeline",
"version": "3.2.2",
"version": "3.3.0",
"description": "",

@@ -19,13 +19,13 @@ "main": "build/index.js",

"devDependencies": {
"@types/jest": "^23.3.1",
"jest": "^23.5.0",
"@types/jest": "^23.3.2",
"jest": "^23.6.0",
"pg": "^7.4.3",
"ts-jest": "^23.1.4",
"ts-loader": "^4.5.0",
"ts-jest": "^23.10.1",
"ts-loader": "^5.1.1",
"tslib": "^1.9.3",
"typescript": "^3.0.1",
"uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^4.17.1",
"typescript": "^3.0.3",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.19.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
"webpack-dev-server": "^3.1.8"
},

@@ -32,0 +32,0 @@ "jest": {

import props from "./models/props";
import { Milliseconds, ZOOM_DONE, CENTER_CHANGE_DONE } from "./constants";
import { Milliseconds, EventType } from "./constants";
import Band from "./models/band";

@@ -8,2 +8,4 @@ import Canvas from "./views/canvas";

import EventsBand from "./models/band/events";
import Popup from './views/popup';
import eventBus from './event-bus';

@@ -46,3 +48,3 @@ export type Multiplier = .25 | .5 | 1 | 2 | 4 | 8 | 16

private models: Band<MinimapBandConfig | EventsBandConfig>[] = []
private views: (Canvas | Debug)[] = []
private views: (Canvas | Debug | Popup)[] = []

@@ -55,3 +57,3 @@ private zoomMarker: number

registerView(view: Canvas | Debug) {
registerView(view: Canvas | Debug | Popup) {
this.views.push(view)

@@ -107,3 +109,3 @@ }

this.adjustMinimapBands()
document.dispatchEvent(new CustomEvent(ZOOM_DONE))
eventBus.dispatch(EventType.ZoomDone)
this.stop()

@@ -143,3 +145,3 @@ }

this.elapsedTimeTotal = 0
document.dispatchEvent(new CustomEvent(CENTER_CHANGE_DONE))
eventBus.dispatch(EventType.CenterChange)
}

@@ -215,2 +217,3 @@

playForward() {
eventBus.dispatch(EventType.Play)
this.direction = Direction.Forward

@@ -221,2 +224,3 @@ this.nextFrame()

playBackward() {
eventBus.dispatch(EventType.Play)
this.direction = Direction.Backward

@@ -227,2 +231,3 @@ this.nextFrame()

stop() {
eventBus.dispatch(EventType.Pause)
this.direction = Direction.Stop

@@ -229,0 +234,0 @@ this.activeBand = null

import animator, { Animator } from './animator'
import { CENTER_CHANGE_DONE, ZOOM_DONE } from './constants'
import props, { Props } from './models/props'
import View from './views';
import { EventType } from './constants';

@@ -12,3 +12,3 @@ export type OnChangeFunction = (props: Props, e?: Event) => void

constructor(private onChange: OnChangeFunction) {
constructor() {
document.addEventListener('keydown', (ev) => {

@@ -19,12 +19,32 @@ if (ev.keyCode === 189) props.controlBand.zoomOut() // -

if (this.onChange != null && typeof this.onChange === 'function') {
document.addEventListener(CENTER_CHANGE_DONE, this.handleChange)
document.addEventListener(ZOOM_DONE, this.handleChange)
}
// if (this.onChange != null && typeof this.onChange === 'function') {
// document.addEventListener(EventType.CENTER_CHANGE_DONE, this.handleChange)
// document.addEventListener(EventType.ZOOM_DONE, this.handleChange)
// }
}
private handleChange = () => {
this.onChange(props)
on(eventName: string, func: any) {
const nameMap = {
centerchange: EventType.CenterChange,
pause: EventType.Pause,
play: EventType.Play,
scrolldone: EventType.ScrollDone,
select: EventType.Select,
zoomdone: EventType.ZoomDone,
}
if (Object.keys(nameMap).indexOf(eventName) > -1) {
const eventType = (nameMap as any)[eventName]
let realFunc
if (eventType === EventType.CenterChange) realFunc = () => func(props)
else if (eventType === EventType.Select) realFunc = (ev: any) => func(ev.detail)
else realFunc = func
document.addEventListener(eventType, realFunc)
}
}
// private handleChange = () => {
// this.onChange(props)
// }
protected resize = () => {

@@ -31,0 +51,0 @@ props.resize()

import { RawEv3nt } from "./models/event";
export const EVENT_HEIGHT = 14
export const IMAGE_SIZES = [16, 32, 64, 128, 256]
// The height of an event. This is best seen by the height of an interval
export const EVENT_HEIGHT = 16
// Function for letter width is lineair: letter_width(event_height) = 7.5/40 * event_height + 3.5
// - font size = 72 => letter width = 17
// - font size = 48 => letter width = 12.5
// - font size = 32 => letter width = 9.5
export const LETTER_WIDTH = Math.round(EVENT_HEIGHT * .1875 + 3.5)
// Function for font size is lineair: font_size(event_height) = 5/16 * event_height + 6
// Taken from two points:
// - event height = 16 => font size = 11
// - event height = 32 => font size = 16
export const FONT_SIZE = Math.round(EVENT_HEIGHT * .3125 + 6)
// The vertical space between two events. This is best seen between two intervals
export const ROW_SPACING = Math.round(EVENT_HEIGHT / 3)
// The height (in px) of a row of events.
export const EVENT_ROW_HEIGHT = 16
export const EVENT_ROW_HEIGHT = EVENT_HEIGHT + ROW_SPACING
export const DATE_BAR_HEIGHT = EVENT_ROW_HEIGHT
export const RULER_LABELS_HEIGHT = 60
export const CENTER_CHANGE_DONE = 'CENTER_CHANGE_DONE'
export const ZOOM_DONE = 'ZOOM_DONE'
export const SCROLL_DONE = 'SCROLL_DONE'
// The bounding box is the box where the image must fit within.
// In this case the image should not be higher or wider than
// 2 times the event row height
export const IMAGE_BOUNDING_BOX = (EVENT_ROW_HEIGHT * 2) - ROW_SPACING * 2
export const IMAGE_BORDER_SIZE = Math.round(ROW_SPACING / 2)
export const IMAGE_SIZE = IMAGE_SIZES.reduce((prev, curr) => Math.abs(curr - IMAGE_BOUNDING_BOX) < Math.abs(prev - IMAGE_BOUNDING_BOX) ? curr : prev)
export enum EventType {
CenterChange = 'CenterChange',
ZoomDone = 'ZoomDone',
ScrollDone = 'ScrollDone',
Pause = 'Pause',
Play = 'Play',
Select = 'Select'
}
export const PIXELS_PER_LETTER = 8
export const DEFAULT_IMAGE_PATH = '/images'
export type Milliseconds = number

@@ -37,2 +67,2 @@ export type Grid = [Milliseconds, Milliseconds][][]

'rgba(0,128,0'
].map(color => (opacity: number = 1) => `${color},${opacity})`)
].map(color => (opacity: number = 1) => `${color},${opacity})`)

@@ -0,1 +1,3 @@

import { EventType } from './constants';
type EventListener = [string, EventListenerOrEventListenerObject, Target]

@@ -13,2 +15,10 @@ export type Target = Document | Window | HTMLElement

dispatch(eventType: EventType, payload?: any) {
const event = (payload != null) ?
new CustomEvent(eventType, { detail: payload }) :
new CustomEvent(eventType)
document.dispatchEvent(event)
}
register(type: string, listener: EventListenerOrEventListenerObject, target: Target = document) {

@@ -15,0 +25,0 @@ target.addEventListener(type, listener)

@@ -6,4 +6,4 @@ import props, { Props } from './models/props'

import { debounce, calcPixelsPerMillisecond } from './utils'
import { OrderedEvents, orderEvents } from './utils/events.worker'
import Api, { OnChangeFunction } from './api'
import { OrderedTimeline, orderEvents } from './utils/events.worker'
import Api from './api'
import EventsBandView from './views/band/events'

@@ -13,7 +13,9 @@ import Canvas from './views/canvas'

import Label from './views/label'
import Popup from './views/popup'
import MinimapBand from './models/band/minimap'
import EventsBand from './models/band/events'
import { formatDate } from './utils/dates';
import { RawEv3nt } from './models/event';
import { BandType } from './models/band';
import { formatDate } from './utils/dates'
import { Ev3ntLocation, RawEv3nt, Ev3nt, Voyage } from './models/event'
import { BandType } from './models/band'
import { EventType } from './constants';
// import Debug from './views/debug'

@@ -23,23 +25,27 @@

Config as TimelineConfig,
Props as TimelineProps,
Ev3nt,
Ev3ntLocation,
EventsBand,
EventType,
MinimapBand,
OrderedEvents,
OrderedTimeline,
Props as TimelineProps,
RawEv3nt,
calcPixelsPerMillisecond,
formatDate,
orderEvents,
RawEv3nt
Voyage,
}
export type OnSelectFunction = (e: RawEv3nt) => void
export type OnSelectFunction = (e: Ev3nt, band: EventsBand, props: Props) => void
// FIXME top row is visible when vertical scrolling (see Halicarnassus)
// FIX config without events
// TODO sort intervals first and than the points in time on top
// TODO use available vertical space (not fixed to EVENT_HEIGHT), see examples/100m
// TODO expose only API, put the Timeline and it's render in a separate view
// TODO add async loading of events
// TODO add API to constrain by spacial data
// TODO Add open ranges (ie: people still alive) and EDTF dates
// TODO Add open ranges (ie: people still alive)
// TODO If event granularity is equal to band granularity a point in time should be rendered as an interval (as unsure?)
// TODO flip PiT when on edge of timeline
// TODO make it possible to have only minimap bands (see examples/floods)
// TODO use available vertical space (not fixed to EVENT_HEIGHT), see examples/100m
// TODO add context menu for settings (which bands to show, toggle hor/ver scroll, change colors)

@@ -51,7 +57,13 @@ // TODO add info about how many events below and above current view (show after scroll and hide after x seconds)

// TODO make option for fixed minimap, no zoom when events band get's zoomed
// interface Options {
// config: Config,
// onSelect?: OnSelectFunction
// }
export default class Timeline extends Api {
private wrapper: HTMLElement
private wrapper: HTMLDivElement
private popup: Popup
constructor(protected config: Config, onChange?: OnChangeFunction, private onSelect?: OnSelectFunction) {
super(onChange)
// constructor(protected config: Config, onChange?: OnChangeFunction, private onSelect?: OnSelectFunction) {
constructor(config: Config) {
super()

@@ -61,2 +73,4 @@ props.init(config)

this.popup = new Popup(this.wrapper)
const debouncedResize = debounce(this.resize, 600)

@@ -66,2 +80,10 @@ window.addEventListener('resize', debouncedResize)

hidePopup() {
this.popup.hide()
}
showPopup(event: Ev3nt) {
this.popup.show(event)
}
private render() {

@@ -85,3 +107,3 @@ this.wrapper = createElement(

band.type === BandType.EventsBand ?
new EventsBandView(band as EventsBand, this.onSelect) :
new EventsBandView(band as EventsBand) :
new BandView(band)

@@ -88,0 +110,0 @@ )

@@ -6,6 +6,5 @@ import Band, { BandType } from '.'

import props from '../props'
import { RawEv3nt } from '../event'
import { orderEvents } from '../../utils/events.worker';
import { byDate } from '../../utils/dates';
import { calcPixelsPerMillisecond } from '../../utils';
import { Ev3nt } from '../event'
import { OrderedBand } from '../../utils/events.worker'
import { byDate } from '../../utils/dates'

@@ -21,5 +20,5 @@ export default class EventsBand extends Band<EventsBandConfig> {

events: RawEv3nt[] = []
events: Ev3nt[] = []
rowCount: number = 0
visibleEvents: RawEv3nt[] = []
visibleEvents: Ev3nt[] = []

@@ -50,11 +49,7 @@ private _offsetY: Pixels = 0

init() {
init(orderedBand: OrderedBand) {
super.init()
const pixelsPerMillisecond = calcPixelsPerMillisecond(props.viewportWidth, this.config.zoomLevel || 0, props.time)
const orderedEvents = this.config.orderedEvents == null ?
orderEvents(this.config.events, pixelsPerMillisecond) :
this.config.orderedEvents
this.events = orderedEvents.events
this.rowCount = orderedEvents.row_count
this.events = orderedBand.events
this.rowCount = orderedBand.rowCount

@@ -108,2 +103,3 @@ this.height = EVENT_ROW_HEIGHT * this.rowCount

// event.width (px) === event.time (ms)

@@ -113,5 +109,36 @@ event.width = Math.round((event.time) * this.pixelsPerMillisecond) // || [<- width ->] ||

// event.padding (px) === event.space (ms)
event.padding = Math.round((event.space) * this.pixelsPerMillisecond) // || [ event ]<- padding -> ||
event.uncertain_from_width = 0
if (event.dmin != null) {
let uncertain_from_to
if (event.d != null) {
uncertain_from_to = event.d
}
else if (event.ed != null) {
uncertain_from_to = event.ed
} else if (event.dmax != null) {
uncertain_from_to = event.dmin + (event.dmax - event.dmin) / 2
} else {
throw Error(['updateEvents', 'Width uncertain from is not definable', JSON.stringify(event)].join('\n'))
}
event.uncertain_from_width = (uncertain_from_to - event.dmin) * this.pixelsPerMillisecond
}
event.uncertain_to_width = 0
if (event.dmax != null) {
let uncertain_to_from
if (event.ed != null) {
uncertain_to_from = event.ed
}
else if (event.d != null) {
uncertain_to_from = event.d
} else if (event.dmin != null) {
uncertain_to_from = event.dmin + (event.dmax - event.dmin) / 2
} else {
throw Error(['updateEvents', 'Width uncertain to is not definable', JSON.stringify(event)].join('\n'))
}
event.uncertain_to_width = (event.dmax - uncertain_to_from) * this.pixelsPerMillisecond
}
event.top = this.top + this.availableHeight - ((event.row + 1) * EVENT_ROW_HEIGHT) + this.offsetY

@@ -130,3 +157,3 @@

getEventByCoordinates(x: Pixels, y: Pixels): RawEv3nt {
getEventByCoordinates(x: Pixels, y: Pixels): Ev3nt {
const timestamp = this.timestampAtPosition(x)

@@ -139,3 +166,3 @@

if (
!(e.from < timestamp && e.from + e.time + e.space > timestamp) ||
!(e.from < timestamp && e.screenTo > timestamp) ||
(e.row < this.lowestVisibleRow || e.row > this.highestVisibleRow)

@@ -150,2 +177,6 @@ ) return false

// orderEvents() {
// orderEvents(this.events, this.pixelsPerMillisecond)
// }
zoomIn() {

@@ -152,0 +183,0 @@ animator.zoomTo(this, this.zoomLevel + 1)

@@ -7,2 +7,3 @@ import { getGranularity, Granularity, subsequentDate } from '../../utils/dates'

import animator from '../../animator';
import { OrderedBand } from '../../utils/events.worker';

@@ -48,4 +49,4 @@ export enum BandType {

// The amount of pixels taken by one day. Metric used for calculating
// the x-position of an event or ruler on the timeline.
// The amount of pixels taken by one millisecond. Metric used to convert
// milliseconds to pixels and vice versa (px = ms / ppm and ms = px * ppm)
pixelsPerMillisecond: Pixels

@@ -90,2 +91,3 @@

this.availableHeight = this.visibleHeight - DATE_BAR_HEIGHT
if (this.availableHeight / this.visibleHeight < .666) this.availableHeight = this.visibleHeight * .666
this.visibleRowsCount = Math.floor(this.availableHeight / EVENT_ROW_HEIGHT) - 1

@@ -101,3 +103,3 @@ this.top = Math.round(this.config.topOffsetRatio * props.viewportHeight)

init() {
init(_orderedBand?: OrderedBand): void {
this.zoomLevel = this.config.zoomLevel

@@ -104,0 +106,0 @@ this.setVerticalProps()

@@ -81,12 +81,17 @@ import Band, { BandType } from '.'

if (event.from > to || event.to < from) continue
const x = this.positionAtTimestamp(event.from)
const y = this.maxRowCount - ((event.row + 2) * this.eventHeight)
const eventWidth = Math.round(event.time * this.pixelsPerMillisecond)
const eventLeft = this.positionAtTimestamp(event.date_min != null ? event.date_min : event.date)
const y = this.maxRowCount - ((event.row + 1) * this.eventHeight)
const width = eventWidth < 1 ? 1 : eventWidth
this.nextCtx.rect(eventLeft, y, width, this.eventHeight)
this.nextCtx.fillStyle = `rgb(190, 190, 190)`
this.nextCtx.fillRect(x, y, width, this.eventHeight)
if (event.img) {
this.nextCtx.fillStyle = `rgb(240, 240, 240)`
this.nextCtx.fillRect(x, y - this.eventHeight * 2, this.eventHeight * 2, this.eventHeight * 2)
}
}
})
this.nextCtx.fillStyle = `rgb(190, 190, 190)`
this.nextCtx.fill()
}

@@ -93,0 +98,0 @@

import { Ratio } from "../../constants"
import { OrderedEvents } from "../../utils/events.worker"
import { RawEv3nt } from "../event"
import { OrderedTimeline } from "../../utils/events.worker"
import { RawEv3nt, Ev3nt } from "../event"
import MinimapBand from "../band/minimap"

@@ -42,12 +42,16 @@ import EventsBand from "../band/events"

label?: string
orderedEvents?: OrderedEvents
orderedEvents?: OrderedTimeline
}
export default class Config {
bands: (EventsBand | MinimapBand)[]
center?: number
controlBand: EventsBand
controlBand?: EventsBand
bands: (EventsBand | MinimapBand)[]
imagePath?: string
parent?: Ev3nt
// The HTML element where the Timeline will be attached to. The element should be a

@@ -54,0 +58,0 @@ // block element with a width and height.

@@ -1,67 +0,103 @@

import { Milliseconds, Pixels } from '../constants';
import { Milliseconds, Pixels, PIXELS_PER_LETTER, EVENT_HEIGHT } from '../constants';
import { Granularity } from '../utils/dates';
// import Band from './band';
export enum ImageFileType {
NONE = 'none',
JPG = 'jpg',
SVG = 'svg',
GIF = 'gif',
PNG = 'png',
}
class Point {
type: "Point"
coordinates: [number, number]
}
export class Ev3ntLocation {
coor: Point
coor4326?: [number, number]
dmin?: Milliseconds
dmin_g?: Granularity
d?: Milliseconds
d_g?: Granularity
ed?: Milliseconds
ed_g?: Granularity
dmax?: Milliseconds
dmax_g?: Granularity
}
export class Voyage {
d: Milliseconds
ed: Milliseconds
route: string
sp?: Point // Start point
ep?: Point // End point
}
export class RawEv3nt {
date: Milliseconds
date_granularity?: Granularity = Granularity.DAY
date_min?: Milliseconds
date_min_granularity?: Granularity
description?: string
end_date?: Milliseconds
end_date_granularity?: Granularity
end_date_max?: Milliseconds
end_date_max_granularity?: Granularity
id?: string
label?: string
row?: number
wikidata_identifier?: string
class: string[]
d: Milliseconds
d_g: Granularity
dmax: Milliseconds
dmax_g: Granularity
dmin: Milliseconds
dmin_g: Granularity
dsc: string
ed: Milliseconds
ed_g: Granularity
id: string
img: ImageFileType
lbl: string
locs: Ev3ntLocation[]
voyages: Voyage[]
wid: string
}
export class Ev3nt extends RawEv3nt {
from: Milliseconds
to: Milliseconds
screenTo: Milliseconds
tags: string[]
locations: any[]
// The length of time an event took.
// A Point in Time has time = 0
// For an interval, if something takes 1 year, time = 31536000000
// For an interval, if the event takes 1 year, time = 31536000000
time?: Milliseconds
// The space an event needs for display
// Point in Time = label width + padding
// Interval = padding
space?: Milliseconds
row: number
/* runtime */
// Same as from, to, screenTo and time as in: they all just need the pixelsPerMS var to be calc'd?
left?: Pixels
padding?: Pixels
top?: Pixels
width?: Pixels
uncertain_from_width?: Pixels
uncertain_to_width?: Pixels
color?: string
// textWidth?: Pixels
}
image?: HTMLImageElement
/* runtime */
// class Ev3nt extends RawEv3nt {
// left: Pixels
// width: Pixels
constructor(event: RawEv3nt, pixelsPerMillisecond?: Pixels) {
super()
// constructor(rawEvent: RawEv3nt, band: Band) {
// super()
for (const key in event) {
if ((event as any)[key] != null) (this as any)[key] = (event as any)[key]
}
// Object.keys(rawEvent).forEach(k => this[k] = rawEvent[k])
if (this.lbl == null) this.lbl = 'NO LABEL'
if (this.id == null) this.id = 'id_' + crypto.getRandomValues(new Uint8Array(4)).join('_')
// this.left = band.positionAtDate(this.date)
// this.width = this.isInterval() ?
// (this.end_date - this.date) * band.pixelsPerMillisecond :
// 0
// this.row = rawEvent.row
// // this.flip = this.left + Constants.EVENT_MIN_SPACE > visibleDomain.width
// }
this.from = this.dmin || this.d
this.to = this.dmax || this.ed
if (this.to == null) this.to = this.from
this.time = this.to - this.from
// isInterval(): boolean {
// return this.end_date != null
// }
// }
// export default Ev3nt;
if (pixelsPerMillisecond != null) {
const paddingRight = Math.round(EVENT_HEIGHT * 2 / pixelsPerMillisecond)
let space = ((this.lbl.length * PIXELS_PER_LETTER) / pixelsPerMillisecond) + paddingRight
space = space > this.time ? space - this.time : 0
this.screenTo = Math.round(this.from + this.time + space)
}
}
}

@@ -1,7 +0,9 @@

import { CENTER_CHANGE_DONE, Milliseconds, Pixels } from "../constants"
import { Milliseconds, Pixels, DEFAULT_IMAGE_PATH, EventType } from "../constants"
import Config from "./config"
import MinimapBand from "./band/minimap"
import { debounce } from "../utils"
import EventsBand from "./band/events";
import { BandType } from './band';
import EventsBand from "./band/events"
import { BandType } from './band'
import { RawEv3nt } from './event';
import { orderEvents } from '..';
import eventBus from '../event-bus';

@@ -19,2 +21,4 @@ function onEventsBand (band: MinimapBand | EventsBand): band is EventsBand {

parent: RawEv3nt
bands: (EventsBand | MinimapBand)[]

@@ -26,2 +30,4 @@ eventsBands: EventsBand[]

imagePath: string
// Timestamp of the start date of the timeline

@@ -50,3 +56,3 @@ from: Milliseconds

else this._center = n
this.centerChangeDone()
eventBus.dispatch(EventType.CenterChange)
}

@@ -62,28 +68,32 @@

private centerChangeDone = debounce(() => {
document.dispatchEvent(new CustomEvent(CENTER_CHANGE_DONE))
}, 300)
init(config: Config) {
if (config.rootElement == null) console.error('[init] No rootElement found')
this.imagePath = config.imagePath != null ? config.imagePath : DEFAULT_IMAGE_PATH
this.rootElement = config.rootElement
this.dimensions = this.rootElement
const [froms, tos] = config.bands.reduce((prev, curr) => {
if (curr.type === BandType.MinimapBand) return prev
const band = curr as EventsBand
const events = band.config.orderedEvents == null ? band.config.events : band.config.orderedEvents.events
prev[0].push(events[0].date_min || events[0].date)
prev[1].push(events.reduce((prev2, curr2) => {
return Math.max(prev2, curr2.end_date || -Infinity, curr2.end_date_max || -Infinity)
}, -Infinity))
return prev
}, [[], []])
this.bands = config.bands
this.eventsBands = this.bands.filter(onEventsBand)
this.minimapBands = this.bands.filter(onMinimapBand)
this.controlBand = config.controlBand != null ? config.controlBand : this.eventsBands[0]
this.from = Math.min(...froms)
this.to = Math.max(...tos)
const t0 = performance.now()
const options = {
bands: this.eventsBands
.map(band => ({
events: band.config.events,
zoomLevel: band.config.zoomLevel
})),
parent: config.parent,
viewportWidth: this.viewportWidth
}
const orderResult = orderEvents(options)
this.parent = orderResult.parent
this.from = orderResult.from
this.to = orderResult.to
this.time = orderResult.time
const t1 = performance.now();
console.log('Performance: ', `${t1 - t0}ms\n[from] ${new Date(this.from).toUTCString()}\n[ to ] ${new Date(this.to).toUTCString()}`)
this.time = this.to - this.from
this.center = (config.center != null) ?

@@ -93,8 +103,7 @@ config.center :

this.bands = config.bands
this.eventsBands = this.bands.filter(onEventsBand)
this.minimapBands = this.bands.filter(onMinimapBand)
this.controlBand = config.controlBand != null ? config.controlBand : this.eventsBands[0]
for (const [index, band] of this.eventsBands.entries()) {
band.init(orderResult.bands[index])
}
for (const band of this.bands) {
for (const band of this.minimapBands) {
band.init()

@@ -101,0 +110,0 @@ }

@@ -15,3 +15,3 @@ import { Milliseconds, Pixels } from "../constants"

WEEK = "WEEK",
MONTH = "MONHT",
MONTH = "MONTH",
YEAR = "YEAR",

@@ -100,3 +100,3 @@ YEAR_5 = "YEAR_5", /* 5 YEARS */

if (pixelsPerMillisecond > 8e-11) return Granularity.DECADE_5
if (pixelsPerMillisecond > 1e-11) return Granularity.CENTURY
if (pixelsPerMillisecond > 1.5e-11) return Granularity.CENTURY
if (pixelsPerMillisecond > 5e-12) return Granularity.CENTURY_5

@@ -198,9 +198,9 @@ return Granularity.MILLENIUM

export function byDate(a: RawEv3nt, b: RawEv3nt) {
const aFrom = a.date_min != null ? a.date_min : a.date
const bFrom = b.date_min != null ? b.date_min : b.date
const aFrom = a.dmin != null ? a.dmin : a.d
const bFrom = b.dmin != null ? b.dmin : b.d
if (aFrom < bFrom) return -1
if (aFrom > bFrom) return 1
const aTo = a.end_date_max != null ? a.end_date_max : a.end_date
const bTo = b.end_date_max != null ? b.end_date_max : b.end_date
const aTo = a.dmax != null ? a.dmax : a.ed
const bTo = b.dmax != null ? b.dmax : b.ed
if (aTo < bTo) return -1

@@ -207,0 +207,0 @@ if (aTo > bTo) return 1

@@ -1,90 +0,123 @@

import { Milliseconds, Grid, EVENT_HEIGHT } from "../constants"
import { RawEv3nt } from "../models/event";
import { Milliseconds, EVENT_ROW_HEIGHT, Pixels } from "../constants"
import { Ev3nt, RawEv3nt } from "../models/event"
import { calcPixelsPerMillisecond } from './index'
export class OrderedEvents {
events: RawEv3nt[] = []
// grid: Grid = []
row_count: number = 0
interface InputBand {
events: RawEv3nt[]
zoomLevel: number
}
export interface OrderedBand {
events: Ev3nt[]
pixelsPerMillisecond?: Pixels
rowCount: number
zoomLevel: number
}
interface Options {
parent?: RawEv3nt,
bands: InputBand[]
viewportWidth: Pixels,
}
const pixelsPerLetter = 8
export class OrderedTimeline {
bands: OrderedBand[]
from: Milliseconds
parent: Ev3nt
time: Milliseconds
to: Milliseconds
}
export function orderEvents(events: RawEv3nt[], pixelsPerMillisecond: Milliseconds): OrderedEvents {
if (!events.length) return new OrderedEvents()
export function orderEvents(options: Options): OrderedTimeline {
if (options.bands == null || !options.bands.length) return new OrderedTimeline()
/** Keep a count the number of rows. It's returned to the main thread to construct the events bar and indicators */
let rowCount: number = 0
let from = options.bands.reduce((prev, curr) => {
const firstEvent = curr.events[0]
return Math.min(prev, firstEvent.dmin || Infinity, firstEvent.d || Infinity)
}, Infinity)
/**
* The grid exists of rows of cells. A cell is an event defined by it's left position and width:
* cell = [left, width], row = [cell, cell, etc], grid = [row, row, etc]
*/
const grid: Grid = []
let to = options.bands.reduce((prev, curr) => {
const highest = curr.events.reduce((prev2, curr2) => {
return Math.max(prev2, curr2.d || - Infinity, curr2.ed || -Infinity, curr2.dmax || -Infinity)
}, -Infinity)
return Math.max(highest, prev)
}, -Infinity)
const paddingRight = EVENT_HEIGHT * 2 / pixelsPerMillisecond
let parent
if (options.parent != null) {
parent = new Ev3nt(options.parent) as Ev3nt
from = Math.min(from, parent.dmin || Infinity, parent.d || Infinity)
to = Math.max(to, parent.ed || -Infinity, parent.dmax || -Infinity)
}
const addRow = (event: RawEv3nt): RawEv3nt => {
// Create a variable to hold the row to find
let row: number
const time = to - from
function processBand(band: InputBand) {
const pixelsPerMillisecond = calcPixelsPerMillisecond(options.viewportWidth, band.zoomLevel, time)
if (event.label == null) event.label = 'NO LABEL'
event.from = event.date_min || event.date
event.to = event.end_date_max || event.end_date
if (event.to == null) event.to = event.from
event.time = event.to == null ? 0 : event.to - event.from
// If the event is a Point in Time, we use the label width to determine the width
event.space = 0
if (!event.time) {
if (event.label == null) event.label = 'NO LABEL'
event.space = ((event.label.length * pixelsPerLetter) / pixelsPerMillisecond) + paddingRight
const rows: number[] = [-Infinity]
const imageSize: Milliseconds = Math.round(EVENT_ROW_HEIGHT * 2 / pixelsPerMillisecond)
function rowHasSpace(row: number, imageFrom: Milliseconds) {
return (rows[row + 1] == null || rows[row + 1] < imageFrom) && (rows[row + 2] == null || rows[row + 2] < imageFrom)
}
// Search the grid for a row which has space for the current event
let rowIterator = 0
while (row == null && rowIterator < grid.length) {
let cellIterator = 0
let hasSpace = true
function addRow(rawEvent: RawEv3nt): Ev3nt {
const event = new Ev3nt(rawEvent, pixelsPerMillisecond)
while (hasSpace && cellIterator < grid[rowIterator].length) {
// If event.to is smaller than cell.from, the rest of the cells
// will also be "after" `event` and we don't have to check the rest,
// so break
if (event.to < grid[rowIterator][cellIterator][0]) break;
let row: number
if (event.img) {
// A point in time with an image starts half an image earlier than the point (in time)
const imageFrom = event.time ? event.from : event.from - imageSize / 2
const imageTo = event.time ? event.from + imageSize : event.from + imageSize / 2
// Check if event.from is greater than cell.to, otherwise
// there is overlap and hence no space
hasSpace = event.from > grid[rowIterator][cellIterator][1]
cellIterator++
}
row = rows.findIndex(r => imageFrom > r)
if (hasSpace) {
grid[rowIterator].push([event.from, event.from + event.time + event.space])
row = rowIterator
}
if (row > -1) {
let hasSpace = false
while (!hasSpace) {
hasSpace = rowHasSpace(row, imageFrom)
if (hasSpace) break
row = rows.findIndex((r, i) => i > row && imageFrom > r)
if (row === -1) hasSpace = true
}
}
rowIterator++
}
if (row === -1) {
row = rows.push(event.screenTo) - 1
rows.push(imageTo)
rows.push(imageTo)
} else {
rows[row] = event.screenTo
rows[row + 1] = imageTo
rows[row + 2] = imageTo
}
} else {
row = rows.findIndex(r => event.from > r)
// If row is undefined, it means there is no space in the current grid and
// we need to add an extra row to the grid
if (row == null) row = grid.push([[event.from, event.from + event.time + event.space]]) - 1
if (row === -1) {
row = rows.push(event.screenTo) - 1
} else {
rows[row] = event.screenTo
}
}
// Increment the row count if necessary
if (row > rowCount) rowCount = row
event.row = row
// Add the found row to the event
event.row = row
return event
}
return event
return {
events: band.events.map(addRow),
zoomLevel: band.zoomLevel,
pixelsPerMillisecond,
rowCount: rows.length,
}
}
events = events.map(addRow)
return {
events,
// from,
// to,
// grid,
row_count: grid.length
bands: options.bands.map(processBand),
from,
parent,
time,
to,
}

@@ -91,0 +124,0 @@ }

@@ -1,2 +0,2 @@

import { RawEv3nt } from "../models/event";
import { Ev3nt } from "../models/event";
import { Milliseconds, Ratio, Pixels } from "../constants";

@@ -12,10 +12,2 @@

// export const onVisible = (from, to) => (e: RawEv3nt) => {
// const eventFrom = e.date_min || e.date
// let eventTo = e.end_date_max || e.end_date
// if (eventTo == null) eventTo = eventFrom
// if (eventFrom == null && eventTo == null) return false
// return !(eventTo < from || eventFrom > to)
// }
/**

@@ -67,6 +59,7 @@ * Convert a zoom level to a visible ratio

const d = new Date(ts)
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`
return d.toUTCString()
// return `${d.getUTCFullYear()}-${d.getUTClMonth() + 1}-${d.getDate()}`
}
export function logEvent(event: RawEv3nt, ...rest: string[]) {
console.log(event.label, event, event.left, formatDate(event.from), formatDate(event.to), rest)
export function logEvent(event: Ev3nt, ...rest: string[]) {
console.log(event.lbl, event, formatDate(event.from), formatDate(event.to), rest)
}
import BandView from './index'
import eventBus from '../../event-bus'
import EventsBand from '../../models/band/events'
import { logEvent } from '../../utils'
import { OnSelectFunction } from '../../index'
import { EventType } from '../../constants';
// import { logEvent } from '../../utils'
// import { OnSelectFunction } from '../../index'
// import props from '../../models/props';
export default class EventsBandView extends BandView {
constructor(public band: EventsBand, private select: OnSelectFunction) {
constructor(public band: EventsBand) {
super(band)

@@ -30,6 +32,4 @@ }

const event = this.band.getEventByCoordinates(ev.clientX, ev.clientY)
if (event && this.select) {
this.select(event)
logEvent(event)
}
eventBus.dispatch(EventType.Select, event)
}

@@ -36,0 +36,0 @@

@@ -7,3 +7,3 @@ import Band, { BandType } from '../../models/band'

import View from '../index'
import { Milliseconds, Pixels, SCROLL_DONE } from '../../constants'
import { Milliseconds, Pixels, EventType } from '../../constants'
import { MinimapBandConfig, EventsBandConfig } from '../../models/config'

@@ -114,3 +114,3 @@ import EventsBand from '../../models/band/events'

if (this.lastDragInterval > 200 || significantDrag) {
document.dispatchEvent(new CustomEvent(SCROLL_DONE))
eventBus.dispatch(EventType.ScrollDone)
}

@@ -117,0 +117,0 @@ }

import createElement from '../../utils/create-element'
import props from '../../models/props'
import { EVENT_HEIGHT, PIXELS_PER_LETTER, DATE_BAR_HEIGHT } from '../../constants'
import { EVENT_HEIGHT, FONT_SIZE, IMAGE_BOUNDING_BOX, IMAGE_SIZE, IMAGE_BORDER_SIZE, EventType } from '../../constants'
import MinimapBand from '../../models/band/minimap'

@@ -9,3 +9,4 @@ import animator from '../../animator'

import drawRulers from './rulers'
import { BandType } from '../../models/band';
import eventBus from '../../event-bus'
import { Ev3nt } from '../../models/event'

@@ -26,4 +27,67 @@ /**

animator.registerView(this)
eventBus.register(EventType.ZoomDone, this.onAnimationDone)
eventBus.register(EventType.ScrollDone, this.onAnimationDone)
}
private async updateImages() {
for (const band of props.eventsBands) {
for (const event of band.visibleEvents) {
if (event.img == null) continue
if (event.image == null) {
const path = `${props.imagePath}/${event.wid}__${IMAGE_SIZE}.${event.img}`
event.image = new Image()
const onImgLoad = this.onImgLoad(event)
event.image.addEventListener('load', onImgLoad)
event.image.addEventListener('error', onImgLoad)
event.image.src = path
} else {
this.drawImage(event)
}
}
}
}
private onImgLoad = (event: Ev3nt) => {
const callback = (ev: Event) => {
event.image.removeEventListener('load', callback)
event.image.removeEventListener('error', callback)
if (ev.type === 'error') {
event.image = null
return
}
if (event.image.width > event.image.height) {
// First set the height, so we can use the old width
event.image.height = Math.round(event.image.height * (IMAGE_BOUNDING_BOX / event.image.width))
event.image.width = IMAGE_BOUNDING_BOX
} else {
// First set the width, so we can use the old height
event.image.width = Math.round(event.image.width * (IMAGE_BOUNDING_BOX / event.image.height))
event.image.height = IMAGE_BOUNDING_BOX
}
this.drawImage(event)
}
return callback
}
// Border uses fillRect instead of strokeRect, because strokeRect gives a different color. Don't ask me why.
private drawImage(event: Ev3nt) {
if (event.image == null || !event.image.complete || !event.image.naturalWidth) return
const x = event.time ? event.left : event.left - (event.image.width / 2) - IMAGE_BORDER_SIZE
const y = event.top - event.image.height
this.ctx.fillStyle = event.color
this.ctx.fillRect(x, y - IMAGE_BORDER_SIZE * 2, event.image.width + IMAGE_BORDER_SIZE * 2, event.image.height + IMAGE_BORDER_SIZE * 2)
this.ctx.drawImage(event.image, x + IMAGE_BORDER_SIZE, y - IMAGE_BORDER_SIZE, event.image.width, event.image.height)
}
private onAnimationDone = () => {
// this.updateImages()
}
render() {

@@ -66,11 +130,12 @@ this.canvas = createElement('canvas', 'main', [

update = () => {
props.bands
.forEach(band => {
if (band.type === BandType.EventsBand)
this.drawEventsBand(band as EventsBand)
else
this.drawMinimapBand(band as MinimapBand)
})
for (const band of props.eventsBands) {
this.drawEventsBand(band)
}
for (const band of props.minimapBands) {
this.drawMinimapBand(band)
}
this.drawIndicators()
this.updateImages()
}

@@ -93,4 +158,30 @@

} else {
let left = event.left
let width = event.width
if (event.uncertain_from_width > 1) {
const gradient = this.ctx.createLinearGradient(event.left, 0, event.left + event.uncertain_from_width, 0)
gradient.addColorStop(0, 'white')
gradient.addColorStop(1, event.color)
this.ctx.fillStyle = gradient
this.ctx.fillRect(event.left, event.top, event.uncertain_from_width, EVENT_HEIGHT)
left = event.left + event.uncertain_from_width
width -= event.uncertain_from_width
}
if (event.uncertain_to_width > 1) {
width -= event.uncertain_to_width
const gradientLeft = left + width
const gradientWidth = gradientLeft + event.uncertain_to_width
const gradient = this.ctx.createLinearGradient(gradientLeft, 0, gradientWidth, 0)
gradient.addColorStop(0, event.color)
gradient.addColorStop(1, 'white')
this.ctx.fillStyle = gradient
this.ctx.fillRect(gradientLeft, event.top, event.uncertain_to_width, EVENT_HEIGHT)
}
this.ctx.fillStyle = event.color
this.ctx.fillRect(event.left, event.top, event.width, EVENT_HEIGHT)
this.ctx.fillRect(left, event.top, width, EVENT_HEIGHT)
}

@@ -103,19 +194,16 @@ }

private drawEventsText(band: EventsBand) {
this.ctx.font = '11px sans-serif'
this.ctx.font = `${FONT_SIZE}px sans-serif`
this.ctx.fillStyle = `rgb(40, 40, 40)`
for (const event of band.visibleEvents) {
let eventWidth = event.time === 0 ? event.padding : event.width
let eventLeft = event.left
if (event.left < 0 && event.time !== 0) {
eventWidth = event.width + event.left
eventLeft = 0
eventLeft = -event.uncertain_from_width
}
let eventLabelLength = event.label.length * PIXELS_PER_LETTER
if (eventLabelLength <= eventWidth) {
const paddingLeft = event.time ? 3 : 8
this.ctx.fillText(event.label, eventLeft + paddingLeft, event.top + EVENT_HEIGHT - 3)
}
const paddingLeft = event.time ? FONT_SIZE / 3 : FONT_SIZE / 1.2
const x = eventLeft + paddingLeft + event.uncertain_from_width
const y = event.top + FONT_SIZE + ((EVENT_HEIGHT - FONT_SIZE) / 2) - 2
this.ctx.fillText(event.lbl, Math.round(x), Math.round(y))
}

@@ -159,3 +247,3 @@ }

// Cover the DATE_BAR
this.indicatorsCtx.rect(leftIndicatorRightX, indicatorTOP + band.visibleHeight - DATE_BAR_HEIGHT, rightIndicatorLeftX - leftIndicatorRightX, DATE_BAR_HEIGHT)
this.indicatorsCtx.rect(leftIndicatorRightX, indicatorTOP + band.availableHeight, rightIndicatorLeftX - leftIndicatorRightX, band.visibleHeight - band.availableHeight)
}

@@ -162,0 +250,0 @@

import MinimapBand from "../../models/band/minimap"
import EventsBand from "../../models/band/events"
import props from "../../models/props"
import { Milliseconds } from "../../constants"
import { Milliseconds, FONT_SIZE } from "../../constants"
import { labelBody, Granularity } from "../../utils/dates"
const smallFont: string = "11px sans-serif"
const bigFont: string = "13px sans-serif"
function isSpecialRuler(date: Milliseconds, band: MinimapBand | EventsBand) {

@@ -28,3 +25,2 @@ if (band.granularity === Granularity.CENTURY && new Date(date).getUTCFullYear() % 1000 === 0) return true

// let date = findClosestRulerDate(band.from, band.granularity)
let date = band.nextDate(band.from)

@@ -47,3 +43,3 @@ const y = band.config.topOffsetRatio * props.viewportHeight

ctx.beginPath()
ctx.font = smallFont
ctx.font = `${FONT_SIZE}px sans-serif`
// Normal ruler font fill

@@ -61,3 +57,3 @@ ctx.fillStyle = `rgb(205, 205, 205)`

ctx.beginPath()
ctx.font = bigFont
ctx.font = `${FONT_SIZE * 1.2}px sans-serif`
// Special ruler font fill

@@ -64,0 +60,0 @@ ctx.fillStyle = `rgb(120, 120, 120)`

@@ -8,2 +8,3 @@ # Z-index

4 red line
10 popup
10 debug

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc