UNPKG

@progress/kendo-angular-inputs

Version:

Kendo UI for Angular Inputs Package - Everything you need to build professional form functionality (Checkbox, ColorGradient, ColorPalette, ColorPicker, FlatColorPicker, FormField, MaskedTextBox, NumericTextBox, RadioButton, RangeSlider, Slider, Switch, Te

492 lines (491 loc) 21.2 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Component, Input, Output, EventEmitter, ElementRef, HostBinding, ViewChild, Renderer2, ChangeDetectorRef } from '@angular/core'; import { getRGBA, parseColor, getColorFromRGBA } from './utils'; import { isPresent } from '../common/utils'; import { guid, isDocumentAvailable } from '@progress/kendo-angular-common'; import { Subscription } from 'rxjs'; import { LocalizationService } from '@progress/kendo-angular-l10n'; import { NumericTextBoxComponent } from './../numerictextbox/numerictextbox.component'; import { caretAltExpandIcon } from '@progress/kendo-svg-icons'; import { NumericLabelDirective } from './color-gradient-numeric-label.directive'; import { NgIf } from '@angular/common'; import { ButtonComponent } from '@progress/kendo-angular-buttons'; import { TextBoxComponent } from '../textbox/textbox.component'; import { TextLabelDirective } from './color-gradient-text-label.directive'; import * as i0 from "@angular/core"; import * as i1 from "@progress/kendo-angular-l10n"; const DEFAULT_SIZE = 'medium'; /** * @hidden */ export class ColorInputComponent { host; renderer; cdr; localizationService; /** * The id of the hex input. */ focusableId = `k-${guid()}`; /** * The color format view. */ formatView; /** * The size property specifies the padding of the ColorInput. * * The possible values are: * * `small` * * `medium` (default) * * `large` * * `none` */ size = DEFAULT_SIZE; /** * The inputs tabindex. */ tabindex = -1; /** * The color value that will be parsed and populate the hex & rgba inputs. * Required input property. */ value; /** * Sets whether the alpha slider will be shown. */ opacity = true; /** * Sets the disabled state of the ColorInput. */ disabled = false; /** * Sets the read-only state of the ColorInput. * * @default false */ readonly = false; /** * Emits a parsed rgba string color. */ valueChange = new EventEmitter(); /** * Emits when the user tabs out of the last focusable input. */ tabOut = new EventEmitter(); colorInputClass = true; opacityInput; hexInput; blueInput; toggleFormatButton; /** * The rgba inputs values. */ rgba = {}; /* * The hex input value. */ hex; /** * Indicates whether any of the inputs are focused. */ get isFocused() { if (!(isDocumentAvailable() && isPresent(this.host))) { return false; } const activeElement = document.activeElement; return this.host.nativeElement.contains(activeElement); } /** * Indicates whether any of the rgba inputs have value. */ get rgbaInputValid() { return Object.keys(this.rgba).every(key => isPresent(this.rgba[key])); } /** * @hidden */ caretAltExpandIcon = caretAltExpandIcon; subscriptions = new Subscription(); constructor(host, renderer, cdr, localizationService) { this.host = host; this.renderer = renderer; this.cdr = cdr; this.localizationService = localizationService; } ngAfterViewInit() { this.initDomEvents(); } ngOnDestroy() { if (this.subscriptions) { this.subscriptions.unsubscribe(); } } ngOnChanges(changes) { if (isPresent(changes['value']) && !this.isFocused) { this.hex = parseColor(this.value, 'hex', this.opacity); this.rgba = getRGBA(this.value); this.rgba.a = parseColor(this.value, 'rgba', this.opacity) ? this.rgba.a : 1; } } get formatButtonTitle() { return this.localizationService.get('formatButton'); } handleRgbaValueChange() { const color = getColorFromRGBA(this.rgba); if (!this.rgbaInputValid || color === this.value) { return; } this.value = color; this.rgba = getRGBA(this.value); this.hex = parseColor(color, 'hex', this.opacity); this.valueChange.emit(color); } focusDragHandle(event) { event.preventDefault(); event.stopImmediatePropagation(); this.tabOut.emit(); } handleHexValueChange(hex) { this.hex = hex; const color = parseColor(hex, 'rgba', this.opacity); if (!isPresent(color) || color === this.value) { return; } this.value = color; this.rgba = getRGBA(color); this.valueChange.emit(color); } handleRgbaInputBlur() { if (!this.rgbaInputValid) { this.rgba = getRGBA(this.value); } } handleHexInputBlur() { this.hex = parseColor(this.value, 'hex', this.opacity); } focusLast() { this.lastInput().focus(); } onTab() { if (this.opacity) { return; } } toggleFormatView() { this.formatView = this.formatView === 'hex' ? 'rgba' : 'hex'; // needed to update the view when ChangeDetectionStrategy.OnPush this.cdr.markForCheck(); } initDomEvents() { if (!this.host) { return; } this.subscriptions.add(this.renderer.listen(this.toggleFormatButton.nativeElement, 'click', () => this.toggleFormatView())); } lastInput() { return this.hexInput?.nativeElement || this.opacityInput || this.blueInput; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorInputComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColorInputComponent, isStandalone: true, selector: "kendo-colorinput", inputs: { focusableId: "focusableId", formatView: "formatView", size: "size", tabindex: "tabindex", value: "value", opacity: "opacity", disabled: "disabled", readonly: "readonly" }, outputs: { valueChange: "valueChange", tabOut: "tabOut" }, host: { properties: { "class.k-colorgradient-inputs": "this.colorInputClass", "class.k-hstack": "this.colorInputClass" } }, viewQueries: [{ propertyName: "opacityInput", first: true, predicate: ["opacityInput"], descendants: true }, { propertyName: "hexInput", first: true, predicate: ["hexInput"], descendants: true }, { propertyName: "blueInput", first: true, predicate: ["blue"], descendants: true }, { propertyName: "toggleFormatButton", first: true, predicate: ["toggleFormatButton"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: ` <div class="k-vstack"> <button kendoButton type="button" fillMode="flat" #toggleFormatButton icon="caret-alt-expand" [svgIcon]="caretAltExpandIcon" [size]="size" class="k-colorgradient-toggle-mode" [attr.aria-label]="formatButtonTitle" [attr.title]="formatButtonTitle" [disabled]="disabled" [tabindex]="tabindex.toString()" > </button> </div> <div *ngIf="formatView === 'hex'" class="k-vstack k-flex-1"> <kendo-textbox #hexInput kendoTextLabel [focusableId]="focusableId" class="k-hex-value" [size]="size" [class.k-readonly]="readonly" [disabled]="disabled" [readonly]="readonly" [value]="hex || ''" (blur)="handleHexInputBlur()" (input)="handleHexValueChange(hexInput.value)" [tabindex]="tabindex" (keydown.tab)="focusDragHandle($event)"> </kendo-textbox> <label [for]="focusableId" class="k-colorgradient-input-label">HEX</label> </div> <ng-container *ngIf="formatView === 'rgba'"> <div class="k-vstack"> <kendo-numerictextbox #red kendoAdditionalNumericLabel="red" [localizationService]="localizationService" [disabled]="disabled" [size]="size" [readonly]="readonly" [tabindex]="tabindex" [min]="0" [max]="255" [(value)]="rgba.r" [autoCorrect]="true" [spinners]="false" [format]="'n'" [decimals]="0" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()"> </kendo-numerictextbox> <label [for]="red.focusableId" class="k-colorgradient-input-label">R</label> </div> <div class="k-vstack"> <kendo-numerictextbox #green kendoAdditionalNumericLabel="green" [localizationService]="localizationService" [disabled]="disabled" [readonly]="readonly" [tabindex]="tabindex" [size]="size" [min]="0" [max]="255" [(value)]="rgba.g" [autoCorrect]="true" [spinners]="false" [format]="'n'" [decimals]="0" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()"> </kendo-numerictextbox> <label [for]="green.focusableId" class="k-colorgradient-input-label">G</label> </div> <div class="k-vstack"> <kendo-numerictextbox #blue kendoAdditionalNumericLabel="blue" [localizationService]="localizationService" [disabled]="disabled" [readonly]="readonly" [tabindex]="tabindex" [size]="size" [min]="0" [max]="255" [(value)]="rgba.b" [autoCorrect]="true" [spinners]="false" [format]="'n'" [decimals]="0" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()" (keydown.tab)="onTab()"> </kendo-numerictextbox> <label [for]="blue.focusableId" class="k-colorgradient-input-label">B</label> </div> <div class="k-vstack" *ngIf="opacity"> <kendo-numerictextbox #opacityInput #alpha kendoAdditionalNumericLabel="alpha" [localizationService]="localizationService" [disabled]="disabled" [readonly]="readonly" [tabindex]="tabindex" [size]="size" [min]="0" [max]="1" [(value)]="rgba.a" [autoCorrect]="true" [spinners]="false" [step]="0.01" [format]="'n2'" [decimals]="2" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()" (keydown.tab)="focusDragHandle($event)"> </kendo-numerictextbox> <label [for]="alpha.focusableId" class="k-colorgradient-input-label">A</label> </div> </ng-container> `, isInline: true, dependencies: [{ kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: NumericLabelDirective, selector: "[kendoAdditionalNumericLabel]", inputs: ["kendoAdditionalNumericLabel", "localizationService"] }, { kind: "component", type: TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: TextLabelDirective, selector: "[kendoTextLabel]", inputs: ["focusableId"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorInputComponent, decorators: [{ type: Component, args: [{ selector: 'kendo-colorinput', template: ` <div class="k-vstack"> <button kendoButton type="button" fillMode="flat" #toggleFormatButton icon="caret-alt-expand" [svgIcon]="caretAltExpandIcon" [size]="size" class="k-colorgradient-toggle-mode" [attr.aria-label]="formatButtonTitle" [attr.title]="formatButtonTitle" [disabled]="disabled" [tabindex]="tabindex.toString()" > </button> </div> <div *ngIf="formatView === 'hex'" class="k-vstack k-flex-1"> <kendo-textbox #hexInput kendoTextLabel [focusableId]="focusableId" class="k-hex-value" [size]="size" [class.k-readonly]="readonly" [disabled]="disabled" [readonly]="readonly" [value]="hex || ''" (blur)="handleHexInputBlur()" (input)="handleHexValueChange(hexInput.value)" [tabindex]="tabindex" (keydown.tab)="focusDragHandle($event)"> </kendo-textbox> <label [for]="focusableId" class="k-colorgradient-input-label">HEX</label> </div> <ng-container *ngIf="formatView === 'rgba'"> <div class="k-vstack"> <kendo-numerictextbox #red kendoAdditionalNumericLabel="red" [localizationService]="localizationService" [disabled]="disabled" [size]="size" [readonly]="readonly" [tabindex]="tabindex" [min]="0" [max]="255" [(value)]="rgba.r" [autoCorrect]="true" [spinners]="false" [format]="'n'" [decimals]="0" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()"> </kendo-numerictextbox> <label [for]="red.focusableId" class="k-colorgradient-input-label">R</label> </div> <div class="k-vstack"> <kendo-numerictextbox #green kendoAdditionalNumericLabel="green" [localizationService]="localizationService" [disabled]="disabled" [readonly]="readonly" [tabindex]="tabindex" [size]="size" [min]="0" [max]="255" [(value)]="rgba.g" [autoCorrect]="true" [spinners]="false" [format]="'n'" [decimals]="0" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()"> </kendo-numerictextbox> <label [for]="green.focusableId" class="k-colorgradient-input-label">G</label> </div> <div class="k-vstack"> <kendo-numerictextbox #blue kendoAdditionalNumericLabel="blue" [localizationService]="localizationService" [disabled]="disabled" [readonly]="readonly" [tabindex]="tabindex" [size]="size" [min]="0" [max]="255" [(value)]="rgba.b" [autoCorrect]="true" [spinners]="false" [format]="'n'" [decimals]="0" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()" (keydown.tab)="onTab()"> </kendo-numerictextbox> <label [for]="blue.focusableId" class="k-colorgradient-input-label">B</label> </div> <div class="k-vstack" *ngIf="opacity"> <kendo-numerictextbox #opacityInput #alpha kendoAdditionalNumericLabel="alpha" [localizationService]="localizationService" [disabled]="disabled" [readonly]="readonly" [tabindex]="tabindex" [size]="size" [min]="0" [max]="1" [(value)]="rgba.a" [autoCorrect]="true" [spinners]="false" [step]="0.01" [format]="'n2'" [decimals]="2" (blur)="handleRgbaInputBlur()" (valueChange)="handleRgbaValueChange()" (keydown.tab)="focusDragHandle($event)"> </kendo-numerictextbox> <label [for]="alpha.focusableId" class="k-colorgradient-input-label">A</label> </div> </ng-container> `, standalone: true, imports: [ButtonComponent, NgIf, NumericTextBoxComponent, NumericLabelDirective, TextBoxComponent, TextLabelDirective] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i1.LocalizationService }]; }, propDecorators: { focusableId: [{ type: Input }], formatView: [{ type: Input }], size: [{ type: Input }], tabindex: [{ type: Input }], value: [{ type: Input }], opacity: [{ type: Input }], disabled: [{ type: Input }], readonly: [{ type: Input }], valueChange: [{ type: Output }], tabOut: [{ type: Output }], colorInputClass: [{ type: HostBinding, args: ['class.k-colorgradient-inputs'] }, { type: HostBinding, args: ['class.k-hstack'] }], opacityInput: [{ type: ViewChild, args: ['opacityInput'] }], hexInput: [{ type: ViewChild, args: ['hexInput'] }], blueInput: [{ type: ViewChild, args: ['blue'] }], toggleFormatButton: [{ type: ViewChild, args: ['toggleFormatButton', { static: false, read: ElementRef }] }] } });