@stimulus-library/controllers
Version:
A library of useful controllers for Stimulus
85 lines (84 loc) • 2.49 kB
JavaScript
import { formatDuration } from "date-fns/formatDuration";
import { intervalToDuration } from "date-fns/intervalToDuration";
import { toDate } from "date-fns/toDate";
import { BaseController } from "@stimulus-library/utilities";
import { useInterval } from "@stimulus-library/mixins";
export class DurationController extends BaseController {
get _format() {
const keys = [
"years",
"months",
"weeks",
"days",
"hours",
];
if (this._minutes) {
keys.push("minutes");
}
if (this._seconds) {
keys.push("seconds");
}
return keys;
}
get _output() {
let { years, months, weeks, days, hours, minutes, seconds } = this._duration;
years || (years = 0);
months || (months = 0);
weeks || (weeks = 0);
days || (days = 0);
hours || (hours = 0);
minutes || (minutes = 0);
seconds || (seconds = 0);
const largeDenominators = [years, months, weeks, days, hours];
if (!this._minutes && !this._seconds && largeDenominators.every((x) => x === 0)) {
minutes = minutes + seconds / 60.0;
return `${(minutes / 60).toFixed(1)} hours`;
}
return formatDuration(this._duration, { format: this._format, delimiter: ", " });
}
get _seconds() {
return this.hasSecondsValue ? this.secondsValue : true;
}
get _minutes() {
return this.hasMinutesValue ? this.minutesValue : true;
}
get _timestamp() {
if (this.hasTimestampValue) {
return toDate(this.timestampValue * 1000);
}
else {
throw new Error("Expected `timestampValue` to be present");
}
}
get _duration() {
return intervalToDuration({ start: new Date(), end: this._timestamp });
}
get _tickInterval() {
if (this._seconds) {
return 1000;
}
else if (this._minutes) {
return 15000;
}
else {
return 120000;
}
}
connect() {
this._clearInterval = useInterval(this, this._update, this._tickInterval);
this._update();
}
_update() {
try {
this.el.innerHTML = this._output;
}
catch {
this._clearInterval();
}
}
}
DurationController.values = {
timestamp: Number,
minutes: Boolean,
seconds: Boolean,
};