UNPKG

@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
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