@koalarx/ui
Version:
Koala UI is a modern and accessible component library designed to speed up interface development in Angular projects. With simple integration and clear documentation, you can easily build robust and visually appealing applications.
366 lines (358 loc) • 18.5 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, ViewContainerRef, input, effect, Directive, ElementRef, output, ApplicationRef, EnvironmentInjector, booleanAttribute, createComponent, inputBinding } from '@angular/core';
import { NgxMaskPipe } from 'ngx-mask';
import { AppConfig } from '@koalarx/ui/core/config';
import { KlNumber } from '@koalarx/utils/KlNumber';
import { Loader } from '@koalarx/ui/core/components/loader';
class HookChange {
viewContainerRef = inject(ViewContainerRef);
hookChange = input.required(...(ngDevMode ? [{ debugName: "hookChange" }] : []));
constructor() {
effect(() => {
this.hookChange();
const onChange = this.viewContainerRef.element.nativeElement.onchange;
if (onChange) {
onChange();
}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HookChange, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: HookChange, isStandalone: true, selector: "[hookChange]", inputs: { hookChange: { classPropertyName: "hookChange", publicName: "hookChange", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HookChange, decorators: [{
type: Directive,
args: [{ selector: '[hookChange]' }]
}], ctorParameters: () => [], propDecorators: { hookChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "hookChange", required: true }] }] } });
class InputMask {
ngxMask = inject(NgxMaskPipe);
elementRef = inject((ElementRef));
get currentValue() {
return this.input.value;
}
get input() {
return this.elementRef.nativeElement;
}
mask = input.required(...(ngDevMode ? [{ debugName: "mask" }] : []));
constructor() {
effect(() => {
const mask = this.mask();
if (mask) {
this.elementRef.nativeElement.addEventListener('keyup', () => this.applyMask(mask));
this.elementRef.nativeElement.addEventListener('keypress', () => this.applyMask(mask));
this.elementRef.nativeElement.addEventListener('keydown', () => this.applyMask(mask));
setTimeout(() => this.applyMask(mask), 1);
}
});
}
applyMask(mask) {
this.setValue(this.ngxMask.transform(this.currentValue, mask));
}
setValue(value) {
this.input.value = value;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: InputMask, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: InputMask, isStandalone: true, selector: "input[mask]", inputs: { mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: true, transformFunction: null } }, providers: [NgxMaskPipe], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: InputMask, decorators: [{
type: Directive,
args: [{ selector: 'input[mask]', providers: [NgxMaskPipe] }]
}], ctorParameters: () => [], propDecorators: { mask: [{ type: i0.Input, args: [{ isSignal: true, alias: "mask", required: true }] }] } });
class InputCurrencyMask {
elementRef = inject((ElementRef));
appConfig = inject(AppConfig);
writedValue = 0.0;
decimalCount = input(2, ...(ngDevMode ? [{ debugName: "decimalCount" }] : []));
currencyValue = output();
get decimalFormatConfig() {
let prefix = '$';
let thousandSeparator = ',';
let decimalSeparator = '.';
switch (this.appConfig.language) {
case 'en':
prefix = '$';
break;
case 'ptBr':
thousandSeparator = '.';
decimalSeparator = ',';
prefix = 'R$';
break;
}
return {
prefix,
thousandSeparator,
decimalSeparator,
};
}
maskCoin(value) {
const { prefix, thousandSeparator, decimalSeparator } = this.decimalFormatConfig;
return new KlNumber(value).maskCoin(prefix, thousandSeparator, decimalSeparator, this.decimalCount());
}
unmaskCoin(value) {
const { prefix, thousandSeparator, decimalSeparator } = this.decimalFormatConfig;
return parseFloat(value
.replace(prefix, '')
.replace(new RegExp(`\\${thousandSeparator}`, 'g'), '')
.replace(decimalSeparator, '.')
.trim());
}
applyMask() {
this.setValue(this.maskCoin(this.writedValue));
}
get currentValue() {
return this.input.value;
}
setValue(value) {
this.input.value = value;
}
get input() {
return this.elementRef.nativeElement;
}
onFocus = () => {
this.putInputCaretOnTheEnd();
};
onKeyUp = (event) => {
if (/\d/.test(event.key) || event.key === 'Backspace') {
this.updateWritedValue(event.key, event.key === 'Backspace');
if (isNaN(this.writedValue)) {
this.writedValue = 0;
}
this.applyMask();
}
else if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
this.putInputCaretOnTheEnd();
}
};
onKeyPress = (event) => {
event.preventDefault();
};
onKeyDown = (event) => {
if (event.key === 'Backspace') {
event.preventDefault();
}
};
onPaste = (event) => {
event.preventDefault();
if (!event.clipboardData) {
return;
}
const pastedValue = event.clipboardData.getData('Text');
let unmaskedValue = parseFloat(pastedValue);
if (pastedValue.includes(',')) {
unmaskedValue = this.unmaskCoin(event.clipboardData.getData('Text'));
}
this.setValue(this.maskCoin(unmaskedValue));
};
onReset = () => {
this.writedValue = 0.0;
this.applyMask();
};
onChange = () => {
if (this.writedValue !== 0) {
return;
}
let unmaskedValue = +this.currentValue;
if (isNaN(unmaskedValue)) {
unmaskedValue = this.unmaskCoin(this.currentValue);
}
this.writedValue = unmaskedValue;
this.applyMask();
};
putInputCaretOnTheEnd() {
setTimeout(() => this.input.setSelectionRange(this.currentValue.length, this.currentValue.length));
}
updateWritedValue(key, backspace = false) {
let decimal = '';
for (let i = 0; i < this.decimalCount(); i++) {
decimal += '0';
}
if (backspace) {
const match = (this.writedValue / 10)
.toString()
.match(new RegExp(`^-?\\d+(?:\\.\\d{0,${this.decimalCount()}})?`));
if (match) {
this.writedValue = parseFloat(match[0]);
}
}
const currentValue = Math.round(this.writedValue * +`1${decimal}`);
this.writedValue = parseFloat(`${currentValue}${key}`) / +`1${decimal}`;
this.currencyValue.emit(this.writedValue);
}
ngOnDestroy() {
const inputElement = this.elementRef.nativeElement;
inputElement.removeEventListener('focus', this.onFocus);
inputElement.removeEventListener('keyup', this.onKeyUp);
inputElement.removeEventListener('keypress', this.onKeyPress);
inputElement.removeEventListener('keydown', this.onKeyDown);
inputElement.removeEventListener('paste', this.onPaste);
inputElement.removeEventListener('reset', this.onReset);
}
ngOnInit() {
this.writedValue = this.unmaskCoin(this.currentValue);
this.input.style.textAlign = 'right';
const inputElement = this.elementRef.nativeElement;
inputElement.addEventListener('focus', this.onFocus);
inputElement.addEventListener('keyup', this.onKeyUp);
inputElement.addEventListener('keypress', this.onKeyPress);
inputElement.addEventListener('keydown', this.onKeyDown);
inputElement.addEventListener('paste', this.onPaste);
inputElement.addEventListener('reset', this.onReset);
inputElement.onchange = this.onChange;
setTimeout(() => this.applyMask());
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: InputCurrencyMask, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: InputCurrencyMask, isStandalone: true, selector: "input[currencyMask]", inputs: { decimalCount: { classPropertyName: "decimalCount", publicName: "decimalCount", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { currencyValue: "currencyValue" }, providers: [NgxMaskPipe], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: InputCurrencyMask, decorators: [{
type: Directive,
args: [{
selector: 'input[currencyMask]',
providers: [NgxMaskPipe],
}]
}], propDecorators: { decimalCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "decimalCount", required: false }] }], currencyValue: [{ type: i0.Output, args: ["currencyValue"] }] } });
class Tooltip {
elementRef = inject((ElementRef));
tooltip = input.required(...(ngDevMode ? [{ debugName: "tooltip" }] : []));
tooltipPosition = input('top', ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : []));
constructor() {
effect(() => {
const element = this.elementRef.nativeElement;
const tooltipText = this.tooltip();
element.classList.add('tooltip');
element.dataset['tip'] = tooltipText;
switch (this.tooltipPosition()) {
case 'top':
element.classList.add('tooltip-top');
break;
case 'bottom':
element.classList.add('tooltip-bottom');
break;
case 'left':
element.classList.add('tooltip-left');
break;
case 'right':
element.classList.add('tooltip-right');
break;
}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Tooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: Tooltip, isStandalone: true, selector: "[tooltip]", inputs: { tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: true, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Tooltip, decorators: [{
type: Directive,
args: [{ selector: '[tooltip]' }]
}], ctorParameters: () => [], propDecorators: { tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: true }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }] } });
class Button {
elementRef = inject((ElementRef));
appRef = inject(ApplicationRef);
injector = inject(EnvironmentInjector);
loaderComponent = null;
color = input('neutral', ...(ngDevMode ? [{ debugName: "color" }] : []));
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : []));
circle = input(false, { ...(ngDevMode ? { debugName: "circle" } : {}), transform: booleanAttribute });
outline = input(false, { ...(ngDevMode ? { debugName: "outline" } : {}), transform: booleanAttribute });
soft = input(false, { ...(ngDevMode ? { debugName: "soft" } : {}), transform: booleanAttribute });
showLoader = input(false, { ...(ngDevMode ? { debugName: "showLoader" } : {}), transform: booleanAttribute });
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}), transform: booleanAttribute });
size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : []));
constructor() {
effect(() => this.toggleLoader(this.showLoader()));
effect(() => {
const disabled = this.disabled();
this.elementRef.nativeElement.disabled = disabled;
});
}
createLoaderComponent() {
const spanContainer = this.elementRef.nativeElement.insertBefore(document.createElement('span'), this.elementRef.nativeElement.firstChild);
spanContainer.classList.add('flex', 'items-center', 'justify-center', 'h-full');
this.loaderComponent = createComponent(Loader, {
environmentInjector: this.injector,
hostElement: spanContainer,
bindings: [inputBinding('size', () => this.size())],
});
return this.loaderComponent;
}
toggleLoader(show) {
if (show) {
const loaderComponent = this.createLoaderComponent();
this.elementRef.nativeElement.disabled = true;
this.appRef.attachView(loaderComponent.hostView);
}
else {
if (!this.disabled()) {
this.elementRef.nativeElement.disabled = false;
}
if (this.loaderComponent) {
this.appRef.detachView(this.loaderComponent.hostView);
this.loaderComponent.destroy();
this.loaderComponent = null;
}
}
}
getColorClass(color) {
switch (color) {
case 'neutral':
return 'btn-neutral';
case 'primary':
return 'btn-primary';
case 'secondary':
return 'btn-secondary';
case 'accent':
return 'btn-accent';
case 'info':
return 'btn-info';
case 'success':
return 'btn-success';
case 'warning':
return 'btn-warning';
case 'error':
return 'btn-error';
case 'ghost':
return 'btn-ghost';
default:
throw new Error(`Unknown button color: ${color}`);
}
}
getSizeClass(size) {
switch (size) {
case 'extraSmall':
return 'btn-xs';
case 'small':
return 'btn-sm';
case 'medium':
return 'btn-md';
case 'large':
return 'btn-lg';
case 'extraLarge':
return 'btn-xl';
default:
throw new Error(`Unknown button size: ${size}`);
}
}
ngOnInit() {
this.elementRef.nativeElement.type = this.type();
this.elementRef.nativeElement.classList.add('btn');
this.elementRef.nativeElement.classList.add(this.getColorClass(this.color()));
this.elementRef.nativeElement.classList.add(this.getSizeClass(this.size()));
if (this.outline()) {
this.elementRef.nativeElement.classList.add('btn-outline');
}
if (this.circle()) {
this.elementRef.nativeElement.classList.add('btn-circle');
}
if (this.soft()) {
this.elementRef.nativeElement.classList.add('btn-soft');
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Button, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: Button, isStandalone: true, selector: "button[klButton], a[klButton]", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, circle: { classPropertyName: "circle", publicName: "circle", isSignal: true, isRequired: false, transformFunction: null }, outline: { classPropertyName: "outline", publicName: "outline", isSignal: true, isRequired: false, transformFunction: null }, soft: { classPropertyName: "soft", publicName: "soft", isSignal: true, isRequired: false, transformFunction: null }, showLoader: { classPropertyName: "showLoader", publicName: "showLoader", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: Button, decorators: [{
type: Directive,
args: [{ selector: 'button[klButton], a[klButton]' }]
}], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], circle: [{ type: i0.Input, args: [{ isSignal: true, alias: "circle", required: false }] }], outline: [{ type: i0.Input, args: [{ isSignal: true, alias: "outline", required: false }] }], soft: [{ type: i0.Input, args: [{ isSignal: true, alias: "soft", required: false }] }], showLoader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLoader", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
/**
* Generated bundle index. Do not edit.
*/
export { Button, HookChange, InputCurrencyMask, InputMask, Tooltip };
//# sourceMappingURL=koalarx-ui-shared-directives.mjs.map