import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'vsp-number-stepper',
template: `
@if (unit) {
{{ unit }}
}
`,
})
export class VspNumberStepper {
@Input() value = 0;
@Output() valueChange = new EventEmitter();
@Input() min?: number;
@Input() max?: number;
@Input() step = 1;
@Input() unit?: string;
@Input() disabled = false;
@Input() id?: string;
set(v: number): void {
let n = v;
if (this.min != null && n < this.min) n = this.min;
if (this.max != null && n > this.max) n = this.max;
this.value = n;
this.valueChange.emit(n);
}
onInput(e: Event): void {
const raw = (e.target as HTMLInputElement).value;
const n = Number(raw);
if (raw !== '' && raw !== '-' && Number.isFinite(n)) {
this.value = n;
this.valueChange.emit(n);
}
}
}
@Component({
selector: 'vsp-copy-button',
template: ``,
})
export class VspCopyButton {
@Input() text = '';
@Input() label = 'Copy';
@Input() size = 'sm';
done = false;
get cls(): string {
return 'btn btn-ghost' + (this.size === 'sm' ? ' btn-sm' : '');
}
async copy(): Promise {
try {
await navigator.clipboard?.writeText(this.text);
} catch {
/* clipboard unavailable */
}
this.done = true;
setTimeout(() => (this.done = false), 1400);
}
}
@Component({
selector: 'vsp-inline-edit',
template: `@if (editing) {
} @else {
{{
value || placeholder
}}
}`,
})
export class VspInlineEdit {
@Input() value = '';
@Input() placeholder = 'Empty';
@Output() save = new EventEmitter();
editing = false;
draft = '';
start(): void {
this.draft = this.value;
this.editing = true;
}
commit(): void {
this.editing = false;
if (this.draft !== this.value) this.save.emit(this.draft);
}
cancel(): void {
this.draft = this.value;
this.editing = false;
}
}