@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
1,167 lines • 54.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 { take } from 'rxjs/operators';
import { Component, HostBinding, Input, Output, EventEmitter, ViewChild, ElementRef, TemplateRef, ViewContainerRef, forwardRef, ChangeDetectorRef, NgZone, Renderer2, Injector, isDevMode } from '@angular/core';
import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
import { Subscription } from 'rxjs';
import { FlatColorPickerComponent } from './flatcolorpicker.component';
import { PopupService } from '@progress/kendo-angular-popup';
import { ButtonComponent } from '@progress/kendo-angular-buttons';
import { AdaptiveService } from '@progress/kendo-angular-utils';
import { validatePackage } from '@progress/kendo-licensing';
import { Keys, KendoInput, isChanged, closest, guid, ResizeSensorComponent, isDocumentAvailable } from '@progress/kendo-angular-common';
import { LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
import { packageMetadata } from '../package-metadata';
import { PALETTEPRESETS } from './models';
import { ActiveColorClickEvent, ColorPickerCloseEvent, ColorPickerOpenEvent } from './events';
import { parseColor } from './utils';
import { getStylingClasses, isPresent } from '../common/utils';
import { ColorPickerLocalizationService } from './localization/colorpicker-localization.service';
import { DEFAULT_ACCESSIBLE_PRESET, DEFAULT_PRESET } from './constants';
import { IconWrapperComponent } from '@progress/kendo-angular-icons';
import { parseCSSClassNames } from '@progress/kendo-angular-common';
import { caretAltDownIcon } from '@progress/kendo-svg-icons';
import { NgClass, NgIf } from '@angular/common';
import { LocalizedColorPickerMessagesDirective } from './localization/localized-colorpicker-messages.directive';
import { updateActionSheetAdaptiveAppearance } from './models/adaptive-mode';
import { AdaptiveRendererComponent } from './adaptiveness/adaptive-renderer.component';
import * as i0 from "@angular/core";
import * as i1 from "@progress/kendo-angular-popup";
import * as i2 from "@progress/kendo-angular-l10n";
import * as i3 from "@progress/kendo-angular-utils";
const DOM_FOCUS_EVENTS = ['focus', 'blur'];
const DEFAULT_SIZE = 'medium';
const DEFAULT_ROUNDED = 'medium';
const DEFAULT_FILL_MODE = 'solid';
/**
* @hidden
*/
let nextColorPickerId = 0;
/**
* Represents the [Kendo UI ColorPicker component for Angular]({% slug overview_colorpicker %}).
*
* The ColorPicker is a powerful tool for choosing colors from Gradient and Palette views
* which are rendered in its popup. It supports previewing the selected color, reverting it to its previous state or clearing it completely.
*/
export class ColorPickerComponent {
host;
popupService;
cdr;
localizationService;
ngZone;
renderer;
injector;
adaptiveService;
hostClasses = true;
get focusedClass() {
return this.isFocused;
}
get disabledClass() {
return this.disabled;
}
get ariaReadonly() {
return this.readonly;
}
get ariaExpanded() {
return this.isOpen;
}
get hostTabindex() {
return this.tabindex;
}
direction;
role = 'combobox';
hasPopup = 'dialog';
get isControlInvalid() {
return (this.control?.invalid)?.toString();
}
/**
* @hidden
*/
focusableId;
/**
* Specifies the views that will be rendered in the popup.
* By default both the gradient and palette views will be rendered.
*/
views = ['gradient', 'palette'];
/**
* @hidden
*/
set view(view) {
this.views = [view];
}
get view() {
return (this.views && this.views.length > 0) ? this.views[0] : null;
}
/**
* Enables or disables the adaptive mode. By default, adaptive rendering is disabled.
*/
adaptiveMode = 'none';
/**
* Sets the initially active view in the popup. The property supports two-way binding.
*
* The supported values are:
* * `gradient`
* * `palette`
*/
activeView;
/**
* Sets the read-only state of the ColorPicker.
*
* @default false
*/
readonly = false;
/**
* Sets the disabled state of the ColorPicker. To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_colorpicker#toc-managing-the-colorpicker-disabled-state-in-reactive-forms).
*
* @default false
*/
disabled = false;
/**
* Specifies the output format of the ColorPicker.
*
* If the input value is in a different format, it will be parsed into the specified output `format`.
*
* The supported values are:
* * `rgba` (default)
* * `hex`
*/
format = 'rgba';
/**
* Specifies the value of the initially selected color.
*/
set value(value) {
this._value = parseColor(value, this.format, this.gradientSettings.opacity);
}
get value() {
return this._value;
}
/**
* Configures the popup of the ColorPicker.
*/
set popupSettings(value) {
this._popupSettings = Object.assign(this._popupSettings, value);
}
get popupSettings() {
return this._popupSettings;
}
/**
* Configures the palette that is displayed in the ColorPicker popup.
*/
set paletteSettings(value) {
this._paletteSettings = Object.assign(this._paletteSettings, value);
}
get paletteSettings() {
return this._paletteSettings;
}
/**
* Configures the gradient that is displayed in the ColorPicker popup.
*/
set gradientSettings(value) {
this._gradientSettings = Object.assign(this._gradientSettings, value);
}
get gradientSettings() {
return this._gradientSettings;
}
/**
* Defines the name of an [existing icon in the Kendo UI theme]({% slug icons %}).
* Provide only the name of the icon without the `k-icon` or the `k-i-` prefixes.
*
* For example, `pencil-tools` will be parsed to `k-icon k-i-pencil-tools`.
*/
icon;
/**
* A CSS class name which displays an icon in the ColorPicker button.
* `iconClass` is compatible with the `ngClass` syntax.
*
* Takes precedence over `icon` if both are defined.
*/
iconClass;
/**
* Defines an SVGIcon to be rendered within the button.
* The input can take either an [existing Kendo SVG icon](slug:svgicon_list) or a custom one.
*/
set svgIcon(icon) {
if (isDevMode() && icon && this.icon && this.iconClass) {
throw new Error('Setting both icon/svgIcon and iconClass options at the same time is not supported.');
}
this._svgIcon = icon;
}
get svgIcon() {
return this._svgIcon;
}
/**
* Specifies whether the ColorPicker should display a 'Clear color' button.
*
* @default true
*/
clearButton = true;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*
* @default 0
*/
set tabindex(value) {
const tabindex = Number(value);
const defaultValue = 0;
this._tabindex = !isNaN(tabindex) ? tabindex : defaultValue;
}
get tabindex() {
return !this.disabled ? this._tabindex : undefined;
}
/**
* Displays `Apply` and `Cancel` action buttons and color preview panes.
*
* When enabled, the component value will not change immediately upon
* color selection, but only after the `Apply` button is clicked.
*
* The `Cancel` button reverts the current selection to its
* previous state i.e. to the current value.
*
* @default false
*/
preview = false;
/**
* Configures the layout of the `Apply` and `Cancel` action buttons.
*
* The possible values are:
* * `start`
* * `center`
* * `end` (default)
* * `stretch`
*/
actionsLayout = 'end';
/**
* The size property specifies the padding of the ColorPicker internal elements
* ([see example]({% slug appearance_colorpicker %}#toc-size)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The rounded property specifies the border radius of the ColorPicker
* ([see example](slug:appearance_colorpicker#toc-roundness)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `full`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
/**
* The fillMode property specifies the background and border styles of the ColorPicker
* ([see example]({% slug appearance_colorpicker %}#toc-fill-mode)).
*
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
set fillMode(fillMode) {
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE;
this.handleClasses(newFillMode, 'fillMode');
this._fillMode = newFillMode;
}
get fillMode() {
return this._fillMode;
}
/**
* Fires each time the value is changed.
*/
valueChange = new EventEmitter();
/**
* Fires each time the Popup (or ActionSheet in adaptive mode) is about to open.
* This event is preventable. If you cancel it, the Popup (or the ActionSheet) will remain closed.
*/
open = new EventEmitter();
/**
* Fires each time the Popup (or ActionSheet in adaptive mode) is about to close.
* This event is preventable. If you cancel it, the Popup (or the ActionSheet) will remain open.
*/
close = new EventEmitter();
/**
* Fires each time ColorPicker is focused.
*/
onFocus = new EventEmitter();
/**
* Fires each time the ColorPicker is blurred.
*/
onBlur = new EventEmitter();
/**
* Fires when the user cancels the current color selection.
*
* Fires on preview pane or 'Cancel' button click.
*/
cancel = new EventEmitter();
/**
* Fires each time the left side of the ColorPicker wrapper is clicked.
* The event is triggered regardless of whether a ColorPicker icon is set or not.
*
* The [ActiveColorClickEvent]({% slug api_inputs_activecolorclickevent %}) event provides the option to prevent the popup opening.
*/
activeColorClick = new EventEmitter();
/**
* @hidden
* Fires each time the clear button is clicked.
*/
clearButtonClick = new EventEmitter();
/**
* Fires each time the view is about to change.
* Used to provide a two-way binding for the `activeView` property.
*/
activeViewChange = new EventEmitter();
/**
* Indicates whether the ColorPicker wrapper is focused.
*/
isFocused = false;
/**
* @hidden
*/
windowSize = 'large';
/**
* Returns the current open state. Returns `true` if the Popup (or ActionSheet in adaptive mode) is currently open.
*/
get isOpen() {
return isPresent(this.popupRef) || this.isActionSheetExpanded;
}
/**
* @hidden
*/
get customIconStyles() {
if (this.iconClass) {
let parsedIconClass = '';
parseCSSClassNames(this.iconClass).forEach(iconClass => {
parsedIconClass += iconClass + ' ';
});
return parsedIconClass.slice(0, -1);
}
return '';
}
/**
* @hidden
*/
get isAdaptiveModeEnabled() {
return this.adaptiveMode === 'auto';
}
/**
* @hidden
*/
get isAdaptive() {
return this.isAdaptiveModeEnabled && this.windowSize !== 'large';
}
/**
* @hidden
*/
get actionSheet() {
return this.adaptiveRenderer?.actionSheet;
}
/**
* @hidden
*/
get isActionSheetExpanded() {
return Boolean(this.actionSheet?.expanded);
}
/**
* @hidden
*/
get iconStyles() {
if (this.icon && !this.iconClass) {
return `${this.icon}`;
}
return '';
}
/**
* Provides a reference to a container element inside the component markup.
* The container element references the location of the appended popup—
* for example, inside the component markup.
*/
container;
activeColor;
popupTemplate;
flatColorPicker;
/**
* @hidden
*/
adaptiveRenderer;
/**
* @hidden
*/
arrowDownIcon = caretAltDownIcon;
popupRef;
_svgIcon;
_value;
_tabindex = 0;
_popupSettings = { animate: true };
_paletteSettings = {};
_gradientSettings = { opacity: true, delay: 0 };
_size = 'medium';
_rounded = 'medium';
_fillMode = 'solid';
dynamicRTLSubscription;
subscriptions = new Subscription();
popupSubs = new Subscription();
colorPickerId;
control;
constructor(host, popupService, cdr, localizationService, ngZone, renderer, injector, adaptiveService) {
this.host = host;
this.popupService = popupService;
this.cdr = cdr;
this.localizationService = localizationService;
this.ngZone = ngZone;
this.renderer = renderer;
this.injector = injector;
this.adaptiveService = adaptiveService;
validatePackage(packageMetadata);
this.dynamicRTLSubscription = this.localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
this.colorPickerId = nextColorPickerId++;
}
ngOnInit() {
const defaultPreset = (this.format !== 'name') ? DEFAULT_PRESET : DEFAULT_ACCESSIBLE_PRESET;
const settingsPalette = this._paletteSettings.palette;
const presetColumns = typeof settingsPalette === 'string' && PALETTEPRESETS[settingsPalette] ?
PALETTEPRESETS[settingsPalette].columns :
undefined;
this._paletteSettings = {
palette: settingsPalette || defaultPreset,
tileSize: this._paletteSettings.tileSize,
columns: this._paletteSettings.columns || presetColumns || 10
};
this.handleHostId();
this.renderer.setAttribute(this.host.nativeElement, 'aria-controls', `k-colorpicker-popup-${this.colorPickerId}`);
this.control = this.injector.get(NgControl, null);
}
ngAfterViewInit() {
const stylingInputs = ['size', 'rounded', 'fillMode'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
this.setHostElementAriaLabel();
this.initDomEvents();
this.windowSize = this.adaptiveService.size;
if (this.actionSheet && isDocumentAvailable()) {
// The following syntax is used as it does not violate CSP compliance
this.actionSheet.element.nativeElement.style.setProperty('--kendo-actionsheet-height', '60vh');
this.actionSheet.element.nativeElement.style.setProperty('--kendo-actionsheet-max-height', 'none');
}
}
ngOnChanges(changes) {
if (changes.format && changes.format.currentValue === 'name') {
this.activeView = 'palette';
}
if (this.activeView === 'gradient' && this.gradientSettings.opacity) {
this.format = 'rgba';
this.value = parseColor(this.value, this.format, this.gradientSettings.opacity);
}
if (isChanged('value', changes)) {
this.setHostElementAriaLabel();
}
}
ngOnDestroy() {
this.closePopup();
if (this.dynamicRTLSubscription) {
this.dynamicRTLSubscription.unsubscribe();
}
this.subscriptions.unsubscribe();
this.handleDomEvents('remove', DOM_FOCUS_EVENTS);
}
/**
* @hidden
*/
onResize() {
const currentWindowSize = this.adaptiveService.size;
if (this.isAdaptiveModeEnabled && this.windowSize !== currentWindowSize) {
if (this.isOpen) {
this.toggleWithEvents(false);
}
this.windowSize = currentWindowSize;
}
}
/**
* @hidden
*/
handleCancelEvent(ev) {
this.cancel.emit(ev);
}
/**
* @hidden
*/
togglePopup() {
if (!this.isActionSheetExpanded) {
this.focus();
this.toggleWithEvents(!this.isOpen);
}
}
/**
* @hidden
*/
handleWrapperClick(event) {
if (this.disabled) {
return;
}
this.focus();
if (closest(event.target, (element) => element === this.activeColor.nativeElement)) {
const event = new ActiveColorClickEvent(this.value);
this.activeColorClick.emit(event);
if (!event.isOpenPrevented() || this.isOpen) {
this.toggleWithEvents(!this.isOpen);
}
return;
}
if (!this.isActionSheetExpanded) {
this.toggleWithEvents(!this.isOpen);
}
}
/**
* Focuses the wrapper of the ColorPicker.
*/
focus() {
this.isFocused = true;
this.host.nativeElement.focus();
}
/**
* @hidden
*/
handleWrapperFocus() {
if (this.isFocused) {
return;
}
this.ngZone.run(() => {
this.focus();
this.onFocus.emit();
});
}
/**
* Blurs the ColorPicker.
*/
blur() {
this.isFocused = false;
this.host.nativeElement.blur();
this.notifyNgTouched();
}
/**
* @hidden
*/
handleWrapperBlur() {
if (!this.isActionSheetExpanded) {
if (this.isOpen) {
return;
}
this.ngZone.run(() => {
this.onBlur.emit();
this.isFocused = false;
});
}
}
/**
* Clears the value of the ColorPicker.
*/
reset() {
if (!isPresent(this.value)) {
return;
}
this._value = undefined;
this.setHostElementAriaLabel();
this.notifyNgChanged(undefined);
}
/**
* Toggles the Popup (or ActionSheet in adaptive mode) of the ColorPicker.
* Does not trigger the `open` and `close` events of the component.
*
* @param open An optional parameter. Specifies whether the popup will be opened or closed.
*/
toggle(open) {
this.windowSize = this.adaptiveService.size;
if (this.disabled || this.readonly) {
return;
}
this.cdr.markForCheck();
if (this.isActionSheetExpanded) {
this.closeActionSheet();
}
else {
this.closePopup();
}
open = isPresent(open) ? open : !this.isOpen;
if (open) {
if (this.isAdaptive && !this.isActionSheetExpanded) {
this.openActionSheet();
}
else {
this.openPopup();
}
this.focusFirstElement();
}
}
/**
* @hidden
*/
handleValueChange(color) {
const parsedColor = parseColor(color, this.format, this.gradientSettings.opacity);
const valueChange = parsedColor !== this.value;
if (valueChange) {
this.value = parsedColor;
this.valueChange.emit(parsedColor);
this.setHostElementAriaLabel();
this.notifyNgChanged(parsedColor);
}
}
/**
* @hidden
*/
handlePopupBlur(event) {
if (!this.isActionSheetExpanded) {
if (this.popupBlurInvalid(event)) {
return;
}
this.isFocused = false;
this.onBlur.emit();
this.notifyNgTouched();
this.toggleWithEvents(false);
}
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
}
/**
* @hidden
*/
registerOnChange(fn) {
this.notifyNgChanged = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.notifyNgTouched = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled) {
this.cdr.markForCheck();
this.disabled = isDisabled;
}
/**
* @hidden
*/
handleWrapperKeyDown(event) {
if (event.keyCode === Keys.ArrowDown || event.keyCode === Keys.Enter) {
event.preventDefault();
this.ngZone.run(() => {
this.toggleWithEvents(true);
});
}
}
/**
* @hidden
*/
onApply() {
this.handleValueChange(this.flatColorPicker.selection);
this.toggleWithEvents(false);
}
/**
* @hidden
*/
onCancel(e) {
this.flatColorPicker.resetSelection(e);
this.toggleWithEvents(false);
}
/**
* @hidden
*/
handlePopupKeyDown(event) {
if (event.keyCode === Keys.Escape) {
this.toggleWithEvents(false);
this.host.nativeElement.focus();
}
if (event.keyCode === Keys.Tab) {
const currentElement = event.shiftKey ? this.firstFocusableElement.nativeElement : this.lastFocusableElement.nativeElement;
const nextElement = event.shiftKey ? this.lastFocusableElement.nativeElement : this.firstFocusableElement.nativeElement;
if (event.target === currentElement) {
event.preventDefault();
nextElement.focus();
}
}
}
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
setHostElementAriaLabel() {
const ariaLabelValue = `${this.value ? this.value : this.localizationService.get('colorPickerNoColor')}`;
this.renderer.setAttribute(this.host.nativeElement, 'aria-label', ariaLabelValue);
}
handleClasses(value, input) {
const elem = this.host.nativeElement;
const classes = getStylingClasses('picker', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
popupBlurInvalid(ev) {
const focusInFlatColorPickerElement = this.popupRef?.popupElement?.contains(ev.relatedTarget);
const hostClicked = closest(ev.relatedTarget, (element) => element === this.host.nativeElement);
return Boolean(hostClicked || focusInFlatColorPickerElement);
}
toggleWithEvents(open) {
const sameState = this.isOpen === open;
if (this.disabled || this.readonly || sameState) {
return;
}
let eventArgs;
if (open) {
eventArgs = new ColorPickerOpenEvent();
this.open.emit(eventArgs);
}
else {
eventArgs = new ColorPickerCloseEvent();
this.close.emit(eventArgs);
}
if (!eventArgs.isDefaultPrevented()) {
this.toggle(open);
}
if (open) {
this.focusFirstElement();
}
}
focusFirstElement() {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
if (this.flatColorPicker) {
const gradientDragHandle = this.flatColorPicker.gradient?.gradientDragHandle;
const palette = this.flatColorPicker.palette?.host;
const elementToFocus = gradientDragHandle ? gradientDragHandle : palette;
elementToFocus.nativeElement.focus();
}
});
}
openActionSheet() {
this.windowSize = this.adaptiveService.size;
this.actionSheet.toggle(true);
updateActionSheetAdaptiveAppearance(this.actionSheet, this.windowSize, this.renderer);
}
closeActionSheet() {
this.actionSheet.toggle(false);
this.focus();
}
openPopup() {
const horizontalAlign = this.direction === "rtl" ? "right" : "left";
const anchorPosition = { horizontal: horizontalAlign, vertical: "bottom" };
const popupPosition = { horizontal: horizontalAlign, vertical: "top" };
this.popupRef = this.popupService.open({
anchor: this.activeColor,
animate: this.popupSettings.animate,
appendTo: this.popupSettings.appendTo,
popupAlign: popupPosition,
anchorAlign: anchorPosition,
popupClass: 'k-colorpicker-popup',
content: this.popupTemplate,
positionMode: 'absolute'
});
this.renderer.setAttribute(this.popupRef.popupElement.querySelector('.k-colorpicker-popup'), 'id', `k-colorpicker-popup-${this.colorPickerId}`);
this.popupSubs.add(this.popupRef.popupAnchorViewportLeave.subscribe(() => {
this.toggleWithEvents(false);
if (!this.isOpen) {
this.host.nativeElement.focus({
preventScroll: true
});
}
}));
}
closePopup() {
if (!this.isOpen) {
return;
}
this.popupSubs.unsubscribe();
this.popupRef.close();
this.popupRef = null;
}
get firstFocusableElement() {
if (!this.flatColorPicker.header || (this.views.length <= 1 && !this.flatColorPicker.clearButton)) {
const gradient = this.flatColorPicker.gradient;
return gradient ? gradient.gradientDragHandle : this.flatColorPicker.palette.host;
}
return this.views.length > 1 ? this.flatColorPicker.header.viewButtonsCollection.toArray()[0] : this.flatColorPicker.header.clearButtonElement;
}
get lastFocusableElement() {
if (this.preview) {
return this.flatColorPicker.footer?.lastButton || this.adaptiveRenderer.applyButton.nativeElement;
}
if (this.flatColorPicker.palette) {
return this.flatColorPicker.palette.host;
}
const gradient = this.flatColorPicker.gradient;
const inputs = gradient && gradient.inputs;
if (gradient && inputs && inputs.formatView === 'hex') {
return inputs.hexInput;
}
return this.gradientSettings.opacity ? inputs.opacityInput.numericInput : inputs.blueInput.numericInput;
}
notifyNgTouched = () => { };
notifyNgChanged = () => { };
handleDomEvents(action, events) {
const hostElement = this.host.nativeElement;
events.forEach(ev => hostElement[`${action}EventListener`](ev, this.domFocusListener, true));
}
initDomEvents() {
if (!this.host) {
return;
}
const hostElement = this.host.nativeElement;
this.ngZone.runOutsideAngular(() => {
this.subscriptions.add(this.renderer.listen(hostElement, 'focusin', () => {
this.handleWrapperFocus();
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'focusout', (event) => {
const closestPopup = this.popupRef ?
closest(event.relatedTarget, (element) => element === this.flatColorPicker.host.nativeElement) :
false;
const closestWrapper = closest(event.relatedTarget, (element) => element === this.host.nativeElement);
const closestActionSheet = this.isActionSheetExpanded ? closest(event.relatedTarget, (element) => element === this.actionSheet.element.nativeElement) :
false;
if (!closestPopup && !closestWrapper && !closestActionSheet) {
this.handleWrapperBlur();
}
}));
this.handleDomEvents('add', DOM_FOCUS_EVENTS);
this.subscriptions.add(this.renderer.listen(hostElement, 'keydown', (event) => {
this.handleWrapperKeyDown(event);
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'click', (event) => {
this.ngZone.run(() => {
!this.isActionSheetExpanded && this.handleWrapperClick(event);
});
}));
});
}
domFocusListener = (event) => event.stopImmediatePropagation();
handleHostId() {
const hostElement = this.host.nativeElement;
const existingId = hostElement.getAttribute('id');
if (existingId) {
this.focusableId = existingId;
}
else {
const id = `k-${guid()}`;
hostElement.setAttribute('id', id);
this.focusableId = id;
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerComponent, deps: [{ token: i0.ElementRef }, { token: i1.PopupService }, { token: i0.ChangeDetectorRef }, { token: i2.LocalizationService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.Injector }, { token: i3.AdaptiveService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColorPickerComponent, isStandalone: true, selector: "kendo-colorpicker", inputs: { views: "views", view: "view", adaptiveMode: "adaptiveMode", activeView: "activeView", readonly: "readonly", disabled: "disabled", format: "format", value: "value", popupSettings: "popupSettings", paletteSettings: "paletteSettings", gradientSettings: "gradientSettings", icon: "icon", iconClass: "iconClass", svgIcon: "svgIcon", clearButton: "clearButton", tabindex: "tabindex", preview: "preview", actionsLayout: "actionsLayout", size: "size", rounded: "rounded", fillMode: "fillMode" }, outputs: { valueChange: "valueChange", open: "open", close: "close", onFocus: "focus", onBlur: "blur", cancel: "cancel", activeColorClick: "activeColorClick", clearButtonClick: "clearButtonClick", activeViewChange: "activeViewChange" }, host: { properties: { "class.k-colorpicker": "this.hostClasses", "class.k-icon-picker": "this.hostClasses", "class.k-picker": "this.hostClasses", "class.k-focus": "this.focusedClass", "attr.aria-disabled": "this.disabledClass", "class.k-disabled": "this.disabledClass", "attr.aria-readonly": "this.ariaReadonly", "attr.aria-expanded": "this.ariaExpanded", "attr.tabindex": "this.hostTabindex", "attr.dir": "this.direction", "attr.role": "this.role", "attr.aria-haspopup": "this.hasPopup", "attr.aria-invalid": "this.isControlInvalid", "class.k-readonly": "this.readonly" } }, providers: [{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ColorPickerComponent)
}, {
provide: KendoInput,
useExisting: forwardRef(() => ColorPickerComponent)
},
ColorPickerLocalizationService,
{
provide: LocalizationService,
useExisting: ColorPickerLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.colorpicker'
}
], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "activeColor", first: true, predicate: ["activeColor"], descendants: true, static: true }, { propertyName: "popupTemplate", first: true, predicate: ["popupTemplate"], descendants: true, static: true }, { propertyName: "flatColorPicker", first: true, predicate: ["flatColorPicker"], descendants: true }, { propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }], exportAs: ["kendoColorPicker"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoColorPickerLocalizedMessages
i18n-colorPickerNoColor="kendo.colorpicker.colorPickerNoColor|The aria-label applied to the ColorPicker component when the value is empty."
colorPickerNoColor="Colorpicker no color chosen"
i18n-flatColorPickerNoColor="kendo.colorpicker.flatColorPickerNoColor|The aria-label applied to the FlatColorPicker component when the value is empty."
flatColorPickerNoColor="Flatcolorpicker no color chosen"
i18n-colorGradientNoColor="kendo.colorpicker.colorGradientNoColor|The aria-label applied to the ColorGradient component when the value is empty."
colorGradientNoColor="Colorgradient no color chosen"
i18n-colorPaletteNoColor="kendo.colorpicker.colorPaletteNoColor|The aria-label applied to the ColorPalette component when the value is empty."
colorPaletteNoColor="Colorpalette no color chosen"
i18n-colorGradientHandle="kendo.colorpicker.colorGradientHandle|The title for the gradient color drag handle chooser."
colorGradientHandle="Choose color"
i18n-clearButton="kendo.colorpicker.clearButton|The title for the clear button."
clearButton="Clear value"
i18n-hueSliderHandle="kendo.colorpicker.hueSliderHandle|The title for the hue slider handle."
hueSliderHandle="Set hue"
i18n-opacitySliderHandle="kendo.colorpicker.opacitySliderHandle|The title for the opacity slider handle."
opacitySliderHandle="Set opacity"
i18n-contrastRatio="kendo.colorpicker.contrastRatio|The contrast ratio message for the contrast tool."
contrastRatio="Contrast ratio"
i18n-previewColor="kendo.colorpicker.previewColor|The message for the color preview pane."
previewColor="Color preview"
i18n-revertSelection="kendo.colorpicker.revertSelection|The message for the selected color pane."
revertSelection="Revert selection"
i18n-gradientView="kendo.colorpicker.gradientView|The message for the gradient view button."
gradientView="Gradient view"
i18n-paletteView="kendo.colorpicker.paletteView|The message for the palette view button."
paletteView="Palette view"
i18n-formatButton="kendo.colorpicker.formatButton|The message for the input format toggle button."
formatButton="Change color format"
i18n-applyButton="kendo.colorpicker.applyButton|The message for the Apply action button."
applyButton="Apply"
i18n-cancelButton="kendo.colorpicker.cancelButton|The message for the Cancel action button."
cancelButton="Cancel"
i18n-closeButton="kendo.colorpicker.closeButton|The title for the Close button."
closeButton="Close"
i18n-adaptiveTitle="kendo.colorpicker.adaptiveTitle|The title for the ActionSheet when in adaptive mode."
adaptiveTitle="Choose Color"
i18n-redChannelLabel="kendo.colorpicker.redChannelLabel|The label of the NumericTextBox representing the red color channel."
redChannelLabel="Red channel"
i18n-greenChannelLabel="kendo.colorpicker.greenChannelLabel|The label of the NumericTextBox representing the green color channel."
greenChannelLabel="Green channel"
i18n-blueChannelLabel="kendo.colorpicker.blueChannelLabel|The label of the NumericTextBox representing the blue color channel."
blueChannelLabel="Blue channel"
i18n-alphaChannelLabel="kendo.colorpicker.alphaChannelLabel|The label of the NumericTextBox representing the alpha color channel."
alphaChannelLabel="Alpha channel"
i18n-redInputPlaceholder="kendo.colorpicker.redInputPlaceholder|The placeholder for the red color input."
redChannelLabel="R"
i18n-greenInputPlaceholder="kendo.colorpicker.greenInputPlaceholder|The placeholder for the green color input."
greenInputPlaceholder="G"
i18n-blueInputPlaceholder="kendo.colorpicker.blueInputPlaceholder|The placeholder for the blue color input."
blueInputPlaceholder="B"
i18n-hexInputPlaceholder="kendo.colorpicker.hexInputPlaceholder|The placeholder for the HEX color input."
hexInputPlaceholder="HEX">
</ng-container>
<span #activeColor class="k-input-inner">
<span
class="k-value-icon k-color-preview"
[ngClass]="{'k-icon-color-preview': customIconStyles || iconStyles || svgIcon, 'k-no-color': !value}"
>
<kendo-icon-wrapper
*ngIf="iconClass || icon || svgIcon"
[name]="iconStyles"
innerCssClass="k-color-preview-icon"
[customFontClass]="customIconStyles"
[svgIcon]="svgIcon"
>
</kendo-icon-wrapper>
<span class="k-color-preview-mask" [style.background-color]="value"></span>
</span>
</span>
<button
kendoButton
tabindex="-1"
type="button"
icon="caret-alt-down"
[size]="size"
[svgIcon]="arrowDownIcon"
[fillMode]="fillMode"
[disabled]="disabled"
rounded="none"
aria-hidden="true"
class="k-input-button"
>
</button>
<ng-template #popupTemplate>
<kendo-flatcolorpicker
#flatColorPicker
[value]="value"
[format]="format"
[size]="isAdaptive ? 'large' : size"
[views]="views"
[activeView]="activeView"
[actionsLayout]="actionsLayout"
[adaptiveMode]="isActionSheetExpanded"
[preview]="preview"
[gradientSettings]="gradientSettings"
[paletteSettings]="paletteSettings"
[clearButton]="clearButton"
(cancel)="handleCancelEvent($event)"
(focusout)="handlePopupBlur($event)"
(valueChange)="handleValueChange($event)"
(keydown)="handlePopupKeyDown($event)"
(activeViewChange)="activeViewChange.emit($event)"
(clearButtonClick)="clearButtonClick.emit()"
(actionButtonClick)="togglePopup()">
</kendo-flatcolorpicker>
</ng-template>
<ng-container #container></ng-container>
<kendo-adaptive-renderer
[actionSheetTemplate]="popupTemplate"
[isActionSheetExpanded]="isActionSheetExpanded"
[preview]="preview"
(actionSheetClose)="onCancel($event)"
(onApply)="onApply()"
(onCancel)="onCancel($event)"
>
</kendo-adaptive-renderer>
<kendo-resize-sensor *ngIf="isOpen || isAdaptiveModeEnabled" (resize)="onResize()"></kendo-resize-sensor>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedColorPickerMessagesDirective, selector: "[kendoColorPickerLocalizedMessages], [kendoFlatColorPickerLocalizedMessages], [kendoColorGradientLocalizedMessages], [kendoColorPaletteLocalizedMessages]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { 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: "component", type: FlatColorPickerComponent, selector: "kendo-flatcolorpicker", inputs: ["readonly", "disabled", "format", "value", "tabindex", "clearButton", "preview", "actionsLayout", "activeView", "views", "gradientSettings", "adaptiveMode", "paletteSettings", "size"], outputs: ["valueChange", "cancel", "activeViewChange", "clearButtonClick", "actionButtonClick"], exportAs: ["kendoFlatColorPicker"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "component", type: AdaptiveRendererComponent, selector: "kendo-adaptive-renderer", inputs: ["title", "subtitle", "actionSheetTemplate", "isActionSheetExpanded", "preview"], outputs: ["actionSheetClose", "onExpand", "onCollapse", "onApply", "onCancel"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoColorPicker',
selector: 'kendo-colorpicker',
providers: [{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ColorPickerComponent)
}, {
provide: KendoInput,
useExisting: forwardRef(() => ColorPickerComponent)
},
ColorPickerLocalizationService,
{
provide: LocalizationService,
useExisting: ColorPickerLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.colorpicker'
}],
template: `
<ng-container kendoColorPickerLocalizedMessages
i18n-colorPickerNoColor="kendo.colorpicker.colorPickerNoColor|The aria-label applied to the ColorPicker component when the value is empty."
colorPickerNoColor="Colorpicker no color chosen"
i18n-flatColorPickerNoColor="kendo.colorpicker.flatColorPickerNoColor|The aria-label applied to the FlatColorPicker component when the value is empty."
flatColorPickerNoColor="Flatcolorpicker no color chosen"
i18n-colorGradientNoColor="kendo.colorpicker.colorGradientNoColor|The aria-label applied to the ColorGradient component when the value is empty."
colorGradientNoColor="Colorgradient no color chosen"
i18n-colorPaletteNoColor="kendo.colorpicker.colorPaletteNoColor|The aria-label applied to the ColorPalette component when the value is empty."
colorPaletteNoColor="Colorpalette no color chosen"
i18n-colorGradientHandle="kendo.colorpicker.colorGradientHandle|The title for the gradient color drag handle chooser."
colorGradientHandle="Choose color"
i18n-clearButton="kendo.colorpicker.clearButton|The title for the clear button."
clearButton="Clear value"
i18n-hueSliderHandle="kendo.colorpicker.hueSliderHandle|The title for the hue slider handle."
hueSliderHandle="Set hue"
i18n-opacitySliderHandle="kendo.colorpicker.opacitySliderHandle|The title for the opacity slider handle."
opacitySliderHandle="Set opacity"
i18n-contrastRatio="kendo.colorpicker.contrastRatio|The contrast ratio message for the contrast tool."
contrastRatio="Contrast ratio"
i18n-previewColor="kendo.colorpicker.previewColor|The message for the color preview pane."
previewColor="Color preview"
i18n-revertSelection="kendo.colorpicker.revertSelection|The message for the selected color pane."
revertSelection="Revert selection"
i18n-gradientView="kendo.colorpicker.gradientView|The message for the gradient view button."
gradientView="Gradient view"
i18n-paletteView="kendo.colorpicker.paletteView|The message for the palette view button."
paletteView="Palette view"
i18n-formatButton="kendo.colorpicker.formatButton|The message for the input format toggle button."
formatButton="Change color format"
i18n-applyButton="kendo.colorpicker.applyButton|The message for the Apply action button."
applyButton="Apply"
i18n-cancelButton="kendo.colorpicker.cancelButton|The message for the Cancel action button."
cancelButton="Cancel"
i18n-closeButton="kendo.colorpicker.closeButton|The title for the Close button."
closeButton="Close"
i18n-adaptiveTitle="kendo.colorpicker.adaptiveTitle|The title for the ActionSheet when in adaptive mode."
adaptiveTitle="Choose Color"
i18n-redChannelLabel="kendo.colorpicker.redChannelLabel|The label of the NumericTextBox representing the red color channel."
redChannelLabel="Red channel"
i18n-greenChannelLabel="kendo.colorpicker.greenChannelLabel|The label of the NumericTextBox representing the green color channel."
greenChannelLabel="Green channel"
i18n-blueChannelLabel="kendo.colorpicker.blueChannelLabel|The label of the NumericTextBox representing the blue color channel."
blueChannelLabel="Blue channel"
i18n-alphaChannelLabel="kendo.colorpicker.alphaChannelLabel|The label of the NumericTextBox representing the alpha color channel."
alphaChannelLabel="Alpha channel"
i18n-redInputPlaceholder="kendo.colorpicker.redInputPlaceholder|The placeholder for the red color input."
redChannelLabel="R"
i18n-greenInputPlaceholder="kendo.colorpicker.greenInputPlaceholder|The placeholder for the green color input."
greenInputPlaceholder="G"
i18n-blueInputPlaceholder="kendo.colorpicker.blueInputPlaceholder|The placeholder for the blue color input."
blueInputPlaceholder="B"
i18n-hexInputPlaceholder="kendo.colorpicker.hexInputPlaceholder|The placeholder for the HEX color input."
hexInputPlaceholder="HEX">
</ng-container>
<span #activeColor class="k-input-inner">
<span
class="k-value-icon k-color-preview"
[ngClass]="{'k-icon-color-preview': customIconStyles || iconStyles || svgIcon, 'k-no-color': !value}"
>
<kendo-icon-wrapper
*ngIf="iconClass || icon || svgIcon"
[name]="iconStyles"
innerCssClass="k-color-preview-icon"
[customFontClass]="customIconStyles"
[svgIcon]="svgIcon"
>
</kendo-icon-wrapper>
<span class="k-color-preview-mask" [style.background-color]="value"></span>
</span>
</span>
<button
kendoButton
tabindex="-1"
type="button"
icon="caret-alt-down"
[size]="size"
[svgIcon]="arrowDownIcon"
[fillMode]="fillMode"
[disabled]="disabled"
rounded="none"
aria-hidden="true"
class="k-input-button"
>
</button>
<ng-template #popupTemplate>
<kendo-flatcolorpicker
#flatColorPicker
[value]="value"
[format]="format"
[size]="isAdaptive ? 'large' : size"
[views]="views"
[activeView]="activeView"
[actionsLayout]="actionsLayout"
[adaptiveMode]="isActionSheetExpanded"
[preview]="preview"
[gradientSettings]="gradientSettings"
[paletteSettings]="paletteSettings"
[clearButton]="clearButton"
(cancel)="handleCancelEvent($event)"
(focusout)="handlePopupBlur($event)"
(valueChange)="handleValueChange($event)"
(keydown)="handlePopupKeyDown($event)"
(activeViewChange)="activeViewChange.emit($event)"
(clearButtonClick)="clearButtonClick.emit()"
(actionButtonClick)="togglePopup()">
</kendo-flatcolorpicker>
</ng-template>
<ng-container #container></ng-container>
<kendo-adaptive-renderer
[actionSheetTemplate]="popupTemplate"
[isActionSheetExpanded]="isActionSheetExpanded"
[preview]="preview"
(actionSheetClose)="onCancel($event)"
(onApply)="onApply()"
(onCancel)="onCancel($event)"
>
</kendo-adaptive-renderer>
<kendo-resize-sensor *ngIf="isOpen || isAdaptiveModeEnabled" (resize)="onResize()"></kendo-resize-sensor>
`,
standalone: true,
imports: [LocalizedColorPickerMessagesDirective, NgClass, NgIf, IconWrapperComponent, ButtonComponent, FlatColorPickerComponent, ResizeSensorComponent, AdaptiveRendererComponent]
}]
}], ctorParameters: function ()