@obliczeniowo/elementary
Version:
Library made in Angular version 20
274 lines (268 loc) • 17.8 kB
JavaScript
import * as i1 from '@obliczeniowo/elementary/buttons';
import { ButtonsModule } from '@obliczeniowo/elementary/buttons';
import * as i0 from '@angular/core';
import { input, EventEmitter, effect, HostBinding, ViewChild, Output, Input, Component, Pipe, NgModule } from '@angular/core';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import { ElementaryMath } from '@obliczeniowo/elementary/math';
import { Point2D, Dates } from '@obliczeniowo/elementary/classes';
import { DrawingSvgInterface } from '@obliczeniowo/elementary/drawing';
/**
* Basic usage of component is to display time as HH:mm:ss format combined with a little dynamic svg
* element that display clock pointing time given in input time as Date object or [h, m, s]
*
* You can set 'interactive' mode by 'display' input set { interactive: true, ... }
* In this mode you can change time by clicking on modifying area fields, this will emit
* new date every time you click on this areas
*
* To have easy way of manipulate time size of clock-time must be at least 150px
*
* In interactive mode you can add own controls buttons:
*
* @example
*
* <obl-clock-time [display]="{ time: true; interactive: true }" [column]="true" #clock>
* <button (click)="setDate(clock)">OK</button>
* <obl-clock-time>
*/
class ClockTimeComponent {
renderer;
/** size of clock */
size = input(30);
/** switch on/off displaying time text */
display = input({
seconds: true,
time: true
});
/** font size */
fontSize = input();
/** if display time is set to tru this one will control if clock and time text is displayed in one row or in column */
column = false;
/**
* set time by Date object or table of [hours, minutes, seconds]
*/
date = input(new Date(), {
transform: (value) => {
let date;
if (value instanceof Date) {
date = value;
}
else {
date = new Date();
date.setHours(value[0]);
date.setMinutes(value[1]);
date.setSeconds(value[2]);
}
const h = date.getHours();
const m = date.getMinutes();
const s = date.getSeconds();
this.hAngle = ((h % 12) + m / 60 + s / 3600) * Math.PI / 6;
this.mAngle = (m + s / 60) * Math.PI / 30;
this.sAngle = s * Math.PI / 30;
this.pmAm = date.getHours() / 12 > 1;
return date;
}
});
/** Emit when date is changed */
changed = new EventEmitter();
svg;
get noTime() {
return !this.display().time;
}
interactiveTime;
dc;
hRay = 2;
mRay = 3;
sRay = 3.5;
hAngle = 0;
mAngle = 0;
sAngle = 0;
pmAm = false;
mouse = new Point2D();
constructor(renderer) {
this.renderer = renderer;
effect(() => {
this.draw();
});
}
ngAfterViewInit() {
if (this.svg) {
this.dc = new DrawingSvgInterface(this.svg.nativeElement, this.renderer);
this.draw();
}
}
switchPmAm() {
this.pmAm = !this.pmAm;
this.date().setHours(this.date().getHours() + (this.pmAm ? -12 : 12));
if (this.interactiveTime) {
this.interactiveTime = new Date(this.date());
}
}
clicked(event) {
if (!this.display().interactive) {
return;
}
if (this.interactiveTime) {
this.date().setSeconds(this.interactiveTime.getSeconds());
this.date().setMinutes(this.interactiveTime.getMinutes());
this.date().setHours(this.interactiveTime.getHours());
this.changed.emit(new Date(this.date()));
}
}
mouseMove(event) {
if (!this.display().interactive) {
return;
}
const scale = (this.getBrowserName() === 'firefox' ? 10 : 11) / this.size();
const box = this.dc.svgContainer.getBoundingClientRect();
this.mouse = new Point2D((event.x - box.left) * scale, (event.y - box.top) * scale).subtract(new Point2D(5, 5));
const { hRay, mRay, mouse } = this;
const len = mouse.sickLength();
const angle = mouse.angle();
const date = new Date(this.date());
if (len < hRay * hRay) {
date.setHours(Math.round(ElementaryMath.fmod(angle + Math.PI * 2.5, 2 * Math.PI) / (2 * Math.PI) * 11 + (this.pmAm ? 12 : 0)) % (12 + (this.pmAm ? 12 : 0)));
}
else if (len < mRay * mRay) {
date.setMinutes(Math.round((angle + Math.PI) / (2 * Math.PI) * 60 + 45) % 60);
}
this.interactiveTime = date;
this.draw();
}
draw(dc = this.dc) {
if (dc) {
const center = new Point2D(5, 5);
dc.clear();
dc.drawCircle(center, 4.5, 0.7, 'var(--default-text-color)');
if (this.display().interactive) {
dc.drawCircle(center, this.mRay, 0, undefined, undefined, {
svgOnly: {
classes: ['minutes-area']
}
});
dc.drawCircle(center, this.hRay, 0, undefined, undefined, {
svgOnly: {
classes: ['hours-area']
}
});
}
dc.drawPolyline([
center.add(new Point2D(this.hRay * Math.sin(this.hAngle), -this.hRay * Math.cos(this.hAngle))),
center,
center.add(new Point2D(this.mRay * Math.sin(this.mAngle), -this.mRay * Math.cos(this.mAngle)))
], 0.5, 'var(--default-text-color)');
if (this.display().interactive) {
if (this.interactiveTime && !Dates.equalToTimeLevel(this.interactiveTime, this.date())) {
const h = this.interactiveTime.getHours();
const m = this.interactiveTime.getMinutes();
const hAngle = ((h % 12) + m / 60) * Math.PI / 6;
const mAngle = m * Math.PI / 30;
dc.drawPolyline([
center.add(new Point2D(this.hRay * Math.sin(hAngle), -this.hRay * Math.cos(hAngle))),
center,
center.add(new Point2D(this.mRay * Math.sin(mAngle), -this.mRay * Math.cos(mAngle)))
], 0.5, 'var(--obl-clock-time-set-pointer, gray)');
}
}
if (this.size() > 99) {
/** draw seconds pointer */
if (this.display().seconds) {
dc.drawLine(center, center.add(new Point2D(this.sRay * Math.sin(this.sAngle), -this.sRay * Math.cos(this.sAngle))), 0.25, 'var(--default-text-color)');
}
/** draw scale */
for (let i = 0; i < 12; i++) {
const angle = i * Math.PI / 6;
dc.drawLine(center.add(new Point2D(this.sRay * Math.sin(angle), -this.sRay * Math.cos(angle))), center.add(new Point2D(1.1 * this.sRay * Math.sin(angle), -(this.sRay * 1.1) * Math.cos(angle))), 0.1, 'var(--default-text-color)');
}
}
}
}
getBrowserName() {
const agent = window.navigator.userAgent.toLowerCase();
switch (true) {
case agent.includes('edge'):
return 'edge';
case agent.includes('opr') && !!window.opr:
return 'opera';
case agent.includes('chrome') && !!window.chrome:
return 'chrome';
case agent.includes('trident'):
return 'ie';
case agent.includes('firefox'):
return 'firefox';
case agent.includes('safari'):
return 'safari';
default:
return 'other';
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: ClockTimeComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: ClockTimeComponent, isStandalone: false, selector: "obl-clock-time", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, fontSize: { classPropertyName: "fontSize", publicName: "fontSize", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: false, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, host: { properties: { "class.column": "this.column", "class.no-time": "this.noTime" } }, viewQueries: [{ propertyName: "svg", first: true, predicate: ["svg"], descendants: true }], ngImport: i0, template: "<svg\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n viewBox=\"0 0 10 10\"\n (mousemove)=\"mouseMove($event)\"\n (click)=\"clicked($event)\"\n #svg\n></svg>\n\n@if (display().time) {\n <span\n [style.font-size.px]=\"fontSize() || size() * 0.6\"\n [style.line-height.px]=\"fontSize() || size() * 0.6\"\n >\n {{ (interactiveTime ?? date()) | date : (display().seconds ? 'HH:mm:ss' : 'HH:mm') }}\n <ng-content></ng-content>\n </span>\n}\n\n@if (display().interactive) {\n <div class=\"actions\">\n <button oblButton (click)=\"switchPmAm()\"> {{ pmAm && 'PM' || 'AM' }} </button>\n </div>\n}\n", styles: [":root{--obl-primary: #00afaf;--obl-secondary: #008caf;--default-border-color: gray;--default-focus-color: gray;--default-border-outline-color: #080808;--default-disabled-color: gray;--default-background-color: white;--default-hover-color: #eeeeee;--obl-default-error-color: red;--obl-dialog-background: #d3d3d3;--default-radio-color: black;--disabled-color: gray;--default-hex-button-border-color: #008caf;--default-hex-button-hover-border-color: #00afaf;--select-item-background-color: #e4e4e4;--select-item-text-color: #5a5a5a;--default-text-color: black;--obl-default-button-text-color: black;--obl-default-icon-color: black;--equalizer-background-bar-color: #575656;--equalizer-value-bar-color: #e6e6e6;--diagram-3d-background-color: black;--slider-value-container-color: gray;--slider-value-color: #d1d1d1;--slider-hover-value-color: white;--digit-fill-color: #cccccc;--digit-lighted-color: black;--horizontal-progress-bar-value-color: #504f4f;--horizontal-progress-bar-background-pattern-color: #dddddd;--horizontal-progress-bar-value-pattern-color: #b3b3b3;--horizontal-progress-bar-border-rect-color: #cccccc;--temperature-text-color: black;--temperature-path-stroke-color: black;--post-diagram-scale-line-color: #c8c8c8;--volume-channel-secondary-color: gray;--volume-channel-primary-color: #f2f2f2;--arch-progress-secondary-color: #eeeeee;--obl-linear-diagram-greed-color: gray;--obl-rating-selected-color: gold;--obl-rating-color: #cccccc}:host{display:flex;align-items:center;position:relative}:host svg{margin-right:10px}:host svg ::ng-deep .hours-area,:host svg ::ng-deep .minutes-area{opacity:.5}:host svg ::ng-deep .minutes-area{fill:var(--obl-secondary)}:host svg ::ng-deep .hours-area{fill:var(--obl-primary)}:host.no-time svg{margin-right:0}:host.column{flex-direction:column}:host.column svg{margin-right:0;margin-bottom:10px}:host circle{stroke:var(--default-text-color)!important}.actions{position:absolute;right:5px;top:5px}.actions button{font-size:12px;padding:5px;border-radius:10px}\n"], dependencies: [{ kind: "directive", type: i1.ButtonDirective, selector: "oblButton, [oblButton]", inputs: ["oblButton", "icon", "blockWhenLoading", "loading", "toggle", "selected", "link", "target"], exportAs: ["oblButton"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: ClockTimeComponent, decorators: [{
type: Component,
args: [{ selector: 'obl-clock-time', standalone: false, template: "<svg\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n viewBox=\"0 0 10 10\"\n (mousemove)=\"mouseMove($event)\"\n (click)=\"clicked($event)\"\n #svg\n></svg>\n\n@if (display().time) {\n <span\n [style.font-size.px]=\"fontSize() || size() * 0.6\"\n [style.line-height.px]=\"fontSize() || size() * 0.6\"\n >\n {{ (interactiveTime ?? date()) | date : (display().seconds ? 'HH:mm:ss' : 'HH:mm') }}\n <ng-content></ng-content>\n </span>\n}\n\n@if (display().interactive) {\n <div class=\"actions\">\n <button oblButton (click)=\"switchPmAm()\"> {{ pmAm && 'PM' || 'AM' }} </button>\n </div>\n}\n", styles: [":root{--obl-primary: #00afaf;--obl-secondary: #008caf;--default-border-color: gray;--default-focus-color: gray;--default-border-outline-color: #080808;--default-disabled-color: gray;--default-background-color: white;--default-hover-color: #eeeeee;--obl-default-error-color: red;--obl-dialog-background: #d3d3d3;--default-radio-color: black;--disabled-color: gray;--default-hex-button-border-color: #008caf;--default-hex-button-hover-border-color: #00afaf;--select-item-background-color: #e4e4e4;--select-item-text-color: #5a5a5a;--default-text-color: black;--obl-default-button-text-color: black;--obl-default-icon-color: black;--equalizer-background-bar-color: #575656;--equalizer-value-bar-color: #e6e6e6;--diagram-3d-background-color: black;--slider-value-container-color: gray;--slider-value-color: #d1d1d1;--slider-hover-value-color: white;--digit-fill-color: #cccccc;--digit-lighted-color: black;--horizontal-progress-bar-value-color: #504f4f;--horizontal-progress-bar-background-pattern-color: #dddddd;--horizontal-progress-bar-value-pattern-color: #b3b3b3;--horizontal-progress-bar-border-rect-color: #cccccc;--temperature-text-color: black;--temperature-path-stroke-color: black;--post-diagram-scale-line-color: #c8c8c8;--volume-channel-secondary-color: gray;--volume-channel-primary-color: #f2f2f2;--arch-progress-secondary-color: #eeeeee;--obl-linear-diagram-greed-color: gray;--obl-rating-selected-color: gold;--obl-rating-color: #cccccc}:host{display:flex;align-items:center;position:relative}:host svg{margin-right:10px}:host svg ::ng-deep .hours-area,:host svg ::ng-deep .minutes-area{opacity:.5}:host svg ::ng-deep .minutes-area{fill:var(--obl-secondary)}:host svg ::ng-deep .hours-area{fill:var(--obl-primary)}:host.no-time svg{margin-right:0}:host.column{flex-direction:column}:host.column svg{margin-right:0;margin-bottom:10px}:host circle{stroke:var(--default-text-color)!important}.actions{position:absolute;right:5px;top:5px}.actions button{font-size:12px;padding:5px;border-radius:10px}\n"] }]
}], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { column: [{
type: Input
}, {
type: HostBinding,
args: ['class.column']
}], changed: [{
type: Output
}], svg: [{
type: ViewChild,
args: ['svg']
}], noTime: [{
type: HostBinding,
args: ['class.no-time']
}] } });
class TimePipe {
transform(time, ...args) {
time = Math.ceil(time);
const hours = Math.floor(time / 3600);
const minutes = Math.floor(time / 60) % 60;
const seconds = time % 60;
return (hours ? hours + ':' : '') + `0${minutes}`.slice(-2) + ':' + `0${seconds}`.slice(-2);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TimePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: TimePipe, isStandalone: true, name: "time" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TimePipe, decorators: [{
type: Pipe,
args: [{
name: 'time',
standalone: true
}]
}] });
class TimeModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TimeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: TimeModule, declarations: [ClockTimeComponent], imports: [CommonModule,
ButtonsModule], exports: [ClockTimeComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TimeModule, providers: [
TimePipe
], imports: [CommonModule,
ButtonsModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TimeModule, decorators: [{
type: NgModule,
args: [{
declarations: [
ClockTimeComponent,
],
providers: [
TimePipe
],
imports: [
CommonModule,
ButtonsModule
],
exports: [
ClockTimeComponent,
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { ClockTimeComponent, TimeModule, TimePipe };
//# sourceMappingURL=obliczeniowo-elementary-time.mjs.map