@obliczeniowo/elementary
Version:
Library made in Angular version 20
283 lines (277 loc) • 16 kB
JavaScript
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