@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
JavaScript
/**-----------------------------------------------------------------------------------------
* 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"
icon="caret-alt-expand"
[ ]="caretAltExpandIcon"
[ ]="size"
class="k-colorgradient-toggle-mode"
[ ]="formatButtonTitle"
[ ]="formatButtonTitle"
[ ]="disabled"
[ ]="tabindex.toString()"
>
</button>
</div>
<div *ngIf="formatView === 'hex'" class="k-vstack k-flex-1">
<kendo-textbox
kendoTextLabel
[ ]="focusableId"
class="k-hex-value"
[ ]="size"
[ ]="readonly"
[ ]="disabled"
[ ]="readonly"
[ ]="hex || ''"
(blur)="handleHexInputBlur()"
(input)="handleHexValueChange(hexInput.value)"
[ ]="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
kendoAdditionalNumericLabel="red"
[ ]="localizationService"
[ ]="disabled"
[ ]="size"
[ ]="readonly"
[ ]="tabindex"
[ ]="0"
[ ]="255"
[(value)]="rgba.r"
[ ]="true"
[ ]="false"
[ ]="'n'"
[ ]="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
kendoAdditionalNumericLabel="green"
[ ]="localizationService"
[ ]="disabled"
[ ]="readonly"
[ ]="tabindex"
[ ]="size"
[ ]="0"
[ ]="255"
[(value)]="rgba.g"
[ ]="true"
[ ]="false"
[ ]="'n'"
[ ]="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
kendoAdditionalNumericLabel="blue"
[ ]="localizationService"
[ ]="disabled"
[ ]="readonly"
[ ]="tabindex"
[ ]="size"
[ ]="0"
[ ]="255"
[(value)]="rgba.b"
[ ]="true"
[ ]="false"
[ ]="'n'"
[ ]="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
kendoAdditionalNumericLabel="alpha"
[ ]="localizationService"
[ ]="disabled"
[ ]="readonly"
[ ]="tabindex"
[ ]="size"
[ ]="0"
[ ]="1"
[(value)]="rgba.a"
[ ]="true"
[ ]="false"
[ ]="0.01"
[ ]="'n2'"
[ ]="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"
icon="caret-alt-expand"
[ ]="caretAltExpandIcon"
[ ]="size"
class="k-colorgradient-toggle-mode"
[ ]="formatButtonTitle"
[ ]="formatButtonTitle"
[ ]="disabled"
[ ]="tabindex.toString()"
>
</button>
</div>
<div *ngIf="formatView === 'hex'" class="k-vstack k-flex-1">
<kendo-textbox
kendoTextLabel
[ ]="focusableId"
class="k-hex-value"
[ ]="size"
[ ]="readonly"
[ ]="disabled"
[ ]="readonly"
[ ]="hex || ''"
(blur)="handleHexInputBlur()"
(input)="handleHexValueChange(hexInput.value)"
[ ]="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
kendoAdditionalNumericLabel="red"
[ ]="localizationService"
[ ]="disabled"
[ ]="size"
[ ]="readonly"
[ ]="tabindex"
[ ]="0"
[ ]="255"
[(value)]="rgba.r"
[ ]="true"
[ ]="false"
[ ]="'n'"
[ ]="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
kendoAdditionalNumericLabel="green"
[ ]="localizationService"
[ ]="disabled"
[ ]="readonly"
[ ]="tabindex"
[ ]="size"
[ ]="0"
[ ]="255"
[(value)]="rgba.g"
[ ]="true"
[ ]="false"
[ ]="'n'"
[ ]="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
kendoAdditionalNumericLabel="blue"
[ ]="localizationService"
[ ]="disabled"
[ ]="readonly"
[ ]="tabindex"
[ ]="size"
[ ]="0"
[ ]="255"
[(value)]="rgba.b"
[ ]="true"
[ ]="false"
[ ]="'n'"
[ ]="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
kendoAdditionalNumericLabel="alpha"
[ ]="localizationService"
[ ]="disabled"
[ ]="readonly"
[ ]="tabindex"
[ ]="size"
[ ]="0"
[ ]="1"
[(value)]="rgba.a"
[ ]="true"
[ ]="false"
[ ]="0.01"
[ ]="'n2'"
[ ]="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 }]
}] } });