UNPKG

@obliczeniowo/elementary

Version:
283 lines (277 loc) 16 kB
import * as i0 from '@angular/core'; import { input, EventEmitter, effect, HostBinding, HostListener, Output, Input, Component, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import * as i1 from '@obliczeniowo/elementary/icons'; import { Point2D } from '@obliczeniowo/elementary/classes'; class HexButtonComponent { icons; elementRef; /** x pos can be css style like calc(50% + 10px) */ x = input('0'); /** y pos can be css style like calc(50% + 10px) */ y = input('0'); /** icon name */ icon = input(); /** */ scale = input(1); /** */ disabled; click = new EventEmitter(); mouseOver() { this.hover = true; } mouseLeave() { this.hover = false; } get transform() { return `translate(${this.x()}, ${this.y()}) scale(${this.scale()})`; } ; hover = false; clicked() { if (!this.disabled) { this.click.emit(); } } _ray = 24; offset = 4; _iconSvg; _iconWidth = 0; get iconWidth() { return this._iconWidth; } k = 0.5; iconScale = 1; get ray() { return this._ray; } _outside = ''; get outside() { return this._outside; } _inside = ''; get inside() { return this._inside; } constructor(icons, elementRef) { this.icons = icons; this.elementRef = elementRef; this.recalc(); effect(() => { const iconName = this.icon(); if (iconName) { this.icons.getIcon(iconName).subscribe(iconSvg => { this._iconSvg = iconSvg; const icon = this.elementRef.nativeElement.querySelector('g.icon'); if (icon && this._iconSvg) { while (icon.firstChild) { icon.removeChild(icon.firstChild); } icon.innerHTML = this._iconSvg.innerHTML; const viewBox = (this._iconSvg.getAttribute('viewBox') || '').split(' ').map(v => +v); if (viewBox.length) { this._iconWidth = viewBox[2] - viewBox[0]; this.iconScale = this.k * 2 * this.ray / (this._iconWidth || 1); } } }); } }); } recalc() { const n = 6; const offset = Math.PI / n; const points = (ray) => new Array(n).fill(0).map((_, index) => { const angle = index * Math.PI / (n / 2) + offset; return [ ray * Math.sin(angle), ray * Math.cos(angle) ].join(','); }).join(' '); this._outside = points(this.ray); this._inside = points(this.ray - this.offset); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexButtonComponent, deps: [{ token: i1.IconResourceService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.4", type: HexButtonComponent, isStandalone: false, selector: "g[obl-hex-button]", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: false, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { click: "click" }, host: { listeners: { "mouseenter": "mouseOver()", "mouseleave": "mouseLeave()" }, properties: { "class.disabled": "this.disabled", "style.transform": "this.transform", "class.hover": "this.hover" } }, ngImport: i0, template: "<svg:polygon\n [attr.points]=\"outside\"\n class=\"clickable\"\n (click)=\"clicked()\"\n></svg:polygon>\n\n<svg:polygon\n [attr.points]=\"inside\"\n class=\"clickable\"\n></svg:polygon>\n\n<svg:g\n class=\"icon clickable\"\n [style.transform]=\"\n 'translate(' +\n (-ray * k) +\n 'px, ' +\n (-ray * k) +\n 'px)'\n + 'scale(' +\n iconScale +\n ')'\n \"\n></svg:g>\n", styles: ["g{fill:var(--default-hex-button-border-color)}path,polygon{stroke:var(--default-hex-button-border-color);stroke-width:2px;fill:var(--default-background-color)}:host{--obl-default-icon-color: var(--default-hex-button-border-color)}:host:hover path,:host:hover polygon{stroke:var(--default-hex-button-hover-border-color);fill:var(--default-hover-color)}:host.disabled path,:host.disabled polygon{stroke:var(--default-disabled-color)}:host.disabled g{fill:var(--default-disabled-color)}\n"] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexButtonComponent, decorators: [{ type: Component, args: [{ selector: 'g[obl-hex-button]', standalone: false, template: "<svg:polygon\n [attr.points]=\"outside\"\n class=\"clickable\"\n (click)=\"clicked()\"\n></svg:polygon>\n\n<svg:polygon\n [attr.points]=\"inside\"\n class=\"clickable\"\n></svg:polygon>\n\n<svg:g\n class=\"icon clickable\"\n [style.transform]=\"\n 'translate(' +\n (-ray * k) +\n 'px, ' +\n (-ray * k) +\n 'px)'\n + 'scale(' +\n iconScale +\n ')'\n \"\n></svg:g>\n", styles: ["g{fill:var(--default-hex-button-border-color)}path,polygon{stroke:var(--default-hex-button-border-color);stroke-width:2px;fill:var(--default-background-color)}:host{--obl-default-icon-color: var(--default-hex-button-border-color)}:host:hover path,:host:hover polygon{stroke:var(--default-hex-button-hover-border-color);fill:var(--default-hover-color)}:host.disabled path,:host.disabled polygon{stroke:var(--default-disabled-color)}:host.disabled g{fill:var(--default-disabled-color)}\n"] }] }], ctorParameters: () => [{ type: i1.IconResourceService }, { type: i0.ElementRef }], propDecorators: { disabled: [{ type: HostBinding, args: ['class.disabled'] }, { type: Input }], click: [{ type: Output }], mouseOver: [{ type: HostListener, args: ['mouseenter'] }], mouseLeave: [{ type: HostListener, args: ['mouseleave'] }], transform: [{ type: HostBinding, args: ['style.transform'] }], hover: [{ type: HostBinding, args: ['class.hover'] }] } }); class HexExtendedButtonComponent { change; opened = false; ray = 24; elements = []; translate = 'translate(50%, 50%)'; _width = 0; get width() { return this.opened && this._width || this.ray * 2; } _height = 0; get height() { return this.opened && this._height || this.ray * 2; } animatedWidth = this.ray * 2; animatedHeight = this.ray * 2; h = Math.sqrt(3) / 2; rayTranslate = new Point2D(0, this.h * 2); move = new Point2D(1.5, -this.h); time; constructor(change) { this.change = change; } ngOnChanges(changes) { if (changes.elements) { this.recalc(); } } ngnDestroy() { if (this.time) { clearInterval(this.time); } } clicked(element) { if (!element.disabled) { this.toggleOpen(); element.clicked(); } } levelCount(level) { return level === 0 && 1 || level * 6; } toggleOpen() { if (this.time) { clearInterval(this.time); } this.elements.forEach(e => e.animation = this.opened && 1 || 0); this.opened = !this.opened; this.animated(); } maxRounds(elements = this.elements || []) { let sum = 1; let countRound = 0; while (sum < elements.length + 1) { sum += this.levelCount(countRound); countRound++; } return countRound; } recalc() { const maxRounds = this.maxRounds(); if (maxRounds === 0) { return; } const bray = this.ray + 3; this._width = (1.5 * (maxRounds - 1) + 1) * bray * 2 + 6; this._height = (this.h * (maxRounds - 1) * 2 + this.h) * bray * 2 + 6; let index = 0; for (let dRay = 1; dRay < maxRounds; dRay++) { for (let dAngle = 0; dAngle < 6; dAngle++) { const angle = Math.PI / 3 * dAngle; const ray = this.rayTranslate.multiply(bray * dRay).rotate(-angle); for (let dMove = 0; dMove < dRay; dMove++) { const move = this.move.multiply(bray * dMove).rotate(-angle); if (index < this.elements.length) { const t = ray.add(move); t.x = Math.floor(t.x); t.y = Math.floor(t.y); this.elements[index].pos = t; this.elements[index].animation = this.opened && 1 || 0; index++; } } } } } animated() { if (!this.elements.length) { return; } this.time = setInterval(() => { const t = this.elements.findIndex(e => (e?.animation || 0) < 1); if (t > -1) { for (let i = t; i < this.elements.length; i++) { const element = this.elements[i]; const zero = !this.elements[i].animation; element.animation = Math.min((element?.animation || 0) + 0.08, 1); if (zero) { break; } } const rounds = this.maxRounds(this.elements.filter(e => e.animation) || []); const bray = this.ray + 3; this.animatedWidth = Math.min(this.animatedWidth + this.ray * 0.5, (1.5 * (rounds - 1) + 1) * bray * 2 + 6); this.animatedHeight = Math.min(this.animatedHeight + this.ray * 0.5, (this.h * (rounds - 1) * 2 + this.h) * bray * 2 + 6); } else if (this.animatedWidth > this.ray * 2 && !this.opened) { this.animatedWidth = Math.max(this.animatedWidth * 0.9, this.ray * 2); this.animatedHeight = Math.max(this.animatedHeight * 0.9, this.ray * 2); } else { clearInterval(this.time); this.time = undefined; } this.change.detectChanges(); }, 10); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexExtendedButtonComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: HexExtendedButtonComponent, isStandalone: false, selector: "obl-hex-extended-button", inputs: { elements: "elements" }, host: { properties: { "style.width.px": "this.animatedWidth", "style.height.px": "this.animatedHeight" } }, usesOnChanges: true, ngImport: i0, template: "<svg\n [attr.width]=\"width\"\n [attr.height]=\"height\"\n [attr.viewBox]=\"'0 0 ' + width + ' ' + height\"\n [style.minWidth.px]=\"width\"\n [style.minHeight.px]=\"height\"\n>\n @if (!opened) {\n <g\n obl-hex-button\n [icon]=\"'add'\"\n x=\"50%\"\n y=\"50%\"\n (click)=\"toggleOpen()\"\n ></g>\n }\n\n @if (opened) {\n <g\n obl-hex-button\n [icon]=\"'subtract'\"\n x=\"50%\"\n y=\"50%\"\n (click)=\"toggleOpen()\"\n class=\"central\"\n ></g>\n }\n\n @if (opened) {\n @for (element of elements; track $index) {\n <g>\n <g\n obl-hex-button\n [icon]=\"element.icon\"\n [x]=\"'calc(50% + ' + (element?.pos?.x || 0) + 'px)'\"\n [y]=\"'calc(50% + ' + (element?.pos?.y || 0) + 'px)'\"\n [scale]=\"element.animation || 0\"\n [disabled]=\"element.disabled\"\n (click)=\"clicked(element)\"\n ></g>\n </g>\n }\n }\n</svg>\n", styles: [".central{--default-hex-button-border-color: #00aeff}:host{display:flex;overflow:hidden;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "component", type: HexButtonComponent, selector: "g[obl-hex-button]", inputs: ["x", "y", "icon", "scale", "disabled"], outputs: ["click"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexExtendedButtonComponent, decorators: [{ type: Component, args: [{ selector: 'obl-hex-extended-button', standalone: false, template: "<svg\n [attr.width]=\"width\"\n [attr.height]=\"height\"\n [attr.viewBox]=\"'0 0 ' + width + ' ' + height\"\n [style.minWidth.px]=\"width\"\n [style.minHeight.px]=\"height\"\n>\n @if (!opened) {\n <g\n obl-hex-button\n [icon]=\"'add'\"\n x=\"50%\"\n y=\"50%\"\n (click)=\"toggleOpen()\"\n ></g>\n }\n\n @if (opened) {\n <g\n obl-hex-button\n [icon]=\"'subtract'\"\n x=\"50%\"\n y=\"50%\"\n (click)=\"toggleOpen()\"\n class=\"central\"\n ></g>\n }\n\n @if (opened) {\n @for (element of elements; track $index) {\n <g>\n <g\n obl-hex-button\n [icon]=\"element.icon\"\n [x]=\"'calc(50% + ' + (element?.pos?.x || 0) + 'px)'\"\n [y]=\"'calc(50% + ' + (element?.pos?.y || 0) + 'px)'\"\n [scale]=\"element.animation || 0\"\n [disabled]=\"element.disabled\"\n (click)=\"clicked(element)\"\n ></g>\n </g>\n }\n }\n</svg>\n", styles: [".central{--default-hex-button-border-color: #00aeff}:host{display:flex;overflow:hidden;justify-content:center;align-items:center}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { elements: [{ type: Input }], animatedWidth: [{ type: HostBinding, args: ['style.width.px'] }], animatedHeight: [{ type: HostBinding, args: ['style.height.px'] }] } }); class HexButtonModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: HexButtonModule, declarations: [HexButtonComponent, HexExtendedButtonComponent], imports: [CommonModule], exports: [HexExtendedButtonComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexButtonModule, imports: [CommonModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: HexButtonModule, decorators: [{ type: NgModule, args: [{ declarations: [ HexButtonComponent, HexExtendedButtonComponent ], imports: [ CommonModule ], exports: [ HexExtendedButtonComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { HexButtonModule, HexExtendedButtonComponent }; //# sourceMappingURL=obliczeniowo-elementary-hex-button.mjs.map