@nent/core
Version:
273 lines (272 loc) • 7.3 kB
JavaScript
/*!
* NENT 2022
*/
import { Component, Element, Event, h, Host, Method, Prop, State, Build, } from '@stencil/core';
import { eventBus } from '../../services/actions';
import { debugIf } from '../../services/common';
import { ROUTE_EVENTS } from '../n-views/services/interfaces';
import { routingState } from '../n-views/services/state';
import { FrameTimer } from './services/timer';
/**
* This element creates a timer for the presentation
* element to use in place of a video, to time actions
* or manipulate HTML by time.
*
* @system presentation
*/
export class PresentationTimer {
constructor() {
this.elapsed = 0;
/**
* To debug timed elements, set this value to true.
*/
this.debug = false;
/**
* Duration before the timer stops and raises
* the ended event (seconds). 0 = never
*/
this.duration = 0;
/**
* Interval in milliseconds to request
* between the getAnimationFrame. This
* affects the precision.
*/
this.interval = 200;
/**
* Display elapsed seconds
*/
this.display = false;
/**
* If set, disables auto-starting the timer
* on render. This will be removed if in a view,
* when the view is activated or when the start
* method is called.
*/
this.deferLoad = false;
this.now = Build.isTesting || Build.isServer
? () => new Date().getTime()
: () => performance.now();
}
get currentRoute() {
var _a;
const parent = this.el.closest('n-view-prompt') || this.el.closest('n-view');
if (parent)
return parent.route;
return ((_a = routingState.router) === null || _a === void 0 ? void 0 : _a.exactRoute) || null;
}
/**
* Begin the timer. This is called automatically
* by the presentation element.
*/
async begin() {
this.timer.begin();
}
/**
* Stop the timer.
*/
async stop() {
this.timer.stop();
}
componentWillLoad() {
this.timer = new FrameTimer(window, this.interval, this.duration, () => this.now(), () => {
this.elapsed = this.timer.currentTime.elapsedSeconds;
}, this.debug);
}
render() {
return h(Host, null, this.display ? this.elapsed : null);
}
componentDidLoad() {
var _a, _b;
this.ready.emit(true);
if (this.currentRoute) {
debugIf(this.debug, `n-presentation-timer: syncing to route ${this.currentRoute.path}`);
if ((_b = (_a = this.currentRoute) === null || _a === void 0 ? void 0 : _a.match) === null || _b === void 0 ? void 0 : _b.isExact) {
this.timer.begin();
}
this.navigationSubscription = eventBus.on(ROUTE_EVENTS.RouteChanged, () => {
var _a, _b;
if ((_b = (_a = this.currentRoute) === null || _a === void 0 ? void 0 : _a.match) === null || _b === void 0 ? void 0 : _b.isExact) {
this.timer.begin();
}
else {
this.timer.stop();
}
});
}
else {
this.timer.begin();
}
}
disconnectedCallback() {
var _a;
this.timer.destroy();
(_a = this.navigationSubscription) === null || _a === void 0 ? void 0 : _a.call(this);
}
static get is() { return "n-presentation-timer"; }
static get properties() { return {
"debug": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "To debug timed elements, set this value to true."
},
"attribute": "debug",
"reflect": false,
"defaultValue": "false"
},
"timer": {
"type": "unknown",
"mutable": true,
"complexType": {
"original": "ITimer",
"resolved": "ITimer",
"references": {
"ITimer": {
"location": "import",
"path": "../n-presentation/services/interfaces"
}
}
},
"required": true,
"optional": false,
"docs": {
"tags": [],
"text": "Normalized timer."
}
},
"duration": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Duration before the timer stops and raises\nthe ended event (seconds). 0 = never"
},
"attribute": "duration",
"reflect": false,
"defaultValue": "0"
},
"interval": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Interval in milliseconds to request\nbetween the getAnimationFrame. This\naffects the precision."
},
"attribute": "interval",
"reflect": false,
"defaultValue": "200"
},
"display": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Display elapsed seconds"
},
"attribute": "display",
"reflect": false,
"defaultValue": "false"
},
"deferLoad": {
"type": "boolean",
"mutable": true,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "If set, disables auto-starting the timer\non render. This will be removed if in a view,\nwhen the view is activated or when the start\nmethod is called."
},
"attribute": "defer-load",
"reflect": false,
"defaultValue": "false"
}
}; }
static get states() { return {
"elapsed": {}
}; }
static get events() { return [{
"method": "ready",
"name": "ready",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Ready event letting the presentation layer know it can\nbegin."
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}]; }
static get methods() { return {
"begin": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "Begin the timer. This is called automatically\nby the presentation element.",
"tags": []
}
},
"stop": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "Stop the timer.",
"tags": []
}
}
}; }
static get elementRef() { return "el"; }
}