@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
19,782 lines • 774 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import * as i0 from '@angular/core';
import { InjectionToken, isDevMode, Directive, Optional, EventEmitter, ElementRef, Component, Input, HostBinding, Output, ViewChild, ContentChild, ViewChildren, forwardRef, Inject, Injectable, HostListener, ContentChildren, ViewContainerRef, ChangeDetectionStrategy, NgModule } from '@angular/core';
import { NgControl, NG_VALUE_ACCESSOR, NG_VALIDATORS, RadioControlValueAccessor } from '@angular/forms';
import { Subscription, fromEvent, interval, merge, BehaviorSubject, Subject } from 'rxjs';
import { take, tap, filter, concatMap, startWith, takeUntil, skip, debounceTime, throttleTime } from 'rxjs/operators';
import * as i1 from '@progress/kendo-angular-l10n';
import { ComponentMessages, LocalizationService, L10N_PREFIX, RTL } from '@progress/kendo-angular-l10n';
import * as i7 from '@progress/kendo-angular-common';
import { Keys, guid, anyChanged, isDocumentAvailable, hasObservers, KendoInput, EventsOutsideAngularDirective, DraggableDirective, ResizeSensorComponent, isObjectPresent, removeHTMLAttributes, parseAttributes, isControlRequired, setHTMLAttributes, SuffixTemplateDirective, PrefixTemplateDirective, isChanged, isPresent as isPresent$1, isSafari, PreventableEvent, findFocusableChild, parseCSSClassNames, closest as closest$1, SeparatorComponent, ResizeBatchService, KENDO_ADORNMENTS } from '@progress/kendo-angular-common';
export { PrefixTemplateDirective, SeparatorComponent, SuffixTemplateDirective } from '@progress/kendo-angular-common';
import { validatePackage } from '@progress/kendo-licensing';
import { caretAltUpIcon, caretAltDownIcon, caretAltLeftIcon, caretAltRightIcon, checkIcon, exclamationCircleIcon, xIcon, caretAltExpandIcon, xCircleIcon, dropletSlashIcon, dropletSliderIcon, paletteIcon, starIcon, starOutlineIcon, hyperlinkOpenIcon } from '@progress/kendo-svg-icons';
import { NgFor, NgClass, NgSwitch, NgSwitchCase, NgTemplateOutlet, NgIf, NgStyle } from '@angular/common';
import { ButtonComponent } from '@progress/kendo-angular-buttons';
import { browser, mobileOS } from '@progress/kendo-common';
import * as i1$1 from '@progress/kendo-angular-intl';
import { IconWrapperComponent, IconsService } from '@progress/kendo-angular-icons';
import { parseColor as parseColor$1, Color, namedColors } from '@progress/kendo-drawing';
import * as i1$2 from '@progress/kendo-angular-popup';
import { PopupService } from '@progress/kendo-angular-popup';
import * as i3 from '@progress/kendo-angular-utils';
import { AdaptiveService } from '@progress/kendo-angular-utils';
import { ActionSheetComponent, ActionSheetTemplateDirective } from '@progress/kendo-angular-navigation';
import { SignaturePad } from '@progress/kendo-inputs-common';
import { DialogComponent, DialogContainerService, DialogService, WindowService, WindowContainerService } from '@progress/kendo-angular-dialog';
/**
* @hidden
*
* Checks if the value is `null` or `undefined`. Falsy values like '', 0, false, NaN, etc. are regarded as present.
*/
const isPresent = (value) => value !== null && value !== undefined;
/**
* @hidden
*/
const areSame = (value1, value2) => value1 === value2 || (value1 === null && value2 === undefined) || (value1 === undefined && value2 === null);
/**
* @hidden
*/
const requiresZoneOnBlur = (ngControl) => ngControl &&
(!ngControl.touched || (ngControl.control && ngControl.control.updateOn === 'blur'));
/**
* @hidden
*
* Fits the contender number into the specified bounds. If the number is NaN or null, the min is returned.
*
* @param contender Represents the number you want to fit into specified bounds.
* @param min The inclusive lower bound number.
* @param max The inclusive upper bound number.
*/
const fitIntoBounds = (contender, min, max) => {
if (!isPresent(contender) || isNaN(contender)) {
return min;
}
return contender <= min ? min : contender >= max ? max : contender;
};
/**
* @hidden
*/
const SIZE_MAP = {
small: 'sm',
medium: 'md',
large: 'lg'
};
/**
* @hidden
*/
const ROUNDED_MAP = {
small: 'sm',
medium: 'md',
large: 'lg',
full: 'full'
};
/**
* @hidden
*/
const isNone = (style) => style === 'none';
/**
* @hidden
*
* Returns the styling classes to be added and removed
*/
const getStylingClasses = (componentType, stylingOption, previousValue, newValue) => {
switch (stylingOption) {
case 'size':
return {
toRemove: `k-${componentType}-${SIZE_MAP[previousValue]}`,
toAdd: newValue !== 'none' ? `k-${componentType}-${SIZE_MAP[newValue]}` : ''
};
case 'rounded':
return {
toRemove: `k-rounded-${ROUNDED_MAP[previousValue]}`,
toAdd: newValue !== 'none' ? `k-rounded-${ROUNDED_MAP[newValue]}` : ''
};
case 'fillMode':
return {
toRemove: `k-${componentType}-${previousValue}`,
toAdd: newValue !== 'none' ? `k-${componentType}-${newValue}` : ''
};
default:
break;
}
};
/**
* @hidden
*
* Used to differentiate between the Radio and CheckBox components in their base class.
*/
const COMPONENT_TYPE = new InjectionToken('TYPE_TOKEN');
/**
* @hidden
*/
const replaceMessagePlaceholder = (message, name, value) => message.replace(new RegExp(`{\\s*${name}\\s*}`, 'g'), value);
/**
* @hidden
*/
const MAX_PRECISION = 20;
/**
* @hidden
*/
const limitPrecision = (precision) => Math.min(precision, MAX_PRECISION);
/**
* @hidden
*/
const fractionLength = (value) => {
return (String(value).split('.')[1] || "").length;
};
const maxFractionLength = (value1, value2) => {
return Math.max(fractionLength(value1), fractionLength(value2));
};
/**
* @hidden
*/
const toFixedPrecision = (value, precision) => {
const maxPrecision = limitPrecision(precision);
return parseFloat(value.toFixed(maxPrecision));
};
/**
* @hidden
*/
const add = (value1, value2) => {
const maxPrecision = maxFractionLength(value1, value2);
return toFixedPrecision(value1 + value2, maxPrecision);
};
/**
* @hidden
*/
const subtract = (value1, value2) => {
return add(value1, -value2);
};
/**
* @hidden
*/
const multiply = (value1, value2) => {
const maxPrecision = fractionLength(value1) + fractionLength(value2);
return toFixedPrecision(value1 * value2, maxPrecision);
};
/**
* @hidden
*/
const divide = (dividend, divisor) => {
if (divisor === 0) {
return NaN;
}
const power = maxFractionLength(dividend, divisor);
const correctionValue = Math.pow(10, power);
return ((correctionValue * dividend) / (correctionValue * divisor));
};
/**
* @hidden
*/
const remainder = (dividend, divisor) => {
return Math.abs(subtract(dividend, multiply(divisor, Math.floor(divide(dividend, divisor)))));
};
/**
* @hidden
*/
const calculateFixedTrackSize = ({ max, min, smallStep, fixedTickWidth }) => ((max - min) / smallStep) * fixedTickWidth;
/**
* @hidden
*/
const calculateTicksCount = (min = 0, max = 0, smallStep = 1) => {
if (smallStep <= 0) {
throw new Error('Invalid argument: smallStep must be a positive number');
}
const adjustedRange = Math.abs(subtract(max, min));
const adjustedRatio = Math.floor(divide(adjustedRange, smallStep));
const result = add(adjustedRatio, 1);
return result;
};
/**
* @hidden
*/
const calculateValueFromTick = (index, { max, min, smallStep, reverse, vertical }) => {
const value = add(min, multiply(index, smallStep));
return vertical || reverse ? Math.abs(subtract(value, max)) : value;
};
/**
* @hidden
*/
const calculateHandlePosition = ({ trackWidth, min, max, value }) => {
const step = trackWidth / Math.abs(max - min);
const pos = isPresent(value) ? step * (value - min) : min;
return Math.floor(pos);
};
/**
* @hidden
*/
const decreaseValueToStep = (value, { max, min, smallStep, largeStep }, large = false) => {
const step = large && largeStep ? multiply(smallStep, largeStep) : smallStep;
const stepValue = subtract(value, min);
let result;
const stepRemainder = remainder(stepValue, step);
if (stepRemainder === 0) {
result = subtract(stepValue, step);
}
else {
result = subtract(stepValue, stepRemainder);
}
return limitValue(add(result, min), min, max);
};
/**
* @hidden
*/
const increaseValueToStep = (value, { max, min, smallStep, largeStep }, large = false) => {
const step = large && largeStep ? multiply(smallStep, largeStep) : smallStep;
const stepValue = subtract(value, min);
const stepRemainder = remainder(stepValue, step);
const result = add(subtract(stepValue, stepRemainder), step);
return limitValue(add(result, min), min, max);
};
/**
* @hidden
*/
const isStartHandle = (dragHandle) => dragHandle.id.indexOf('k-start-handle') > -1;
/**
* @hidden
*/
const snapValue = (value, options) => {
const { smallStep, min, max } = options;
const limited = limitValue(value, min, max);
if (value !== limited) {
return limited;
}
const left = decreaseValueToStep(value, options);
const right = increaseValueToStep(value, options);
if ((value - min) % smallStep === 0) {
return value;
}
if (right - value <= (right - left) / 2) {
return right;
}
return left;
};
/**
* @hidden
*/
const trimValue = (max, min, value) => {
if (value > max) {
return max;
}
if (value < min) {
return min;
}
return value;
};
/**
* @hidden
*/
const trimValueRange = (max, min, value) => {
return value ? [trimValue(max, min, value[0]), trimValue(max, min, value[1])] : [min, min];
};
/**
* @hidden
*/
const identity = (value) => value;
/**
* @hidden
*/
const isSameRange = (value1, value2) => areSame(value1[0], value2[0]) && areSame(value1[1], value2[1]);
/**
* @hidden
*/
const elementOffset = (element) => {
const box = element.getBoundingClientRect();
const documentElement = document.documentElement;
return {
left: box.left + (window.pageXOffset || documentElement.scrollLeft) - (documentElement.clientLeft || 0),
top: box.top + (window.pageYOffset || documentElement.scrollTop) - (documentElement.clientTop || 0)
};
};
/**
* @hidden
*/
const limitValue = (value, min, max) => {
return Math.max(Math.min(value, max), min);
};
/**
* @hidden
*/
const eventValue = (eventArgs, scaleElement, options) => {
const { min, max, vertical, rtl } = options;
const trackOffset = elementOffset(scaleElement);
const offset = vertical ? eventArgs.pageY - trackOffset.top : eventArgs.pageX - trackOffset.left;
const scale = (max - min) / (vertical ? scaleElement.clientHeight : scaleElement.clientWidth);
const offsetValue = offset * scale;
let value = rtl || vertical ? max - offsetValue : min + offsetValue;
const stepFractionLength = fractionLength(options.smallStep);
value = toFixedPrecision(value, stepFractionLength + 1);
return snapValue(value, options);
};
/**
* @hidden
*/
const isButton = (element) => {
return element.className.indexOf('k-button-increase') >= 0 || element.className.indexOf('k-button-decrease') >= 0;
};
/**
* @hidden
*/
const increment = (options) => {
return increaseValueToStep(options.value, options);
};
/**
* @hidden
*/
const decrement = (options) => {
return decreaseValueToStep(options.value, options);
};
/**
* @hidden
*/
const incrementLarge = (options) => {
return increaseValueToStep(options.value, options, true);
};
/**
* @hidden
*/
const decrementLarge = (options) => {
return decreaseValueToStep(options.value, options, true);
};
/**
* @hidden
*/
const validateValue = (value) => {
if (isDevMode && value && value[0] > value[1]) {
throw new Error('[RangeSlider] The start value should not be greater than the end value.');
}
};
/**
* @hidden
*/
var slidersUtil = {
calculateFixedTrackSize,
calculateValueFromTick,
calculateTicksCount,
calculateHandlePosition,
decreaseValueToStep,
decrement,
decrementLarge,
eventValue,
identity,
increment,
incrementLarge,
isButton,
isSameRange,
isStartHandle,
increaseValueToStep,
trimValue,
trimValueRange,
snapValue,
validateValue
};
/**
* @hidden
*/
class SliderModelBase {
props;
wrapper;
track;
renderer;
button;
tickSizes;
constructor(props, wrapper, track, renderer, button) {
this.props = props;
this.wrapper = wrapper;
this.track = track;
this.renderer = renderer;
this.button = button;
this.props = props;
this.wrapper = wrapper;
this.track = track;
this.tickSizes = this.getTickSizes();
}
resizeTrack() {
const orientation = this.props.vertical ? 'height' : 'width';
const altOrientation = this.props.vertical ? 'width' : 'height';
const trackWidth = this.trackWidth();
this.track.parentElement.style[orientation] = `${trackWidth}px`;
this.track.parentElement.style[altOrientation] = '';
}
resizeTicks(ticksContainer, ticks) {
const dimension = this.props.vertical ? "height" : "width";
[...ticks].map((tick, index) => tick.style[dimension] = `${this.tickSizes[index]}px`);
if (this.props.vertical) {
this.adjustPadding(ticksContainer);
}
}
resizeWrapper() {
const dimension = this.props.vertical ? "height" : "width";
const fixedTrackWidth = calculateFixedTrackSize(this.props);
const wrapperParentEl = this.wrapper.parentElement;
if (fixedTrackWidth) {
wrapperParentEl.style[dimension] = "auto";
}
}
trackWidth() {
if (this.props.fixedTickWidth) {
return calculateFixedTrackSize(this.props);
}
const wrapperWidth = this.elementSize(this.wrapper.parentElement);
const trackOffset = this.getTrackOffset();
return wrapperWidth - trackOffset;
}
getTickSizes() {
const { min, max, smallStep } = this.props;
const count = calculateTicksCount(min, max, smallStep);
const trackSize = this.trackWidth();
const distStep = trackSize / subtract(max, min);
const result = [];
let usedSpace = 0;
let endPoint = 0;
for (let i = 0; i < count; i++) {
if (i === 0 || i === count - 1) {
endPoint += (smallStep / 2) * distStep;
}
else {
endPoint += smallStep * distStep;
}
// ensure that the sum of the tick sizes does not exceed the track width
endPoint = +endPoint.toFixed(2) - 0.01;
const size = Math.round(endPoint - usedSpace);
result.push(size);
usedSpace += size;
}
if (usedSpace >= trackSize) {
result[result.length - 1] -= 1;
}
return result;
}
adjustPadding(ticksContainer) {
const totalTickSize = this.tickSizes.reduce((prev, curr) => prev + curr, 0);
const trackWidth = this.trackWidth();
const reminder = trackWidth - totalTickSize;
if (reminder !== 0) {
const padding = reminder + this.elementOffset(this.track);
ticksContainer.style.paddingTop = `${padding}px`;
}
}
elementOffset(element) {
const { vertical } = this.props;
const style = getComputedStyle(element);
return parseInt(vertical ? style.bottom : style.left, 10);
}
elementSize(element) {
const { vertical } = this.props;
return vertical ? element.clientHeight : element.clientWidth;
}
getTrackOffset() {
const showButtons = this.props.buttons && isPresent(this.button);
if (!showButtons) {
return 0;
}
const BUTTONS_COUNT = 2;
const buttonStyles = this.button.nativeElement.getBoundingClientRect();
const wrapperGap = parseInt(window.getComputedStyle(this.wrapper.parentElement).gap);
const buttonSize = this.props.vertical ? buttonStyles?.height : buttonStyles?.width;
return (buttonSize + wrapperGap) * BUTTONS_COUNT;
}
}
/**
* @hidden
*/
class SliderModel extends SliderModelBase {
handlePosition;
positionHandle(dragHandle) {
const { max, min, reverse, vertical } = this.props;
const position = vertical ? 'bottom' : reverse ? 'right' : 'left';
const trackWidth = this.trackWidth();
const value = trimValue(max, min, this.props.value);
this.handlePosition = calculateHandlePosition({
min,
max,
reverse,
value,
trackWidth
});
this.renderer.setStyle(dragHandle, position, `${this.handlePosition}px`);
}
positionSelection(selection) {
const { vertical } = this.props;
const dimension = vertical ? 'height' : 'width';
const size = this.handlePosition;
this.renderer.setStyle(selection, dimension, `${size}px`);
}
}
const UNTOUCHED = 'ng-untouched';
const toClassList = (classNames) => String(classNames).trim().split(' ');
/**
* @hidden
*/
const hasClass = (element, className) => Boolean(toClassList(element.className).find((name) => name === className));
/**
* @hidden
*/
function invokeElementMethod(element, name, ...args) {
if (element && element.nativeElement) {
// eslint-disable-next-line prefer-spread
return element.nativeElement[name].apply(element.nativeElement, args);
}
}
/**
* @hidden
*/
const isUntouched = (element) => element && element.nativeElement && hasClass(element.nativeElement, UNTOUCHED);
/**
* @hidden
*/
const containsFocus = (hostElement, contender) => hostElement && contender && (hostElement === contender || hostElement.contains(contender));
/**
* @hidden
*/
const closest = (node, predicate) => {
while (node && !predicate(node)) {
node = node.parentNode;
}
return node;
};
/**
* @hidden
*/
const packageMetadata = {
name: '@progress/kendo-angular-inputs',
productName: 'Kendo UI for Angular',
productCode: 'KENDOUIANGULAR',
productCodes: ['KENDOUIANGULAR'],
publishDate: 1743579576,
version: '18.4.0',
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
};
/**
* Represents the template for the labels of the Slider.
* To define the labels template, nest an `<ng-template>` tag with the `kendoSliderLabelTemplate` directive inside
* the `<kendo-slider>` tag. The template context is passed to the `label` value.
*
* @example
* ```ts-no-run
*
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-slider [largeStep]="2">
* <ng-template kendoSliderLabelTemplate let-value="value">
* <b>{{value}}</b>
* </ng-template>
* </kendo-slider>
* `
* })
*
* class AppComponent {
* }
*
* ```
*/
class LabelTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LabelTemplateDirective, isStandalone: true, selector: "[kendoSliderLabelTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoSliderLabelTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* @hidden
*/
class SliderBase {
localizationService;
injector;
renderer;
ngZone;
changeDetector;
hostElement;
/**
* Defines the title of the ticks ([see example]({% slug ticks_slider %}#toc-titles)). The default title
* for each tick is its Slider value. If you use a callback function, the function accepts an argument
* that holds the value of the component and returns a string with the new title.
*/
title = identity;
/**
* Denotes the location of the tick marks in the Slider ([see example]({% slug ticks_slider %}#toc-placement)).
*
* The available options are:
* * `before`—The tick marks are located to the top side of the horizontal track or to the left side of a vertical track.
* * `after`—The tick marks are located to the bottom side of the horizontal track or to the right side of the vertical track.
* * `both`— (Default) The tick marks are located on both sides of the track.
* * `none`—The tick marks are not visible. The actual elements are not added to the DOM tree.
*/
tickPlacement = 'both';
/**
* If `vertical` is set to `true`, the orientation of the Slider changes from horizontal to vertical
* ([see example]({% slug orientation_slider %})).
*/
vertical = false;
/**
* The minimum value of the Slider ([see example]({% slug predefinedsteps_slider %}#toc-small-steps)).
* The attribute accepts both integers and floating-point numbers.
*/
min = 0;
/**
* The maximum value of the Slider ([see example]({% slug predefinedsteps_slider %}#toc-small-steps)).
* The attribute accepts both integers and floating-point numbers.
*/
max = 10;
/**
* The step value of the Slider ([see example]({% slug predefinedsteps_slider %}#toc-small-steps)).
* Accepts positive values only. Can be an integer or a floating-point number.
*/
smallStep = 1;
/**
* Specifies that every n<sup>th</sup> tick will be large and will have a label
* ([see example]({% slug predefinedsteps_slider %}#toc-large-steps)).
* Accepts positive integer values only.
*/
largeStep = null;
/**
* Sets the width between each two ticks along the track ([see example]({% slug ticks_slider %}#toc-width)). The value
* has to be set in pixels. If no `fixedTickWidth` is provided, the Slider automatically adjusts the tick width to
* accommodate the elements within the size of the component.
*/
fixedTickWidth;
/**
* Determines whether the Slider is disabled ([see example]({% slug disabledstate_slider %})). To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_slider#toc-managing-the-slider-disabled-state-in-reactive-forms).
*/
disabled = false;
/**
* Determines whether the Slider is in its read-only state ([see example]({% slug readonly_slider %})).
*
* @default false
*/
readonly = false;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the Slider.
*/
tabindex = 0;
/**
* Fires each time the user focuses the component.
*/
onFocus = new EventEmitter();
/**
* Fires each time the component is blurred.
*/
onBlur = new EventEmitter();
/**
* Fires each time the user selects a new value.
*/
valueChange = new EventEmitter();
direction;
get horizontalClass() {
return !this.vertical;
}
get verticalClass() {
return this.vertical;
}
sliderClass = true;
get disabledClass() {
return this.disabled;
}
wrapper;
track;
sliderSelection;
ticksContainer;
ticks;
labelTemplate;
subscriptions = new Subscription();
isFocused;
isDragged;
control;
constructor(localizationService, injector, renderer, ngZone, changeDetector, hostElement) {
this.localizationService = localizationService;
this.injector = injector;
this.renderer = renderer;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.hostElement = hostElement;
validatePackage(packageMetadata);
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.changeDetector.markForCheck();
this.disabled = isDisabled;
}
ngOnInit() {
this.subscriptions.add(this.localizationService
.changes
.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
this.sizeComponent();
}));
if (this.hostElement) {
this.renderer.removeAttribute(this.hostElement.nativeElement, "tabindex");
}
this.control = this.injector.get(NgControl, null);
}
/**
* @hidden
*/
get isDisabled() {
return this.disabled || this.readonly;
}
/**
* @hidden
*/
ifEnabled = (callback, event) => {
if (!this.isDisabled) {
callback.call(this, event);
}
};
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
get reverse() {
return this.localizationService.rtl && !this.vertical;
}
get keyBinding() {
const reverse = this.reverse;
return {
[Keys.ArrowLeft]: reverse ? increment : decrement,
[Keys.ArrowRight]: reverse ? decrement : increment,
[Keys.ArrowDown]: decrement,
[Keys.ArrowUp]: increment,
[Keys.PageUp]: incrementLarge,
[Keys.PageDown]: decrementLarge,
[Keys.Home]: ({ min }) => min,
[Keys.End]: ({ max }) => max
};
}
resetStyles(elements) {
elements.forEach(el => {
if (el) {
if (this.vertical) {
this.renderer.removeStyle(el, 'width');
this.renderer.removeStyle(el, 'left');
this.renderer.removeStyle(el, 'right');
}
else {
this.renderer.removeStyle(el, 'height');
this.renderer.removeStyle(el, 'bottom');
}
this.renderer.removeStyle(el, 'padding-top');
}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderBase, deps: [{ token: i1.LocalizationService }, { token: i0.Injector }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SliderBase, selector: "kendo-slider-base", inputs: { title: "title", tickPlacement: "tickPlacement", vertical: "vertical", min: "min", max: "max", smallStep: "smallStep", largeStep: "largeStep", fixedTickWidth: "fixedTickWidth", disabled: "disabled", readonly: "readonly", tabindex: "tabindex" }, outputs: { onFocus: "focus", onBlur: "blur", valueChange: "valueChange" }, host: { properties: { "class.k-readonly": "this.readonly", "attr.dir": "this.direction", "class.k-slider-horizontal": "this.horizontalClass", "class.k-slider-vertical": "this.verticalClass", "class.k-slider": "this.sliderClass", "class.k-disabled": "this.disabledClass" } }, queries: [{ propertyName: "labelTemplate", first: true, predicate: LabelTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "wrapper", first: true, predicate: ["wrap"], descendants: true, static: true }, { propertyName: "track", first: true, predicate: ["track"], descendants: true, static: true }, { propertyName: "sliderSelection", first: true, predicate: ["sliderSelection"], descendants: true, static: true }, { propertyName: "ticksContainer", first: true, predicate: ["ticks"], descendants: true, read: ElementRef }, { propertyName: "ticks", first: true, predicate: ["ticks"], descendants: true }], ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderBase, decorators: [{
type: Component,
args: [{
selector: 'kendo-slider-base',
template: ``
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Injector }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { title: [{
type: Input
}], tickPlacement: [{
type: Input
}], vertical: [{
type: Input
}], min: [{
type: Input
}], max: [{
type: Input
}], smallStep: [{
type: Input
}], largeStep: [{
type: Input
}], fixedTickWidth: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], tabindex: [{
type: Input
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], valueChange: [{
type: Output
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], horizontalClass: [{
type: HostBinding,
args: ['class.k-slider-horizontal']
}], verticalClass: [{
type: HostBinding,
args: ['class.k-slider-vertical']
}], sliderClass: [{
type: HostBinding,
args: ['class.k-slider']
}], disabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], wrapper: [{
type: ViewChild,
args: ['wrap', { static: true }]
}], track: [{
type: ViewChild,
args: ['track', { static: true }]
}], sliderSelection: [{
type: ViewChild,
args: ['sliderSelection', { static: true }]
}], ticksContainer: [{
type: ViewChild,
args: ['ticks', { read: ElementRef, static: false }]
}], ticks: [{
type: ViewChild,
args: ['ticks', { static: false }]
}], labelTemplate: [{
type: ContentChild,
args: [LabelTemplateDirective, { static: false }]
}] } });
/* eslint-disable @angular-eslint/component-selector */
/**
* @hidden
*/
class SliderTick {
value;
classes = {
'k-tick': true
};
large;
constructor(value) {
this.value = value;
}
}
/**
* @hidden
*/
class SliderTicksComponent {
wrapperClasses = 'k-reset k-slider-items';
tickTitle;
vertical;
step;
largeStep;
min;
max;
labelTemplate;
tickElements;
ticks = [];
ngOnChanges(_) {
this.createTicks();
}
createTicks() {
const count = calculateTicksCount(this.min, this.max, this.step);
const largeStep = this.largeStep;
const tickValueProps = {
max: this.max,
min: this.min,
smallStep: this.step
};
const result = [];
for (let i = 0; i < count; i++) {
result.push(new SliderTick(calculateValueFromTick(i, tickValueProps)));
if (largeStep && i % largeStep === 0) {
result[i].large = true;
result[i].classes['k-tick-large'] = true;
}
}
if (result.length > 0) {
Object.assign(result[0].classes, this.endTickClasses(true));
Object.assign(result[result.length - 1].classes, this.endTickClasses(false));
}
this.ticks = result;
}
endTickClasses(first) {
return {
'k-first': (first && !this.vertical) || (!first && this.vertical),
'k-last': (!first && !this.vertical) || (first && this.vertical)
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderTicksComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SliderTicksComponent, isStandalone: true, selector: "[kendoSliderTicks]", inputs: { tickTitle: "tickTitle", vertical: "vertical", step: "step", largeStep: "largeStep", min: "min", max: "max", labelTemplate: "labelTemplate" }, host: { properties: { "class": "this.wrapperClasses" } }, viewQueries: [{ propertyName: "tickElements", predicate: ["tickElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<li #tickElement *ngFor="let tick of ticks;"
[ngClass]="tick.classes"
title="{{ tickTitle(tick.value) }}"
role="presentation"
>
<ng-container [ngSwitch]="tick.large">
<span class="k-label" *ngSwitchCase="true">
<ng-container [ngTemplateOutlet]="labelTemplate || defaultLabel" [ngTemplateOutletContext]="tick">
</ng-container>
</span>
<ng-container *ngSwitchCase="false"> </ng-container>
</ng-container>
</li>
<ng-template #defaultLabel let-value="value">
{{ tickTitle(value) }}
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderTicksComponent, decorators: [{
type: Component,
args: [{
selector: '[kendoSliderTicks]',
template: `
<li #tickElement *ngFor="let tick of ticks;"
[ngClass]="tick.classes"
title="{{ tickTitle(tick.value) }}"
role="presentation"
>
<ng-container [ngSwitch]="tick.large">
<span class="k-label" *ngSwitchCase="true">
<ng-container [ngTemplateOutlet]="labelTemplate || defaultLabel" [ngTemplateOutletContext]="tick">
</ng-container>
</span>
<ng-container *ngSwitchCase="false"> </ng-container>
</ng-container>
</li>
<ng-template #defaultLabel let-value="value">
{{ tickTitle(value) }}
</ng-template>
`,
standalone: true,
imports: [NgFor, NgClass, NgSwitch, NgSwitchCase, NgTemplateOutlet]
}]
}], propDecorators: { wrapperClasses: [{
type: HostBinding,
args: ['class']
}], tickTitle: [{
type: Input
}], vertical: [{
type: Input
}], step: [{
type: Input
}], largeStep: [{
type: Input
}], min: [{
type: Input
}], max: [{
type: Input
}], labelTemplate: [{
type: Input
}], tickElements: [{
type: ViewChildren,
args: ['tickElement']
}] } });
/**
* @hidden
*/
class SliderMessages extends ComponentMessages {
/**
* The title of the **Decrease** button of the Slider.
*/
decrement;
/**
* The title of the **Increase** button of the Slider.
*/
increment;
/**
* The title of the drag handle of the Slider.
*/
dragHandle;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SliderMessages, selector: "kendo-slider-messages-base", inputs: { decrement: "decrement", increment: "increment", dragHandle: "dragHandle" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-slider-messages-base'
}]
}], propDecorators: { decrement: [{
type: Input
}], increment: [{
type: Input
}], dragHandle: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedSliderMessagesDirective extends SliderMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedSliderMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedSliderMessagesDirective, isStandalone: true, selector: "[kendoSliderLocalizedMessages]", providers: [
{
provide: SliderMessages,
useExisting: forwardRef(() => LocalizedSliderMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedSliderMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: SliderMessages,
useExisting: forwardRef(() => LocalizedSliderMessagesDirective)
}
],
selector: '[kendoSliderLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/* eslint-disable @typescript-eslint/no-explicit-any */
const PRESSED$1 = 'k-pressed';
/**
* Represents the [Kendo UI Slider component for Angular]({% slug overview_slider %}).
*/
class SliderComponent extends SliderBase {
localization;
injector;
renderer;
ngZone;
changeDetector;
hostElement;
/**
* @hidden
*/
focusableId = `k-${guid()}`;
/**
* Changes the `title` attribute of the drag handle so that it can be localized.
*/
dragHandleTitle;
/**
* Sets the title of the **Increase** button of the Slider ([see example]({% slug sidebuttons_slider %}#toc-titles)).
*/
incrementTitle;
/**
* Determines if the animation will be played on value change.
* Regardless of this setting, no animation will be played during the initial rendering.
*/
animate = true;
/**
* Sets the title of the **Decrease** button of the Slider ([see example]({% slug sidebuttons_slider %}#toc-titles)).
*/
decrementTitle;
/**
* Renders the arrow side buttons of the Slider ([see example]({% slug sidebuttons_slider %}#toc-hidden-state)).
* When `showButtons` is set to `false`, the buttons are not displayed.
*/
showButtons = true;
/**
* The current value of the Slider when it is initially displayed.
* The component can use either NgModel or the `value` binding but not both of them at the same time.
*/
value = this.min;
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* @hidden
*/
get currentValue() {
return isPresent(this.value) ? this.value.toString() : '';
}
/**
* @hidden
*/
arrowUpIcon = caretAltUpIcon;
/**
* @hidden
*/
arrowDownIcon = caretAltDownIcon;
/**
* @hidden
*/
arrowLeftIcon = caretAltLeftIcon;
/**
* @hidden
*/
arrowRightIcon = caretAltRightIcon;
draghandle;
decreaseButton;
increaseButton;
focusChangedProgrammatically = false;
isInvalid;
constructor(localization, injector, renderer, ngZone, changeDetector, hostElement) {
super(localization, injector, renderer, ngZone, changeDetector, hostElement);
this.localization = localization;
this.injector = injector;
this.renderer = renderer;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.hostElement = hostElement;
}
/**
* Focuses the Slider.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <button (click)="slider.focus()">Focus</button>
* <kendo-slider #slider></kendo-slider>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
if (!this.disabled) {
this.focusChangedProgrammatically = true;
invokeElementMethod(this.draghandle, 'focus');
this.focusChangedProgrammatically = false;
}
}
/**
* Blurs the Slider.
*/
blur() {
this.focusChangedProgrammatically = true;
invokeElementMethod(this.draghandle, 'blur');
this.handleBlur();
this.focusChangedProgrammatically = false;
}
ngOnChanges(changes) {
if (anyChanged(['value', 'fixedTickWidth', 'tickPlacement'], changes, true)) {
this.ngZone.onStable.asObservable().pipe(take(1)).subscribe(() => {
this.sizeComponent(false);
});
}
}
ngAfterViewInit() {
if (!isDocumentAvailable()) {
return;
}
if (this.showButtons) {
this.setValueChangeInterval(this.increaseButton.nativeElement, () => this.increaseValue());
this.setValueChangeInterval(this.decreaseButton.nativeElement, () => this.decreaseValue());
}
this.sizeComponent(false);
if (this.ticks) {
this.ticks.tickElements
.changes
.subscribe(() => this.sizeComponent(false));
}
this.attachElementEventHandlers();
this.isSliderInvalid();
}
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
}
}
/**
* @hidden
*/
get incrementMessage() {
return this.incrementTitle || this.localizationService.get('increment');
}
/**
* @hidden
*/
get decrementMessage() {
return this.decrementTitle || this.localizationService.get('decrement');
}
/**
* @hidden
*/
get dragHandleMessage() {
return this.dragHandleTitle || this.localizationService.get('dragHandle');
}
/**
* @hidden
*/
onWrapClick = (args) => {
const target = args.target;
if (!this.isDisabled && !(target.closest('.k-button'))) {
const value = eventValue(args, this.track.nativeElement, this.getProps());
this.changeValue(value);
}
invokeElementMethod(this.draghandle, 'focus');
};
/**
* @hidden
*/
handleDragPress(args) {
if (args.originalEvent) {
args.originalEvent.preventDefault();
}
this.renderer.removeClass(this.hostElement.nativeElement, 'k-slider-transitions');
}
/**
* @hidden
*/
onHandleDrag(args) {
this.dragging = true;
this.changeValue(eventValue(args, this.track.nativeElement, this.getProps()));
}
/**
* @hidden
*/
onKeyDown = (e) => {
const options = this.getProps();
const { max, min } = options;
const handler = this.keyBinding[e.keyCode];
if (this.isDisabled || !handler) {
return;
}
const value = handler(options);
this.changeValue(trimValue(max, min, value));
e.preventDefault();
};
/**
* @hidden
*/
onHandleRelease() {
this.dragging = false; //needed for animation
this.renderer.addClass(this.hostElement.nativeElement, 'k-slider-transitions');
}
//ngModel binding
/**
* @hidden
*/
writeValue(value) {
this.changeDetector.markForCheck();
this.value = value;
this.sizeComponent(this.animate);
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
*/
changeValue(value) {
if (!areSame(this.value, value)) {
this.ngZone.run(() => {
this.value = value;
this.ngChange(value);
this.valueChange.emit(value);
this.sizeComponent(this.animate);
this.changeDetector.markForCheck();
});
}
this.isSliderInvalid();
}
/**
* @hidden
*/
sizeComponent(animate) {
if (!isDocumentAvailable()) {
return;
}
const wrapper = this.wrapper.nativeElement;
const track = this.track.nativeElement;
const selectionEl = this.sliderSelection.nativeElement;
const dragHandleEl = this.draghandle.nativeElement;
const ticks = this.ticks ? this.ticksContainer.nativeElement : null;
if (!animate) {
this.renderer.removeClass(this.hostElement.nativeElement, 'k-slider-transitions');
}
this.resetStyles([track, selectionEl, dragHandleEl, ticks, this.hostElement.nativeElement]);
const props = this.getProps();
const model = new SliderModel(props, wrapper, track, this.renderer, this.increaseButton);
model.resizeTrack();
if (this.ticks) { //for case when tickPlacement: none
model.resizeTicks(this.ticksContainer.nativeElement, this.ticks.tickElements.map(element => element.nativeElement));
}
model.positionHandle(dragHandleEl);
model.positionSelection(selectionEl);
if (!animate) {
this.hostElement.nativeElement.getBoundingClientRect();
this.renderer.addClass(this.hostElement.nativeElement, 'k-slider-transitions');
}
if (this.fixedTickWidth) {
model.resizeWrapper();
}
}
set focused(value) {
if (this.isFocused !== value && this.hostElement) {
this.isFocused = value;
}
}
set dragging(value) {
if (this.isDragged !== value && this.sliderSelection && this.draghandle) {
const sliderSelection = this.sliderSelection.nativeElement;
const draghandle = this.draghandle.nativeElement;
if (value) {
this.renderer.addClass(sliderSelection, PRESSED$1);
this.renderer.addClass(draghandle, PRESSED$1);
}
else {
this.renderer.removeClass(sliderSelection, PRESSED$1);
this.renderer.removeClass(draghandle, PRESSED$1);
}
this.isDragged = value;
}
}
setValueChangeInterval(element, callback) {
this.ngZone.runOutsideAngular(() => {
const pointerdown = fromEvent(element, 'pointerdown');
const pointerup = fromEvent(element, 'pointerup');
const pointerout = fromEvent(element, 'pointerout');
const subscription = pointerdown.pipe(tap((e) => e.preventDefault()), filter((e) => e.button === 0 && !this.isDisabled), concatMap(() => interval(150).pipe(startWith(-1), takeUntil(merge(pointerup, pointerout))))).subscribe(() => {
if (!this.isFocused) {
invokeElementMethod(this.draghandle, 'focus');
}
callback();
});
this.subscriptions.add(subscription);
});
}
ngChange = (_) => { };
ngTouched = () => { };
decreaseValue = () => {
this.changeValue(decreaseValueToStep(this.value, this.getProps()));
};
increaseValue = () => {
this.changeValue(increaseValueToStep(this.value, this.getProps()));
};
getProps() {
return {
buttons: this.showButtons,
disabled: this.disabled,
fixedTickWidth: this.fixedTickWidth,
largeStep: this.largeStep,
max: this.max,
min: this.min,
readonly: this.readonly,
reverse: this.reverse,
rtl: this.localizationService.rtl,
smallStep: this.smallStep,
value: trimValue(this.max, this.min, this.value),
vertical: this.vertical
};
}
isSliderInvalid() {
const sliderClasses = this.hostElement.nativeElement.classList;
this.isInvalid = sliderClasses.contains('ng-invalid') ? true : false;
this.renderer.setAttribute(this.draghandle.nativeElement, 'aria-invalid', `${this.isInvalid}`);
}
attachElementEventHandlers() {
const hostElement = this.hostElement.nativeElement;
let tabbing = false;
let cursorInsideWrapper = false;
this.ngZone.runOutsideAngular(() => {
// focusIn and focusOut are relative to the host element
this.subscriptions.add(this.renderer.listen(hostElement, 'focusin', () => {
if (!this.isFocused) {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically) {
this.onFocus.emit();
}
this.focused = true;
});
}
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'focusout', (args) => {
if (!this.isFocused) {
return;
}
if (tabbing) {
if (args.relatedTarget !== this.draghandle.nativeElement) {
this.handleBlur();
}
tabbing = false;
}
else {
if (!cursorInsideWrapper) {
this.handleBlur();
}
}
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'mouseenter', () => {
cursorInsideWrapper = true;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'mouseleave', () => {
cursorInsideWrapper = false;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'keydown', (args) => {
if (args.keyCode === Keys.Tab) {
tabbing = true;
}
else {
tabbing = false;
}
}));
});
}
handleBlur = () => {
this.changeDetector.markForCheck();
this.focused = false;
if (hasObservers(this.onBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
if (!this.focusChangedProgrammatically) {
this.onBlur.emit();
}
});
}
};
get decreaseButtonArrowIcon() {
const icon = !this.vertical ?
this.direction === 'ltr' ?
'caret-alt-left' :
'caret-alt-right' :
'caret-alt-down';
return icon;
}
get increaseButtonArrowIcon() {
const icon = !this.vertical ?
this.direction === 'ltr' ?
'caret-alt-right' :
'caret-alt-left' :
'caret-alt-up';
return icon;
}
get decreaseButtonArrowSVGIcon() {
const icon = !this.vertical ?
this.direction === 'ltr' ?
this.arrowLeftIcon :
this.arrowRightIcon :
this.arrowDownIcon;
return icon;
}
get increaseButtonArrowSVGIcon() {
const icon = !this.vertical ?
this.direction === 'ltr' ?
this.arrowRightIcon :
this.arrowLeftIcon :
this.arrowUpIcon;
return icon;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Injector }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SliderComponent, isStandalone: true, selector: "kendo-slider", inputs: { focusableId: "focusableId", dragHandleTitle: "dragHandleTitle", incrementTitle: "incrementTitle", animate: "animate", decrementTitle: "decrementTitle", showButtons: "showButtons", value: "value", tabIndex: "tabIndex" }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.slider' },
{ multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderComponent) },
{ provide: KendoInput, useExisting: forwardRef(() => SliderComponent) }
], viewQueries: [{ propertyName: "draghandle", first: true, predicate: ["draghandle"], descendants: true, static: true }, { propertyName: "decreaseButton", first: true, predicate: ["decreaseButton"], descendants: true, read: ElementRef }, { propertyName: "increaseButton", first: true, predicate: ["increaseButton"], descendants: true, read: ElementRef }], exportAs: ["kendoSlider"], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoSliderLocalizedMessages
i18n-increment="kendo.slider.increment|The title of the **Increase** button of the Slider."
increment="increment"
i18n-decrement="kendo.slider.decrement|The title of the **Decrease** button of the Slider."
decrement="decrement"
i18n-dragHandle="kendo.slider.dragHandle|The title of the drag handle of the Slider."
dragHandle="Drag"
>
<button
kendoButton
#decreaseButton
*ngIf="showButtons"
type="button"
rounded="full"
[icon]="decreaseButtonArrowIcon"
[svgIcon]="decreaseButtonArrowSVGIcon"
class="k-button-decrease"
[title]="decrementMessage"
aria-hidden="true"
[attr.tabindex]="-1"
></button>
<div
#wrap
class="k-slider-track-wrap"
[class.k-slider-topleft]="tickPlacement === 'before'"
[class.k-slider-bottomright]="tickPlacement === 'after'"
[kendoEventsOutsideAngular]="{ click: onWrapClick, keydown: onKeyDown }"
>
<ul kendoSliderTicks
#ticks
*ngIf="tickPlacement !== 'none'"
[tickTitle]="title"
[vertical]="vertical"
[step]="smallStep"
[largeStep]="largeStep"
[min]="min"
[max]="max"
[labelTemplate]="labelTemplate?.templateRef"
aria-hidden="true"
>
</ul>
<div #track class="k-slider-track">
<div #sliderSelection class="k-slider-selection">
</div>
<span #draghandle
role="slider"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="currentValue"
[attr.aria-valuetext]="currentValue"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-orientation]="vertical ? 'vertical' : 'horizontal'"
[style.touch-action]="isDisabled ? '' : 'none'"
class="k-draghandle k-draghandle-end"
[title]="dragHandleMessage"
[attr.tabindex]="disabled ? '-1' : tabIndex"
[id]="focusableId"
kendoDraggable
(kendoPress)="ifEnabled(handleDragPress, $event)"
(kendoDrag)="ifEnabled(onHandleDrag, $event)"
(kendoRelease)="ifEnabled(onHandleRelease, $event)"
></span>
</div>
</div>
<button
kendoButton
#increaseButton
*ngIf="showButtons"
type="button"
rounded="full"
[icon]="increaseButtonArrowIcon"
[svgIcon]="increaseButtonArrowSVGIcon"
class="k-button-increase"
[title]="incrementMessage"
[attr.tabindex]="-1"
aria-hidden="true"
></button>
<kendo-resize-sensor (resize)="sizeComponent(false)"></kendo-resize-sensor>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedSliderMessagesDirective, selector: "[kendoSliderLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { kind: "component", type: SliderTicksComponent, selector: "[kendoSliderTicks]", inputs: ["tickTitle", "vertical", "step", "largeStep", "min", "max", "labelTemplate"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoSlider',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.slider' },
{ multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderComponent) },
{ provide: KendoInput, useExisting: forwardRef(() => SliderComponent) }
],
selector: 'kendo-slider',
template: `
<ng-container kendoSliderLocalizedMessages
i18n-increment="kendo.slider.increment|The title of the **Increase** button of the Slider."
increment="increment"
i18n-decrement="kendo.slider.decrement|The title of the **Decrease** button of the Slider."
decrement="decrement"
i18n-dragHandle="kendo.slider.dragHandle|The title of the drag handle of the Slider."
dragHandle="Drag"
>
<button
kendoButton
#decreaseButton
*ngIf="showButtons"
type="button"
rounded="full"
[icon]="decreaseButtonArrowIcon"
[svgIcon]="decreaseButtonArrowSVGIcon"
class="k-button-decrease"
[title]="decrementMessage"
aria-hidden="true"
[attr.tabindex]="-1"
></button>
<div
#wrap
class="k-slider-track-wrap"
[class.k-slider-topleft]="tickPlacement === 'before'"
[class.k-slider-bottomright]="tickPlacement === 'after'"
[kendoEventsOutsideAngular]="{ click: onWrapClick, keydown: onKeyDown }"
>
<ul kendoSliderTicks
#ticks
*ngIf="tickPlacement !== 'none'"
[tickTitle]="title"
[vertical]="vertical"
[step]="smallStep"
[largeStep]="largeStep"
[min]="min"
[max]="max"
[labelTemplate]="labelTemplate?.templateRef"
aria-hidden="true"
>
</ul>
<div #track class="k-slider-track">
<div #sliderSelection class="k-slider-selection">
</div>
<span #draghandle
role="slider"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="currentValue"
[attr.aria-valuetext]="currentValue"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-orientation]="vertical ? 'vertical' : 'horizontal'"
[style.touch-action]="isDisabled ? '' : 'none'"
class="k-draghandle k-draghandle-end"
[title]="dragHandleMessage"
[attr.tabindex]="disabled ? '-1' : tabIndex"
[id]="focusableId"
kendoDraggable
(kendoPress)="ifEnabled(handleDragPress, $event)"
(kendoDrag)="ifEnabled(onHandleDrag, $event)"
(kendoRelease)="ifEnabled(onHandleRelease, $event)"
></span>
</div>
</div>
<button
kendoButton
#increaseButton
*ngIf="showButtons"
type="button"
rounded="full"
[icon]="increaseButtonArrowIcon"
[svgIcon]="increaseButtonArrowSVGIcon"
class="k-button-increase"
[title]="incrementMessage"
[attr.tabindex]="-1"
aria-hidden="true"
></button>
<kendo-resize-sensor (resize)="sizeComponent(false)"></kendo-resize-sensor>
`,
standalone: true,
imports: [LocalizedSliderMessagesDirective, NgIf, ButtonComponent, EventsOutsideAngularDirective, SliderTicksComponent, DraggableDirective, ResizeSensorComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Injector }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { focusableId: [{
type: Input
}], dragHandleTitle: [{
type: Input
}], incrementTitle: [{
type: Input
}], animate: [{
type: Input
}], decrementTitle: [{
type: Input
}], showButtons: [{
type: Input
}], value: [{
type: Input
}], tabIndex: [{
type: Input
}], draghandle: [{
type: ViewChild,
args: ['draghandle', { static: true }]
}], decreaseButton: [{
type: ViewChild,
args: ['decreaseButton', { read: ElementRef }]
}], increaseButton: [{
type: ViewChild,
args: ['increaseButton', { read: ElementRef }]
}] } });
/**
* @hidden
*/
class RangeSliderModel extends SliderModelBase {
startHandlePosition;
endHandlePosition;
positionHandle(dragHandle) {
if (!dragHandle.id) {
return;
}
const { max, min, reverse, vertical } = this.props;
const position = vertical ? 'bottom' : reverse ? 'right' : 'left';
const trackWidth = this.trackWidth();
const value = isStartHandle(dragHandle) ? trimValueRange(max, min, this.props.value)[0]
: trimValueRange(max, min, this.props.value)[1];
if (isStartHandle(dragHandle)) {
this.startHandlePosition = calculateHandlePosition({
min,
max,
reverse,
value,
trackWidth
});
this.renderer.setStyle(dragHandle, position, `${this.startHandlePosition}px`);
}
else {
this.endHandlePosition = calculateHandlePosition({
min,
max,
reverse,
value,
trackWidth
});
this.renderer.setStyle(dragHandle, position, `${this.endHandlePosition}px`);
}
}
positionSelection(dragHandle, selection) {
const { reverse, vertical } = this.props;
const dimension = vertical ? 'height' : 'width';
const position = vertical ? 'bottom' : reverse ? 'right' : 'left';
const size = Math.abs(this.endHandlePosition - this.startHandlePosition);
const currentSelectionPosition = vertical ? dragHandle.style.bottom : reverse ? dragHandle.style.right : dragHandle.style.left;
this.renderer.setStyle(selection, dimension, `${size}px`);
this.renderer.setStyle(selection, position, parseFloat(currentSelectionPosition) + 'px');
}
}
/**
* @hidden
*/
class RangeSliderMessages extends ComponentMessages {
/**
* The title of the range `start` drag handle.
*/
dragHandleStart;
/**
* The title of the range `end` drag handle.
*/
dragHandleEnd;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RangeSliderMessages, selector: "kendo-rangeslider-messages-base", inputs: { dragHandleStart: "dragHandleStart", dragHandleEnd: "dragHandleEnd" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-rangeslider-messages-base'
}]
}], propDecorators: { dragHandleStart: [{
type: Input
}], dragHandleEnd: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedRangeSliderMessagesDirective extends RangeSliderMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedRangeSliderMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedRangeSliderMessagesDirective, isStandalone: true, selector: "[kendoSliderLocalizedMessages]", providers: [
{
provide: RangeSliderMessages,
useExisting: forwardRef(() => LocalizedRangeSliderMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedRangeSliderMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: RangeSliderMessages,
useExisting: forwardRef(() => LocalizedRangeSliderMessagesDirective)
}
],
selector: '[kendoSliderLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
const PRESSED = 'k-pressed';
/**
* Represents the [Kendo UI RangeSlider component for Angular]({% slug overview_rangeslider %}).
*/
class RangeSliderComponent extends SliderBase {
localization;
injector;
renderer;
ngZone;
changeDetector;
hostElement;
/**
* Sets the range value of the RangeSlider.
* The component can use either NgModel or the `value` binding but not both of them at the same time.
*/
value;
draghandleStart;
draghandleEnd;
/**
* @hidden
*/
startHandleId = `k-start-handle-${guid()}`;
/**
* @hidden
*/
endHandleId = `k-end-handle-${guid()}`;
/**
* @hidden
*/
focusableId = this.startHandleId;
draggedHandle;
lastHandlePosition;
activeHandle = 'startHandle';
focusChangedProgrammatically = false;
isInvalid;
constructor(localization, injector, renderer, ngZone, changeDetector, hostElement) {
super(localization, injector, renderer, ngZone, changeDetector, hostElement);
this.localization = localization;
this.injector = injector;
this.renderer = renderer;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.hostElement = hostElement;
}
/**
* Focuses the RangeSlider.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <div>
* <button class="k-button" (click)="slider.focus()">Focus</button>
* </div>
* <kendo-rangeslider #slider></kendo-rangeslider>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
this.focusChangedProgrammatically = true;
invokeElementMethod(this.draghandleStart, 'focus');
this.focusChangedProgrammatically = false;
}
/**
* Blurs the RangeSlider.
*/
blur() {
this.focusChangedProgrammatically = true;
const activeHandle = this.activeHandle === 'startHandle' ? this.draghandleStart : this.draghandleEnd;
invokeElementMethod(activeHandle, 'blur');
this.handleBlur();
this.focusChangedProgrammatically = false;
}
ngOnInit() {
if (!this.value) {
this.value = [this.min, this.max];
}
super.ngOnInit();
}
ngOnChanges(changes) {
if (anyChanged(['value', 'fixedTickWidth', 'tickPlacement'], changes, true)) {
if (changes['value'] && changes['value'].currentValue) {
validateValue(changes['value'].currentValue);
}
this.ngZone.onStable.asObservable().pipe(take(1)).subscribe(() => {
this.sizeComponent();
});
}
}
ngAfterViewInit() {
if (!isDocumentAvailable()) {
return;
}
this.sizeComponent();
if (this.ticks) {
this.ticks.tickElements
.changes
.subscribe(() => this.sizeComponent());
}
this.isRangeSliderInvalid();
this.attachElementEventHandlers();
}
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
}
}
/**
* @hidden
*/
textFor(key) {
return this.localization.get(key);
}
/**
* @hidden
*/
get valueText() {
return this.value ? `${this.value[0]} - ${this.value[1]}` : '';
}
/**
* @hidden
*/
onWrapClick = (args) => {
if (!this.isDisabled) {
this.value = this.value || [this.min, this.min];
const trackValue = eventValue(args, this.track.nativeElement, this.getProps());
let newRangeValue;
const [startValue, endValue] = newRangeValue = this.value;
if (trackValue <= startValue) {
newRangeValue = [trackValue, endValue];
this.activeHandle = 'startHandle';
}
else if (startValue < trackValue && trackValue < endValue) {
if (trackValue < (startValue + endValue) / 2) {
newRangeValue = [trackValue, endValue];
this.activeHandle = 'startHandle';
}
else {
newRangeValue = [startValue, trackValue];
this.activeHandle = 'endHandle';
}
}
else if (trackValue >= endValue) {
newRangeValue = [startValue, trackValue];
this.activeHandle = 'endHandle';
}
const activeHandle = this.activeHandle === 'startHandle' ? this.draghandleStart : this.draghandleEnd;
invokeElementMethod(activeHandle, 'focus');
this.changeValue(newRangeValue);
}
};
/**
* @hidden
*/
handleDragPress(args) {
if (args.originalEvent) {
args.originalEvent.preventDefault();
}
const target = args.originalEvent.target;
this.draggedHandle = target;
const nonDraggedHandle = this.draghandleStart.nativeElement === this.draggedHandle ? this.draghandleEnd.nativeElement : this.draghandleStart.nativeElement;
this.renderer.removeStyle(nonDraggedHandle, 'zIndex');
this.renderer.setStyle(target, 'zIndex', 1);
}
/**
* @hidden
*/
onHandleDrag(args) {
this.value = this.value || [this.min, this.min];
const target = args.originalEvent.target;
const lastCoords = this.draggedHandle.getBoundingClientRect();
this.lastHandlePosition = { x: lastCoords.left, y: lastCoords.top };
this.dragging = { value: true, target };
const mousePos = {
x: (args.pageX - 0.5) - (lastCoords.width / 2),
y: (args.pageY - (lastCoords.width / 2))
};
const left = mousePos.x < this.lastHandlePosition.x;
const right = mousePos.x > this.lastHandlePosition.x;
const up = mousePos.y > this.lastHandlePosition.y;
const moveStartHandle = () => this.changeValue([eventValue(args, this.track.nativeElement, this.getProps()), this.value[1]]);
const moveEndHandle = () => this.changeValue([this.value[0], eventValue(args, this.track.nativeElement, this.getProps())]);
const moveBothHandles = () => this.changeValue([eventValue(args, this.track.nativeElement, this.getProps()), eventValue(args, this.track.nativeElement, this.getProps())]);
const activeStartHandle = isStartHandle(this.draggedHandle);
const vertical = this.vertical;
const horizontal = !vertical;
const forward = (vertical && up) || (this.reverse ? horizontal && right : horizontal && left);
const incorrectValueState = this.value[0] > this.value[1];
if (this.value[0] === this.value[1] || incorrectValueState) {
if (forward) {
// eslint-disable-next-line no-unused-expressions
activeStartHandle ? moveStartHandle() : moveBothHandles();
}
else {
// eslint-disable-next-line no-unused-expressions
activeStartHandle ? moveBothHandles() : moveEndHandle();
}
}
else {
// eslint-disable-next-line no-unused-expressions
activeStartHandle ? moveStartHandle() : moveEndHandle();
}
}
/**
* @hidden
*/
onKeyDown = (e) => {
this.value = this.value || [this.min, this.min];
const options = this.getProps();
const { max, min } = options;
const handler = this.keyBinding[e.keyCode];
if (this.isDisabled || !handler) {
return;
}
const startHandleIsActive = isStartHandle(e.target);
const nonDraggedHandle = startHandleIsActive ? this.draghandleEnd.nativeElement : this.draghandleStart.nativeElement;
this.renderer.removeStyle(nonDraggedHandle, 'zIndex');
this.renderer.setStyle(e.target, 'zIndex', 1);
const value = handler({ ...options, value: startHandleIsActive ? this.value[0] : this.value[1] });
if (startHandleIsActive) {
if (value > this.value[1]) {
this.value[1] = value;
}
}
else {
if (value < this.value[0]) {
this.value[0] = value;
}
}
const trimmedValue = trimValue(max, min, value);
const newValue = startHandleIsActive ? [trimmedValue, this.value[1]]
: [this.value[0], trimmedValue];
this.changeValue(newValue);
e.preventDefault();
};
/**
* @hidden
*/
onHandleRelease(args) {
this.dragging = { value: false, target: args.originalEvent.target }; //needed for animation
this.draggedHandle = undefined;
}
//ngModel binding
/**
* @hidden
*/
writeValue(value) {
validateValue(value);
this.value = value;
this.sizeComponent();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
*/
changeValue(value) {
if (!this.value || !isSameRange(this.value, value)) {
this.ngZone.run(() => {
this.value = value;
this.ngChange(value);
if (this.value) {
this.valueChange.emit(value);
}
this.sizeComponent();
});
}
this.isRangeSliderInvalid();
}
/**
* @hidden
*/
sizeComponent() {
if (!isDocumentAvailable()) {
return;
}
const wrapper = this.wrapper.nativeElement;
const track = this.track.nativeElement;
const selectionEl = this.sliderSelection.nativeElement;
const dragHandleStartEl = this.draghandleStart.nativeElement;
const dragHandleEndEl = this.draghandleEnd.nativeElement;
const ticks = this.ticks ? this.ticksContainer.nativeElement : null;
this.resetStyles([track, selectionEl, dragHandleStartEl, dragHandleEndEl, ticks, this.hostElement.nativeElement]);
const props = this.getProps();
const model = new RangeSliderModel(props, wrapper, track, this.renderer);
model.resizeTrack();
if (this.ticks) { //for case when tickPlacement: none
model.resizeTicks(this.ticksContainer.nativeElement, this.ticks.tickElements.map(element => element.nativeElement));
}
model.positionHandle(dragHandleStartEl);
model.positionHandle(dragHandleEndEl);
model.positionSelection(dragHandleStartEl, selectionEl);
if (this.fixedTickWidth) {
model.resizeWrapper();
}
}
/**
* @hidden
*/
get isDisabled() {
return this.disabled || this.readonly;
}
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
set focused(value) {
if (this.isFocused !== value && this.hostElement) {
this.isFocused = value;
}
}
set dragging(data) {
if (this.isDragged !== data.value && this.sliderSelection && this.draghandleStart && this.draghandleEnd) {
const sliderSelection = this.sliderSelection.nativeElement;
const draghandle = data.target;
if (data.value) {
this.renderer.addClass(sliderSelection, PRESSED);
this.renderer.addClass(draghandle, PRESSED);
}
else {
this.renderer.removeClass(sliderSelection, PRESSED);
this.renderer.removeClass(draghandle, PRESSED);
}
this.isDragged = data.value;
}
}
ngChange = (_) => { };
ngTouched = () => { };
getProps() {
return {
disabled: this.disabled,
fixedTickWidth: this.fixedTickWidth,
largeStep: this.largeStep,
max: this.max,
min: this.min,
readonly: this.readonly,
reverse: this.reverse,
rtl: this.localizationService.rtl,
smallStep: this.smallStep,
value: trimValueRange(this.max, this.min, this.value),
vertical: this.vertical,
buttons: false
};
}
isRangeSliderInvalid() {
const rangeSliderClasses = this.hostElement.nativeElement.classList;
this.isInvalid = rangeSliderClasses.contains('ng-invalid') ? true : false;
this.renderer.setAttribute(this.draghandleStart.nativeElement, 'aria-invalid', `${this.isInvalid}`);
this.renderer.setAttribute(this.draghandleEnd.nativeElement, 'aria-invalid', `${this.isInvalid}`);
}
attachElementEventHandlers() {
const hostElement = this.hostElement.nativeElement;
let tabbing = false;
let cursorInsideWrapper = false;
this.ngZone.runOutsideAngular(() => {
// focusIn and focusOut are relative to the host element
this.subscriptions.add(this.renderer.listen(hostElement, 'focusin', () => {
if (!this.isFocused) {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically) {
this.onFocus.emit();
}
this.focused = true;
});
}
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'focusout', (args) => {
if (!this.isFocused) {
return;
}
if (tabbing) {
if (args.relatedTarget !== this.draghandleStart.nativeElement && args.relatedTarget !== this.draghandleEnd.nativeElement) {
this.handleBlur();
}
tabbing = false;
}
else {
if (!cursorInsideWrapper) {
this.handleBlur();
}
}
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'mouseenter', () => {
cursorInsideWrapper = true;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'mouseleave', () => {
cursorInsideWrapper = false;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'keydown', (args) => {
if (args.keyCode === Keys.Tab) {
tabbing = true;
}
else {
tabbing = false;
}
}));
});
}
handleBlur = () => {
this.changeDetector.markForCheck();
this.focused = false;
if (hasObservers(this.onBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
if (!this.focusChangedProgrammatically) {
this.onBlur.emit();
}
});
}
};
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Injector }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RangeSliderComponent, isStandalone: true, selector: "kendo-rangeslider", inputs: { value: "value" }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.rangeslider' },
{ multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RangeSliderComponent) },
{ provide: KendoInput, useExisting: forwardRef(() => RangeSliderComponent) }
], viewQueries: [{ propertyName: "draghandleStart", first: true, predicate: ["draghandleStart"], descendants: true, static: true }, { propertyName: "draghandleEnd", first: true, predicate: ["draghandleEnd"], descendants: true, static: true }], exportAs: ["kendoRangeSlider"], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoSliderLocalizedMessages
i18n-dragHandleStart="kendo.rangeslider.dragHandleStart|The title of the **Start** drag handle of the Slider."
dragHandleStart="Drag"
i18n-dragHandleEnd="kendo.rangeslider.dragHandleEnd|The title of the **End** drag handle of the Slider."
dragHandleEnd="Drag"
>
<div
#wrap
class="k-slider-track-wrap"
[class.k-slider-topleft]="tickPlacement === 'before'"
[class.k-slider-bottomright]="tickPlacement === 'after'"
[kendoEventsOutsideAngular]="{ click: onWrapClick, keydown: onKeyDown }"
>
<ul kendoSliderTicks
#ticks
*ngIf="tickPlacement !== 'none'"
[tickTitle]="title"
[vertical]="vertical"
[step]="smallStep"
[largeStep]="largeStep"
[min]="min"
[max]="max"
[labelTemplate]="labelTemplate?.templateRef"
[attr.aria-hidden]="true"
>
</ul>
<div #track class="k-slider-track">
<div #sliderSelection class="k-slider-selection">
</div>
<span #draghandleStart
role="slider"
[id]="startHandleId"
[attr.tabindex]="disabled ? undefined : tabindex"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="value ? value[0] : null"
[attr.aria-valuetext]="valueText"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-orientation]="vertical ? 'vertical' : 'horizontal'"
[style.touch-action]="isDisabled ? '' : 'none'"
class="k-draghandle"
[title]="textFor('dragHandleStart')"
kendoDraggable
(kendoPress)="ifEnabled(handleDragPress ,$event)"
(kendoDrag)="ifEnabled(onHandleDrag ,$event)"
(kendoRelease)="ifEnabled(onHandleRelease, $event)"
></span>
<span #draghandleEnd
role="slider"
[id]="endHandleId"
[attr.tabindex]="disabled ? undefined : tabindex"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="value ? value[1] : null"
[attr.aria-valuetext]="valueText"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-orientation]="vertical ? 'vertical' : 'horizontal'"
[style.touch-action]="isDisabled ? '' : 'none'"
class="k-draghandle"
[title]="textFor('dragHandleEnd')"
kendoDraggable
(kendoPress)="ifEnabled(handleDragPress ,$event)"
(kendoDrag)="ifEnabled(onHandleDrag ,$event)"
(kendoRelease)="ifEnabled(onHandleRelease, $event)"
></span>
</div>
</div>
<kendo-resize-sensor (resize)="sizeComponent()"></kendo-resize-sensor>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedRangeSliderMessagesDirective, selector: "[kendoSliderLocalizedMessages]" }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: SliderTicksComponent, selector: "[kendoSliderTicks]", inputs: ["tickTitle", "vertical", "step", "largeStep", "min", "max", "labelTemplate"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoRangeSlider',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.rangeslider' },
{ multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RangeSliderComponent) },
{ provide: KendoInput, useExisting: forwardRef(() => RangeSliderComponent) }
],
selector: 'kendo-rangeslider',
template: `
<ng-container kendoSliderLocalizedMessages
i18n-dragHandleStart="kendo.rangeslider.dragHandleStart|The title of the **Start** drag handle of the Slider."
dragHandleStart="Drag"
i18n-dragHandleEnd="kendo.rangeslider.dragHandleEnd|The title of the **End** drag handle of the Slider."
dragHandleEnd="Drag"
>
<div
#wrap
class="k-slider-track-wrap"
[class.k-slider-topleft]="tickPlacement === 'before'"
[class.k-slider-bottomright]="tickPlacement === 'after'"
[kendoEventsOutsideAngular]="{ click: onWrapClick, keydown: onKeyDown }"
>
<ul kendoSliderTicks
#ticks
*ngIf="tickPlacement !== 'none'"
[tickTitle]="title"
[vertical]="vertical"
[step]="smallStep"
[largeStep]="largeStep"
[min]="min"
[max]="max"
[labelTemplate]="labelTemplate?.templateRef"
[attr.aria-hidden]="true"
>
</ul>
<div #track class="k-slider-track">
<div #sliderSelection class="k-slider-selection">
</div>
<span #draghandleStart
role="slider"
[id]="startHandleId"
[attr.tabindex]="disabled ? undefined : tabindex"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="value ? value[0] : null"
[attr.aria-valuetext]="valueText"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-orientation]="vertical ? 'vertical' : 'horizontal'"
[style.touch-action]="isDisabled ? '' : 'none'"
class="k-draghandle"
[title]="textFor('dragHandleStart')"
kendoDraggable
(kendoPress)="ifEnabled(handleDragPress ,$event)"
(kendoDrag)="ifEnabled(onHandleDrag ,$event)"
(kendoRelease)="ifEnabled(onHandleRelease, $event)"
></span>
<span #draghandleEnd
role="slider"
[id]="endHandleId"
[attr.tabindex]="disabled ? undefined : tabindex"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="value ? value[1] : null"
[attr.aria-valuetext]="valueText"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-orientation]="vertical ? 'vertical' : 'horizontal'"
[style.touch-action]="isDisabled ? '' : 'none'"
class="k-draghandle"
[title]="textFor('dragHandleEnd')"
kendoDraggable
(kendoPress)="ifEnabled(handleDragPress ,$event)"
(kendoDrag)="ifEnabled(onHandleDrag ,$event)"
(kendoRelease)="ifEnabled(onHandleRelease, $event)"
></span>
</div>
</div>
<kendo-resize-sensor (resize)="sizeComponent()"></kendo-resize-sensor>
`,
standalone: true,
imports: [LocalizedRangeSliderMessagesDirective, EventsOutsideAngularDirective, NgIf, SliderTicksComponent, DraggableDirective, ResizeSensorComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Injector }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { value: [{
type: Input
}], draghandleStart: [{
type: ViewChild,
args: ['draghandleStart', { static: true }]
}], draghandleEnd: [{
type: ViewChild,
args: ['draghandleEnd', { static: true }]
}] } });
/**
* @hidden
*/
class Messages extends ComponentMessages {
/**
* The title of the **On** button of the Switch.
*/
on;
/**
* The title of the **Off** button of the Switch.
*/
off;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: Messages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: Messages, selector: "kendo-switch-messages-base", inputs: { on: "on", off: "off" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: Messages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-switch-messages-base'
}]
}], propDecorators: { on: [{
type: Input
}], off: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedSwitchMessagesDirective extends Messages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedSwitchMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedSwitchMessagesDirective, isStandalone: true, selector: "[kendoSwitchLocalizedMessages]", providers: [
{
provide: Messages,
useExisting: forwardRef(() => LocalizedSwitchMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedSwitchMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: Messages,
useExisting: forwardRef(() => LocalizedSwitchMessagesDirective)
}
],
selector: '[kendoSwitchLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
const FOCUSED$5 = 'k-focus';
const DEFAULT_SIZE$e = 'medium';
const DEFAULT_THUMB_ROUNDED = 'full';
const DEFAULT_TRACK_ROUNDED = 'full';
/**
* Represents the [Kendo UI Switch component for Angular]({% slug overview_switch %}).
*/
class SwitchComponent {
renderer;
hostElement;
localizationService;
injector;
changeDetector;
ngZone;
/**
* @hidden
*/
get focusableId() {
if (this.hostElement.nativeElement.hasAttribute('id')) {
return this.hostElement.nativeElement.getAttribute('id');
}
return `k-${guid()}`;
}
/**
* Sets the **On** label ([see example]({% slug labels_switch %})).
* Takes precedence over the [custom messages component]({% slug api_inputs_switchcustommessagescomponent %}).
*/
onLabel;
/**
* Sets the **Off** label ([see example]({% slug labels_switch %})).
* Takes precedence over the [custom messages component]({% slug api_inputs_switchcustommessagescomponent %}).
*/
offLabel;
/**
* Sets the value of the Switch when it is initially displayed.
*/
set checked(value) {
this.setHostClasses(value);
this._checked = value;
}
get checked() {
return this._checked;
}
/**
* Determines whether the Switch is disabled ([see example]({% slug disabled_switch %})). To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_switch#toc-managing-the-switch-disabled-state-in-reactive-forms).
*/
disabled = false;
/**
* Determines whether the Switch is in its read-only state ([see example]({% slug readonly_switch %})).
*
* @default false
*/
readonly = false;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the Switch.
*/
tabindex = 0;
/**
* Specifies the width and height of the Switch.
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$e;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* Specifies the border radius of the Switch thumb.
*
* The possible values are:
* * `full` (default)
* * `small`
* * `medium`
* * `large`
* * `none`
*/
set thumbRounded(thumbRounded) {
const newThumbRounded = thumbRounded ? thumbRounded : DEFAULT_THUMB_ROUNDED;
this.handleThumbClasses(newThumbRounded);
this._thumbRounded = newThumbRounded;
}
get thumbRounded() {
return this._thumbRounded;
}
/**
* Specifies the border radius of the Switch track.
*
* The possible values are:
* * `full` (default)
* * `small`
* * `medium`
* * `large`
* * `none`
*/
set trackRounded(trackRounded) {
const newTrackRounded = trackRounded ? trackRounded : DEFAULT_TRACK_ROUNDED;
this.handleTrackClasses(newTrackRounded);
this._trackRounded = newTrackRounded;
}
get trackRounded() {
return this._trackRounded;
}
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* Fires each time the Switch component is focused as a result of user interaction.
*/
onFocus = new EventEmitter();
/**
* Fires each time the Switch component is blurred as a result of user interaction.
*/
onBlur = new EventEmitter();
/**
* Fires each time the user selects a new value.
*/
valueChange = new EventEmitter();
direction;
get ieClass() {
return browser && browser.msie;
}
hostRole = 'switch';
get hostId() {
return this.focusableId;
}
get ariaChecked() {
return this.checked;
}
get ariaInvalid() {
return this.isControlInvalid ? true : undefined;
}
get hostTabIndex() {
return this.disabled ? undefined : this.tabIndex;
}
get ariaDisabled() {
return this.disabled ? true : undefined;
}
get ariaReadonly() {
return this.readonly;
}
hostClasses = true;
get disabledClass() {
return this.disabled;
}
track;
thumb;
/**
* @hidden
*/
initialized = false;
localizationChangeSubscription;
isFocused;
control;
domSubscriptions = [];
_checked = false;
_size = 'medium';
_trackRounded = 'full';
_thumbRounded = 'full';
constructor(renderer, hostElement, localizationService, injector, changeDetector, ngZone) {
this.renderer = renderer;
this.hostElement = hostElement;
this.localizationService = localizationService;
this.injector = injector;
this.changeDetector = changeDetector;
this.ngZone = ngZone;
validatePackage(packageMetadata);
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
this.keyDownHandler = this.keyDownHandler.bind(this);
this.clickHandler = this.clickHandler.bind(this);
}
/**
* @hidden
*/
get onLabelMessage() {
return this.onLabel !== undefined ? this.onLabel : this.localizationService.get('on');
}
/**
* @hidden
*/
get offLabelMessage() {
return this.offLabel !== undefined ? this.offLabel : this.localizationService.get('off');
}
ngChange = (_) => { };
ngTouched = () => { };
get isEnabled() {
return !this.disabled && !this.readonly;
}
ngOnInit() {
if (this.hostElement) {
const wrapper = this.hostElement.nativeElement;
this.renderer.removeAttribute(wrapper, "tabindex");
}
this.localizationChangeSubscription = this.localizationService
.changes
.pipe(skip(1))
.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
this.control = this.injector.get(NgControl, null);
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.initialized = true);
}
ngAfterViewInit() {
const wrapper = this.hostElement.nativeElement;
if (!this.checked && !wrapper.classList.contains('k-switch-off')) {
this.renderer.addClass(wrapper, 'k-switch-off');
}
this.handleClasses(this.size, 'size');
this.handleTrackClasses(this.trackRounded);
this.handleThumbClasses(this.thumbRounded);
this.attachHostHandlers();
}
ngOnDestroy() {
if (this.localizationChangeSubscription) {
this.localizationChangeSubscription.unsubscribe();
}
this.domSubscriptions.forEach(subscription => subscription());
const wrapper = this.hostElement.nativeElement;
wrapper.removeEventListener('focus', this.handleFocus, true);
wrapper.removeEventListener('blur', this.handleBlur, true);
}
/**
* Focuses the Switch.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <button (click)="switch.focus()">Focus</button>
* <kendo-switch #switch></kendo-switch>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
if (!this.hostElement) {
return;
}
this.hostElement.nativeElement.focus();
}
/**
* Blurs the Switch.
*/
blur() {
if (!this.hostElement) {
return;
}
this.hostElement.nativeElement.blur();
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this.changeDetector.markForCheck();
}
/**
* @hidden
*/
handleFocus = (event) => {
if (this.isFocused) {
return;
}
event.stopImmediatePropagation();
this.focused = true;
if (hasObservers(this.onFocus)) {
this.ngZone.run(() => {
const eventArgs = { originalEvent: event };
this.onFocus.emit(eventArgs);
});
}
};
/**
* @hidden
*/
handleBlur = (event) => {
const relatedTarget = event && event.relatedTarget;
if (this.hostElement.nativeElement.contains(relatedTarget)) {
return;
}
event.stopImmediatePropagation();
this.changeDetector.markForCheck();
this.focused = false;
if (hasObservers(this.onBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
const eventArgs = { originalEvent: event };
this.onBlur.emit(eventArgs);
});
}
};
/**
* @hidden
*/
get isControlInvalid() {
return this.control && this.control.touched && !this.control.valid;
}
/**
* @hidden
*/
writeValue(value) {
this.checked = value === null ? false : value;
this.changeDetector.markForCheck();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
*/
keyDownHandler(e) {
const keyCode = e.keyCode;
if (this.isEnabled && (keyCode === Keys.Space || keyCode === Keys.Enter)) {
this.changeValue(!this.checked);
e.preventDefault();
}
}
/**
* @hidden
*/
clickHandler() {
if (this.isEnabled) {
this.changeValue(!this.checked);
}
}
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
changeValue(value) {
if (this.checked !== value) {
this.ngZone.run(() => {
this.checked = value;
this.ngChange(value);
this.valueChange.emit(value);
this.changeDetector.markForCheck();
});
}
}
set focused(value) {
if (this.isFocused !== value && this.hostElement) {
const wrapper = this.hostElement.nativeElement;
if (value) {
this.renderer.addClass(wrapper, FOCUSED$5);
}
else {
this.renderer.removeClass(wrapper, FOCUSED$5);
}
this.isFocused = value;
}
}
attachHostHandlers() {
this.ngZone.runOutsideAngular(() => {
const wrapper = this.hostElement.nativeElement;
this.domSubscriptions.push(this.renderer.listen(wrapper, 'click', this.clickHandler), this.renderer.listen(wrapper, 'keydown', this.keyDownHandler));
wrapper.addEventListener('focus', this.handleFocus, true);
wrapper.addEventListener('blur', this.handleBlur, true);
});
}
setHostClasses(value) {
const wrapper = this.hostElement.nativeElement;
if (value) {
this.renderer.removeClass(wrapper, 'k-switch-off');
this.renderer.addClass(wrapper, 'k-switch-on');
}
else {
this.renderer.removeClass(wrapper, 'k-switch-on');
this.renderer.addClass(wrapper, 'k-switch-off');
}
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('switch', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
handleTrackClasses(value) {
const track = this.track?.nativeElement;
if (!track) {
return;
}
const classes = getStylingClasses('switch', 'rounded', this.trackRounded, value);
if (classes.toRemove) {
this.renderer.removeClass(track, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(track, classes.toAdd);
}
}
handleThumbClasses(value) {
const thumb = this.thumb?.nativeElement;
if (!thumb) {
return;
}
const classes = getStylingClasses('switch', 'rounded', this.thumbRounded, value);
if (classes.toRemove) {
this.renderer.removeClass(thumb, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(thumb, classes.toAdd);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.LocalizationService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SwitchComponent, isStandalone: true, selector: "kendo-switch", inputs: { focusableId: "focusableId", onLabel: "onLabel", offLabel: "offLabel", checked: "checked", disabled: "disabled", readonly: "readonly", tabindex: "tabindex", size: "size", thumbRounded: "thumbRounded", trackRounded: "trackRounded", tabIndex: "tabIndex" }, outputs: { onFocus: "focus", onBlur: "blur", valueChange: "valueChange" }, host: { properties: { "class.k-readonly": "this.readonly", "attr.dir": "this.direction", "class.k-ie": "this.ieClass", "attr.role": "this.hostRole", "attr.id": "this.hostId", "attr.aria-checked": "this.ariaChecked", "attr.aria-invalid": "this.ariaInvalid", "attr.tabindex": "this.hostTabIndex", "attr.aria-disabled": "this.ariaDisabled", "attr.aria-readonly": "this.ariaReadonly", "class.k-switch": "this.hostClasses", "class.k-disabled": "this.disabledClass" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.switch' },
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SwitchComponent) /* eslint-disable-line*/
},
{
provide: KendoInput,
useExisting: forwardRef(() => SwitchComponent)
}
], viewQueries: [{ propertyName: "track", first: true, predicate: ["track"], descendants: true, static: true }, { propertyName: "thumb", first: true, predicate: ["thumb"], descendants: true, static: true }], exportAs: ["kendoSwitch"], ngImport: i0, template: `
<ng-container kendoSwitchLocalizedMessages
i18n-on="kendo.switch.on|The **On** label of the Switch."
on="ON"
i18n-off="kendo.switch.off|The **Off** label of the Switch."
off="OFF"
>
<span
#track
class="k-switch-track"
[style.transitionDuration]="initialized ? '200ms' : '0ms'"
>
<span class="k-switch-label-on" [attr.aria-hidden]="true" >{{onLabelMessage}}</span>
<span class="k-switch-label-off" [attr.aria-hidden]="true">{{offLabelMessage}}</span>
</span>
<span
class="k-switch-thumb-wrap"
[style.transitionDuration]="initialized ? '200ms' : '0ms'">
<span #thumb class="k-switch-thumb"></span>
</span>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedSwitchMessagesDirective, selector: "[kendoSwitchLocalizedMessages]" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoSwitch',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.switch' },
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SwitchComponent) /* eslint-disable-line*/
},
{
provide: KendoInput,
useExisting: forwardRef(() => SwitchComponent)
}
],
selector: 'kendo-switch',
template: `
<ng-container kendoSwitchLocalizedMessages
i18n-on="kendo.switch.on|The **On** label of the Switch."
on="ON"
i18n-off="kendo.switch.off|The **Off** label of the Switch."
off="OFF"
>
<span
#track
class="k-switch-track"
[style.transitionDuration]="initialized ? '200ms' : '0ms'"
>
<span class="k-switch-label-on" [attr.aria-hidden]="true" >{{onLabelMessage}}</span>
<span class="k-switch-label-off" [attr.aria-hidden]="true">{{offLabelMessage}}</span>
</span>
<span
class="k-switch-thumb-wrap"
[style.transitionDuration]="initialized ? '200ms' : '0ms'">
<span #thumb class="k-switch-thumb"></span>
</span>
`,
standalone: true,
imports: [LocalizedSwitchMessagesDirective]
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.LocalizationService }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }]; }, propDecorators: { focusableId: [{
type: Input
}], onLabel: [{
type: Input
}], offLabel: [{
type: Input
}], checked: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], tabindex: [{
type: Input
}], size: [{
type: Input
}], thumbRounded: [{
type: Input
}], trackRounded: [{
type: Input
}], tabIndex: [{
type: Input
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], valueChange: [{
type: Output
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], ieClass: [{
type: HostBinding,
args: ['class.k-ie']
}], hostRole: [{
type: HostBinding,
args: ['attr.role']
}], hostId: [{
type: HostBinding,
args: ['attr.id']
}], ariaChecked: [{
type: HostBinding,
args: ['attr.aria-checked']
}], ariaInvalid: [{
type: HostBinding,
args: ['attr.aria-invalid']
}], hostTabIndex: [{
type: HostBinding,
args: ['attr.tabindex']
}], ariaDisabled: [{
type: HostBinding,
args: ['attr.aria-disabled']
}], ariaReadonly: [{
type: HostBinding,
args: ['attr.aria-readonly']
}], hostClasses: [{
type: HostBinding,
args: ['class.k-switch']
}], disabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], track: [{
type: ViewChild,
args: ['track', { static: true }]
}], thumb: [{
type: ViewChild,
args: ['thumb', { static: true }]
}] } });
/**
* Represents the [Kendo UI TextBox directive]({% slug overview_textbox %}) for the Inputs components for Angular.
* Used to style the textbox of any `input` element.
*
* @example
* ```ts-no-run
* <input kendoTextBox />
* <input kendoTextBox type="email" />
* <input kendoTextBox type="password" />
* ```
*/
class TextBoxDirective {
renderer;
inputElement;
ngZone;
hostClasses = true;
/**
* @hidden
*/
onFocus = new EventEmitter();
/**
* @hidden
*/
onBlur = new EventEmitter();
/**
* @hidden
*/
onValueChange = new EventEmitter();
/**
* @hidden
*/
autoFillStart = new EventEmitter();
/**
* @hidden
*/
autoFillEnd = new EventEmitter();
/**
* @hidden
*/
set value(text) {
if (!this.inputElement) {
return;
}
this.inputElement.nativeElement.value = (text === undefined || text === null) ? '' : text;
this.onValueChange.emit();
}
/**
* @hidden
*/
get value() {
return this.inputElement.nativeElement.value;
}
get id() {
return this.inputElement.nativeElement.id;
}
set id(id) {
this.renderer.setAttribute(this.inputElement.nativeElement, 'id', id);
}
listeners = [];
constructor(renderer, inputElement, ngZone) {
this.renderer = renderer;
this.inputElement = inputElement;
this.ngZone = ngZone;
}
ngAfterViewInit() {
const input = this.inputElement.nativeElement;
this.listeners = [
this.renderer.listen(input, 'focus', () => this.onFocus.emit()),
this.renderer.listen(input, 'blur', () => this.onBlur.emit())
];
this.ngZone.runOutsideAngular(() => {
this.renderer.listen(input, 'animationstart', (e) => {
if (e.animationName === 'autoFillStart') {
this.autoFillStart.emit();
}
else if (e.animationName === 'autoFillEnd') {
this.autoFillEnd.emit();
}
});
});
}
ngOnDestroy() {
this.listeners.forEach(listener => listener());
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TextBoxDirective, isStandalone: true, selector: "input[kendoTextBox]", inputs: { value: "value" }, host: { properties: { "class.k-textbox": "this.hostClasses", "class.k-input": "this.hostClasses", "class.k-input-md": "this.hostClasses", "class.k-rounded-md": "this.hostClasses", "class.k-input-solid": "this.hostClasses" } }, providers: [{
provide: KendoInput,
useExisting: forwardRef(() => TextBoxDirective)
}], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[kendoTextBox]',
providers: [{
provide: KendoInput,
useExisting: forwardRef(() => TextBoxDirective)
}],
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-textbox']
}, {
type: HostBinding,
args: ['class.k-input']
}, {
type: HostBinding,
args: ['class.k-input-md']
}, {
type: HostBinding,
args: ['class.k-rounded-md']
}, {
type: HostBinding,
args: ['class.k-input-solid']
}], value: [{
type: Input
}] } });
/**
* Represents the [Kendo UI TextArea directive for the Inputs components for Angular]({% slug overview_textarea %}).
* Provides floating labels to `textarea` elements.
*
* @example
* ```ts-no-run
* <textarea kendoTextArea></textarea>
* ```
*/
class TextAreaDirective {
renderer;
element;
zone;
changeDetector;
injector;
elementClasses = true;
autofillClass = true;
direction;
/**
* Fires each time the textarea value is changed.
*/
valueChange = new EventEmitter();
/**
* Specifies if the `textarea` element will resize its height automatically
* ([see example](slug:textarea_sizing#toc-auto-resizing)).
*
* @default false
*/
autoSize = false;
/**
* Specifies the textarea value.
*/
value;
/**
* @hidden
*/
onFocus = new EventEmitter();
/**
* @hidden
*/
onBlur = new EventEmitter();
/**
* @hidden
*/
onValueChange = new EventEmitter();
/**
* @hidden
*/
autoFillStart = new EventEmitter();
/**
* @hidden
*/
autoFillEnd = new EventEmitter();
get id() {
return this.element.nativeElement.id;
}
set id(id) {
this.renderer.setAttribute(this.element.nativeElement, 'id', id);
}
listeners = [];
inputSubscription;
initialHeight;
control;
resizeSubscription;
constructor(renderer, element, zone, changeDetector, injector, rtl) {
this.renderer = renderer;
this.element = element;
this.zone = zone;
this.changeDetector = changeDetector;
this.injector = injector;
this.direction = rtl ? 'rtl' : 'ltr';
}
/**
* @hidden
*/
writeValue(value) {
this.elementValue = value;
this.resize();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled) {
this.setElementProperty('disabled', isDisabled);
}
ngOnInit() {
const element = this.element.nativeElement;
this.zone.runOutsideAngular(() => {
this.listeners = [
this.renderer.listen(element, 'focus', this.handleFocus.bind(this)),
this.renderer.listen(element, 'blur', this.handleBlur.bind(this)),
this.renderer.listen(element, 'animationstart', (e) => {
if (e.animationName === 'autoFillStart') {
this.autoFillStart.emit();
}
else if (e.animationName === 'autoFillEnd') {
this.autoFillEnd.emit();
}
})
];
if (isDocumentAvailable() && this.autoSize) {
this.resizeSubscription = fromEvent(window, 'resize')
.pipe((debounceTime(50)))
.subscribe(() => this.resize());
}
this.inputSubscription = fromEvent(element, 'input')
.subscribe(this.handleInput.bind(this));
});
this.control = this.injector.get(NgControl, null);
}
ngOnChanges(changes) {
const element = this.element.nativeElement;
if (changes.value) {
this.elementValue = this.value;
}
if (changes.autoSize) {
if (this.autoSize) {
this.initialHeight = element.offsetHeight;
this.renderer.setStyle(element, 'resize', 'none');
}
else {
this.renderer.setStyle(element, 'overflow-y', 'auto');
this.renderer.setStyle(element, 'resize', 'both');
element.style.height = `${this.initialHeight}px`;
}
}
this.zone.onStable.pipe(take(1)).subscribe(() => this.resize());
}
ngOnDestroy() {
this.listeners.forEach(listener => listener());
if (this.inputSubscription) {
this.inputSubscription.unsubscribe();
}
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
}
ngChange = (_) => { };
ngTouched = () => { };
get elementValue() {
if (this.element) {
return this.element.nativeElement.value;
}
return '';
}
set elementValue(value) {
this.setElementProperty('value', (value === undefined || value === null) ? '' : value);
}
setElementProperty(name, value) {
if (this.element) {
this.renderer.setProperty(this.element.nativeElement, name, value);
}
}
resize() {
if (!this.autoSize) {
return;
}
const element = this.element.nativeElement;
this.renderer.setStyle(element, 'overflow-y', 'hidden');
element.style.height = `${this.initialHeight}px`;
const scrollHeight = element.scrollHeight;
if (scrollHeight > this.initialHeight) {
element.style.height = `${scrollHeight}px`;
}
}
handleInput() {
const value = this.elementValue;
this.value = value;
if (this.control || hasObservers(this.onValueChange) || hasObservers(this.valueChange)) {
this.zone.run(() => {
this.ngChange(value);
this.onValueChange.emit(value);
this.valueChange.emit(value);
this.changeDetector.markForCheck();
});
}
this.resize();
}
handleFocus() {
if (hasObservers(this.onFocus)) {
this.zone.run(() => {
this.onFocus.emit();
});
}
}
handleBlur() {
if (hasObservers(this.onBlur) || requiresZoneOnBlur(this.control)) {
this.zone.run(() => {
this.ngTouched();
this.onBlur.emit();
this.changeDetector.markForCheck();
});
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: RTL, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TextAreaDirective, isStandalone: true, selector: "textarea[kendoTextArea]", inputs: { autoSize: "autoSize", value: "value" }, outputs: { valueChange: "valueChange" }, host: { properties: { "class.k-textarea": "this.elementClasses", "class.k-input": "this.elementClasses", "class.k-input-md": "this.elementClasses", "class.k-rounded-md": "this.elementClasses", "class.k-input-solid": "this.elementClasses", "class.k-autofill": "this.autofillClass", "attr.dir": "this.direction" } }, providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextAreaDirective),
multi: true
}, {
provide: KendoInput,
useExisting: forwardRef(() => TextAreaDirective)
}], usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaDirective, decorators: [{
type: Directive,
args: [{
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextAreaDirective),
multi: true
}, {
provide: KendoInput,
useExisting: forwardRef(() => TextAreaDirective)
}],
selector: 'textarea[kendoTextArea]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RTL]
}] }]; }, propDecorators: { elementClasses: [{
type: HostBinding,
args: ['class.k-textarea']
}, {
type: HostBinding,
args: ['class.k-input']
}, {
type: HostBinding,
args: ['class.k-input-md']
}, {
type: HostBinding,
args: ['class.k-rounded-md']
}, {
type: HostBinding,
args: ['class.k-input-solid']
}], autofillClass: [{
type: HostBinding,
args: ['class.k-autofill']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], valueChange: [{
type: Output
}], autoSize: [{
type: Input
}], value: [{
type: Input
}] } });
/**
* @hidden
*/
const createMaxValidator = (maxValue) => {
return (c) => {
if (!isPresent(maxValue) || !isPresent(c.value) || c.value <= maxValue) {
return null;
}
return {
maxError: {
maxValue: maxValue,
value: c.value
}
};
};
};
/**
* @hidden
*/
const createMinValidator = (minValue) => {
return (c) => {
if (!isPresent(minValue) || !isPresent(c.value) || c.value >= minValue) {
return null;
}
return {
minError: {
minValue: minValue,
value: c.value
}
};
};
};
/**
* @hidden
*/
const MIN_DOC_LINK = 'https://www.telerik.com/kendo-angular-ui/components/inputs/api/NumericTextBoxComponent/#toc-min';
/**
* @hidden
*/
const MAX_DOC_LINK = 'https://www.telerik.com/kendo-angular-ui/components/inputs/api/NumericTextBoxComponent/#toc-max';
/**
* @hidden
*/
const POINT = ".";
/**
* @hidden
*/
const INITIAL_SPIN_DELAY = 500;
/**
* @hidden
*/
const SPIN_DELAY = 50;
/**
* @hidden
*/
const EXPONENT_REGEX = /[eE][\-+]?([0-9]+)/;
/**
* @hidden
*/
const numericRegex = (options) => {
const { autoCorrect, decimals, min } = options;
let separator = options.separator;
if (separator === POINT) {
separator = '\\' + separator;
}
const signPattern = autoCorrect && min !== null && min >= 0 ? '' : '-?';
let numberPattern;
if (decimals === 0) {
numberPattern = '\\d*';
}
else {
numberPattern = `(?:(?:\\d+(${separator}\\d*)?)|(?:${separator}\\d*))?`;
}
return new RegExp(`^${signPattern}${numberPattern}$`);
};
/**
* @hidden
*/
const decimalPart = (value) => {
return value >= 0 ? Math.floor(value) : Math.ceil(value);
};
/**
* @hidden
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop$1 = (_) => { };
/**
* @hidden
*/
const defined = (value) => {
return typeof value !== 'undefined';
};
/**
* @hidden
*/
const isNumber = (value) => {
return !isNaN(value) && value !== null;
};
/**
* @hidden
*/
function pad(value, digits) {
const count = digits - String(value).length;
let result = value;
if (count > 0) {
const padString = new Array(count + 1).join("0");
result = parseFloat(value + padString);
}
return result;
}
/**
* @hidden
*/
const getDeltaFromMouseWheel = (e) => {
let delta = 0;
if (e.wheelDelta) {
delta = e.wheelDelta / 120;
delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);
}
else if (e.detail) {
delta = Math.round(-e.detail / 3);
}
return delta;
};
/**
* @hidden
*/
const getCaretPosition = (element) => element.selectionStart;
/**
* @hidden
*/
const extractSignificantNumericChars = (formattedString, separator) => {
const significantCharacters = `${separator}0123456789-`;
return formattedString.split('').reduce((acc, curr) => significantCharacters.includes(curr) ? ++acc : acc, 0);
};
/**
* @hidden
*/
const isRightClick = (event) => {
const isRightClickIE = event.button && event.button === 2;
const isRightClickOther = event.which && event.which === 3;
return isRightClickIE || isRightClickOther;
};
/**
* @hidden
*/
var ArrowDirection;
(function (ArrowDirection) {
ArrowDirection[ArrowDirection["Down"] = -1] = "Down";
ArrowDirection[ArrowDirection["None"] = 0] = "None";
ArrowDirection[ArrowDirection["Up"] = 1] = "Up";
})(ArrowDirection || (ArrowDirection = {}));
/**
* Specifies a separator in the content of components like the TextArea and the TextBox. ([see examples]({% slug adornments_textbox %}#toc-separator)).
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textbox>
* <ng-template kendoTextBoxSuffixTemplate>
* <kendo-input-separator></kendo-input-separator>
* <button kendoButton look="clear" icon="image"></button>
* </ng-template>
* </kendo-textbox>
* `
* })
* class AppComponent {}
* ```
*/
class InputSeparatorComponent {
/**
* Specifies the orientation of the separator. Applicable for the adornments of the [`TextAreaComponent`](slug:api_inputs_textareacomponent).
*
* @default 'vertical'
*/
orientation = 'vertical';
get vertical() {
return this.orientation === 'vertical';
}
get horizontal() {
return this.orientation === 'horizontal';
}
hostClass = true;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: InputSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: InputSeparatorComponent, isStandalone: true, selector: "kendo-input-separator, kendo-textbox-separator", inputs: { orientation: "orientation" }, host: { properties: { "class.k-input-separator-vertical": "this.vertical", "class.k-input-separator-horizontal": "this.horizontal", "class.k-input-separator": "this.hostClass" } }, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: InputSeparatorComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-input-separator, kendo-textbox-separator',
template: ``,
standalone: true
}]
}], propDecorators: { orientation: [{
type: Input
}], vertical: [{
type: HostBinding,
args: ['class.k-input-separator-vertical']
}], horizontal: [{
type: HostBinding,
args: ['class.k-input-separator-horizontal']
}], hostClass: [{
type: HostBinding,
args: ['class.k-input-separator']
}] } });
/**
* @hidden
*/
class SharedInputEventsDirective {
ngZone;
renderer;
cdr;
hostElement;
clearButtonClicked;
isFocused;
isFocusedChange = new EventEmitter();
onFocus = new EventEmitter();
handleBlur = new EventEmitter();
subscriptions = new Subscription();
constructor(ngZone, renderer, cdr) {
this.ngZone = ngZone;
this.renderer = renderer;
this.cdr = cdr;
}
ngAfterViewInit() {
const hostElement = this.hostElement.nativeElement;
let cursorInsideWrapper = false;
let tabbing = false;
this.ngZone.runOutsideAngular(() => {
// focusIn and focusOut are relative to the host element
this.subscriptions.add(this.renderer.listen(hostElement, 'focusin', () => {
this.cdr.detectChanges();
if (!this.isFocused) {
this.ngZone.run(() => {
this.onFocus.emit();
this.isFocused = true;
this.isFocusedChange.emit(this.isFocused);
});
}
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'focusout', (args) => {
if (!this.isFocused) {
return;
}
if (tabbing) {
const closestTextbox = closest(args.relatedTarget, (element) => element === hostElement);
if (!closestTextbox) {
this.handleBlur.emit();
}
tabbing = false;
}
else {
if (!cursorInsideWrapper && !this?.clearButtonClicked) {
this.handleBlur.emit();
}
}
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'mouseenter', () => {
cursorInsideWrapper = true;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'mouseleave', () => {
cursorInsideWrapper = false;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'keydown', (args) => {
if (args.keyCode === Keys.Tab) {
tabbing = true;
}
else {
tabbing = false;
}
}));
});
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SharedInputEventsDirective, deps: [{ token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SharedInputEventsDirective, isStandalone: true, selector: "[kendoInputSharedEvents]", inputs: { hostElement: "hostElement", clearButtonClicked: "clearButtonClicked", isFocused: "isFocused" }, outputs: { isFocusedChange: "isFocusedChange", onFocus: "onFocus", handleBlur: "handleBlur" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SharedInputEventsDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoInputSharedEvents]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { hostElement: [{
type: Input
}], clearButtonClicked: [{
type: Input
}], isFocused: [{
type: Input
}], isFocusedChange: [{
type: Output
}], onFocus: [{
type: Output
}], handleBlur: [{
type: Output
}] } });
/**
* @hidden
*/
class NumericTextBoxMessages extends ComponentMessages {
/**
* The title of the **Decrement** button of the NumericTextBox.
*/
decrement;
/**
* The title of the **Increment** button of the NumericTextBox.
*/
increment;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: NumericTextBoxMessages, selector: "kendo-numerictextbox-messages-base", inputs: { decrement: "decrement", increment: "increment" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-numerictextbox-messages-base'
}]
}], propDecorators: { decrement: [{
type: Input
}], increment: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedNumericTextBoxMessagesDirective extends NumericTextBoxMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedNumericTextBoxMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedNumericTextBoxMessagesDirective, isStandalone: true, selector: "[kendoNumericTextBoxLocalizedMessages]", providers: [
{
provide: NumericTextBoxMessages,
useExisting: forwardRef(() => LocalizedNumericTextBoxMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedNumericTextBoxMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: NumericTextBoxMessages,
useExisting: forwardRef(() => LocalizedNumericTextBoxMessagesDirective)
}
],
selector: '[kendoNumericTextBoxLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/* eslint-disable @typescript-eslint/no-explicit-any */
const PARSABLE_OPTIONS = ['min', 'max', 'step', 'decimals'];
const PARSABLE_DEFAULTS = {
decimals: null,
max: null,
min: null,
step: 1
};
const FOCUSED$4 = 'k-focus';
const DEFAULT_SIZE$d = 'medium';
const DEFAULT_ROUNDED$8 = 'medium';
const DEFAULT_FILL_MODE$6 = 'solid';
/**
* Represents the [Kendo UI NumericTextBox component for Angular]({% slug overview_numerictextbox %}).
*/
class NumericTextBoxComponent {
intl;
renderer;
localizationService;
injector;
ngZone;
changeDetector;
hostElement;
/**
* @hidden
*/
focusableId = `k-${guid()}`;
/**
* Determines whether the NumericTextBox is disabled ([see example]({% slug disabled_numerictextbox %})). To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_numerictextbox#toc-managing-the-numerictextbox-disabled-state-in-reactive-forms).
*/
disabled = false;
/**
* Determines whether the NumericTextBox is in its read-only state ([see example]({% slug readonly_numerictextbox %})).
*
* @default false
*/
readonly = false;
/**
* Sets the title of the `input` element of the NumericTextBox.
*/
title = '';
/**
* Specifies whether the value will be auto-corrected based on the minimum and maximum values
* ([see example]({% slug precision_numerictextbox %})).
*/
autoCorrect = false;
/**
* Specifies the number format which is used when the NumericTextBox is not focused
* ([see example]({% slug formats_numerictextbox %})).
* If `format` is set to `null` or `undefined`, the default format will be used.
*/
get format() {
const format = this._format;
return format !== null && format !== undefined ? format : 'n2';
}
set format(value) {
this._format = value;
}
/**
* Specifies the greatest value that is valid
* ([see example]({% slug precision_numerictextbox %}#toc-value-ranges)).
*/
max;
/**
* Specifies the smallest value that is valid
* ([see example]({% slug precision_numerictextbox %}#toc-value-ranges)).
*/
min;
/**
* Specifies the number of decimals that the user can enter when the input is focused
* ([see example]({% slug precision_numerictextbox %})).
*/
decimals = null;
/**
* Specifies the input placeholder.
*/
placeholder;
/**
* Specifies the value that is used to increment or decrement the component value
* ([see example]({% slug predefinedsteps_numerictextbox %})).
*/
step = 1;
/**
* Specifies whether the **Up** and **Down** spin buttons will be rendered
* ([see example]({% slug spinbuttons_numerictextbox %})).
*/
spinners = true;
/**
* Determines whether the built-in minimum or maximum validators are enforced when a form is validated.
*
* > The 4.2.0 Angular version introduces the `min` and `max` validation directives. As a result, even if you set `rangeValidation`
* to `false`, the built-in Angular validators will be executed.
*/
rangeValidation = true;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*/
tabindex = 0;
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* Determines whether the value of the NumericTextBox will be changed via scrolling. Defaults to `true`.
*
* @default true
*/
changeValueOnScroll = true;
/**
* Determines whether the whole value will be selected when the NumericTextBox is clicked. Defaults to `true`.
*/
selectOnFocus = true;
/**
* Specifies the value of the NumericTextBox
* ([see example]({% slug formats_numerictextbox %})).
*/
value = null;
/**
* Specifies the maximum number of characters the end user can type or paste in the input.
* The locale-specific decimal separator and negative sign (`-`) are included in the length of the value when present.
* The `maxlength` restriction is not applied to the length of the formatted value when the component is not focused.
*/
maxlength;
/**
* The size property specifies padding of the NumericTextBox internal input element
* ([see example]({% slug appearance_numerictextbox %}#toc-size)).
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$d;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The `rounded` property specifies the border radius of the NumericTextBox
* ([see example](slug:appearance_numerictextbox#toc-roundness)).
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED$8;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
/**
* The `fillMode` property specifies the background and border styles of the NumericTextBox
* ([see example](slug:appearance_numerictextbox#toc-fill-mode)).
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
set fillMode(fillMode) {
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE$6;
this.handleClasses(newFillMode, 'fillMode');
this._fillMode = newFillMode;
}
get fillMode() {
return this._fillMode;
}
/**
* Sets the HTML attributes of the inner focusable input element. Attributes which are essential for certain component functionalities cannot be changed.
*/
set inputAttributes(attributes) {
if (isObjectPresent(this.parsedAttributes)) {
removeHTMLAttributes(this.parsedAttributes, this.renderer, this.numericInput.nativeElement);
}
this._inputAttributes = attributes;
this.parsedAttributes = this.inputAttributes ?
parseAttributes(this.inputAttributes, this.defaultAttributes) :
this.inputAttributes;
this.setInputAttributes();
}
get inputAttributes() {
return this._inputAttributes;
}
/**
* Fires each time the user selects a new value ([see example](slug:events_numerictextbox)).
*/
valueChange = new EventEmitter();
/**
* Fires each time the user focuses the NumericTextBox element ([see example](slug:events_numerictextbox)).
*/
onFocus = new EventEmitter();
/**
* Fires each time the NumericTextBox component gets blurred ([see example](slug:events_numerictextbox)).
*/
onBlur = new EventEmitter();
/**
* Fires each time the user focuses the `input` element.
*/
inputFocus = new EventEmitter();
/**
* Fires each time the `input` element gets blurred.
*/
inputBlur = new EventEmitter();
/**
* @hidden
*/
numericInput;
/**
* @hidden
*/
suffixTemplate;
/**
* @hidden
*/
prefixTemplate;
direction;
/**
* @hidden
*/
ArrowDirection = ArrowDirection;
/**
* @hidden
*/
arrowDirection = ArrowDirection.None;
get disableClass() {
return this.disabled;
}
hostClasses = true;
/**
* @hidden
*/
arrowUpIcon = caretAltUpIcon;
/**
* @hidden
*/
arrowDownIcon = caretAltDownIcon;
subscriptions;
inputValue = '';
spinTimeout;
isFocused;
minValidateFn = noop$1;
maxValidateFn = noop$1;
numericRegex;
_format = "n2";
previousSelection;
pressedKey;
control;
isPasted = false;
mouseDown = false;
_size = 'medium';
_rounded = 'medium';
_fillMode = 'solid';
ngChange = noop$1;
ngTouched = noop$1;
ngValidatorChange = noop$1;
domEvents = [];
_inputAttributes;
parsedAttributes = {};
get defaultAttributes() {
return {
id: this.focusableId,
disabled: this.disabled ? '' : null,
readonly: this.readonly ? '' : null,
tabindex: this.tabIndex,
placeholder: this.placeholder,
title: this.title,
maxlength: this.maxlength,
'aria-valuemin': this.min,
'aria-valuemax': this.max,
'aria-valuenow': this.value,
required: this.isControlRequired ? '' : null,
'aria-invalid': this.isControlInvalid
};
}
get mutableAttributes() {
return {
autocomplete: 'off',
autocorrect: 'off',
role: 'spinbutton'
};
}
constructor(intl, renderer, localizationService, injector, ngZone, changeDetector, hostElement) {
this.intl = intl;
this.renderer = renderer;
this.localizationService = localizationService;
this.injector = injector;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.hostElement = hostElement;
validatePackage(packageMetadata);
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
}
ngOnInit() {
this.subscriptions = this.localizationService
.changes
.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
this.subscriptions.add(this.intl.changes.subscribe(this.intlChange.bind(this)));
if (this.hostElement) {
this.renderer.removeAttribute(this.hostElement.nativeElement, "tabindex");
}
this.control = this.injector.get(NgControl, null);
this.ngZone.runOutsideAngular(() => {
this.domEvents.push(this.renderer.listen(this.hostElement.nativeElement, 'mousewheel', this.handleWheel.bind(this)));
this.domEvents.push(this.renderer.listen(this.hostElement.nativeElement, 'DOMMouseScroll', this.handleWheel.bind(this)));
});
}
ngAfterViewInit() {
const stylingInputs = ['size', 'rounded', 'fillMode'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
}
/**
* @hidden
*/
increasePress = (e) => {
this.arrowPress(ArrowDirection.Up, e);
};
/**
* @hidden
*/
decreasePress = (e) => {
this.arrowPress(ArrowDirection.Down, e);
};
/**
* @hidden
*/
releaseArrow = () => {
clearTimeout(this.spinTimeout);
if (this.arrowDirection !== ArrowDirection.None) {
this.arrowDirection = ArrowDirection.None;
this.changeDetector.detectChanges();
}
};
/**
* @hidden
*/
ngOnChanges(changes) {
if (anyChanged(PARSABLE_OPTIONS, changes, false)) {
this.parseOptions(PARSABLE_OPTIONS.filter(option => changes[option]));
}
this.verifySettings();
if (anyChanged(['min', 'max', 'rangeValidation'], changes, false)) {
this.minValidateFn = this.rangeValidation ? createMinValidator(this.min) : noop$1;
this.maxValidateFn = this.rangeValidation ? createMaxValidator(this.max) : noop$1;
this.ngValidatorChange();
}
if (anyChanged(['autoCorrect', 'decimals', 'min'], changes)) {
delete this.numericRegex;
}
if (anyChanged(['value', 'format'], changes, false)) {
this.verifyValue(this.value);
this.value = this.restrictModelValue(this.value);
if (!this.focused || (this.intl.parseNumber(this.elementValue) !== this.value)) {
this.setInputValue();
}
}
}
/**
* @hidden
*/
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
}
clearTimeout(this.spinTimeout);
this.domEvents.forEach(unbindHandler => unbindHandler());
}
/**
* @hidden
*/
validate(control) {
return this.minValidateFn(control) || this.maxValidateFn(control);
}
/**
* @hidden
*/
registerOnValidatorChange(fn) {
this.ngValidatorChange = fn;
}
/**
* @hidden
*/
writeValue(value) {
this.verifyValue(value);
const restrictedValue = this.restrictModelValue(value);
this.value = restrictedValue;
this.setInputValue();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.changeDetector.markForCheck();
this.disabled = isDisabled;
}
/**
* Focuses the NumericTextBox.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <button (click)="numerictextbox.focus()">Focus NumericTextBox</button>
* <kendo-numerictextbox #numerictextbox></kendo-numerictextbox>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
invokeElementMethod(this.numericInput, 'focus');
}
/**
* Blurs the NumericTextBox.
*/
blur() {
invokeElementMethod(this.numericInput, 'blur');
}
/**
* Notifies the `NumericTextBoxComponent` that the input value should be changed.
* Can be used to update the input after setting the component properties directly.
*/
notifyValueChange() {
this.setInputValue();
}
/**
* @hidden
*/
handlePaste = () => {
this.isPasted = true;
};
/**
* @hidden
*/
handleInput = () => {
const input = this.numericInput.nativeElement;
let { selectionStart, selectionEnd, value: inputValue } = input;
if (this.pressedKey === Keys.NumpadDecimal) {
inputValue = this.replaceNumpadDotValue();
}
if (this.isPasted) {
inputValue = this.formatInputValue(this.intl.parseNumber(inputValue));
}
if (!this.isValid(inputValue)) {
input.value = this.inputValue;
this.setSelection(selectionStart - 1, selectionEnd - 1);
return;
}
const parsedValue = this.intl.parseNumber(inputValue);
let value = this.restrictDecimals(parsedValue);
if (this.autoCorrect) {
const limited = this.limitInputValue(value);
value = limited.value;
selectionStart = limited.selectionStart;
selectionEnd = limited.selectionEnd;
}
if (parsedValue !== value || this.hasTrailingZeros(inputValue) || !this.focused) {
this.setInputValue(value);
this.setSelection(selectionStart, selectionEnd);
}
else {
this.inputValue = inputValue;
}
if (this.isPasted) {
input.value = this.inputValue;
}
this.updateValue(value);
this.previousSelection = null;
this.isPasted = false;
};
/**
* @hidden
*/
handleDragEnter = () => {
if (!this.focused && !this.isDisabled) {
this.setInputValue(this.value, true);
}
};
/**
* @hidden
*/
handleMouseDown = () => {
this.mouseDown = true;
};
/**
* @hidden
*/
handleInputFocus = () => {
if (!this.focused) {
this.focused = true;
if (!this.isDisabled) {
const shouldSelectAll = this.selectOnFocus || !this.mouseDown;
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
if (shouldSelectAll) {
this.selectAll();
}
else {
this.selectCaret();
}
}, 0);
});
}
if (hasObservers(this.onFocus)) {
this.ngZone.run(() => {
this.onFocus.emit();
});
}
}
this.mouseDown = false;
if (hasObservers(this.inputFocus)) {
this.ngZone.run(() => {
this.inputFocus.emit();
});
}
};
/**
* @hidden
*/
handleFocus() {
this.ngZone.run(() => {
if (!this.focused && hasObservers(this.onFocus)) {
this.onFocus.emit();
}
this.focused = true;
});
}
/**
* @hidden
*/
handleBlur = () => {
this.changeDetector.markForCheck();
this.focused = false;
//blur is thrown before input when dragging the input text in IE
if (this.inputValue !== this.elementValue) {
this.handleInput();
}
this.setInputValue();
if (hasObservers(this.onBlur)) {
this.ngZone.run(() => {
this.ngTouched();
this.onBlur.emit();
});
}
};
/**
* @hidden
*/
handleInputBlur = () => {
this.changeDetector.markForCheck();
//blur is thrown before input when dragging the input text in IE
if (this.inputValue !== this.elementValue) {
this.handleInput();
}
this.setInputValue();
if (hasObservers(this.inputBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
this.inputBlur.emit();
});
}
};
/**
* @hidden
*/
handleKeyDown = (e) => {
if (this.isDisabled) {
return;
}
let step;
if (e.keyCode === Keys.ArrowDown) {
step = -1;
}
else if (e.keyCode === Keys.ArrowUp) {
step = 1;
}
if (step && this.step) {
e.preventDefault();
this.addStep(step);
}
const input = this.numericInput.nativeElement;
this.previousSelection = {
end: input.selectionEnd,
start: input.selectionStart
};
this.pressedKey = e.keyCode;
};
/**
* @hidden
*/
handleWheel = (e) => {
if (this.focused && !this.isDisabled && this.changeValueOnScroll) {
e.preventDefault();
const delta = getDeltaFromMouseWheel(e);
this.addStep(delta);
}
};
/**
* @hidden
*/
get incrementTitle() {
return this.localizationService.get('increment');
}
/**
* @hidden
*/
get decrementTitle() {
return this.localizationService.get('decrement');
}
/**
* @hidden
*/
get isControlInvalid() {
return this.control && this.control.touched && !this.control.valid;
}
/**
* @hidden
*/
get isControlRequired() {
return isControlRequired(this.control?.control);
}
/**
* @hidden
*/
get focused() {
return this.isFocused;
}
/**
* @hidden
*/
set focused(value) {
if (this.isFocused !== value && this.hostElement) {
const wrap = this.hostElement.nativeElement;
if (value) {
this.renderer.addClass(wrap, FOCUSED$4);
}
else {
this.renderer.removeClass(wrap, FOCUSED$4);
}
this.isFocused = value;
}
}
get decimalSeparator() {
const numberSymbols = this.intl.numberSymbols();
return numberSymbols.decimal;
}
get elementValue() {
return this.numericInput.nativeElement.value;
}
set elementValue(value) {
this.renderer.setProperty(this.numericInput.nativeElement, 'value', value);
}
get hasDecimals() {
return this.decimals !== null && this.decimals >= 0;
}
get isDisabled() {
return this.disabled || this.readonly;
}
arrowPress(direction, e) {
e.preventDefault();
if (this.isDisabled || isRightClick(e)) {
return;
}
if (!mobileOS) {
this.focus();
this.focused = true;
}
if (this.arrowDirection !== direction) {
this.arrowDirection = direction;
this.changeDetector.detectChanges();
}
if (this.step) {
this.spin(direction, INITIAL_SPIN_DELAY);
}
else {
this.setInputValue();
}
}
updateValue(value) {
if (!areSame(this.value, value)) {
this.ngZone.run(() => {
this.value = value;
this.ngChange(value);
this.valueChange.emit(value);
this.changeDetector.markForCheck();
});
}
}
replaceNumpadDotValue() {
let value = this.inputValue || "";
if (this.previousSelection) {
const input = this.numericInput.nativeElement;
const { selectionStart, selectionEnd } = input;
const { start, end } = this.previousSelection;
input.value = value = value.substring(0, start) + this.decimalSeparator + value.substring(end);
this.setSelection(selectionStart, selectionEnd);
}
return value;
}
isValid(value) {
if (!this.numericRegex) {
this.numericRegex = numericRegex({
autoCorrect: this.autoCorrect,
decimals: this.decimals,
min: this.min,
separator: this.decimalSeparator
});
}
return this.numericRegex.test(value);
}
spin(step, timeout) {
clearTimeout(this.spinTimeout);
this.spinTimeout = window.setTimeout(() => {
this.spin(step, SPIN_DELAY);
}, timeout);
this.addStep(step);
}
addStep(step) {
let value = add(this.value || 0, this.step * step);
value = this.limitValue(value);
value = this.restrictDecimals(value);
this.setInputValue(value);
this.updateValue(value);
}
setSelection(start, end) {
if (this.focused) {
invokeElementMethod(this.numericInput, 'setSelectionRange', start, end);
}
}
limitValue(value) {
let result = value;
if (!this.isInRange(value)) {
if (isNumber(this.max) && value > this.max) {
result = this.max;
}
if (isNumber(this.min) && value < this.min) {
result = this.min;
}
}
return result;
}
limitInputValue(value) {
const { selectionStart, selectionEnd, value: enteredValue } = this.numericInput.nativeElement;
let limitedValue = value;
let selectToEnd = false;
if (!this.isInRange(value)) {
const lengthChange = enteredValue.length - String(this.inputValue).length;
const { min, max } = this;
const hasMax = isNumber(max);
const hasMin = isNumber(min);
let padLimit, replaceNext;
let correctedValue = value;
if (selectionStart === 0 && this.inputValue.substr(1) === enteredValue) {
return {
selectionEnd: selectionEnd,
selectionStart: selectionStart,
value: null
};
}
if (hasMax && value > max) {
if (value > 0) {
replaceNext = true;
}
else {
padLimit = max;
}
}
else if (hasMin && value < min) {
if (value > 0) {
padLimit = min;
}
else {
replaceNext = true;
}
}
if (padLimit) {
const paddedValue = this.tryPadValue(value, padLimit);
if (paddedValue && decimalPart(value) !== decimalPart(padLimit)) {
correctedValue = paddedValue;
selectToEnd = true;
}
}
else if (replaceNext) {
if (this.inputValue && selectionStart !== enteredValue.length) {
correctedValue = parseFloat(enteredValue.substr(0, selectionStart) +
enteredValue.substr(selectionStart + lengthChange));
}
}
limitedValue = this.limitValue(correctedValue);
selectToEnd = (selectToEnd || limitedValue !== correctedValue) && this.previousSelection &&
(this.previousSelection.end - this.previousSelection.start + lengthChange) > 0;
}
return {
selectionEnd: selectToEnd ? String(limitedValue).length : selectionEnd,
selectionStart: selectionStart,
value: limitedValue
};
}
tryPadValue(value, limit) {
const limitLength = String(Math.floor(limit)).length;
const zeroPadded = pad(value, limitLength);
const zeroPaddedNext = pad(value, limitLength + 1);
let result;
if (this.isInRange(zeroPadded)) {
result = zeroPadded;
}
else if (this.isInRange(zeroPaddedNext)) {
result = zeroPaddedNext;
}
return result;
}
isInRange(value) {
return !isNumber(value) || ((!isNumber(this.min) || this.min <= value) && (!isNumber(this.max) || value <= this.max));
}
restrictModelValue(value) {
let result = this.restrictDecimals(value, true);
if (this.autoCorrect && this.limitValue(result) !== result) {
result = null;
}
return result;
}
restrictDecimals(value, round) {
let result = value;
if (value && this.hasDecimals) {
const decimals = this.decimals;
const stringValue = String(value);
if (round || EXPONENT_REGEX.test(stringValue)) {
result = toFixedPrecision(value, decimals);
}
else {
const parts = stringValue.split(POINT);
let fraction = parts[1];
if (fraction && fraction.length > decimals) {
fraction = fraction.substr(0, decimals);
result = parseFloat(`${parts[0]}${POINT}${fraction}`);
}
}
}
return result;
}
formatInputValue(value) {
let stringValue = Object.is(value, -0) ? '-0' : String(value);
const exponentMatch = EXPONENT_REGEX.exec(stringValue);
if (exponentMatch) {
stringValue = value.toFixed(limitPrecision(parseInt(exponentMatch[1], 10)));
}
return stringValue.replace(POINT, this.decimalSeparator);
}
formatValue(value, focused) {
let formattedValue;
if (value === null || !defined(value) || value === '') {
formattedValue = '';
}
else if (focused && !this.readonly) {
formattedValue = this.formatInputValue(value);
}
else {
formattedValue = this.intl.formatNumber(value, this.format);
}
return formattedValue;
}
setInputValue(value = this.value, focused = this.focused) {
const formattedValue = this.formatValue(value, focused);
this.elementValue = formattedValue;
this.inputValue = formattedValue;
}
verifySettings() {
if (!isDevMode()) {
return;
}
if (this.min !== null && this.max !== null && this.min > this.max) {
throw new Error(`The max value should be bigger than the min. See ${MIN_DOC_LINK} and ${MAX_DOC_LINK}.`);
}
}
verifyValue(value) {
if (isDevMode() && value && typeof value !== 'number') {
throw new Error(`The NumericTextBox component requires value of type Number and ${JSON.stringify(value)} was set.`);
}
}
parseOptions(options) {
for (let idx = 0; idx < options.length; idx++) {
const name = options[idx];
const value = this[name];
if (typeof value === 'string') {
const parsed = parseFloat(value);
const valid = !isNaN(parsed);
if (isDevMode() && !valid && value !== '') {
throw new Error('The NumericTextBox component requires value of type Number or a String representing ' +
`a number for the ${name} property and ${JSON.stringify(value)} was set.`);
}
this[name] = valid ? parsed : PARSABLE_DEFAULTS[name];
}
}
}
intlChange() {
delete this.numericRegex;
if (this.numericInput && (!this.focused || !this.isValid(this.elementValue))) {
this.setInputValue();
}
}
hasTrailingZeros(inputValue) {
if (this.hasDecimals && this.focused) {
const fraction = inputValue.split(this.decimalSeparator)[1];
return fraction && fraction.length > this.decimals && fraction.lastIndexOf('0') === fraction.length - 1;
}
}
selectAll() {
this.setInputValue();
this.setSelection(0, this.inputValue.length);
}
selectCaret() {
const caretPosition = getCaretPosition(this.numericInput.nativeElement);
const formattedValue = this.elementValue;
const partialValue = formattedValue.substring(0, caretPosition);
this.setInputValue();
if (partialValue.length) {
const significantCharsInFormattedValue = extractSignificantNumericChars(partialValue, this.decimalSeparator);
const adjustedSignificantChars = this.adjustSignificantChars(formattedValue, significantCharsInFormattedValue);
this.setSelection(adjustedSignificantChars, adjustedSignificantChars);
}
else {
this.setSelection(0, 0);
}
}
numberOfLeadingZeroes(formattedValue) {
const separatorIndex = formattedValue.indexOf(this.decimalSeparator);
const matchedLeadingZeroes = formattedValue.match(/^[^1-9]*?(0+)/);
if (matchedLeadingZeroes) {
const lengthOfMatch = matchedLeadingZeroes[0].length;
const lengthOfLeadingZeroesMatch = matchedLeadingZeroes[1].length;
return lengthOfMatch === separatorIndex ? lengthOfLeadingZeroesMatch - 1 : lengthOfLeadingZeroesMatch;
}
return 0;
}
adjustSignificantChars(formattedValue, significantChars) {
const leadingZeroes = this.numberOfLeadingZeroes(formattedValue);
if (leadingZeroes > 0) {
return Math.max(0, significantChars - leadingZeroes);
}
return significantChars;
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('input', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
setInputAttributes() {
const attributesToRender = Object.assign({}, this.mutableAttributes, this.parsedAttributes);
setHTMLAttributes(attributesToRender, this.renderer, this.numericInput.nativeElement, this.ngZone);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxComponent, deps: [{ token: i1$1.IntlService }, { token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i0.Injector }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NumericTextBoxComponent, isStandalone: true, selector: "kendo-numerictextbox", inputs: { focusableId: "focusableId", disabled: "disabled", readonly: "readonly", title: "title", autoCorrect: "autoCorrect", format: "format", max: "max", min: "min", decimals: "decimals", placeholder: "placeholder", step: "step", spinners: "spinners", rangeValidation: "rangeValidation", tabindex: "tabindex", tabIndex: "tabIndex", changeValueOnScroll: "changeValueOnScroll", selectOnFocus: "selectOnFocus", value: "value", maxlength: "maxlength", size: "size", rounded: "rounded", fillMode: "fillMode", inputAttributes: "inputAttributes" }, outputs: { valueChange: "valueChange", onFocus: "focus", onBlur: "blur", inputFocus: "inputFocus", inputBlur: "inputBlur" }, host: { properties: { "class.k-readonly": "this.readonly", "attr.dir": "this.direction", "class.k-disabled": "this.disableClass", "class.k-input": "this.hostClasses", "class.k-numerictextbox": "this.hostClasses" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.numerictextbox' },
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NumericTextBoxComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => NumericTextBoxComponent), multi: true },
{ provide: KendoInput, useExisting: forwardRef(() => NumericTextBoxComponent) }
], queries: [{ propertyName: "suffixTemplate", first: true, predicate: SuffixTemplateDirective, descendants: true }, { propertyName: "prefixTemplate", first: true, predicate: PrefixTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "numericInput", first: true, predicate: ["numericInput"], descendants: true, static: true }], exportAs: ["kendoNumericTextBox"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoNumericTextBoxLocalizedMessages
i18n-increment="kendo.numerictextbox.increment|The title for the **Increment** button in the NumericTextBox"
increment="Increase value"
i18n-decrement="kendo.numerictextbox.decrement|The title for the **Decrement** button in the NumericTextBox"
decrement="Decrease value"
>
</ng-container>
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="focused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<span *ngIf="prefixTemplate" class="k-input-prefix k-input-prefix-horizontal">
<ng-template [ngTemplateOutlet]="prefixTemplate?.templateRef">
</ng-template>
</span>
<kendo-input-separator *ngIf="prefixTemplate && prefixTemplate.showSeparator"></kendo-input-separator>
<input #numericInput
class="k-input-inner"
role="spinbutton"
autocomplete="off"
autocorrect="off"
[id]="focusableId"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="value"
[attr.title]="title"
[attr.placeholder]="placeholder"
[attr.maxLength]="maxlength"
[tabindex]="tabIndex"
[disabled]="disabled"
[readonly]="readonly"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
mousedown: handleMouseDown,
dragenter: handleDragEnter,
keydown: handleKeyDown,
input: handleInput,
focus: handleInputFocus,
blur: handleInputBlur,
paste: handlePaste
}"/>
<kendo-input-separator *ngIf="suffixTemplate && suffixTemplate?.showSeparator"></kendo-input-separator>
<span *ngIf="suffixTemplate" class="k-input-suffix k-input-suffix-horizontal">
<ng-template [ngTemplateOutlet]="suffixTemplate?.templateRef">
</ng-template>
</span>
<span
class="k-input-spinner k-spin-button" *ngIf="spinners"
[kendoEventsOutsideAngular]="{ mouseup: releaseArrow, mouseleave: releaseArrow }"
>
<button
type="button"
[kendoEventsOutsideAngular]="{ mousedown: increasePress }"
[attr.aria-hidden]="true"
[attr.aria-label]="incrementTitle"
[title]="incrementTitle"
class="k-spinner-increase k-button k-button-md k-icon-button k-button-solid k-button-solid-base"
[class.k-active]="arrowDirection === ArrowDirection.Up"
tabindex="-1"
>
<kendo-icon-wrapper
name="caret-alt-up"
innerCssClass="k-button-icon"
[svgIcon]="arrowUpIcon"
>
</kendo-icon-wrapper>
</button>
<button
type="button"
[kendoEventsOutsideAngular]="{ mousedown: decreasePress }"
[attr.aria-hidden]="true"
[attr.aria-label]="decrementTitle"
[title]="decrementTitle"
[class.k-active]="arrowDirection === ArrowDirection.Down"
class="k-spinner-decrease k-button k-button-md k-icon-button k-button-solid k-button-solid-base"
tabindex="-1"
>
<kendo-icon-wrapper
name="caret-alt-down"
innerCssClass="k-button-icon"
[svgIcon]="arrowDownIcon"
>
</kendo-icon-wrapper>
</button>
</span>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedNumericTextBoxMessagesDirective, selector: "[kendoNumericTextBoxLocalizedMessages]" }, { kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: InputSeparatorComponent, selector: "kendo-input-separator, kendo-textbox-separator", inputs: ["orientation"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoNumericTextBox',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.numerictextbox' },
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NumericTextBoxComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => NumericTextBoxComponent), multi: true },
{ provide: KendoInput, useExisting: forwardRef(() => NumericTextBoxComponent) }
],
selector: 'kendo-numerictextbox',
template: `
<ng-container kendoNumericTextBoxLocalizedMessages
i18n-increment="kendo.numerictextbox.increment|The title for the **Increment** button in the NumericTextBox"
increment="Increase value"
i18n-decrement="kendo.numerictextbox.decrement|The title for the **Decrement** button in the NumericTextBox"
decrement="Decrease value"
>
</ng-container>
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="focused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<span *ngIf="prefixTemplate" class="k-input-prefix k-input-prefix-horizontal">
<ng-template [ngTemplateOutlet]="prefixTemplate?.templateRef">
</ng-template>
</span>
<kendo-input-separator *ngIf="prefixTemplate && prefixTemplate.showSeparator"></kendo-input-separator>
<input #numericInput
class="k-input-inner"
role="spinbutton"
autocomplete="off"
autocorrect="off"
[id]="focusableId"
[attr.aria-valuemin]="min"
[attr.aria-valuemax]="max"
[attr.aria-valuenow]="value"
[attr.title]="title"
[attr.placeholder]="placeholder"
[attr.maxLength]="maxlength"
[tabindex]="tabIndex"
[disabled]="disabled"
[readonly]="readonly"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
mousedown: handleMouseDown,
dragenter: handleDragEnter,
keydown: handleKeyDown,
input: handleInput,
focus: handleInputFocus,
blur: handleInputBlur,
paste: handlePaste
}"/>
<kendo-input-separator *ngIf="suffixTemplate && suffixTemplate?.showSeparator"></kendo-input-separator>
<span *ngIf="suffixTemplate" class="k-input-suffix k-input-suffix-horizontal">
<ng-template [ngTemplateOutlet]="suffixTemplate?.templateRef">
</ng-template>
</span>
<span
class="k-input-spinner k-spin-button" *ngIf="spinners"
[kendoEventsOutsideAngular]="{ mouseup: releaseArrow, mouseleave: releaseArrow }"
>
<button
type="button"
[kendoEventsOutsideAngular]="{ mousedown: increasePress }"
[attr.aria-hidden]="true"
[attr.aria-label]="incrementTitle"
[title]="incrementTitle"
class="k-spinner-increase k-button k-button-md k-icon-button k-button-solid k-button-solid-base"
[class.k-active]="arrowDirection === ArrowDirection.Up"
tabindex="-1"
>
<kendo-icon-wrapper
name="caret-alt-up"
innerCssClass="k-button-icon"
[svgIcon]="arrowUpIcon"
>
</kendo-icon-wrapper>
</button>
<button
type="button"
[kendoEventsOutsideAngular]="{ mousedown: decreasePress }"
[attr.aria-hidden]="true"
[attr.aria-label]="decrementTitle"
[title]="decrementTitle"
[class.k-active]="arrowDirection === ArrowDirection.Down"
class="k-spinner-decrease k-button k-button-md k-icon-button k-button-solid k-button-solid-base"
tabindex="-1"
>
<kendo-icon-wrapper
name="caret-alt-down"
innerCssClass="k-button-icon"
[svgIcon]="arrowDownIcon"
>
</kendo-icon-wrapper>
</button>
</span>
</ng-container>
`,
standalone: true,
imports: [LocalizedNumericTextBoxMessagesDirective, SharedInputEventsDirective, NgIf, NgTemplateOutlet, InputSeparatorComponent, EventsOutsideAngularDirective, IconWrapperComponent]
}]
}], ctorParameters: function () { return [{ type: i1$1.IntlService }, { type: i0.Renderer2 }, { type: i1.LocalizationService }, { type: i0.Injector }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { focusableId: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], title: [{
type: Input
}], autoCorrect: [{
type: Input
}], format: [{
type: Input
}], max: [{
type: Input
}], min: [{
type: Input
}], decimals: [{
type: Input
}], placeholder: [{
type: Input
}], step: [{
type: Input
}], spinners: [{
type: Input
}], rangeValidation: [{
type: Input
}], tabindex: [{
type: Input
}], tabIndex: [{
type: Input
}], changeValueOnScroll: [{
type: Input
}], selectOnFocus: [{
type: Input
}], value: [{
type: Input
}], maxlength: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], inputAttributes: [{
type: Input
}], valueChange: [{
type: Output
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], inputFocus: [{
type: Output
}], inputBlur: [{
type: Output
}], numericInput: [{
type: ViewChild,
args: ['numericInput', { static: true }]
}], suffixTemplate: [{
type: ContentChild,
args: [SuffixTemplateDirective]
}], prefixTemplate: [{
type: ContentChild,
args: [PrefixTemplateDirective]
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], disableClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], hostClasses: [{
type: HostBinding,
args: ['class.k-input']
}, {
type: HostBinding,
args: ['class.k-numerictextbox']
}] } });
/**
* Custom component messages override default component messages.
*/
class NumericTextBoxCustomMessagesComponent extends NumericTextBoxMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NumericTextBoxCustomMessagesComponent, isStandalone: true, selector: "kendo-numerictextbox-messages", providers: [
{
provide: NumericTextBoxMessages,
useExisting: forwardRef(() => NumericTextBoxCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: NumericTextBoxMessages,
useExisting: forwardRef(() => NumericTextBoxCustomMessagesComponent)
}
],
selector: 'kendo-numerictextbox-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* @hidden
*/
var ResultType;
(function (ResultType) {
ResultType[ResultType["Literal"] = 0] = "Literal";
ResultType[ResultType["Mask"] = 1] = "Mask";
// eslint-disable-next-line id-denylist
ResultType[ResultType["Undefined"] = 2] = "Undefined";
})(ResultType || (ResultType = {}));
/**
* @hidden
*/
class Result {
value;
rest;
type;
constructor(value, rest, type = ResultType.Undefined) {
this.value = value;
this.rest = rest;
this.type = type;
}
//map :: Functor f => f a ~> (a -> b) -> f b
map(fn) {
return new Result(fn(this.value), this.rest);
}
//chain :: Chain m => m a ~> (a -> m b) -> m b
chain(fn) {
return fn(this.value, this.rest);
}
fold(s, _ /*we don't need it*/) {
return s(this.value, this.rest);
}
concat(r) {
return this.map((vs, _) => r.chain((v, __) => vs.concat([v])));
}
toString() {
return `Result({ value: '${this.value}', rest: ${this.rest} })`;
}
}
/**
* @hidden
*/
class Stream {
input;
control;
inputCursor = 0;
controlCursor = 0;
constructor(input = [], control = []) {
this.input = input;
this.control = control;
}
eof() {
return this.inputCursor >= this.input.length;
}
// Get the first value from the input.
next() {
return {
char: this.input[this.inputCursor++],
control: this.control[this.controlCursor++]
};
}
peek() {
return {
char: this.input[this.inputCursor],
control: this.control[this.controlCursor]
};
}
eat_input() {
this.inputCursor++;
}
eat_control() {
this.controlCursor++;
}
eat() {
this.inputCursor++;
this.controlCursor++;
}
}
const toArray = (value) => (value || '').split('');
const ESCAPE_CHARACTER = '\\';
/**
* @hidden
*/
class Parser {
parse;
constructor(parse) {
this.parse = parse;
}
run(input, control = '') {
if (input instanceof Stream) {
return this.parse(input);
}
else {
return this.parse(new Stream(toArray(input), toArray(control)));
}
}
//map :: Functor f => f a ~> (a -> b) -> f b
map(f) {
return new Parser(stream => this.parse(stream).map(f));
}
//chain :: Chain m => m a ~> (a -> m b) -> m b
chain(f) {
return new Parser(stream => this.parse(stream).chain((v, s) => f(v).run(s)));
}
isLiteral(c) {
return this.run(c).type === ResultType.Literal;
}
}
/**
* @hidden
*/
const mask = ({ prompt, promptPlaceholder }) => rule => new Parser(stream => {
while (!stream.eof()) {
const { char, control } = stream.peek();
if (char === control && control === prompt) {
stream.eat();
return new Result(prompt, stream, ResultType.Mask);
}
if (rule.test(char)) {
stream.eat();
return new Result(char, stream, ResultType.Mask);
}
if (char === promptPlaceholder) {
stream.eat();
return new Result(prompt, stream, ResultType.Mask);
}
stream.eat_input();
}
stream.eat();
return new Result(prompt, stream, ResultType.Mask);
});
/**
* @hidden
*/
const literal = _token => new Parser(stream => {
// let {char, control} = stream.peek();
const char = stream.peek().char;
if (char === _token) {
stream.eat();
return new Result(_token, stream, ResultType.Literal);
}
// if (control === _token) {
// while (!stream.eof() && char !== _token) {
// stream.eat_input();
// char = stream.peek().char;
// }
// }
//
// if (control !== undefined) {
// stream.eat();
// }
return new Result(_token, stream, ResultType.Literal);
});
/**
* @hidden
*/
const unmask = prompt => rule => new Parser(stream => {
while (!stream.eof()) {
const { char, control } = stream.peek();
if (char === prompt && control === prompt) {
stream.eat();
return new Result(char, stream);
}
if (rule.test(char)) {
stream.eat();
return new Result(char, stream);
}
stream.eat_input();
}
stream.eat();
return new Result('', stream);
});
/**
* @hidden
*/
const unliteral = _token => new Parser(stream => {
if (stream.eof()) {
return new Result('', stream);
}
const { char } = stream.peek();
if (char === _token) {
stream.eat();
}
return new Result(_token, stream);
});
/**
* @hidden
*/
const token = (rules, creator) => new Parser(stream => {
let { char } = stream.next();
const rule = rules[char];
if (char === ESCAPE_CHARACTER) {
char = stream.next().char;
return new Result(creator.literal(char), stream);
}
if (!rule) {
return new Result(creator.literal(char), stream);
}
return new Result(creator.mask(rule), stream);
});
/**
* @hidden
*/
const rawMask = ({ prompt, promptPlaceholder }) => new Parser(stream => {
const { char } = stream.next();
if (char === prompt) {
return new Result(promptPlaceholder, stream);
}
return new Result(char, stream);
});
/**
* @hidden
*/
const rawLiteral = includeLiterals => new Parser(stream => {
const { char } = stream.next();
if (includeLiterals) {
return new Result(char, stream);
}
return new Result('', stream);
});
/**
* @hidden
*/
const always = value => new Parser(stream => new Result(value, stream));
/**
* @hidden
*/
const append = (p1, p2) => p1.chain(vs => p2.map(v => vs.concat([v])));
/**
* @hidden
*/
const sequence = list => list.reduce((acc, parser) => append(acc, parser), always([]));
/**
* @hidden
*/
const greedy = parser => new Parser(stream => {
let result = new Result([], stream);
while (!stream.eof()) {
result = result.concat(parser.run(stream));
}
return result;
});
/**
* @hidden
*/
class MaskingService {
rules = {};
prompt = "_";
mask = "";
promptPlaceholder = " ";
includeLiterals = false;
maskTokens = [];
unmaskTokens = [];
rawTokens = [];
validationTokens = [];
update({ mask = '', prompt = '', promptPlaceholder = ' ', rules = {}, includeLiterals = false }) {
this.mask = mask;
this.prompt = prompt;
this.promptPlaceholder = promptPlaceholder;
this.rules = rules;
this.includeLiterals = includeLiterals;
this.tokenize();
}
validationValue(maskedValue = '') {
let value = maskedValue;
sequence(this.validationTokens)
.run(maskedValue)
.fold(unmasked => {
value = unmasked.join('');
});
return value;
}
rawValue(maskedValue = '') {
let value = maskedValue;
if (!this.rawTokens.length) {
return value;
}
sequence(this.rawTokens)
.run(maskedValue)
.fold(unmasked => {
value = unmasked.join('');
});
return value;
}
/**
* @hidden
*/
maskRaw(rawValue = '') {
let value = rawValue;
if (!this.maskTokens.length) {
return value;
}
sequence(this.maskTokens)
.run(rawValue)
.fold(masked => {
value = masked.join('');
});
return value;
}
maskInput(input, control, splitPoint) {
if (input.length < control.length) {
return this.maskRemoved(input, control, splitPoint);
}
return this.maskInserted(input, control, splitPoint);
}
maskInRange(pasted, oldValue, start, end) {
let value = '';
const selection = end;
const beforeChange = oldValue.split('').slice(0, start);
const afterChange = oldValue.split('').slice(end);
sequence(this.maskTokens.slice(start, end))
.run(pasted)
.fold(masked => {
value = beforeChange
.concat(masked)
.concat(afterChange)
.join('');
});
return {
selection,
value
};
}
maskRemoved(input, control, splitPoint) {
let value = '';
let selection = splitPoint;
const unchanged = input.split('').slice(splitPoint);
const changed = input.split('').slice(0, splitPoint).join('');
const take = this.maskTokens.length - (input.length - splitPoint);
sequence(this.maskTokens.slice(0, take))
.run(changed, control)
.fold(masked => {
selection = this.adjustPosition(masked, selection);
value = masked.concat(unchanged).join('');
});
return {
selection,
value
};
}
adjustPosition(input, selection) {
const caretChar = input[selection];
const isLiteral = this.maskTokens[selection].isLiteral(caretChar);
if (!isLiteral && caretChar !== this.prompt) {
return selection + 1;
}
return selection;
}
maskInserted(input, control, splitPoint) {
let value = '';
let selection = splitPoint;
const changed = input.slice(0, splitPoint);
sequence(this.unmaskTokens)
.run(changed, control)
.chain(unmasked => {
selection = unmasked.join('').length;
const unchanged = control.slice(selection);
return sequence(this.maskTokens)
.run(unmasked.join('') + unchanged, control);
})
.fold(masked => {
value = masked.join('');
});
return {
selection,
value
};
}
get maskTokenCreator() {
const { prompt, promptPlaceholder } = this;
return {
literal: rule => literal(rule),
mask: rule => mask({ prompt, promptPlaceholder })(rule)
};
}
get unmaskTokenCreator() {
return {
literal: rule => unliteral(rule),
mask: rule => unmask(this.prompt)(rule)
};
}
get rawTokenCreator() {
const { prompt, promptPlaceholder, includeLiterals } = this;
return {
literal: _ => rawLiteral(includeLiterals),
mask: _ => rawMask({ prompt, promptPlaceholder })
};
}
get validationTokenCreator() {
const { prompt } = this;
return {
literal: _ => rawLiteral(false),
mask: _ => rawMask({ prompt, promptPlaceholder: '' })
};
}
tokenize() {
greedy(token(this.rules, this.maskTokenCreator))
.run(this.mask)
.fold((tokens, _) => {
this.maskTokens = tokens;
});
greedy(token(this.rules, this.unmaskTokenCreator))
.run(this.mask)
.fold((tokens, _) => {
this.unmaskTokens = tokens;
});
greedy(token(this.rules, this.rawTokenCreator))
.run(this.mask)
.fold((tokens, _) => {
this.rawTokens = tokens;
});
greedy(token(this.rules, this.validationTokenCreator))
.run(this.mask)
.fold((tokens, _) => {
this.validationTokens = tokens;
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskingService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskingService, decorators: [{
type: Injectable
}] });
const resolvedPromise = Promise.resolve(null);
const FOCUSED$3 = 'k-focus';
const DEFAULT_SIZE$c = 'medium';
const DEFAULT_ROUNDED$7 = 'medium';
const DEFAULT_FILL_MODE$5 = 'solid';
/**
* Represents the [Kendo UI MaskedTextBox component for Angular]({% slug overview_maskedtextbox %}).
*
* @example
* ```ts-no-run
*
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-maskedtextbox
* [mask]="mask"
* [value]="value">
* </kendo-maskedtextbox>
* `
* })
*
* class AppComponent {
* public value: string = "9580128055807792";
* public mask: string = "0000-0000-0000-0000";
* }
* ```
*/
class MaskedTextBoxComponent {
service;
renderer;
hostElement;
ngZone;
injector;
changeDetector;
/**
* @hidden
*/
focusableId = `k-${guid()}`;
/**
* Determines whether the MaskedTextBox is disabled ([see example]({% slug disabled_maskedtextbox %})). To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_maskedtextbox#toc-managing-the-maskedtextbox-disabled-state-in-reactive-forms).
*/
disabled = false;
/**
* Determines whether the MaskedTextBox is in its read-only state ([see example]({% slug readonly_maskedtextbox %})).
*
* @default false
*/
readonly = false;
/**
* Sets the title of the `input` element.
*/
title;
/**
* The size property specifies the padding of the MaskedTextBox internal input element
* ([see example]({% slug appearance_maskedtextbox %}#toc-size)).
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$c;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The rounded property specifies the border radius of the MaskedTextBox
* ([see example](slug:appearance_maskedtextbox#toc-roundness)).
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED$7;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
/**
* The `fillMode` property specifies the background and border styles of the MaskedTexBox
* ([see example]({% slug appearance_maskedtextbox %}#toc-fill-mode)).
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
set fillMode(fillMode) {
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE$5;
this.handleClasses(newFillMode, 'fillMode');
this._fillMode = newFillMode;
}
get fillMode() {
return this._fillMode;
}
/**
* Represents the current mask ([see example]({% slug value_maskedtextbox %})).
* If no mask is set, the component behaves as a standard `type="text"` input.
*
* > If the mask allows for spaces, set the [promptPlaceholder]({% slug api_inputs_maskedtextboxcomponent %}#toc-promptplaceholder)
* to a character that is not accepted by the mask.
*/
mask;
/**
* Provides a value for the MaskedTextBox.
*/
value;
/**
* Exposes the RegExp-based mask validation array ([see example]({% slug masks_maskedtextbox %})).
*/
set rules(value) {
this._rules = Object.assign({}, this.defaultRules, value);
}
get rules() {
return this._rules || this.defaultRules;
}
/**
* Represents a prompt character for the masked value.
* @default `_`
*/
prompt = '_';
/**
* Indicates a character which represents an empty position in the raw value.
* @default ' '
*/
promptPlaceholder = ' ';
/**
* Indicates whether to include literals in the raw value ([see example]({% slug value_maskedtextbox %})).
* @default false
*/
includeLiterals = false;
/**
* Specifies if the mask should be shown on focus for empty value.
*/
maskOnFocus = false;
/**
* Determines whether the built-in mask validator is enforced when a form is validated
* ([see example]({% slug validation_maskedtextbox %})).
* @default true
*/
maskValidation = true;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*/
tabindex = 0;
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* Sets the HTML attributes of the inner focusable input element. Attributes which are essential for certain component functionalities cannot be changed.
*/
set inputAttributes(attributes) {
if (isObjectPresent(this.parsedAttributes)) {
removeHTMLAttributes(this.parsedAttributes, this.renderer, this.input.nativeElement);
}
this._inputAttributes = attributes;
this.parsedAttributes = this.inputAttributes ?
parseAttributes(this.inputAttributes, this.defaultAttributes) :
this.inputAttributes;
this.setInputAttributes();
}
get inputAttributes() {
return this._inputAttributes;
}
get defaultAttributes() {
return {
id: this.focusableId,
disabled: this.disabled ? '' : null,
readonly: this.readonly ? '' : null,
tabindex: this.tabIndex,
'aria-invalid': this.isControlInvalid,
title: this.title,
required: this.isControlRequired ? '' : null
};
}
get mutableAttributes() {
return {
'aria-placeholder': this.mask,
autocomplete: 'off',
autocorrect: 'off',
autocapitalize: 'off',
spellcheck: 'false'
};
}
/**
* Fires each time the user focuses the MaskedTextBox component.
*
* > To wire the event programmatically, use the `onFocus` property.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-maskedtextbox (focus)="handleFocus()"></kendo-maskedtextbox>
* `
* })
* class AppComponent {
* public handleFocus(): void {
* console.log("Component is focused");
* }
* }
* ```
*/
onFocus = new EventEmitter();
/**
* Fires each time the MaskedTextBox component gets blurred.
*
* > To wire the event programmatically, use the `onBlur` property.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-maskedtextbox (blur)="handleBlur()"></kendo-maskedtextbox>
* `
* })
* class AppComponent {
* public handleBlur(): void {
* console.log("Component is blurred");
* }
* }
* ```
*/
onBlur = new EventEmitter();
/**
* Fires each time the user focuses the `input` element.
*/
inputFocus = new EventEmitter();
/**
* Fires each time the `input` element gets blurred.
*/
inputBlur = new EventEmitter();
/**
* Fires each time the value changes.
*/
valueChange = new EventEmitter();
direction;
hostClasses = true;
get hostDisabledClass() {
return this.disabled;
}
/**
* Represents the `ElementRef` of the visible `input` element.
*/
input;
/**
* @hidden
*/
suffixTemplate;
/**
* @hidden
*/
prefixTemplate;
isFocused;
maskedValue;
focusClick = false;
defaultRules = {
"#": /[\d\s\+\-]/,
"&": /[\S]/,
"0": /[\d]/,
"9": /[\d\s]/,
"?": /[a-zA-Z\s]/,
"A": /[a-zA-Z0-9]/,
"C": /./,
"L": /[a-zA-Z]/,
"a": /[a-zA-Z0-9\s]/
};
_rules;
isPasted = false;
selection = [0, 0];
control;
_size = 'medium';
_rounded = 'medium';
_fillMode = 'solid';
_inputAttributes;
parsedAttributes = {};
constructor(service, renderer, hostElement, ngZone, injector, changeDetector, rtl) {
this.service = service;
this.renderer = renderer;
this.hostElement = hostElement;
this.ngZone = ngZone;
this.injector = injector;
this.changeDetector = changeDetector;
validatePackage(packageMetadata);
this.direction = rtl ? 'rtl' : 'ltr';
this.updateService();
}
ngOnInit() {
if (this.hostElement) {
this.renderer.removeAttribute(this.hostElement.nativeElement, "tabindex");
}
this.control = this.injector.get(NgControl, null);
}
ngAfterViewInit() {
const stylingInputs = ['size', 'rounded', 'fillMode'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
}
/**
* @hidden
* Used by the FloatingLabel to determine if the MaskedTextBox is empty.
*/
isEmpty() {
if (this.input) {
return !this.input.nativeElement.value;
}
}
/**
* @hidden
*/
handleFocus = () => {
this.ngZone.run(() => {
if (!this.focused && hasObservers(this.onFocus)) {
this.onFocus.emit();
}
this.focused = true;
});
if (this.maskOnFocus && this.emptyMask) {
this.updateInput(this.service.maskRaw(this.value));
this.ngZone.runOutsideAngular(() => {
setTimeout(() => { this.setSelection(0, 0); }, 0);
});
}
};
/**
* @hidden
*/
handleInputFocus = () => {
this.handleFocus();
if (hasObservers(this.inputFocus)) {
this.ngZone.run(() => {
this.inputFocus.emit();
});
}
};
/**
* @hidden
*/
handleClick = () => {
if (this.focused && !this.focusClick) {
this.focusClick = true;
}
if (this.promptPlaceholder === null || this.promptPlaceholder === '') {
const { selectionStart, selectionEnd } = this.input.nativeElement;
if (selectionStart === selectionEnd) {
this.setFocusSelection();
}
}
};
/**
* @hidden
*/
handleBlur = () => {
this.changeDetector.markForCheck();
this.focused = false;
this.focusClick = false;
if (this.maskOnFocus && this.emptyMask) {
this.updateInput(this.maskedValue);
}
if (hasObservers(this.onBlur)) {
this.ngZone.run(() => {
this.onBlur.emit();
});
}
this.ngZone.run(() => {
if (this.control) {
this.control && !this.control.touched && this.onTouched();
}
});
};
/**
* @hidden
*/
handleInputBlur = () => {
this.changeDetector.markForCheck();
if (hasObservers(this.inputBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.inputBlur.emit();
});
}
};
/**
* @hidden
*/
handleDragDrop() {
return false;
}
/**
* Focuses the MaskedTextBox.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <button (click)="maskedinput.focus()">Focus the input</button>
* <kendo-maskedtextbox #maskedinput></kendo-maskedtextbox>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
if (!this.input) {
return;
}
this.input.nativeElement.focus();
this.focused = true;
this.setFocusSelection();
}
/**
* Blurs the MaskedTextBox.
*/
blur() {
if (!this.input) {
return;
}
this.input.nativeElement.blur();
this.focused = false;
}
/**
* @hidden
*/
pasteHandler(e) {
const { selectionStart, selectionEnd } = e.target;
if (selectionEnd === selectionStart) {
return;
}
this.isPasted = true;
this.selection = [selectionStart, selectionEnd];
}
/**
* @hidden
*/
inputHandler(e) {
const value = e.target.value;
const [start, end] = this.selection;
if (!this.mask) {
this.updateValueWithEvents(value);
this.isPasted = false;
return;
}
let result;
if (this.isPasted) {
this.isPasted = false;
const rightPart = this.maskedValue.length - end;
const to = value.length - rightPart;
result = this.service.maskInRange(value.slice(start, to), this.maskedValue, start, end);
}
else {
result = this.service.maskInput(value, this.maskedValue || '', e.target.selectionStart);
}
this.updateInput(result.value, result.selection);
this.updateValueWithEvents(result.value);
}
/**
* @hidden
*/
ngOnChanges(changes) {
if (changes['value']) {
this.value = this.normalizeValue(this.value);
}
const next = this.extractChanges(changes);
this.updateService(next);
if (!this.mask) {
this.updateInput(this.value);
return;
}
const maskedValue = this.service.maskRaw(this.value);
this.updateInput(maskedValue, null, true);
if (changes['includeLiterals'] || isChanged('promptPlaceholder', changes)) {
resolvedPromise.then(() => {
this.updateValueWithEvents(this.maskedValue, false);
});
}
}
/**
* @hidden
* Writes a new value to the element.
*/
writeValue(value) {
this.value = this.normalizeValue(value);
this.updateInput(this.service.maskRaw(this.value));
if (this.includeLiterals) {
this.updateValue(this.maskedValue, false);
}
}
/**
* @hidden
* Sets the function that will be called when a `change` event is triggered.
*/
registerOnChange(fn) {
this.onChange = fn;
}
/**
* @hidden
* Sets the function that will be called when a `touch` event is triggered.
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.changeDetector.markForCheck();
this.disabled = isDisabled;
}
/**
* @hidden
*/
validate(_) {
if (this.maskValidation === false || !this.mask) {
return null;
}
if (!this.service.validationValue(this.maskedValue)) {
return null;
}
if (this.maskedValue.indexOf(this.prompt) !== -1) {
return {
patternError: {
mask: this.mask,
maskedValue: this.maskedValue,
value: this.value
}
};
}
return null;
}
/**
* @hidden
*/
get isControlInvalid() {
return this.control && this.control.touched && this.control.invalid;
}
/**
* @hidden
*/
get isControlRequired() {
return isControlRequired(this.control?.control);
}
/**
* @hidden
*/
updateValueWithEvents(maskedValue, callOnChange = true) {
const previousValue = this.value;
this.updateValue(maskedValue, callOnChange);
const valueChanged = this.value !== previousValue;
if (valueChanged && hasObservers(this.valueChange)) {
this.valueChange.emit(this.value);
}
}
onChange = (_) => { };
onTouched = () => { };
updateValue(value, callOnChange = true) {
if (this.mask && !this.service.validationValue(value) && !this.includeLiterals) {
this.value = '';
}
else {
this.value = this.service.rawValue(value);
}
callOnChange && this.onChange(this.value);
}
updateInput(maskedValue = '', selection, isFromOnChanges) {
if (isFromOnChanges && maskedValue === this.maskedValue) {
return;
}
this.maskedValue = maskedValue;
const value = this.maskOnFocus && !this.focused && this.emptyMask ? '' : maskedValue;
this.renderer.setProperty(this.input.nativeElement, "value", value);
if (selection !== undefined) {
this.setSelection(selection, selection);
}
}
extractChanges(changes) {
return Object.keys(changes).filter(key => key !== 'rules').reduce((obj, key) => {
obj[key] = changes[key].currentValue;
return obj;
}, {});
}
updateService(extra) {
const config = Object.assign({
includeLiterals: this.includeLiterals,
mask: this.mask,
prompt: this.prompt,
promptPlaceholder: this.promptPlaceholder,
rules: this.rules
}, extra);
this.service.update(config);
}
setSelection(start = this.selection[0], end = this.selection[1]) {
if (this.focused) {
invokeElementMethod(this.input, 'setSelectionRange', start, end);
}
}
get emptyMask() {
return this.service.maskRaw() === this.maskedValue;
}
setFocusSelection() {
const selectionStart = this.input.nativeElement.selectionStart;
const index = this.maskedValue ? this.maskedValue.indexOf(this.prompt) : 0;
if (index >= 0 && index < selectionStart) {
this.selection = [index, index];
this.setSelection();
}
}
/**
* @hidden
*/
get focused() {
return this.isFocused;
}
/**
* @hidden
*/
set focused(value) {
if (this.isFocused !== value && this.hostElement) {
const element = this.hostElement.nativeElement;
if (value) {
this.renderer.addClass(element, FOCUSED$3);
}
else {
this.renderer.removeClass(element, FOCUSED$3);
}
this.isFocused = value;
}
}
normalizeValue(value) {
const present = isPresent(value);
if (present && typeof value !== 'string') {
if (isDevMode()) {
throw new Error('The MaskedTextBox component supports only string values.');
}
return String(value);
}
return present ? value : '';
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('input', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
setInputAttributes() {
const attributesToRender = Object.assign({}, this.mutableAttributes, this.parsedAttributes);
setHTMLAttributes(attributesToRender, this.renderer, this.input.nativeElement, this.ngZone);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskedTextBoxComponent, deps: [{ token: MaskingService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }, { token: RTL, optional: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: MaskedTextBoxComponent, isStandalone: true, selector: "kendo-maskedtextbox", inputs: { focusableId: "focusableId", disabled: "disabled", readonly: "readonly", title: "title", size: "size", rounded: "rounded", fillMode: "fillMode", mask: "mask", value: "value", rules: "rules", prompt: "prompt", promptPlaceholder: "promptPlaceholder", includeLiterals: "includeLiterals", maskOnFocus: "maskOnFocus", maskValidation: "maskValidation", tabindex: "tabindex", tabIndex: "tabIndex", inputAttributes: "inputAttributes" }, outputs: { onFocus: "focus", onBlur: "blur", inputFocus: "inputFocus", inputBlur: "inputBlur", valueChange: "valueChange" }, host: { listeners: { "paste": "pasteHandler($event)", "input": "inputHandler($event)" }, properties: { "class.k-readonly": "this.readonly", "attr.dir": "this.direction", "class.k-input": "this.hostClasses", "class.k-maskedtextbox": "this.hostClasses", "class.k-disabled": "this.hostDisabledClass" } }, providers: [
MaskingService,
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MaskedTextBoxComponent) /* eslint-disable-line*/
},
{
multi: true,
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MaskedTextBoxComponent) /* eslint-disable-line*/
},
{
provide: KendoInput,
useExisting: forwardRef(() => MaskedTextBoxComponent)
}
], queries: [{ propertyName: "suffixTemplate", first: true, predicate: SuffixTemplateDirective, descendants: true }, { propertyName: "prefixTemplate", first: true, predicate: PrefixTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }], exportAs: ["kendoMaskedTextBox"], usesOnChanges: true, ngImport: i0, template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="focused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<span *ngIf="prefixTemplate" class="k-input-prefix k-input-prefix-horizontal">
<ng-template [ngTemplateOutlet]="prefixTemplate?.templateRef">
</ng-template>
</span>
<kendo-input-separator *ngIf="prefixTemplate && prefixTemplate.showSeparator"></kendo-input-separator>
<input #input
class="k-input-inner"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
[id]="focusableId"
[tabindex]="tabIndex"
[attr.title]="title"
[attr.aria-placeholder]="mask"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[disabled]="disabled"
[readonly]="readonly"
[kendoEventsOutsideAngular]="{
focus: handleInputFocus,
blur: handleInputBlur,
click: handleClick,
dragstart: handleDragDrop,
drop: handleDragDrop
}"
/>
<kendo-input-separator *ngIf="suffixTemplate && suffixTemplate.showSeparator"></kendo-input-separator>
<span *ngIf="suffixTemplate" class="k-input-suffix k-input-suffix-horizontal">
<ng-template [ngTemplateOutlet]="suffixTemplate?.templateRef">
</ng-template>
</span>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: InputSeparatorComponent, selector: "kendo-input-separator, kendo-textbox-separator", inputs: ["orientation"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskedTextBoxComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoMaskedTextBox',
providers: [
MaskingService,
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MaskedTextBoxComponent) /* eslint-disable-line*/
},
{
multi: true,
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MaskedTextBoxComponent) /* eslint-disable-line*/
},
{
provide: KendoInput,
useExisting: forwardRef(() => MaskedTextBoxComponent)
}
],
selector: 'kendo-maskedtextbox',
template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="focused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<span *ngIf="prefixTemplate" class="k-input-prefix k-input-prefix-horizontal">
<ng-template [ngTemplateOutlet]="prefixTemplate?.templateRef">
</ng-template>
</span>
<kendo-input-separator *ngIf="prefixTemplate && prefixTemplate.showSeparator"></kendo-input-separator>
<input #input
class="k-input-inner"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
[id]="focusableId"
[tabindex]="tabIndex"
[attr.title]="title"
[attr.aria-placeholder]="mask"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[disabled]="disabled"
[readonly]="readonly"
[kendoEventsOutsideAngular]="{
focus: handleInputFocus,
blur: handleInputBlur,
click: handleClick,
dragstart: handleDragDrop,
drop: handleDragDrop
}"
/>
<kendo-input-separator *ngIf="suffixTemplate && suffixTemplate.showSeparator"></kendo-input-separator>
<span *ngIf="suffixTemplate" class="k-input-suffix k-input-suffix-horizontal">
<ng-template [ngTemplateOutlet]="suffixTemplate?.templateRef">
</ng-template>
</span>
</ng-container>
`,
standalone: true,
imports: [SharedInputEventsDirective, NgIf, NgTemplateOutlet, InputSeparatorComponent, EventsOutsideAngularDirective]
}]
}], ctorParameters: function () { return [{ type: MaskingService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RTL]
}] }]; }, propDecorators: { focusableId: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], title: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], mask: [{
type: Input
}], value: [{
type: Input
}], rules: [{
type: Input
}], prompt: [{
type: Input
}], promptPlaceholder: [{
type: Input
}], includeLiterals: [{
type: Input
}], maskOnFocus: [{
type: Input
}], maskValidation: [{
type: Input
}], tabindex: [{
type: Input
}], tabIndex: [{
type: Input
}], inputAttributes: [{
type: Input
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], inputFocus: [{
type: Output
}], inputBlur: [{
type: Output
}], valueChange: [{
type: Output
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], hostClasses: [{
type: HostBinding,
args: ['class.k-input']
}, {
type: HostBinding,
args: ['class.k-maskedtextbox']
}], hostDisabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], input: [{
type: ViewChild,
args: ['input', { static: true }]
}], suffixTemplate: [{
type: ContentChild,
args: [SuffixTemplateDirective]
}], prefixTemplate: [{
type: ContentChild,
args: [PrefixTemplateDirective]
}], pasteHandler: [{
type: HostListener,
args: ['paste', ['$event']]
}], inputHandler: [{
type: HostListener,
args: ['input', ['$event']]
}] } });
const FOCUSED$2 = 'k-focus';
const DEFAULT_SIZE$b = 'medium';
/**
* @hidden
*/
class RadioCheckBoxBase {
componentType;
hostElement;
renderer;
cdr;
ngZone;
injector;
/**
* @hidden
*/
focusableId = `k-${guid()}`;
/**
* Sets the `title` attribute of the `input` element of the component.
*/
title;
/**
* Sets the `name` attribute for the component.
*/
name;
/**
* Sets the disabled state of the component.
*
* @default false
*/
disabled = false;
/**
* Specifies the `tabindex` of the component.
*
* @default 0
*/
tabindex = 0;
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* Provides a value for the component.
*/
value;
/**
* The size property specifies the width and height of the component.
*
* @default 'medium'
*
* The possible values are:
* * `small`
* * `medium`
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$b;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* Sets the HTML attributes of the inner focusable input element. Attributes which are essential for certain component functionalities cannot be changed.
*/
set inputAttributes(attributes) {
if (isObjectPresent(this.parsedAttributes)) {
removeHTMLAttributes(this.parsedAttributes, this.renderer, this.input.nativeElement);
}
this._inputAttributes = attributes;
this.parsedAttributes = this.inputAttributes ?
parseAttributes(this.inputAttributes, this.defaultAttributes) :
this.inputAttributes;
this.setInputAttributes();
}
get inputAttributes() {
return this._inputAttributes;
}
ngOnInit() {
this.control = this.injector.get(NgControl, null);
}
/**
* Fires each time the user focuses the component.
*
* > To wire the event programmatically, use the `onFocus` property.
*/
onFocus = new EventEmitter();
/**
* Fires each time the component gets blurred.
*
* > To wire the event programmatically, use the `onBlur` property.
*/
onBlur = new EventEmitter();
/**
* Focuses the component.
*/
focus() {
if (!this.input) {
return;
}
this.focusChangedProgrammatically = true;
this.isFocused = true;
this.input.nativeElement.focus();
this.focusChangedProgrammatically = false;
}
/**
* Blurs the component.
*/
blur() {
this.focusChangedProgrammatically = true;
const isFocusedElement = this.hostElement.nativeElement.querySelector(':focus');
if (isFocusedElement) {
isFocusedElement.blur();
}
this.isFocused = false;
this.focusChangedProgrammatically = false;
}
/**
* @hidden
*/
handleInputBlur = () => {
this.cdr.markForCheck();
if (requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
});
}
};
/**
* @hidden
*/
handleFocus() {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically && hasObservers(this.onFocus)) {
this.onFocus.emit();
}
this.isFocused = true;
});
}
/**
* @hidden
*/
handleBlur() {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically) {
this.ngTouched();
this.onBlur.emit();
}
this.isFocused = false;
});
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
*/
get isControlRequired() {
return isControlRequired(this.control?.control);
}
/**
* @hidden
*/
get isControlInvalid() {
return this.control && this.control.touched && !this.control.valid;
}
/**
* Represents the visible `input` element.
*/
input;
/**
* @hidden
*/
get isFocused() {
return this._isFocused;
}
/**
* @hidden
*/
set isFocused(value) {
if (this._isFocused !== value && this.input) {
const element = this.input.nativeElement;
if (value && !this.disabled) {
this.renderer.addClass(element, FOCUSED$2);
}
else {
this.renderer.removeClass(element, FOCUSED$2);
}
this._isFocused = value;
}
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.cdr.markForCheck();
this.disabled = isDisabled;
}
control;
focusChangedProgrammatically = false;
get defaultAttributes() { return null; }
parsedAttributes = {};
_inputAttributes;
ngChange = (_) => { };
ngTouched = () => { };
_isFocused = false;
_size = DEFAULT_SIZE$b;
constructor(componentType, hostElement, renderer, cdr, ngZone, injector) {
this.componentType = componentType;
this.hostElement = hostElement;
this.renderer = renderer;
this.cdr = cdr;
this.ngZone = ngZone;
this.injector = injector;
}
/**
* @hidden
*/
writeValue(_value) { }
handleClasses(value, input) {
if (!isPresent$1(this.input)) {
return;
}
const inputElem = this.input.nativeElement;
const classes = getStylingClasses(this.componentType, input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(inputElem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(inputElem, classes.toAdd);
}
}
setInputAttributes() {
setHTMLAttributes(this.parsedAttributes, this.renderer, this.input.nativeElement, this.ngZone);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioCheckBoxBase, deps: [{ token: COMPONENT_TYPE }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RadioCheckBoxBase, selector: "ng-component", inputs: { focusableId: "focusableId", title: "title", name: "name", disabled: "disabled", tabindex: "tabindex", tabIndex: "tabIndex", value: "value", size: "size", inputAttributes: "inputAttributes" }, outputs: { onFocus: "focus", onBlur: "blur" }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }], ngImport: i0, template: '', isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioCheckBoxBase, decorators: [{
type: Component,
args: [{
template: ''
}]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [COMPONENT_TYPE]
}] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }]; }, propDecorators: { focusableId: [{
type: Input
}], title: [{
type: Input
}], name: [{
type: Input
}], disabled: [{
type: Input
}], tabindex: [{
type: Input
}], tabIndex: [{
type: Input
}], value: [{
type: Input
}], size: [{
type: Input
}], inputAttributes: [{
type: Input
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], input: [{
type: ViewChild,
args: ['input', { static: true }]
}] } });
const DEFAULT_ROUNDED$6 = 'medium';
class CheckBoxComponent extends RadioCheckBoxBase {
renderer;
hostElement;
cdr;
ngZone;
injector;
hostClass = true;
/**
* Sets the checked state of the component.
*
* @default false
*/
set checkedState(value) {
this._checkedState = value;
if (!isPresent$1(this.input)) {
return;
}
this.input.nativeElement.indeterminate = value === 'indeterminate';
}
get checkedState() {
return this._checkedState;
}
/**
* The rounded property specifies the border radius of the CheckBox
* ([see example](slug:appearance_checkboxdirective#toc-roundness)).
*
* @default 'medium'
*
* The possible values are:
* * `small`
* * `medium`
* * `large`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED$6;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
/**
* Fires each time the inner input's checked state is changed.
* When the state of the component is programmatically changed to `ngModel` or `formControl`
* through its API or form binding, the `checkedStateChange` event is not triggered because it
* might cause a mix-up with the built-in mechanisms of the `ngModel` or `formControl` bindings.
*
* Used to provide a two-way binding for the `checkedState` property.
*/
checkedStateChange = new EventEmitter();
/**
* @hidden
*/
get isChecked() {
return typeof this.checkedState === 'boolean' && this.checkedState;
}
/**
* @hidden
*/
get isIndeterminate() {
return typeof this.checkedState === 'string' && this.checkedState === 'indeterminate';
}
get defaultAttributes() {
return {
type: 'checkbox',
id: this.focusableId,
title: this.title,
tabindex: this.tabindex,
tabIndex: this.tabindex,
disabled: this.disabled ? '' : null,
value: this.value,
checked: this.isChecked,
'aria-invalid': this.isControlInvalid
};
}
_rounded = DEFAULT_ROUNDED$6;
_checkedState = false;
constructor(renderer, hostElement, cdr, ngZone, injector) {
super('checkbox', hostElement, renderer, cdr, ngZone, injector);
this.renderer = renderer;
this.hostElement = hostElement;
this.cdr = cdr;
this.ngZone = ngZone;
this.injector = injector;
validatePackage(packageMetadata);
}
ngAfterViewInit() {
const stylingInputs = ['size', 'rounded'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
this.input.nativeElement.indeterminate = this.checkedState === 'indeterminate';
}
/**
* @hidden
*/
handleChange = ($event) => {
this.ngZone.run(() => {
this.checkedState = $event && $event.target && $event.target.checked;
this.checkedStateChange.emit(this.checkedState);
this.ngChange(this.checkedState);
});
};
/**
* @hidden
*/
writeValue(value) {
this.checkedState = value;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CheckBoxComponent, isStandalone: true, selector: "kendo-checkbox", inputs: { checkedState: "checkedState", rounded: "rounded" }, outputs: { checkedStateChange: "checkedStateChange" }, host: { properties: { "class.k-checkbox-wrap": "this.hostClass" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.checkbox' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckBoxComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => CheckBoxComponent) }
], exportAs: ["kendoCheckBox"], usesInheritance: true, ngImport: i0, template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<input #input
type="checkbox"
class="k-checkbox"
[id]="focusableId"
[attr.title]="title"
[disabled]="disabled"
[class.k-disabled]="disabled"
[attr.tabindex]="disabled ? undefined : tabindex"
[value]="value"
[checked]="isChecked"
[class.k-checked]="isChecked"
[class.k-indeterminate]="isIndeterminate"
[class.k-invalid]="isControlInvalid"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
blur: handleInputBlur,
change: handleChange
}"
/>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoCheckBox',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.checkbox' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckBoxComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => CheckBoxComponent) }
],
selector: 'kendo-checkbox',
template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<input #input
type="checkbox"
class="k-checkbox"
[id]="focusableId"
[attr.title]="title"
[disabled]="disabled"
[class.k-disabled]="disabled"
[attr.tabindex]="disabled ? undefined : tabindex"
[value]="value"
[checked]="isChecked"
[class.k-checked]="isChecked"
[class.k-indeterminate]="isIndeterminate"
[class.k-invalid]="isControlInvalid"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
blur: handleInputBlur,
change: handleChange
}"
/>
</ng-container>
`,
standalone: true,
imports: [SharedInputEventsDirective, EventsOutsideAngularDirective]
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }]; }, propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-checkbox-wrap']
}], checkedState: [{
type: Input
}], rounded: [{
type: Input
}], checkedStateChange: [{
type: Output
}] } });
const DEFAULT_SIZE$a = 'medium';
const DEFAULT_ROUNDED$5 = 'medium';
/**
* Represents the directive that renders the [Kendo UI CheckBox]({% slug overview_checkbox %}) input component.
* The directive is placed on input type="checkbox" elements.
*
* @example
* ```ts-no-run
* <input type="checkbox" kendoCheckBox />
* ```
*/
class CheckBoxDirective {
renderer;
hostElement;
kendoClass = true;
/**
* The size property specifies the width and height of the CheckBox
* ([see example]({% slug appearance_checkboxdirective %}#toc-size)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$a;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The rounded property specifies the border radius of the CheckBox
* ([see example](slug:appearance_checkboxdirective#toc-roundness)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED$5;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
_size = 'medium';
_rounded = 'medium';
constructor(renderer, hostElement) {
this.renderer = renderer;
this.hostElement = hostElement;
}
ngAfterViewInit() {
const stylingInputs = ['size', 'rounded'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('checkbox', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CheckBoxDirective, isStandalone: true, selector: "input[kendoCheckBox]", inputs: { size: "size", rounded: "rounded" }, host: { properties: { "class.k-checkbox": "this.kendoClass" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[kendoCheckBox]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { kendoClass: [{
type: HostBinding,
args: ['class.k-checkbox']
}], size: [{
type: Input
}], rounded: [{
type: Input
}] } });
/**
* @hidden
*
* Returns the hex or rgba string representation of the color.
*/
const parseColor = (value, format, opacityEnabled = false, safe = true) => {
const allowedFormats = ['hex', 'rgba', 'name'];
if (allowedFormats.indexOf(format) === -1) {
throw new Error(`Unsupported color output format '${format}'. The available options are 'hex', 'rgba' or 'name'.`);
}
if (!isPresent(value)) {
return;
}
if (format === 'name') {
return nameFormat(value, safe);
}
const parsedColor = parseColor$1(value.trim(), safe);
if (!isPresent(parsedColor)) {
return;
}
const parsedColorResult = format === 'hex' ? getHexValue(parsedColor, opacityEnabled) : parsedColor.toCssRgba();
return parsedColorResult;
};
/**
* @hidden
*
* Returns an HSV object representation of the color string.
*/
const getHSV = (value, safe = true) => {
const parsed = parseColor$1(value, safe);
if (!isPresent(parsed)) {
return {};
}
return parsed.toHSV();
};
/**
* @hidden
*
* Returns an RGBA object representation of the color string.
*/
const getRGBA = (value, safe = true) => {
const parsed = parseColor$1(value, safe);
if (!isPresent(parsed)) {
return {};
}
return parsed.toBytes();
};
/**
* @hidden
*
* Returns the RGBA string representation of the color.
*/
const getColorFromHSV = (hsva, format = 'rgba', opacityEnabled = false) => {
const hue = fitIntoBounds(hsva.h, 0, 359.9);
const saturation = fitIntoBounds(hsva.s, 0, 1);
const value = fitIntoBounds(hsva.v, 0, 1);
const alpha = fitIntoBounds(hsva.a, 0, 1);
const color = Color.fromHSV(hue, saturation, value, alpha);
return format === 'hex' ? getHexValue(color, opacityEnabled) : color.toCssRgba();
};
/**
* @hidden
*
* Returns the HEX value.
*/
const getHexValue = (color, opacity) => {
return opacity && color.a < 1 ? color.toCss({ alpha: true }) : color.toCss();
};
/**
* @hidden
*
* Returns the RGBA string representation of the color based on the `hue`, assuming the `value`, `saturation` and `alpha` have value of `1`.
*/
const getColorFromHue = (hue) => {
return getColorFromHSV({ h: hue, s: 1, v: 1, a: 1 });
};
/**
* @hidden
*
* Returns the RGBA string representation of the color.
*/
const getColorFromRGBA = (rgba) => {
const red = fitIntoBounds(rgba.r, 0, 255);
const green = fitIntoBounds(rgba.g, 0, 255);
const blue = fitIntoBounds(rgba.b, 0, 255);
const alpha = fitIntoBounds(rgba.a, 0, 1);
return Color.fromBytes(red, green, blue, alpha).toCssRgba();
};
/**
*
* @hidden
*/
function nameFormat(value, safe) {
value = value.toLowerCase().trim();
if (isPresent(namedColors[value])) {
return value;
}
if (parseColor$1(value, safe)) {
value = parseColor$1(value, safe).toHex();
}
const key = Object.keys(namedColors).find(key => namedColors[key] === value);
if (!key && !safe) {
throw new Error(`The provided color ${value} is not supported for 'format="name"' property.To display ${value} color, the component 'format' property should be set to 'hex' or 'rgba' `);
}
return key;
}
/**
* @hidden
*
* Returns the RGB object representation of the color based on the background color.
*/
const getRGBFromRGBA = (foregroundColor, backgroundColor) => {
const r1 = fitIntoBounds(foregroundColor.r, 0, 255);
const g1 = fitIntoBounds(foregroundColor.g, 0, 255);
const b1 = fitIntoBounds(foregroundColor.b, 0, 255);
const a1 = fitIntoBounds(foregroundColor.a, 0, 1);
const r2 = fitIntoBounds(backgroundColor.r, 0, 255);
const g2 = fitIntoBounds(backgroundColor.g, 0, 255);
const b2 = fitIntoBounds(backgroundColor.b, 0, 255);
return {
r: Math.round(((1 - a1) * r2) + (a1 * r1)),
g: Math.round(((1 - a1) * g2) + (a1 * g1)),
b: Math.round(((1 - a1) * b2) + (a1 * b1))
};
};
/**
* @hidden
*
* Returns the relative luminance.
*/
const getLuminance = (rgb) => {
const a = [rgb.r, rgb.g, rgb.b].map(function (v) {
v /= 255;
return v <= 0.03928
? v / 12.92
: Math.pow((v + 0.055) / 1.055, 2.4);
});
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
};
/**
* @hidden
*
* Returns the color contrast.
*/
const getContrast = (luminance1, luminance2) => {
const brightest = Math.max(luminance1, luminance2);
const darkest = Math.min(luminance1, luminance2);
return (brightest + 0.05)
/ (darkest + 0.05);
};
/**
* @hidden
*
* Returns the color contrast from two RGBA colors.
*/
const getContrastFromTwoRGBAs = (a, b) => {
return getContrast(getLuminance(getRGBFromRGBA(a, b)), getLuminance(getRGBFromRGBA(b, { r: 0, g: 0, b: 0, a: 1 })));
};
/**
* @hidden
*/
const bezierCommand = (controlPointCalc) => (point, i, a) => {
// start control point
const [cpsX, cpsY] = controlPointCalc(a[i - 1], a[i - 2], point);
// end control point
const [cpeX, cpeY] = controlPointCalc(point, a[i - 1], a[i + 1], true);
return `C ${cpsX},${cpsY} ${cpeX},${cpeY} ${point[0]},${point[1]}`;
};
/**
* @hidden
*/
const controlPoint = (lineCalc) => (current, previous, next, reverse) => {
// when 'current' is the first or last point of the array
// 'previous' and 'next' are undefined
// replace with 'current'
const p = previous || current;
const n = next || current;
const smooth = 0.1;
// properties of the line between previous and next
const l = lineCalc(p, n);
// If is end-control-point, add PI to the angle to go backward
const angle = l.angle + (reverse ? Math.PI : 0);
const length = l.length * smooth;
// The control point position is relative to the current point
const x = current[0] + Math.cos(angle) * length;
const y = current[1] + Math.sin(angle) * length;
return [x, y];
};
/**
* @hidden
*/
const line = (pointA, pointB) => {
const lengthX = pointB[0] - pointA[0];
const lengthY = pointB[1] - pointA[1];
return {
length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)),
angle: Math.atan2(lengthY, lengthX)
};
};
/**
* @hidden
*/
const d = (points, command) => {
if (points.length === 0) {
return '';
}
// build the d attributes by looping over the points
const d = points.reduce((acc, point, i, a) => i === 0 ?
// if first point
`M ${point[0]},${point[1]}` :
// else
`${acc} ${command(point, i, a)}`, '');
return d;
};
/**
* @hidden
*
* Render the svg <path> element.
*
* @param points (array) Represents the points coordinates as an array of tuples.
* @param command (function) The command that is used (bezierCommand, lineCommand).
* @param point (array) [x,y] Represents the current point coordinates.
* @param i (integer) Represents the index of 'point' in the array 'a'.
* @param a (array) Represents the complete array of points coordinates.
* @output (string) a svg path command.
* @output (string) a Svg <path> element
*/
const svgPath = (points, command) => {
if (points.length === 0) {
return '';
}
// build the d attributes by looping over the points
const d = points.reduce((acc, point, i, a) => i === 0 ?
// if first point
`M ${point[0]},${point[1]}` :
// else
`${acc} ${command(point, i, a)}`, '');
return d;
};
/**
* @hidden
*/
class ColorPickerLocalizationService extends LocalizationService {
constructor(prefix, messageService, _rtl) {
super(prefix, messageService, _rtl);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerLocalizationService, deps: [{ token: L10N_PREFIX }, { token: i1.MessageService, optional: true }, { token: RTL, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerLocalizationService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerLocalizationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [L10N_PREFIX]
}] }, { type: i1.MessageService, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RTL]
}] }]; } });
/**
* @hidden
*/
class FlatColorPickerLocalizationService extends LocalizationService {
colorPickerLocalization;
constructor(prefix, messageService, _rtl, colorPickerLocalization) {
super(prefix, messageService, _rtl);
this.colorPickerLocalization = colorPickerLocalization;
}
get(shortKey) {
if (this.colorPickerLocalization) {
return this.colorPickerLocalization.get(shortKey);
}
return super.get(shortKey);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerLocalizationService, deps: [{ token: L10N_PREFIX }, { token: i1.MessageService, optional: true }, { token: RTL, optional: true }, { token: ColorPickerLocalizationService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerLocalizationService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerLocalizationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [L10N_PREFIX]
}] }, { type: i1.MessageService, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RTL]
}] }, { type: ColorPickerLocalizationService, decorators: [{
type: Optional
}, {
type: Inject,
args: [ColorPickerLocalizationService]
}] }]; } });
/**
* @hidden
*/
class ColorGradientLocalizationService extends LocalizationService {
flatColorPickerLocalization;
constructor(prefix, messageService, _rtl, flatColorPickerLocalization) {
super(prefix, messageService, _rtl);
this.flatColorPickerLocalization = flatColorPickerLocalization;
}
get(shortKey) {
if (this.flatColorPickerLocalization) {
return this.flatColorPickerLocalization.get(shortKey);
}
return super.get(shortKey);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorGradientLocalizationService, deps: [{ token: L10N_PREFIX }, { token: i1.MessageService, optional: true }, { token: RTL, optional: true }, { token: FlatColorPickerLocalizationService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorGradientLocalizationService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorGradientLocalizationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [L10N_PREFIX]
}] }, { type: i1.MessageService, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RTL]
}] }, { type: FlatColorPickerLocalizationService, decorators: [{
type: Optional
}, {
type: Inject,
args: [FlatColorPickerLocalizationService]
}] }]; } });
/**
* @hidden
*/
class NumericLabelDirective {
host;
kendoAdditionalNumericLabel;
localizationService;
constructor(host) {
this.host = host;
}
ngOnInit() {
const localizationToken = `${this.kendoAdditionalNumericLabel}ChannelLabel`;
this.host.numericInput.nativeElement.setAttribute('aria-label', this.localizationService.get(localizationToken));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericLabelDirective, deps: [{ token: NumericTextBoxComponent }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: NumericLabelDirective, isStandalone: true, selector: "[kendoAdditionalNumericLabel]", inputs: { kendoAdditionalNumericLabel: "kendoAdditionalNumericLabel", localizationService: "localizationService" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericLabelDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoAdditionalNumericLabel]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: NumericTextBoxComponent }]; }, propDecorators: { kendoAdditionalNumericLabel: [{
type: Input
}], localizationService: [{
type: Input
}] } });
/**
* @hidden
*
* Checks if input is Japanese IME
*/
const isJapanese = (input) => {
const japaneseRegex = /[\u3000-\u303F]|[\u3040-\u309F]|[\u30A0-\u30FF]|[\uFF00-\uFFEF]|[\u4E00-\u9FAF]|[\u2605-\u2606]|[\u2190-\u2195]|\u203B/g;
return japaneseRegex.test(input);
};
/**
* Specifies the adornments in the suffix container ([see examples](slug:adornments_textbox#toc-suffix-adornments)).
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textbox>
* <ng-template kendoTextBoxSuffixTemplate>
* <button kendoButton look="clear" icon="image"></button>
* </ng-template>
* </kendo-textbox>
* `
* })
* class AppComponent {}
* ```
*/
class TextBoxSuffixTemplateDirective {
templateRef;
/**
* Sets the `showSeparator` attribute of the `kendoTextBoxSuffixTemplate`.
*
* @default false
*/
set showSeparator(value) {
this._showSeparator = value;
}
get showSeparator() {
return this._showSeparator;
}
_showSeparator = false;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxSuffixTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TextBoxSuffixTemplateDirective, isStandalone: true, selector: "[kendoTextBoxSuffixTemplate]", inputs: { showSeparator: "showSeparator" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxSuffixTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoTextBoxSuffixTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; }, propDecorators: { showSeparator: [{
type: Input
}] } });
/**
* Specifies the adornments in the prefix container ([see examples](slug:adornments_textbox#toc-prefix-adornments)).
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textbox>
* <ng-template kendoTextBoxPrefixTemplate>
* <button kendoButton look="clear" icon="image"></button>
* </ng-template>
* </kendo-textbox>
* `
* })
* class AppComponent {}
* ```
*/
class TextBoxPrefixTemplateDirective {
templateRef;
/**
* Sets the `showSeparator` attribute of the `kendoTextBoxPrefixTemplate`.
*
* @default false
*/
set showSeparator(value) {
this._showSeparator = value;
}
get showSeparator() {
return this._showSeparator;
}
_showSeparator = false;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxPrefixTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TextBoxPrefixTemplateDirective, isStandalone: true, selector: "[kendoTextBoxPrefixTemplate]", inputs: { showSeparator: "showSeparator" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxPrefixTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoTextBoxPrefixTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; }, propDecorators: { showSeparator: [{
type: Input
}] } });
/**
* @hidden
*/
class TextBoxMessages extends ComponentMessages {
/**
* The title of the **Clear** button of the TextBox.
*/
clear;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TextBoxMessages, selector: "kendo-textbox-messages-base", inputs: { clear: "clear" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-textbox-messages-base'
}]
}], propDecorators: { clear: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedTextBoxMessagesDirective extends TextBoxMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedTextBoxMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedTextBoxMessagesDirective, isStandalone: true, selector: "[kendoTextBoxLocalizedMessages]", providers: [
{
provide: TextBoxMessages,
useExisting: forwardRef(() => LocalizedTextBoxMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedTextBoxMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: TextBoxMessages,
useExisting: forwardRef(() => LocalizedTextBoxMessagesDirective)
}
],
selector: '[kendoTextBoxLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/* eslint-disable @typescript-eslint/no-explicit-any */
const FOCUSED$1 = 'k-focus';
const DEFAULT_SIZE$9 = 'medium';
const DEFAULT_ROUNDED$4 = 'medium';
const DEFAULT_FILL_MODE$4 = 'solid';
const iconsMap$1 = { checkIcon, exclamationCircleIcon, xIcon };
class TextBoxComponent {
localizationService;
ngZone;
changeDetector;
renderer;
injector;
hostElement;
/**
* @hidden
*/
focusableId = `k-${guid()}`;
/**
* Sets the `title` attribute of the `input` element of the TextBox.
*/
title;
/**
* Sets the `type` attribute of the `input` element of the TextBox.
*/
type = 'text';
/**
* Sets the disabled state of the TextBox. To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_textbox#toc-managing-the-textbox-disabled-state-in-reactive-forms).
*
* @default false
*/
disabled = false;
/**
* Sets the read-only state of the component.
*
* @default false
*/
readonly = false;
/**
* Specifies the `tabindex` of the TextBox.
*
* @default 0
*/
tabindex = 0;
/**
* Provides a value for the TextBox.
*/
value = null;
/**
* Determines whether the whole value will be selected when the TextBox is clicked. Defaults to `false`.
*
* @default false
*/
selectOnFocus = false;
/**
* Specifies when the Success icon will be shown ([see example]({% slug validation_textbox %})).
*
* The possible values are:
*
* `boolean`—The Success icon is displayed, if the condition given by the developer is met.
*
* `initial`—The Success icon will be displayed when the component state is neither `invalid` nor `touched` or `dirty`.
*
* @default false
*/
showSuccessIcon = false;
/**
* Specifies when the Error icon will be shown ([see example]({% slug validation_textbox %})).
*
* The possible values are:
*
* * `initial`—The Error icon will be displayed when the component state is
* `invalid` and `touched` or `dirty`.
* * `boolean`—The Error icon is displayed, if the condition given by the developer is met.
*
* @default false
*/
showErrorIcon = false;
/**
* Specifies whether a Clear button will be rendered.
*
* @default false
*/
clearButton = false;
/**
* Sets a custom icon that will be rendered instead of the default one for a valid user input.
*/
successIcon;
/**
* Sets a custom SVG icon that will be rendered instead of the default one for a valid user input.
*/
successSvgIcon;
/**
* Sets a custom icon that will be rendered instead of the default one for invalid user input.
*/
errorIcon;
/**
* Sets a custom SVG icon that will be rendered instead of the default one for invalid user input.
*/
errorSvgIcon;
/**
* Sets a custom icon that will be rendered instead of the default one.
*/
clearButtonIcon;
/**
* Sets a custom SVG icon that will be rendered instead of the default one.
*/
clearButtonSvgIcon;
/**
* The size property specifies the padding of the TextBox internal input element
* ([see example]({% slug appearance_textbox %}#toc-size)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$9;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The `rounded` property specifies the border radius of the TextBox
* ([see example](slug:appearance_textbox#toc-roundness)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `full`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED$4;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
/**
* The `fillMode` property specifies the background and border styles of the TextBox
* ([see example]({% slug appearance_textbox %}#toc-fill-mode)).
*
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
set fillMode(fillMode) {
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE$4;
this.handleClasses(newFillMode, 'fillMode');
this._fillMode = newFillMode;
}
get fillMode() {
return this._fillMode;
}
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* The hint, which is displayed when the component is empty.
*/
placeholder;
/**
* Specifies the maximum length of the TextBox value.
*/
maxlength;
/**
* Sets the HTML attributes of the inner focusable input element. Attributes which are essential for certain component functionalities cannot be changed.
*/
set inputAttributes(attributes) {
if (isObjectPresent(this.parsedAttributes)) {
removeHTMLAttributes(this.parsedAttributes, this.renderer, this.input.nativeElement);
}
this._inputAttributes = attributes;
this.parsedAttributes = this.inputAttributes ?
parseAttributes(this.inputAttributes, this.defaultAttributes) :
this.inputAttributes;
this.setInputAttributes();
}
get inputAttributes() {
return this._inputAttributes;
}
/**
* Fires each time the value is changed—
* when the component is blurred or the value is cleared through the **Clear** button
* ([see example](slug:events_textbox)).
* When the value of the component is programmatically changed to `ngModel` or `formControl`
* through its API or form binding, the `valueChange` event is not triggered because it
* might cause a mix-up with the built-in `valueChange` mechanisms of the `ngModel` or `formControl` bindings.
*/
valueChange = new EventEmitter();
/**
* Fires each time the user focuses the `input` element.
*/
inputFocus = new EventEmitter();
/**
* Fires each time the `input` element gets blurred.
*/
inputBlur = new EventEmitter();
/**
* Fires each time the user focuses the TextBox component.
*
* > To wire the event programmatically, use the `onFocus` property.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textbox (focus)="handleFocus()"></kendo-textbox>
* `
* })
* class AppComponent {
* public handleFocus(): void {
* console.log('Component is focused.');
* }
* }
* ```
*/
onFocus = new EventEmitter();
/**
* Fires each time the TextBox component gets blurred.
*
* > To wire the event programmatically, use the `onBlur` property.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textbox (blur)="handleBlur()"></kendo-textbox>
* `
* })
* class AppComponent {
* public handleBlur(): void {
* console.log('Component is blurred');
* }
* }
* ```
*/
onBlur = new EventEmitter();
/**
* Represents the visible `input` element of the TextBox.
*/
input;
/**
* @hidden
*/
textBoxSuffixTemplate;
/**
* @hidden
*/
textBoxPrefixTemplate;
/**
* @hidden
*/
suffixTemplate;
/**
* @hidden
*/
prefixTemplate;
get disabledClass() {
return this.disabled;
}
hostClasses = true;
direction;
/**
* @hidden
*/
showClearButton;
/**
* @hidden
*/
clearButtonClicked;
/**
* @hidden
*/
suffix;
/**
* @hidden
*/
prefix;
control;
subscriptions;
_isFocused = false;
focusChangedProgrammatically = false;
_inputAttributes;
_size = 'medium';
_rounded = 'medium';
_fillMode = 'solid';
parsedAttributes = {};
get defaultAttributes() {
return {
id: this.focusableId,
disabled: this.disabled ? '' : null,
readonly: this.readonly ? '' : null,
tabindex: this.disabled ? undefined : this.tabindex,
type: this.type,
placeholder: this.placeholder,
title: this.title,
maxlength: this.maxlength,
'aria-invalid': this.isControlInvalid,
required: this.isControlRequired ? '' : null
};
}
constructor(localizationService, ngZone, changeDetector, renderer, injector, hostElement) {
this.localizationService = localizationService;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.renderer = renderer;
this.injector = injector;
this.hostElement = hostElement;
validatePackage(packageMetadata);
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
}
ngOnInit() {
this.control = this.injector.get(NgControl, null);
this.checkClearButton();
this.subscriptions = this.localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
}
ngAfterViewInit() {
const stylingInputs = ['size', 'rounded', 'fillMode'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
}
ngAfterContentInit() {
this.configureAdornments();
this.subscriptions.add(this.textBoxPrefixTemplate.changes.subscribe(this.configureAdornments.bind(this)));
this.subscriptions.add(this.textBoxSuffixTemplate.changes.subscribe(this.configureAdornments.bind(this)));
}
ngOnChanges(changes) {
if (changes['disabled'] || changes['readonly'] || changes['value']) {
this.checkClearButton();
}
}
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
}
}
/**
* @hidden
*/
svgIcon(name) {
return iconsMap$1[name];
}
/**
* Focuses the TextBox.
*
* @example
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <button (click)="input.focus()">Focus the input</button>
* <kendo-textbox #input></kendo-textbox>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
if (!this.input) {
return;
}
this.focusChangedProgrammatically = true;
this.isFocused = true;
this.input.nativeElement.focus();
this.focusChangedProgrammatically = false;
}
/**
* Blurs the TextBox.
*/
blur() {
this.focusChangedProgrammatically = true;
const isFocusedElement = this.hostElement.nativeElement.querySelector(':focus');
if (isFocusedElement) {
isFocusedElement.blur();
}
this.isFocused = false;
this.focusChangedProgrammatically = false;
}
/**
* @hidden
*/
handleInputFocus = () => {
if (!this.disabled) {
if (this.selectOnFocus && this.value) {
this.ngZone.run(() => {
setTimeout(() => { this.selectAll(); });
});
}
if (!this.isFocused) {
this.handleFocus();
}
if (hasObservers(this.inputFocus)) {
if (!this.focusChangedProgrammatically || (this.focusChangedProgrammatically && this.clearButtonClicked)) {
this.ngZone.run(() => {
this.inputFocus.emit();
});
}
}
}
};
/**
* @hidden
*/
handleInputBlur = () => {
this.changeDetector.markForCheck();
if (hasObservers(this.inputBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
this.inputBlur.emit();
});
}
};
/**
* @hidden
*/
handleInput = (ev) => {
const target = ev.target;
const isBrowserSafari = isSafari(navigator.userAgent);
const incomingValue = isBrowserSafari && isJapanese(target.value) ? ev.data : target.value;
const [caretStart, caretEnd] = [target.selectionStart, target.selectionEnd];
this.updateValue(incomingValue);
if (isBrowserSafari) {
target.setSelectionRange(caretStart, caretEnd);
}
};
/**
* @hidden
*/
clearTitle() {
return this.localizationService.get('clear');
}
/**
* @hidden
*/
checkClearButton() {
this.showClearButton =
!this.disabled &&
!this.readonly &&
this.clearButton &&
!!this.value;
}
/**
* @hidden
*/
clearValue(ev) {
if (ev) {
ev.preventDefault();
}
this.clearButtonClicked = true;
this.input.nativeElement.value = '';
this.input.nativeElement.focus();
this.updateValue('');
this.checkClearButton();
this.clearButtonClicked = false;
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
this.checkClearButton();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.changeDetector.markForCheck();
this.disabled = isDisabled;
}
/**
* @hidden
*/
showErrorsInitial() {
if (!this.control) {
return false;
}
const { invalid, dirty, touched } = this.control;
return invalid && (dirty || touched);
}
/**
* @hidden
*/
showSuccessInitial() {
if (!this.control) {
return false;
}
const { valid, dirty, touched } = this.control;
return valid && (dirty || touched);
}
/**
* @hidden
*/
get isControlInvalid() {
return this.control && this.control.touched && !this.control.valid;
}
/**
* @hidden
*/
get successIconClasses() {
if (!this.successIcon) {
return `check`;
}
}
/**
* @hidden
*/
get customSuccessIconClasses() {
if (this.successIcon) {
return this.successIcon;
}
}
/**
* @hidden
*/
get errorIconClasses() {
if (!this.errorIcon) {
return `exclamation-circle`;
}
}
/**
* @hidden
*/
get customIconClasses() {
if (this.errorIcon) {
return this.errorIcon;
}
}
/**
* @hidden
*/
get customClearButtonClasses() {
if (this.clearButtonIcon) {
return this.clearButtonIcon;
}
}
/**
* @hidden
*/
get clearButtonClass() {
if (!this.clearButtonIcon) {
return 'x';
}
}
/**
* @hidden
*/
get hasErrors() {
return this.showErrorIcon === 'initial'
? this.showErrorsInitial()
: this.showErrorIcon;
}
/**
* @hidden
*/
get isSuccessful() {
return this.showSuccessIcon === 'initial'
? this.showSuccessInitial()
: this.showSuccessIcon;
}
/**
* @hidden
*/
get isFocused() {
return this._isFocused;
}
/**
* @hidden
*/
set isFocused(value) {
if (this._isFocused !== value && this.hostElement) {
const element = this.hostElement.nativeElement;
if (value && !this.disabled) {
this.renderer.addClass(element, FOCUSED$1);
}
else {
this.renderer.removeClass(element, FOCUSED$1);
}
this._isFocused = value;
}
}
/**
* @hidden
*/
get isControlRequired() {
return isControlRequired(this.control?.control);
}
ngChange = (_) => { };
ngTouched = () => { };
setSelection(start, end) {
if (this.isFocused) {
invokeElementMethod(this.input, 'setSelectionRange', start, end);
}
}
selectAll() {
if (this.value) {
this.setSelection(0, this.value.length);
}
}
updateValue(value) {
if (!areSame(this.value, value)) {
this.ngZone.run(() => {
this.value = value;
this.ngChange(value);
this.valueChange.emit(value);
this.checkClearButton();
this.changeDetector.markForCheck();
});
}
}
/**
* @hidden
*/
handleFocus() {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically && hasObservers(this.onFocus)) {
this.onFocus.emit();
}
this.isFocused = true;
});
}
/**
* @hidden
*/
handleBlur() {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically) {
this.onBlur.emit();
}
this.isFocused = false;
});
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('input', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
configureAdornments() {
this.prefix = this.textBoxPrefixTemplate.first || this.prefixTemplate;
this.suffix = this.textBoxSuffixTemplate.first || this.suffixTemplate;
}
setInputAttributes() {
setHTMLAttributes(this.parsedAttributes, this.renderer, this.input.nativeElement, this.ngZone);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxComponent, deps: [{ token: i1.LocalizationService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.Injector }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TextBoxComponent, isStandalone: true, selector: "kendo-textbox", inputs: { focusableId: "focusableId", title: "title", type: "type", disabled: "disabled", readonly: "readonly", tabindex: "tabindex", value: "value", selectOnFocus: "selectOnFocus", showSuccessIcon: "showSuccessIcon", showErrorIcon: "showErrorIcon", clearButton: "clearButton", successIcon: "successIcon", successSvgIcon: "successSvgIcon", errorIcon: "errorIcon", errorSvgIcon: "errorSvgIcon", clearButtonIcon: "clearButtonIcon", clearButtonSvgIcon: "clearButtonSvgIcon", size: "size", rounded: "rounded", fillMode: "fillMode", tabIndex: "tabIndex", placeholder: "placeholder", maxlength: "maxlength", inputAttributes: "inputAttributes" }, outputs: { valueChange: "valueChange", inputFocus: "inputFocus", inputBlur: "inputBlur", onFocus: "focus", onBlur: "blur" }, host: { properties: { "class.k-readonly": "this.readonly", "class.k-disabled": "this.disabledClass", "class.k-textbox": "this.hostClasses", "class.k-input": "this.hostClasses", "attr.dir": "this.direction" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.textbox' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextBoxComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => TextBoxComponent) }
], queries: [{ propertyName: "suffixTemplate", first: true, predicate: SuffixTemplateDirective, descendants: true }, { propertyName: "prefixTemplate", first: true, predicate: PrefixTemplateDirective, descendants: true }, { propertyName: "textBoxSuffixTemplate", predicate: TextBoxSuffixTemplateDirective }, { propertyName: "textBoxPrefixTemplate", predicate: TextBoxPrefixTemplateDirective }], viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }], exportAs: ["kendoTextBox"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoTextBoxLocalizedMessages
i18n-clear="kendo.textbox.clear|The title for the **Clear** button in the TextBox."
clear="Clear">
</ng-container>
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
[clearButtonClicked]="clearButtonClicked"
>
<span *ngIf="prefix" class="k-input-prefix k-input-prefix-horizontal">
<ng-template [ngTemplateOutlet]="prefix?.templateRef">
</ng-template>
</span>
<kendo-input-separator *ngIf="prefix && prefix.showSeparator"></kendo-input-separator>
<input #input
class="k-input-inner"
[id]="focusableId"
[disabled]="disabled"
[readonly]="readonly"
[attr.tabindex]="disabled ? undefined : tabindex"
[value]="value"
[attr.type]="type"
[attr.placeholder]="placeholder"
[attr.title]="title"
[attr.maxlength]="maxlength"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
focus: handleInputFocus,
blur: handleInputBlur,
input: handleInput}"
/>
<span
role="button"
class="k-clear-value"
*ngIf="showClearButton"
(click)="clearValue()"
(mousedown)="$event.preventDefault()"
[tabindex]="tabIndex"
[attr.aria-label]="clearTitle()"
[title]="clearTitle()"
(keydown.enter)="clearValue($event)"
(keydown.space)="clearValue($event)">
<kendo-icon-wrapper
[name]="clearButtonClass"
[customFontClass]="customClearButtonClasses"
[svgIcon]="clearButtonSvgIcon || svgIcon('xIcon')"
>
</kendo-icon-wrapper>
</span>
<kendo-icon-wrapper
*ngIf="hasErrors"
innerCssClass="k-input-validation-icon"
[name]="errorIconClasses"
[customFontClass]="customIconClasses"
[svgIcon]="errorSvgIcon || svgIcon('exclamationCircleIcon')"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="isSuccessful"
innerCssClass="k-input-validation-icon"
[name]="successIconClasses"
[customFontClass]="customSuccessIconClasses"
[svgIcon]="successSvgIcon || svgIcon('checkIcon')"
>
</kendo-icon-wrapper>
<kendo-input-separator *ngIf="suffix && suffix.showSeparator"></kendo-input-separator>
<span *ngIf="suffix" class="k-input-suffix k-input-suffix-horizontal">
<ng-template [ngTemplateOutlet]="suffix?.templateRef">
</ng-template>
</span>
<ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedTextBoxMessagesDirective, selector: "[kendoTextBoxLocalizedMessages]" }, { kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: InputSeparatorComponent, selector: "kendo-input-separator, kendo-textbox-separator", inputs: ["orientation"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoTextBox',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.textbox' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextBoxComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => TextBoxComponent) }
],
selector: 'kendo-textbox',
template: `
<ng-container kendoTextBoxLocalizedMessages
i18n-clear="kendo.textbox.clear|The title for the **Clear** button in the TextBox."
clear="Clear">
</ng-container>
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
[clearButtonClicked]="clearButtonClicked"
>
<span *ngIf="prefix" class="k-input-prefix k-input-prefix-horizontal">
<ng-template [ngTemplateOutlet]="prefix?.templateRef">
</ng-template>
</span>
<kendo-input-separator *ngIf="prefix && prefix.showSeparator"></kendo-input-separator>
<input #input
class="k-input-inner"
[id]="focusableId"
[disabled]="disabled"
[readonly]="readonly"
[attr.tabindex]="disabled ? undefined : tabindex"
[value]="value"
[attr.type]="type"
[attr.placeholder]="placeholder"
[attr.title]="title"
[attr.maxlength]="maxlength"
[attr.aria-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
focus: handleInputFocus,
blur: handleInputBlur,
input: handleInput}"
/>
<span
role="button"
class="k-clear-value"
*ngIf="showClearButton"
(click)="clearValue()"
(mousedown)="$event.preventDefault()"
[tabindex]="tabIndex"
[attr.aria-label]="clearTitle()"
[title]="clearTitle()"
(keydown.enter)="clearValue($event)"
(keydown.space)="clearValue($event)">
<kendo-icon-wrapper
[name]="clearButtonClass"
[customFontClass]="customClearButtonClasses"
[svgIcon]="clearButtonSvgIcon || svgIcon('xIcon')"
>
</kendo-icon-wrapper>
</span>
<kendo-icon-wrapper
*ngIf="hasErrors"
innerCssClass="k-input-validation-icon"
[name]="errorIconClasses"
[customFontClass]="customIconClasses"
[svgIcon]="errorSvgIcon || svgIcon('exclamationCircleIcon')"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="isSuccessful"
innerCssClass="k-input-validation-icon"
[name]="successIconClasses"
[customFontClass]="customSuccessIconClasses"
[svgIcon]="successSvgIcon || svgIcon('checkIcon')"
>
</kendo-icon-wrapper>
<kendo-input-separator *ngIf="suffix && suffix.showSeparator"></kendo-input-separator>
<span *ngIf="suffix" class="k-input-suffix k-input-suffix-horizontal">
<ng-template [ngTemplateOutlet]="suffix?.templateRef">
</ng-template>
</span>
<ng-container>
`,
standalone: true,
imports: [LocalizedTextBoxMessagesDirective, SharedInputEventsDirective, NgIf, NgTemplateOutlet, InputSeparatorComponent, EventsOutsideAngularDirective, IconWrapperComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i0.Injector }, { type: i0.ElementRef }]; }, propDecorators: { focusableId: [{
type: Input
}], title: [{
type: Input
}], type: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], tabindex: [{
type: Input
}], value: [{
type: Input
}], selectOnFocus: [{
type: Input
}], showSuccessIcon: [{
type: Input
}], showErrorIcon: [{
type: Input
}], clearButton: [{
type: Input
}], successIcon: [{
type: Input
}], successSvgIcon: [{
type: Input
}], errorIcon: [{
type: Input
}], errorSvgIcon: [{
type: Input
}], clearButtonIcon: [{
type: Input
}], clearButtonSvgIcon: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], tabIndex: [{
type: Input
}], placeholder: [{
type: Input
}], maxlength: [{
type: Input
}], inputAttributes: [{
type: Input
}], valueChange: [{
type: Output
}], inputFocus: [{
type: Output
}], inputBlur: [{
type: Output
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], input: [{
type: ViewChild,
args: ['input', { static: true }]
}], textBoxSuffixTemplate: [{
type: ContentChildren,
args: [TextBoxSuffixTemplateDirective, { descendants: false }]
}], textBoxPrefixTemplate: [{
type: ContentChildren,
args: [TextBoxPrefixTemplateDirective, { descendants: false }]
}], suffixTemplate: [{
type: ContentChild,
args: [SuffixTemplateDirective]
}], prefixTemplate: [{
type: ContentChild,
args: [PrefixTemplateDirective]
}], disabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], hostClasses: [{
type: HostBinding,
args: ['class.k-textbox']
}, {
type: HostBinding,
args: ['class.k-input']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}] } });
/**
* @hidden
*/
class TextLabelDirective {
textBox;
renderer;
focusableId;
constructor(textBox, renderer) {
this.textBox = textBox;
this.renderer = renderer;
}
ngOnInit() {
this.renderer.setAttribute(this.textBox.input.nativeElement, 'id', this.focusableId);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextLabelDirective, deps: [{ token: TextBoxComponent }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TextLabelDirective, isStandalone: true, selector: "[kendoTextLabel]", inputs: { focusableId: "focusableId" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextLabelDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoTextLabel]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: TextBoxComponent }, { type: i0.Renderer2 }]; }, propDecorators: { focusableId: [{
type: Input
}] } });
/* eslint-disable @typescript-eslint/no-explicit-any */
const DEFAULT_SIZE$8 = 'medium';
/**
* @hidden
*/
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$8;
/**
* 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 }]
}] } });
/**
* @hidden
*/
const DEFAULT_OUTPUT_FORMAT = 'rgba';
/**
* @hidden
*/
const DEFAULT_GRADIENT_BACKGROUND_COLOR = 'rgba(255, 0, 0, 1)';
/**
* @hidden
*/
const DRAGHANDLE_MOVE_SPEED = 5;
/**
* @hidden
*/
const DRAGHANDLE_MOVE_SPEED_SMALL_STEP = 2;
/**
* @hidden
*/
const AAA_RATIO = 7.0;
/**
* @hidden
*/
const AA_RATIO = 4.5;
/**
* @hidden
*/
const DEFAULT_PRESET$1 = 'office';
/**
* @hidden
*/
const DEFAULT_ACCESSIBLE_PRESET$1 = 'accessible';
/**
* @hidden
*/
const STEP_COUNT = 16;
/**
* @hidden
*/
class ContrastValidationComponent {
localization;
type;
pass;
value;
checkIcon = checkIcon;
xCircleIcon = xCircleIcon;
constructor(localization) {
this.localization = localization;
}
get passMessage() {
return this.localization.get('passContrast');
}
get failMessage() {
return this.localization.get('failContrast');
}
get contrastText() {
const ratio = this.type === 'AA' ? AA_RATIO : AAA_RATIO;
return `${this.type}: ${ratio.toFixed(1)}`;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ContrastValidationComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ContrastValidationComponent, isStandalone: true, selector: "[kendoContrastValidation]", inputs: { type: "type", pass: "pass", value: "value" }, ngImport: i0, template: `
<span>{{contrastText}}</span>
<ng-container *ngIf="value">
<span class="k-contrast-validation k-text-success" *ngIf="pass">
{{passMessage}}
<kendo-icon-wrapper name="check" [svgIcon]="checkIcon"></kendo-icon-wrapper>
</span>
<span class="k-contrast-validation k-text-error" *ngIf="!pass">
{{failMessage}}
<kendo-icon-wrapper name="x" [svgIcon]="xCircleIcon"></kendo-icon-wrapper>
</span>
</ng-container>
`, isInline: true, dependencies: [{ 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"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ContrastValidationComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoContrastValidation]',
template: `
<span>{{contrastText}}</span>
<ng-container *ngIf="value">
<span class="k-contrast-validation k-text-success" *ngIf="pass">
{{passMessage}}
<kendo-icon-wrapper name="check" [svgIcon]="checkIcon"></kendo-icon-wrapper>
</span>
<span class="k-contrast-validation k-text-error" *ngIf="!pass">
{{failMessage}}
<kendo-icon-wrapper name="x" [svgIcon]="xCircleIcon"></kendo-icon-wrapper>
</span>
</ng-container>
`,
standalone: true,
imports: [NgIf, IconWrapperComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { type: [{
type: Input
}], pass: [{
type: Input
}], value: [{
type: Input
}] } });
/**
* @hidden
*/
class ContrastComponent {
localization;
value;
ratio;
checkIcon = checkIcon;
xCircleIcon = xCircleIcon;
constructor(localization) {
this.localization = localization;
}
get formatedRatio() {
return this.contrastRatio.toFixed(2);
}
get contrastRatioText() {
return `${this.localization.get('contrastRatio')}: ${this.value ? this.formatedRatio : 'n/a'}`;
}
get satisfiesAACondition() {
return this.contrastRatio >= AA_RATIO;
}
get satisfiesAAACondition() {
return this.contrastRatio >= AAA_RATIO;
}
get contrastRatio() {
const contrast = getContrastFromTwoRGBAs(getRGBA(this.value), getRGBA(this.ratio));
return contrast;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ContrastComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ContrastComponent, isStandalone: true, selector: "[kendoContrastTool]", inputs: { value: "value", ratio: "ratio" }, ngImport: i0, template: `
<div class="k-contrast-ratio">
<span class="k-contrast-ratio-text">{{contrastRatioText}}</span>
<ng-container *ngIf="value">
<span class="k-contrast-validation k-text-success" *ngIf="satisfiesAACondition">
<kendo-icon-wrapper name="check" [svgIcon]="checkIcon"></kendo-icon-wrapper>
<kendo-icon-wrapper *ngIf="satisfiesAAACondition" name="check" [svgIcon]="checkIcon"></kendo-icon-wrapper>
</span>
<span class="k-contrast-validation k-text-error" *ngIf="!satisfiesAACondition">
<kendo-icon-wrapper name="x" [svgIcon]="xCircleIcon"></kendo-icon-wrapper>
</span>
</ng-container>
</div>
<div kendoContrastValidation
type="AA"
[value]="value"
[pass]="satisfiesAACondition">
</div>
<div kendoContrastValidation
type="AAA"
[value]="value"
[pass]="satisfiesAAACondition">
</div>
`, isInline: true, dependencies: [{ 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: ContrastValidationComponent, selector: "[kendoContrastValidation]", inputs: ["type", "pass", "value"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ContrastComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoContrastTool]',
template: `
<div class="k-contrast-ratio">
<span class="k-contrast-ratio-text">{{contrastRatioText}}</span>
<ng-container *ngIf="value">
<span class="k-contrast-validation k-text-success" *ngIf="satisfiesAACondition">
<kendo-icon-wrapper name="check" [svgIcon]="checkIcon"></kendo-icon-wrapper>
<kendo-icon-wrapper *ngIf="satisfiesAAACondition" name="check" [svgIcon]="checkIcon"></kendo-icon-wrapper>
</span>
<span class="k-contrast-validation k-text-error" *ngIf="!satisfiesAACondition">
<kendo-icon-wrapper name="x" [svgIcon]="xCircleIcon"></kendo-icon-wrapper>
</span>
</ng-container>
</div>
<div kendoContrastValidation
type="AA"
[value]="value"
[pass]="satisfiesAACondition">
</div>
<div kendoContrastValidation
type="AAA"
[value]="value"
[pass]="satisfiesAAACondition">
</div>
`,
standalone: true,
imports: [NgIf, IconWrapperComponent, ContrastValidationComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { value: [{
type: Input
}], ratio: [{
type: Input
}] } });
/**
* @hidden
*/
class ColorContrastSvgComponent {
hostClass = true;
wrapper;
hsva;
backgroundColor;
paths;
oldHsva;
oldH;
oldA;
metrics;
ngAfterViewInit() {
if (!isDocumentAvailable()) {
return;
}
this.metrics = this.wrapper.getBoundingClientRect();
this.oldA = this.hsva.value.a;
this.oldH = this.hsva.value.h;
this.hsva.subscribe((value) => {
if (value.h !== this.oldH || value.a !== this.oldA) {
this.oldH = value.h;
this.oldA = value.a;
this.setPaths();
}
});
}
ngOnChanges(changes) {
if (isPresent(changes['backgroundColor']) && this.metrics) {
this.setPaths();
}
}
setPaths() {
const bezierCommandCalc = bezierCommand(controlPoint(line));
this.paths = [svgPath(this.getPaths(AA_RATIO, STEP_COUNT), bezierCommandCalc),
svgPath(this.getPaths(AA_RATIO, STEP_COUNT, true), bezierCommandCalc),
svgPath(this.getPaths(AAA_RATIO, STEP_COUNT), bezierCommandCalc),
svgPath(this.getPaths(AAA_RATIO, STEP_COUNT, true), bezierCommandCalc)];
}
findValue(contrast, saturation, low, high, comparer) {
const mid = (low + high) / 2;
const hsva = { ...this.hsva.value, s: saturation / this.metrics.width, v: 1 - mid / this.metrics.height };
const currentContrast = getContrastFromTwoRGBAs(getRGBA(getColorFromHSV(hsva)), getRGBA(this.backgroundColor || ''));
if (low + 0.5 > high) {
if (currentContrast < contrast + 1 && currentContrast > contrast - 1) {
return mid;
}
else {
return null;
}
}
if (comparer(currentContrast, contrast)) {
return this.findValue(contrast, saturation, low, high - (high - low) / 2, comparer);
}
return this.findValue(contrast, saturation, low + (high - low) / 2, high, comparer);
}
getPaths(contrast, stepCount, reversed = false) {
const points = [];
for (let i = 0; i <= this.metrics.width; i += this.metrics.width / stepCount) {
const value = this.findValue(contrast, i, 0, this.metrics.height, reversed ? ((a, b) => a < b) : ((a, b) => a > b));
if (value !== null) {
points.push([i, value]);
}
}
return points;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorContrastSvgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColorContrastSvgComponent, isStandalone: true, selector: "[kendoColorContrastSvg]", inputs: { wrapper: "wrapper", hsva: "hsva", backgroundColor: "backgroundColor" }, host: { properties: { "class.k-color-contrast-svg": "this.hostClass" } }, usesOnChanges: true, ngImport: i0, template: `
<svg:path *ngFor="let path of paths" [attr.d]="path" fill="none" stroke="white" stroke-width="1"></svg:path>
`, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorContrastSvgComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoColorContrastSvg]',
template: `
<svg:path *ngFor="let path of paths" [attr.d]="path" fill="none" stroke="white" stroke-width="1"></svg:path>
`,
standalone: true,
imports: [NgFor]
}]
}], propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-color-contrast-svg']
}], wrapper: [{
type: Input
}], hsva: [{
type: Input
}], backgroundColor: [{
type: Input
}] } });
/**
* @hidden
*/
class ColorPickerMessages extends ComponentMessages {
/**
* The aria-label applied to the ColorPalette component when the value is empty.
*/
colorPaletteNoColor;
/**
* The aria-label applied to the ColorGradient component when the value is empty.
*/
colorGradientNoColor;
/**
* The aria-label applied to the FlatColorPicker component when the value is empty.
*/
flatColorPickerNoColor;
/**
* The aria-label applied to the ColorPicker component when the value is empty.
*/
colorPickerNoColor;
/**
* The title for the gradient color drag handle chooser.
*/
colorGradientHandle;
/**
* The title for the clear button.
*/
clearButton;
/**
* The title for the hue slider handle.
*/
hueSliderHandle;
/**
* The title for the opacity slider handle.
*/
opacitySliderHandle;
/**
* The placeholder for the HEX color input.
*/
hexInputPlaceholder;
/**
* The placeholder for the red color input.
*/
redInputPlaceholder;
/**
* The placeholder for the green color input.
*/
greenInputPlaceholder;
/**
* The placeholder for the blue color input.
*/
blueInputPlaceholder;
/**
* The placeholder for the alpha input.
*/
alphaInputPlaceholder;
/**
* The aria-label attribute of the red color input.
*/
redChannelLabel;
/**
* The aria-label attribute of the green color input.
*/
greenChannelLabel;
/**
* The aria-label attribute of the blue color input.
*/
blueChannelLabel;
/**
* The aria-label attribute of the alpha color input.
*/
alphaChannelLabel;
/**
* The "Pass" message for the contrast tool.
*/
passContrast;
/**
* The "Fail" message for the contrast tool.
*/
failContrast;
/**
* The "Contrast ratio" message for the contrast tool.
*/
contrastRatio;
/**
* The message for the color preview pane.
*/
previewColor;
/**
* The message for the selected color pane.
*/
revertSelection;
/**
* The message for the gradient view button.
*/
gradientView;
/**
* The message for the palette view button.
*/
paletteView;
/**
* The message for the input format toggle button.
*/
formatButton;
/**
* The message for the Apply action button.
*/
applyButton;
/**
* The message for the Cancel action button.
*/
cancelButton;
/**
* The title for the Close button in adaptive mode.
*/
closeButton;
/**
* The title for the ActionSheet when in adaptive mode.
*/
adaptiveTitle;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ColorPickerMessages, selector: "kendo-colorpicker-messages-base", inputs: { colorPaletteNoColor: "colorPaletteNoColor", colorGradientNoColor: "colorGradientNoColor", flatColorPickerNoColor: "flatColorPickerNoColor", colorPickerNoColor: "colorPickerNoColor", colorGradientHandle: "colorGradientHandle", clearButton: "clearButton", hueSliderHandle: "hueSliderHandle", opacitySliderHandle: "opacitySliderHandle", hexInputPlaceholder: "hexInputPlaceholder", redInputPlaceholder: "redInputPlaceholder", greenInputPlaceholder: "greenInputPlaceholder", blueInputPlaceholder: "blueInputPlaceholder", alphaInputPlaceholder: "alphaInputPlaceholder", redChannelLabel: "redChannelLabel", greenChannelLabel: "greenChannelLabel", blueChannelLabel: "blueChannelLabel", alphaChannelLabel: "alphaChannelLabel", passContrast: "passContrast", failContrast: "failContrast", contrastRatio: "contrastRatio", previewColor: "previewColor", revertSelection: "revertSelection", gradientView: "gradientView", paletteView: "paletteView", formatButton: "formatButton", applyButton: "applyButton", cancelButton: "cancelButton", closeButton: "closeButton", adaptiveTitle: "adaptiveTitle" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-colorpicker-messages-base'
}]
}], propDecorators: { colorPaletteNoColor: [{
type: Input
}], colorGradientNoColor: [{
type: Input
}], flatColorPickerNoColor: [{
type: Input
}], colorPickerNoColor: [{
type: Input
}], colorGradientHandle: [{
type: Input
}], clearButton: [{
type: Input
}], hueSliderHandle: [{
type: Input
}], opacitySliderHandle: [{
type: Input
}], hexInputPlaceholder: [{
type: Input
}], redInputPlaceholder: [{
type: Input
}], greenInputPlaceholder: [{
type: Input
}], blueInputPlaceholder: [{
type: Input
}], alphaInputPlaceholder: [{
type: Input
}], redChannelLabel: [{
type: Input
}], greenChannelLabel: [{
type: Input
}], blueChannelLabel: [{
type: Input
}], alphaChannelLabel: [{
type: Input
}], passContrast: [{
type: Input
}], failContrast: [{
type: Input
}], contrastRatio: [{
type: Input
}], previewColor: [{
type: Input
}], revertSelection: [{
type: Input
}], gradientView: [{
type: Input
}], paletteView: [{
type: Input
}], formatButton: [{
type: Input
}], applyButton: [{
type: Input
}], cancelButton: [{
type: Input
}], closeButton: [{
type: Input
}], adaptiveTitle: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedColorPickerMessagesDirective extends ColorPickerMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedColorPickerMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedColorPickerMessagesDirective, isStandalone: true, selector: "[kendoColorPickerLocalizedMessages], [kendoFlatColorPickerLocalizedMessages], [kendoColorGradientLocalizedMessages], [kendoColorPaletteLocalizedMessages]", providers: [
{
provide: ColorPickerMessages,
useExisting: forwardRef(() => LocalizedColorPickerMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedColorPickerMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: ColorPickerMessages,
useExisting: forwardRef(() => LocalizedColorPickerMessagesDirective)
}
],
selector: '[kendoColorPickerLocalizedMessages], [kendoFlatColorPickerLocalizedMessages], [kendoColorGradientLocalizedMessages], [kendoColorPaletteLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/* eslint-disable @typescript-eslint/no-explicit-any */
let serial$3 = 0;
const DEFAULT_SIZE$7 = 'medium';
/**
* The ColorGradient component enables smooth color transitions and provides options for selecting specific colors over the drag handle.
* The ColorGradient is independently used by `kendo-colorpicker` and can be directly added to the page.
*/
class ColorGradientComponent {
host;
ngZone;
renderer;
cdr;
localizationService;
injector;
hostClasses = true;
get readonlyAttribute() {
return this.readonly;
}
get disabledClass() {
return this.disabled;
}
get gradientId() {
return this.id;
}
direction;
get hostTabindex() {
return this.tabindex?.toString() || '0';
}
ariaRole = 'textbox';
get isControlInvalid() {
return (this.control?.invalid)?.toString();
}
get isDisabled() {
return this.disabled?.toString() || undefined;
}
/**
* @hidden
*/
enterHandler(event) {
if (event.target !== this.host.nativeElement) {
return;
}
this.internalNavigation = true;
this.gradientDragHandle.nativeElement.focus();
}
/**
* @hidden
*/
escapeHandler(event) {
if (!this.host.nativeElement.matches(':focus')) {
event.stopImmediatePropagation();
}
this.internalNavigation = false;
this.host.nativeElement.focus();
}
/**
* @hidden
*/
focusHandler(ev) {
this.internalNavigation = ev.target !== this.host.nativeElement;
}
/**
* @hidden
*/
adaptiveMode = false;
/**
* @hidden
*/
id = `k-colorgradient-${serial$3++}`;
/**
* Defines whether the alpha slider will be displayed.
*
* @default true
*/
opacity = true;
/**
* The size property specifies the padding of the ColorGradient internal elements.
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size || DEFAULT_SIZE$7;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* Sets the disabled state of the ColorGradient. To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_colorgradient#toc-managing-the-colorgradient-disabled-state-in-reactive-forms).
*
* @default false
*/
disabled = false;
/**
* Sets the read-only state of the ColorGradient.
*
* @default false
*/
readonly = false;
/**
* Specifies whether the ColorGradient should display a 'Clear color' button.
*
* @default false
*/
clearButton = false;
/**
* Determines the delay time (in milliseconds) before the value is changed on handle drag. A value of 0 indicates no delay.
*
* @default 0
*/
delay = 0;
/**
* Specifies the value of the initially selected color.
*/
set value(value) {
this._value = parseColor(value, this.format, this.opacity);
}
get value() {
return this._value;
}
/**
* Enables the color contrast tool. Accepts the background color that will be compared to the selected value.
* The tool will calculate the contrast ratio between the two colors.
*/
set contrastTool(value) {
this._contrastTool = parseColor(value, this.format, this.opacity);
}
get contrastTool() {
return this._contrastTool;
}
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*
* @default 0
*/
set tabindex(value) {
if (isPresent(value)) {
const tabindex = Number(value);
this._tabindex = !isNaN(tabindex) ? tabindex : 0;
}
else {
// Allows removal of the tabindex attribute
this._tabindex = value;
}
}
get tabindex() {
return !this.disabled ? this._tabindex : undefined;
}
/**
* Specifies the output format of the ColorGradientComponent.
* The input value may be in a different format, but it will be parsed into the output `format`
* after the component processes it.
*
* The supported values are:
* * (Default) `rgba`
* * `hex`
*/
format = DEFAULT_OUTPUT_FORMAT;
/**
* Fires each time the user selects a new color.
*/
valueChange = new EventEmitter();
/**
* @hidden
*/
backgroundColor = DEFAULT_GRADIENT_BACKGROUND_COLOR;
/**
* @hidden
*
* Represents the currently selected `hue`, `saturation`, `value`, and `alpha` values.
* The values are initially set in `ngOnInit` or in `ngOnChanges` and are
* updated on moving the drag handle or the sliders.
*/
hsva = new BehaviorSubject({});
/**
* Indicates whether the ColorGradient or any of its content is focused.
*/
get isFocused() {
if (!(isDocumentAvailable() && isPresent(this.host))) {
return false;
}
return this.host.nativeElement === document.activeElement || this.host.nativeElement.contains(document.activeElement);
}
/**
* @hidden
*/
get alphaSliderValue() {
// setting the initial value to undefined to force the slider to recalculate the height of the slider track on the next cdr run
if (!(isPresent(this.hsva.value) && isPresent(this.hsva.value.a))) {
return;
}
return this.hsva.value.a * 100;
}
/**
* Determines the step (in pixels) when moving the gradient drag handle using the keyboard arrow keys.
*
* @default 5
*/
gradientSliderStep = DRAGHANDLE_MOVE_SPEED;
/**
* Determines the step (in pixels) when moving the gradient drag handle using the keyboard arrow keys while holding the shift key.
*
* @default 2
*/
gradientSliderSmallStep = DRAGHANDLE_MOVE_SPEED_SMALL_STEP;
gradientDragHandle;
inputs;
alphaSlider;
gradientWrapper;
hsvRectangle;
/**
* @hidden
*/
internalNavigation = false;
/**
* @hidden
*/
dropletSlashIcon = dropletSlashIcon;
_value;
_tabindex = 0;
_contrastTool;
listeners = [];
hueSliderTouched = false;
alphaSliderTouched = false;
_size = 'medium';
updateValues = new Subject();
changeRequestsSubscription;
dynamicRTLSubscription;
hsvHandleCoordinates = { x: 0, y: 0 };
get gradientRect() {
return this.gradientWrapper.nativeElement.getBoundingClientRect();
}
/**
* @hidden
*/
get hsvSliderValueText() {
return `X: ${this.hsvHandleCoordinates.x} Y: ${this.hsvHandleCoordinates.y}`;
}
/**
* @hidden
*/
get contrastToolVisible() {
return this.contrastTool && this.contrastTool.length > 0;
}
/**
* @hidden
*/
get innerTabIndex() {
return this.internalNavigation ? 0 : -1;
}
control;
constructor(host, ngZone, renderer, cdr, localizationService, injector) {
this.host = host;
this.ngZone = ngZone;
this.renderer = renderer;
this.cdr = cdr;
this.localizationService = localizationService;
this.injector = injector;
validatePackage(packageMetadata);
this.dynamicRTLSubscription = localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
}
ngOnInit() {
this.control = this.injector.get(NgControl, null);
}
ngAfterViewInit() {
const stylingInputs = ['size'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.updateUI();
this.cdr.detectChanges();
});
this.addEventListeners();
this.subscribeChanges();
}
ngOnChanges(changes) {
if (isChanged('value', changes) && !this.isFocused) {
this.updateUI();
}
if (isChanged('delay', changes)) {
this.unsubscribeChanges();
this.subscribeChanges();
}
}
ngOnDestroy() {
this.listeners.forEach(removeListener => removeListener());
if (this.dynamicRTLSubscription) {
this.dynamicRTLSubscription.unsubscribe();
}
this.unsubscribeChanges();
}
/**
* Focuses the component.
*/
focus() {
if (this.disabled) {
return;
}
this.gradientDragHandle.nativeElement.focus();
}
/**
* @hidden
*/
reset() {
this.handleValueChange(undefined);
this.updateUI();
}
/**
* @hidden
*/
handleDragPress(args) {
if (this.disabled || this.readonly || !isPresent(args.originalEvent)) {
return;
}
this.focus();
args.originalEvent.preventDefault();
}
/**
* @hidden
*/
onHandleDrag(args) {
if (this.disabled || this.readonly) {
return;
}
this.renderer.addClass(this.gradientWrapper.nativeElement, 'k-dragging');
this.changePosition(args);
}
/**
* @hidden
*/
onHandleRelease() {
if (this.disabled || this.readonly) {
return;
}
this.renderer.removeClass(this.gradientWrapper.nativeElement, 'k-dragging');
this.handleValueChange(getColorFromHSV(this.hsva.value, this.format, this.opacity));
}
/**
* @hidden
*/
onKeyboardAction(args) {
if (this.disabled || this.readonly) {
return;
}
if (args.key && args.key.indexOf('Arrow') !== -1) {
args.preventDefault();
const dragHandleElement = this.gradientDragHandle.nativeElement;
this.renderer.addClass(this.gradientWrapper.nativeElement, 'k-dragging');
let keyboardMoveX = 0;
let keyboardMoveY = 0;
const shiftKey = args.shiftKey;
switch (args.key) {
case 'ArrowRight':
keyboardMoveX = shiftKey ? this.gradientSliderSmallStep : this.gradientSliderStep;
break;
case 'ArrowLeft':
keyboardMoveX = shiftKey ? -this.gradientSliderSmallStep : -this.gradientSliderStep;
break;
case 'ArrowUp':
keyboardMoveY = shiftKey ? -this.gradientSliderSmallStep : -this.gradientSliderStep;
break;
case 'ArrowDown':
keyboardMoveY = shiftKey ? this.gradientSliderSmallStep : this.gradientSliderStep;
break;
default: break;
}
const newY = parseInt(dragHandleElement.style.top, 10) + keyboardMoveY;
const newX = parseInt(dragHandleElement.style.left, 10) + keyboardMoveX;
this.renderer.setStyle(dragHandleElement, 'top', `${newY}px`);
this.renderer.setStyle(dragHandleElement, 'left', `${newX}px`);
this.ngZone.run(() => this.moveDragHandle(newX, newY));
}
}
/**
* @hidden
*/
changePosition(position) {
if (this.disabled || this.readonly) {
return;
}
this.gradientDragHandle.nativeElement.focus();
const gradientRect = this.gradientRect;
const newX = position.clientX - gradientRect.left;
const newY = position.clientY - gradientRect.top;
this.ngZone.run(() => this.moveDragHandle(newX, newY));
}
/**
* @hidden
*/
handleHueSliderChange(hue) {
const hsva = this.hsva.value;
hsva.h = hue;
this.hsva.next(hsva);
this.handleValueChange(getColorFromHSV(this.hsva.value, this.format, this.opacity));
this.backgroundColor = getColorFromHue(hue);
this.setBackgroundColor(this.backgroundColor);
this.setAlphaSliderBackground(this.backgroundColor);
this.hueSliderTouched = true;
}
/**
* @hidden
*/
handleAlphaSliderChange(alpha) {
const hsva = this.hsva.value;
hsva.a = alpha / 100;
this.hsva.next(hsva);
this.handleValueChange(getColorFromHSV(this.hsva.value, this.format, this.opacity));
this.alphaSliderTouched = true;
}
/**
* @hidden
*/
handleInputsValueChange(color) {
const parsed = parseColor(color, this.format, this.opacity);
if (this.value !== parsed) {
this.handleValueChange(parsed);
this.updateUI();
}
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
if (isPresent(this.gradientWrapper)) {
this.updateUI();
}
}
/**
* @hidden
*/
registerOnChange(fn) {
this.notifyNgChanged = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.notifyNgTouched = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled) {
this.cdr.markForCheck();
this.disabled = isDisabled;
}
/**
* @hidden
*/
get colorGradientHandleTitle() {
return this.localizationService.get('colorGradientHandle');
}
/**
* @hidden
*/
get colorGradientHandleAriaLabel() {
const parsed = parseColor(this.value, this.format, this.opacity);
return `${this.value ? parsed : this.localizationService.get('colorGradientNoColor')}`;
}
/**
* @hidden
*/
get hueSliderTitle() {
return this.localizationService.get('hueSliderHandle');
}
/**
* @hidden
*/
get opacitySliderTitle() {
return this.localizationService.get('opacitySliderHandle');
}
/**
* @hidden
*/
get clearButtonTitle() {
return this.localizationService.get('clearButton');
}
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
notifyNgChanged = () => { };
notifyNgTouched = () => { };
moveDragHandle(positionX, positionY) {
const gradientRect = this.gradientRect;
const gradientRectWidth = gradientRect.width;
const gradientRectHeight = gradientRect.height;
const top = fitIntoBounds(positionY, 0, gradientRectHeight);
const left = fitIntoBounds(positionX, 0, gradientRectWidth);
this.setDragHandleElementPosition(top, left);
const hsva = this.hsva.value;
hsva.s = left / gradientRectWidth;
hsva.v = 1 - top / gradientRectHeight;
this.hsva.next(hsva);
this.updateValues.next(getColorFromHSV(this.hsva.value, this.format, this.opacity));
this.setAlphaSliderBackground(getColorFromHSV({ ...this.hsva.value, a: 1 }, this.format, this.opacity));
}
handleValueChange(color) {
if (this.value === color) {
return;
}
this.value = color;
this.valueChange.emit(color);
this.notifyNgChanged(color);
this.setHostElementAriaLabel();
}
setDragHandleElementPosition(top, left) {
const dragHandle = this.gradientDragHandle.nativeElement;
this.hsvHandleCoordinates = { x: left, y: top };
this.renderer.setStyle(dragHandle, 'top', `${top}px`);
this.renderer.setStyle(dragHandle, 'left', `${left}px`);
}
setAlphaSliderBackground(backgroundColor) {
if (!isPresent(this.alphaSlider)) {
return;
}
const sliderTrack = this.alphaSlider.track.nativeElement;
this.renderer.setStyle(sliderTrack, 'background', `linear-gradient(to ${this.adaptiveMode ? 'right' : 'top'}, transparent, ${backgroundColor})`);
}
setHostElementAriaLabel() {
const parsed = parseColor(this.value, this.format, this.opacity);
this.renderer.setAttribute(this.host.nativeElement, 'aria-label', `${this.value ? parsed : this.localizationService.get('colorGradientNoColor')}`);
}
setBackgroundColor(color) {
this.renderer.setStyle(this.hsvRectangle.nativeElement, 'background', color);
}
updateUI() {
if (!isDocumentAvailable()) {
return;
}
if (this.hueSliderTouched || this.alphaSliderTouched) {
this.hueSliderTouched = false;
this.alphaSliderTouched = false;
return;
}
this.hsva.next(this.value ? getHSV(this.value) : { h: 0, s: 0, v: 1, a: 1 });
const gradientRect = this.gradientRect;
const top = (1 - this.hsva.value.v) * gradientRect.height;
const left = this.hsva.value.s * gradientRect.width;
this.setDragHandleElementPosition(top, left);
this.backgroundColor = getColorFromHue(this.hsva.value.h);
this.setBackgroundColor(this.backgroundColor);
this.setAlphaSliderBackground(this.backgroundColor);
this.setHostElementAriaLabel();
}
addEventListeners() {
this.ngZone.runOutsideAngular(() => {
const focusOutListener = this.renderer.listen(this.host.nativeElement, 'focusout', (event) => {
if (!containsFocus(this.host.nativeElement, event.relatedTarget) && isUntouched(this.host)) {
this.ngZone.run(() => this.notifyNgTouched());
}
});
const keydownListener = this.renderer.listen(this.gradientDragHandle.nativeElement, 'keydown', (event) => {
this.onKeyboardAction(event);
});
const keyupListener = this.renderer.listen(this.gradientDragHandle.nativeElement, 'keyup', () => {
this.renderer.removeClass(this.gradientWrapper.nativeElement, 'k-dragging');
if (!this.readonly && !this.disabled) {
this.ngZone.run(() => this.handleValueChange(getColorFromHSV(this.hsva.value, this.format, this.opacity)));
}
});
const dragHandleFocusInListener = this.renderer.listen(this.gradientDragHandle.nativeElement, 'focusin', () => {
this.renderer.addClass(this.gradientDragHandle.nativeElement, 'k-focus');
});
const dragHandleFocusOutListener = this.renderer.listen(this.gradientDragHandle.nativeElement, 'focusout', () => {
this.renderer.removeClass(this.gradientDragHandle.nativeElement, 'k-focus');
});
this.listeners.push(focusOutListener, keydownListener, keyupListener, dragHandleFocusInListener, dragHandleFocusOutListener);
});
}
subscribeChanges() {
this.changeRequestsSubscription = this.updateValues.pipe(throttleTime(this.delay)).subscribe(value => {
this.handleValueChange(value);
});
}
unsubscribeChanges() {
if (this.changeRequestsSubscription) {
this.changeRequestsSubscription.unsubscribe();
}
}
handleClasses(value, input) {
const elem = this.host.nativeElement;
const classes = getStylingClasses('colorgradient', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorGradientComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i1.LocalizationService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColorGradientComponent, isStandalone: true, selector: "kendo-colorgradient", inputs: { adaptiveMode: "adaptiveMode", id: "id", opacity: "opacity", size: "size", disabled: "disabled", readonly: "readonly", clearButton: "clearButton", delay: "delay", value: "value", contrastTool: "contrastTool", tabindex: "tabindex", format: "format", gradientSliderStep: "gradientSliderStep", gradientSliderSmallStep: "gradientSliderSmallStep" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "keydown.enter": "enterHandler($event)", "keydown.escape": "escapeHandler($event)", "focusin": "focusHandler($event)" }, properties: { "class.k-colorgradient": "this.hostClasses", "attr.aria-readonly": "this.readonlyAttribute", "class.k-disabled": "this.disabledClass", "attr.id": "this.gradientId", "attr.dir": "this.direction", "attr.tabindex": "this.hostTabindex", "attr.role": "this.ariaRole", "attr.aria-invalid": "this.isControlInvalid", "attr.aria-disabled": "this.isDisabled", "class.k-readonly": "this.readonly" } }, providers: [
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ColorGradientComponent)
},
{
provide: KendoInput,
useExisting: forwardRef(() => ColorGradientComponent)
},
ColorGradientLocalizationService,
{
provide: LocalizationService,
useExisting: ColorGradientLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.colorgradient'
}
], viewQueries: [{ propertyName: "gradientDragHandle", first: true, predicate: ["gradientDragHandle"], descendants: true }, { propertyName: "inputs", first: true, predicate: ["inputs"], descendants: true }, { propertyName: "alphaSlider", first: true, predicate: ["alphaSlider"], descendants: true }, { propertyName: "gradientWrapper", first: true, predicate: ["gradientWrapper"], descendants: true }, { propertyName: "hsvRectangle", first: true, predicate: ["hsvRectangle"], descendants: true }], exportAs: ["kendoColorGradient"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoColorGradientLocalizedMessages
i18n-colorGradientNoColor="kendo.colorgradient.colorGradientNoColor|The aria-label applied to the ColorGradient component when the value is empty."
colorGradientNoColor="Colorgradient no color chosen"
i18n-colorGradientHandle="kendo.colorgradient.colorGradientHandle|The title for the gradient color drag handle chooser."
colorGradientHandle="Choose color"
i18n-clearButton="kendo.colorgradient.clearButton|The title for the clear button."
clearButton="Clear value"
i18n-hueSliderHandle="kendo.colorgradient.hueSliderHandle|The title for the hue slider handle."
hueSliderHandle="Set hue"
i18n-opacitySliderHandle="kendo.colorgradient.opacitySliderHandle|The title for the opacity slider handle."
opacitySliderHandle="Set opacity"
i18n-passContrast="kendo.colorgradient.passContrast|The pass message for the contrast tool."
passContrast="Pass"
i18n-failContrast="kendo.colorgradient.failContrast|The fail message for the contrast tool."
failContrast="Fail"
i18n-contrastRatio="kendo.colorgradient.contrastRatio|The contrast ratio message for the contrast tool."
contrastRatio="Contrast ratio"
i18n-formatButton="kendo.colorgradient.formatButton|The message for the input format toggle button."
formatButton="Change color format"
i18n-redChannelLabel="kendo.colorgradient.redChannelLabel|The label of the NumericTextBox representing the red color channel."
redChannelLabel="Red channel"
i18n-greenChannelLabel="kendo.colorgradient.greenChannelLabel|The label of the NumericTextBox representing the green color channel."
greenChannelLabel="Green channel"
i18n-blueChannelLabel="kendo.colorgradient.blueChannelLabel|The label of the NumericTextBox representing the blue color channel."
blueChannelLabel="Blue channel"
i18n-alphaChannelLabel="kendo.colorgradient.alphaChannelLabel|The label of the NumericTextBox representing the alpha color channel."
alphaChannelLabel="Alpha channel"
i18n-redInputPlaceholder="kendo.colorgradient.redInputPlaceholder|The placeholder for the red color input."
redChannelLabel="R"
i18n-greenInputPlaceholder="kendo.colorgradient.greenInputPlaceholder|The placeholder for the green color input."
greenInputPlaceholder="G"
i18n-blueInputPlaceholder="kendo.colorgradient.blueInputPlaceholder|The placeholder for the blue color input."
blueInputPlaceholder="B"
i18n-hexInputPlaceholder="kendo.colorgradient.hexInputPlaceholder|The placeholder for the HEX color input."
hexInputPlaceholder="HEX">
</ng-container>
<div [ngClass]="{
'k-colorgradient-canvas': true,
'k-vstack': adaptiveMode,
'k-hstack': !adaptiveMode
}">
<div class="k-hsv-rectangle" #hsvRectangle>
<div
#gradientWrapper
kendoDraggable
class="k-hsv-gradient"
(click)="changePosition($event)"
(kendoPress)="handleDragPress($event)"
(kendoDrag)="onHandleDrag($event)"
(kendoRelease)="onHandleRelease()"
[style.touch-action]="'none'">
<div
#gradientDragHandle
class="k-hsv-draghandle k-draghandle"
[tabindex]="innerTabIndex.toString()"
[attr.title]="colorGradientHandleTitle"
[attr.aria-label]="colorGradientHandleTitle + ' ' + colorGradientHandleAriaLabel"
role="slider"
[attr.aria-valuetext]="hsvSliderValueText"
[attr.aria-readonly]="readonly ? readonly : undefined"
[attr.aria-disabled]="disabled ? disabled : undefined"
[attr.aria-orientation]="'undefined'"
[attr.aria-valuenow]="'0'"
(keydown.shift.tab)="$event.preventDefault(); inputs.focusLast();">
</div>
</div>
<svg kendoColorContrastSvg
*ngIf="contrastToolVisible && gradientWrapper"
class="k-color-contrast-svg"
xmlns="http://www.w3.org/2000/svg"
[wrapper]="gradientWrapper ? gradientWrapper : undefined"
[hsva]="hsva"
[backgroundColor]="contrastTool"
[style]="'position: absolute; overflow: visible; pointer-events: none; left: 0px; top: 0px;'">
</svg>
</div>
<div [ngClass]="{
'k-hsv-controls': true,
'k-sliders-wrap-clearable': clearButton,
'k-vstack': adaptiveMode,
'k-hstack': !adaptiveMode
}">
<button
kendoButton
*ngIf="clearButton"
class="k-clear-color"
fillMode="flat"
icon="droplet-slash"
[svgIcon]="dropletSlashIcon"
[size]="size"
(click)="reset()"
(keydown.enter)="reset()"
(keydown.space)="reset()"
[attr.aria-label]="clearButtonTitle"
[attr.title]="clearButtonTitle"
[tabindex]="innerTabIndex.toString()"
[style]="'position: absolute; top: 0; left: 50%; transform: translateX(-50%);'"
>
</button>
<kendo-slider
[ngClass]="{'k-align-self-end': clearButton}"
[style.height.px]="clearButton ? '140' : null"
class="k-hue-slider k-colorgradient-slider"
[dragHandleTitle]="hueSliderTitle"
[tabindex]="innerTabIndex"
[disabled]="disabled"
[readonly]="readonly"
[showButtons]="false"
tickPlacement="none"
[vertical]="!adaptiveMode"
[min]="0"
[max]="360"
[value]="hsva.value.h"
[smallStep]="5"
[largeStep]="10"
(valueChange)="handleHueSliderChange($event)"
>
</kendo-slider>
<kendo-slider
*ngIf="opacity"
#alphaSlider
[tabindex]="innerTabIndex"
[ngClass]="{'k-align-self-end': clearButton}"
[style.height.px]="clearButton ? '140' : null"
class="k-alpha-slider k-colorgradient-slider"
[dragHandleTitle]="opacitySliderTitle"
[disabled]="disabled"
[readonly]="readonly"
[showButtons]="false"
tickPlacement="none"
[vertical]="!adaptiveMode"
[min]="0"
[max]="100"
[smallStep]="1"
[largeStep]="10"
[value]="alphaSliderValue"
(valueChange)="handleAlphaSliderChange($event)"
>
</kendo-slider>
</div>
</div>
<kendo-colorinput #inputs
[tabindex]="innerTabIndex"
[opacity]="opacity"
[size]="size"
[formatView]="format"
[value]="value"
[disabled]="disabled"
[readonly]="readonly"
(valueChange)="handleInputsValueChange($event)"
(tabOut)="gradientDragHandle.focus()"
>
</kendo-colorinput>
<div class="k-colorgradient-color-contrast k-vbox"
*ngIf="contrastToolVisible"
kendoContrastTool
[value]="value"
[ratio]="contrastTool">
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedColorPickerMessagesDirective, selector: "[kendoColorPickerLocalizedMessages], [kendoFlatColorPickerLocalizedMessages], [kendoColorGradientLocalizedMessages], [kendoColorPaletteLocalizedMessages]" }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ColorContrastSvgComponent, selector: "[kendoColorContrastSvg]", inputs: ["wrapper", "hsva", "backgroundColor"] }, { 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: SliderComponent, selector: "kendo-slider", inputs: ["focusableId", "dragHandleTitle", "incrementTitle", "animate", "decrementTitle", "showButtons", "value", "tabIndex"], exportAs: ["kendoSlider"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ColorInputComponent, selector: "kendo-colorinput", inputs: ["focusableId", "formatView", "size", "tabindex", "value", "opacity", "disabled", "readonly"], outputs: ["valueChange", "tabOut"] }, { kind: "component", type: ContrastComponent, selector: "[kendoContrastTool]", inputs: ["value", "ratio"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorGradientComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoColorGradient',
selector: 'kendo-colorgradient',
providers: [
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ColorGradientComponent)
},
{
provide: KendoInput,
useExisting: forwardRef(() => ColorGradientComponent)
},
ColorGradientLocalizationService,
{
provide: LocalizationService,
useExisting: ColorGradientLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.colorgradient'
}
],
template: `
<ng-container kendoColorGradientLocalizedMessages
i18n-colorGradientNoColor="kendo.colorgradient.colorGradientNoColor|The aria-label applied to the ColorGradient component when the value is empty."
colorGradientNoColor="Colorgradient no color chosen"
i18n-colorGradientHandle="kendo.colorgradient.colorGradientHandle|The title for the gradient color drag handle chooser."
colorGradientHandle="Choose color"
i18n-clearButton="kendo.colorgradient.clearButton|The title for the clear button."
clearButton="Clear value"
i18n-hueSliderHandle="kendo.colorgradient.hueSliderHandle|The title for the hue slider handle."
hueSliderHandle="Set hue"
i18n-opacitySliderHandle="kendo.colorgradient.opacitySliderHandle|The title for the opacity slider handle."
opacitySliderHandle="Set opacity"
i18n-passContrast="kendo.colorgradient.passContrast|The pass message for the contrast tool."
passContrast="Pass"
i18n-failContrast="kendo.colorgradient.failContrast|The fail message for the contrast tool."
failContrast="Fail"
i18n-contrastRatio="kendo.colorgradient.contrastRatio|The contrast ratio message for the contrast tool."
contrastRatio="Contrast ratio"
i18n-formatButton="kendo.colorgradient.formatButton|The message for the input format toggle button."
formatButton="Change color format"
i18n-redChannelLabel="kendo.colorgradient.redChannelLabel|The label of the NumericTextBox representing the red color channel."
redChannelLabel="Red channel"
i18n-greenChannelLabel="kendo.colorgradient.greenChannelLabel|The label of the NumericTextBox representing the green color channel."
greenChannelLabel="Green channel"
i18n-blueChannelLabel="kendo.colorgradient.blueChannelLabel|The label of the NumericTextBox representing the blue color channel."
blueChannelLabel="Blue channel"
i18n-alphaChannelLabel="kendo.colorgradient.alphaChannelLabel|The label of the NumericTextBox representing the alpha color channel."
alphaChannelLabel="Alpha channel"
i18n-redInputPlaceholder="kendo.colorgradient.redInputPlaceholder|The placeholder for the red color input."
redChannelLabel="R"
i18n-greenInputPlaceholder="kendo.colorgradient.greenInputPlaceholder|The placeholder for the green color input."
greenInputPlaceholder="G"
i18n-blueInputPlaceholder="kendo.colorgradient.blueInputPlaceholder|The placeholder for the blue color input."
blueInputPlaceholder="B"
i18n-hexInputPlaceholder="kendo.colorgradient.hexInputPlaceholder|The placeholder for the HEX color input."
hexInputPlaceholder="HEX">
</ng-container>
<div [ngClass]="{
'k-colorgradient-canvas': true,
'k-vstack': adaptiveMode,
'k-hstack': !adaptiveMode
}">
<div class="k-hsv-rectangle" #hsvRectangle>
<div
#gradientWrapper
kendoDraggable
class="k-hsv-gradient"
(click)="changePosition($event)"
(kendoPress)="handleDragPress($event)"
(kendoDrag)="onHandleDrag($event)"
(kendoRelease)="onHandleRelease()"
[style.touch-action]="'none'">
<div
#gradientDragHandle
class="k-hsv-draghandle k-draghandle"
[tabindex]="innerTabIndex.toString()"
[attr.title]="colorGradientHandleTitle"
[attr.aria-label]="colorGradientHandleTitle + ' ' + colorGradientHandleAriaLabel"
role="slider"
[attr.aria-valuetext]="hsvSliderValueText"
[attr.aria-readonly]="readonly ? readonly : undefined"
[attr.aria-disabled]="disabled ? disabled : undefined"
[attr.aria-orientation]="'undefined'"
[attr.aria-valuenow]="'0'"
(keydown.shift.tab)="$event.preventDefault(); inputs.focusLast();">
</div>
</div>
<svg kendoColorContrastSvg
*ngIf="contrastToolVisible && gradientWrapper"
class="k-color-contrast-svg"
xmlns="http://www.w3.org/2000/svg"
[wrapper]="gradientWrapper ? gradientWrapper : undefined"
[hsva]="hsva"
[backgroundColor]="contrastTool"
[style]="'position: absolute; overflow: visible; pointer-events: none; left: 0px; top: 0px;'">
</svg>
</div>
<div [ngClass]="{
'k-hsv-controls': true,
'k-sliders-wrap-clearable': clearButton,
'k-vstack': adaptiveMode,
'k-hstack': !adaptiveMode
}">
<button
kendoButton
*ngIf="clearButton"
class="k-clear-color"
fillMode="flat"
icon="droplet-slash"
[svgIcon]="dropletSlashIcon"
[size]="size"
(click)="reset()"
(keydown.enter)="reset()"
(keydown.space)="reset()"
[attr.aria-label]="clearButtonTitle"
[attr.title]="clearButtonTitle"
[tabindex]="innerTabIndex.toString()"
[style]="'position: absolute; top: 0; left: 50%; transform: translateX(-50%);'"
>
</button>
<kendo-slider
[ngClass]="{'k-align-self-end': clearButton}"
[style.height.px]="clearButton ? '140' : null"
class="k-hue-slider k-colorgradient-slider"
[dragHandleTitle]="hueSliderTitle"
[tabindex]="innerTabIndex"
[disabled]="disabled"
[readonly]="readonly"
[showButtons]="false"
tickPlacement="none"
[vertical]="!adaptiveMode"
[min]="0"
[max]="360"
[value]="hsva.value.h"
[smallStep]="5"
[largeStep]="10"
(valueChange)="handleHueSliderChange($event)"
>
</kendo-slider>
<kendo-slider
*ngIf="opacity"
#alphaSlider
[tabindex]="innerTabIndex"
[ngClass]="{'k-align-self-end': clearButton}"
[style.height.px]="clearButton ? '140' : null"
class="k-alpha-slider k-colorgradient-slider"
[dragHandleTitle]="opacitySliderTitle"
[disabled]="disabled"
[readonly]="readonly"
[showButtons]="false"
tickPlacement="none"
[vertical]="!adaptiveMode"
[min]="0"
[max]="100"
[smallStep]="1"
[largeStep]="10"
[value]="alphaSliderValue"
(valueChange)="handleAlphaSliderChange($event)"
>
</kendo-slider>
</div>
</div>
<kendo-colorinput #inputs
[tabindex]="innerTabIndex"
[opacity]="opacity"
[size]="size"
[formatView]="format"
[value]="value"
[disabled]="disabled"
[readonly]="readonly"
(valueChange)="handleInputsValueChange($event)"
(tabOut)="gradientDragHandle.focus()"
>
</kendo-colorinput>
<div class="k-colorgradient-color-contrast k-vbox"
*ngIf="contrastToolVisible"
kendoContrastTool
[value]="value"
[ratio]="contrastTool">
</div>
`,
standalone: true,
imports: [LocalizedColorPickerMessagesDirective, DraggableDirective, NgIf, ColorContrastSvgComponent, ButtonComponent, SliderComponent, NgClass, ColorInputComponent, ContrastComponent]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i1.LocalizationService }, { type: i0.Injector }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-colorgradient']
}], readonlyAttribute: [{
type: HostBinding,
args: ['attr.aria-readonly']
}], disabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], gradientId: [{
type: HostBinding,
args: ['attr.id']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], hostTabindex: [{
type: HostBinding,
args: ['attr.tabindex']
}], ariaRole: [{
type: HostBinding,
args: ['attr.role']
}], isControlInvalid: [{
type: HostBinding,
args: ['attr.aria-invalid']
}], isDisabled: [{
type: HostBinding,
args: ['attr.aria-disabled']
}], enterHandler: [{
type: HostListener,
args: ['keydown.enter', ['$event']]
}], escapeHandler: [{
type: HostListener,
args: ['keydown.escape', ['$event']]
}], focusHandler: [{
type: HostListener,
args: ['focusin', ['$event']]
}], adaptiveMode: [{
type: Input
}], id: [{
type: Input
}], opacity: [{
type: Input
}], size: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], clearButton: [{
type: Input
}], delay: [{
type: Input
}], value: [{
type: Input
}], contrastTool: [{
type: Input
}], tabindex: [{
type: Input
}], format: [{
type: Input
}], valueChange: [{
type: Output
}], gradientSliderStep: [{
type: Input
}], gradientSliderSmallStep: [{
type: Input
}], gradientDragHandle: [{
type: ViewChild,
args: ['gradientDragHandle']
}], inputs: [{
type: ViewChild,
args: ['inputs']
}], alphaSlider: [{
type: ViewChild,
args: ['alphaSlider']
}], gradientWrapper: [{
type: ViewChild,
args: ['gradientWrapper']
}], hsvRectangle: [{
type: ViewChild,
args: ['hsvRectangle']
}] } });
/**
* @hidden
*/
class ColorPaletteLocalizationService extends LocalizationService {
flatColorPickerLocalization;
constructor(prefix, messageService, _rtl, flatColorPickerLocalization) {
super(prefix, messageService, _rtl);
this.flatColorPickerLocalization = flatColorPickerLocalization;
}
get(shortKey) {
if (this.flatColorPickerLocalization) {
return this.flatColorPickerLocalization.get(shortKey);
}
return super.get(shortKey);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteLocalizationService, deps: [{ token: L10N_PREFIX }, { token: i1.MessageService, optional: true }, { token: RTL, optional: true }, { token: FlatColorPickerLocalizationService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteLocalizationService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteLocalizationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [L10N_PREFIX]
}] }, { type: i1.MessageService, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RTL]
}] }, { type: FlatColorPickerLocalizationService, decorators: [{
type: Optional
}, {
type: Inject,
args: [FlatColorPickerLocalizationService]
}] }]; } });
// eslint-disable max-line-length
/**
* @hidden
*/
const PALETTEPRESETS = {
basic: {
colors: '000000,7f7f7f,880015,ed1c24,ff7f27,fff200,22b14c,00a2e8,3f48cc,a349a4,ffffff,c3c3c3,b97a57,ffaec9,ffc90e,efe4b0,b5e61d,99d9ea,7092be,c8bfe7',
columns: 10
},
office: {
colors: 'ffffff, 000000, e6e6e6, 435569, 4371c4, ed7e32, a5a4a5, febf04, 5a9bd5, 71ae48, f2f2f3, 7f7f7f, d1cece, d5dde3, dae1f4, fce5d4, deeded, fff2cc, deeaf6, e1efd9, d7d8d8, 585959, aeabab, adbaca, b4c5e7, f6caac, dbdbdb, ffe498, bcd6ee, c5e0b2, bfbfc0, 3f3f3f, 767070, 8595b1, 8fabdb, f5b183, c9c8c9, fed965, 9bc4e5, a8d08d, a5a5a6, 262625, 393939, 334050, 2e5496, c45a11, 7b7b7a, bf9000, 2f75b5, 548235, 7f7f7f, 0b0c0c, 161616, 222a34, 203764, 843d0b, 525252, 7f6000, 1d4d79, 375623',
columns: 10
},
apex: {
colors: 'ffffff, 000000, c9c2d1, 69676d, ceb966, 9cb084, 6bb1c9, 6585cf, 7e6bc9, a379bb, f2f2f2, 7f7f7f, f4f2f5, e0e0e2, f5f1e0, ebefe6, e1eff4, e0e6f5, e5e1f4, ece4f1, d8d8d8, 595959, e9e6ec, c2c1c5, ebe3c1, d7dfcd, c3dfe9, c1ceeb, cbc3e9, dac9e3, bfbfbf, 3f3f3f, dedae3, a4a3a8, e1d5a3, c3cfb5, a6d0de, a2b5e2, b1a6de, c7aed6, a5a5a5, 262626, 9688a5, 4e4d51, ae9638, 758c5a, 3d8da9, 365bb0, 533da9, 7d4d99, 7f7f7f, 0c0c0c, 635672, 343336, 746425, 4e5d3c, 295e70, 243c75, 372970, 533366',
columns: 10
},
austin: {
colors: 'ffffff, 000000, caf278, 3e3d2d, 94c600, 71685a, ff6700, 909465, 956b43, fea022, f2f2f2, 7f7f7f, f4fce4, dddcd0, efffc0, e3e1dc, ffe0cb, e8e9df, ece1d6, feecd2, d8d8d8, 595959, e9f9c9, bbb9a1, dfff82, c8c3ba, ffc299, d2d4c0, dac3ad, fed9a6, bfbfbf, 3f3f3f, dff7ae, ada598, cfff43, ada598, ffa365, bcbfa1, c8a585, fec67a, a5a5a5, 262626, a9ea25, 2e2d21, 6f9400, 544e43, bf4d00, 6c6f4b, 6f5032, d77b00, 7f7f7f, 0c0c0c, 74a50f, 1f1e16, 4a6300, 38342d, 7f3300, 484a32, 4a3521, 8f5200',
columns: 10
},
clarity: {
colors: 'ffffff, 292934, f3f2dc, d2533c, 93a299, ad8f67, 726056, 4c5a6a, 808da0, 79463d, f2f2f2, e7e7ec, e7e5b9, f6dcd8, e9ecea, eee8e0, e4dedb, d8dde3, e5e8ec, e9d6d3, d8d8d8, c4c4d1, d5d185, edbab1, d3d9d6, ded2c2, c9beb8, b2bcc8, ccd1d9, d3aea7, bfbfbf, 8a8aa3, aca73b, e4978a, bec7c1, cdbba3, af9e94, 8c9bac, b2bac6, bd857c, a5a5a5, 56566e, 56531d, a43925, 6b7c72, 866b48, 554840, 39434f, 5c697b, 5a342d, 7f7f7f, 3b3b4b, 22210b, 6d2619, 47534c, 594730, 39302b, 262d35, 3d4652, 3c231e',
columns: 10
},
slipstream: {
colors: 'ffffff, 000000, b4dcfa, 212745, 4e67c8, 5eccf3, a7ea52, 5dceaf, ff8021, f14124, f2f2f2, 7f7f7f, 8bc9f7, c7cce4, dbe0f4, def4fc, edfadc, def5ef, ffe5d2, fcd9d3, d8d8d8, 595959, 4facf3, 909aca, b8c2e9, beeafa, dbf6b9, beebdf, ffcca6, f9b3a7, bfbfbf, 3f3f3f, 0d78c9, 5967af, 94a3de, 9ee0f7, caf297, 9de1cf, ffb279, f68d7b, a5a5a5, 262626, 063c64, 181d33, 31479f, 11b2eb, 81d319, 34ac8b, d85c00, c3260c, 7f7f7f, 0c0c0c, 021828, 101322, 202f6a, 0b769c, 568c11, 22725c, 903d00, 821908',
columns: 10
},
metro: {
colors: 'ffffff, 000000, d6ecff, 4e5b6f, 7fd13b, ea157a, feb80a, 00addc, 738ac8, 1ab39f, f2f2f2, 7f7f7f, a7d6ff, d9dde4, e5f5d7, fad0e4, fef0cd, c5f2ff, e2e7f4, c9f7f1, d8d8d8, 595959, 60b5ff, b3bcca, cbecb0, f6a1c9, fee29c, 8be6ff, c7d0e9, 94efe3, bfbfbf, 3f3f3f, 007dea, 8d9baf, b2e389, f272af, fed46b, 51d9ff, aab8de, 5fe7d5, a5a5a5, 262626, 003e75, 3a4453, 5ea226, af0f5b, c58c00, 0081a5, 425ea9, 138677, 7f7f7f, 0c0c0c, 00192e, 272d37, 3f6c19, 750a3d, 835d00, 00566e, 2c3f71, 0c594f',
columns: 10
},
flow: {
colors: 'ffffff, 000000, dbf5f9, 04617b, 0f6fc6, 009dd9, 0bd0d9, 10cf9b, 7cca62, a5c249, f2f2f2, 7f7f7f, b2e9f2, b4ecfc, c7e2fa, c4eeff, c9fafc, c9faed, e4f4df, edf2da, d8d8d8, 595959, 76d9e8, 6adafa, 90c6f6, 89deff, 93f5f9, 94f6db, cae9c0, dbe6b6, bfbfbf, 3f3f3f, 21b2c8, 20c8f7, 59a9f2, 4fceff, 5df0f6, 5ff2ca, b0dfa0, c9da91, a5a5a5, 262626, 105964, 02485c, 0b5394, 0075a2, 089ca2, 0b9b74, 54a838, 7e9532, 7f7f7f, 0c0c0c, 062328, 01303d, 073763, 004e6c, 05686c, 07674d, 387025, 546321',
columns: 10
},
hardcover: {
colors: 'ffffff, 000000, ece9c6, 895d1d, 873624, d6862d, d0be40, 877f6c, 972109, aeb795, f2f2f2, 7f7f7f, e1dca5, f2e0c6, f0d0c9, f6e6d5, f5f2d8, e7e5e1, fbc7bc, eef0e9, d8d8d8, 595959, d0c974, e6c28d, e2a293, eeceaa, ece5b2, cfccc3, f78f7a, dee2d4, bfbfbf, 3f3f3f, a29a36, daa454, d4735e, e6b681, e2d88c, b7b2a5, f35838, ced3bf, a5a5a5, 262626, 514d1b, 664515, 65281a, a2641f, a39428, 655f50, 711806, 879464, 7f7f7f, 0c0c0c, 201e0a, 442e0e, 431b11, 6c4315, 6d621a, 433f35, 4b1004, 5a6243',
columns: 10
},
trek: {
colors: 'ffffff, 000000, fbeec9, 4e3b30, f0a22e, a5644e, b58b80, c3986d, a19574, c17529, f2f2f2, 7f7f7f, f7e09e, e1d6cf, fcecd5, eddfda, f0e7e5, f3eae1, ece9e3, f5e3d1, d8d8d8, 595959, f3cc5f, c4ad9f, f9d9ab, dcc0b6, e1d0cc, e7d5c4, d9d4c7, ebc7a3, bfbfbf, 3f3f3f, d29f0f, a78470, f6c781, cba092, d2b9b2, dbc1a7, c6bfab, e1ac76, a5a5a5, 262626, 694f07, 3a2c24, c87d0e, 7b4b3a, 926255, a17242, 7b7153, 90571e, 7f7f7f, 0c0c0c, 2a1f03, 271d18, 855309, 523226, 614138, 6b4c2c, 524b37, 603a14',
columns: 10
},
verve: {
colors: 'ffffff, 000000, d2d2d2, 666666, ff388c, e40059, 9c007f, 68007f, 005bd3, 00349e, f2f2f2, 7f7f7f, bdbdbd, e0e0e0, ffd7e8, ffc6dc, ffb8f1, f1b2ff, c3dcff, b8cfff, d8d8d8, 595959, 9d9d9d, c1c1c1, ffafd1, ff8eba, ff71e4, e365ff, 87baff, 72a0ff, bfbfbf, 3f3f3f, 696969, a3a3a3, ff87ba, ff5597, ff2ad7, d519ff, 4b98ff, 2b71ff, a5a5a5, 262626, 343434, 4c4c4c, e90062, ab0042, 75005f, 4e005f, 00449e, 002676, 7f7f7f, 0c0c0c, 151515, 333333, 9b0041, 72002c, 4e003f, 34003f, 002d69, 00194f',
columns: 10
},
monochrome: {
colors: '000000, 1a1a1a, 333333, 4d4d4d, 666666, 808080, 999999, b3b3b3, cccccc, e6e6e6, f2f2f2, ffffff',
columns: 12
},
accessible: {
colors: 'black, grey, darkred, red, darkorange, gold, green, blue, darkblue, purple, white, darkgrey, saddlebrown, pink, orange, yellow, lightgreen, lightskyblue, lightblue, mediumpurple',
columns: 10
}
};
/**
* @hidden
*/
class ColorPaletteService {
colorRows = [];
setColorMatrix(palette, columns) {
this.colorRows = [];
if (!(isPresent(palette) && palette.length)) {
return;
}
columns = columns || palette.length;
for (let start = 0; start < palette.length; start += columns) {
const row = palette.slice(start, columns + start);
this.colorRows.push(row);
}
}
getCellCoordsFor(color) {
if (!isPresent(color)) {
return;
}
for (let row = 0; row < this.colorRows.length; row++) {
for (let col = 0; col < this.colorRows[row].length; col++) {
if (this.colorRows[row][col] === color) {
return { row, col };
}
}
}
}
getColorAt(cellCoords) {
if (!(isPresent(cellCoords) && isPresent(this.colorRows[cellCoords.row]))) {
return;
}
return this.colorRows[cellCoords.row][cellCoords.col];
}
getNextCell(current, horizontalStep, verticalStep) {
if (!(isPresent(current) && isPresent(current.row) && isPresent(current.col))) {
return { row: 0, col: 0 };
}
const row = this.clampIndex(current.row + verticalStep, this.colorRows.length - 1);
const col = this.clampIndex(current.col + horizontalStep, this.colorRows[row].length - 1);
return { row, col };
}
clampIndex(index, max) {
const minArrayIndex = 0;
if (index < minArrayIndex) {
return minArrayIndex;
}
if (index > max) {
return max;
}
return index;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteService, decorators: [{
type: Injectable
}] });
/* eslint-disable @typescript-eslint/no-explicit-any */
const DEFAULT_COLUMNS_COUNT = 10;
const DEFAULT_PRESET = 'office';
const DEFAULT_ACCESSIBLE_PRESET = 'accessible';
const DEFAULT_SIZE$6 = 'medium';
let serial$2 = 0;
/**
* The ColorPalette component provides a set of predefined palette presets and enables you to implement a custom color palette.
* The ColorPalette is independently used by `kendo-colorpicker` and can be directly added to the page.
*/
class ColorPaletteComponent {
host;
service;
cdr;
renderer;
localizationService;
ngZone;
/**
* @hidden
*/
direction;
/**
* @hidden
*/
role = 'grid';
/**
* @hidden
*/
get activeDescendant() {
return this.activeCellId;
}
/**
* @hidden
*/
get paletteId() {
return this.id;
}
/**
* @hidden
*/
id = `k-colorpalette-${serial$2++}`;
/**
* Specifies the output format of the ColorPaletteComponent.
* The input value may be in a different format. However, it will be parsed into the output `format`
* after the component processes it.
*
* The supported values are:
* * (Default) `hex`
* * `rgba`
* * `name`
*/
format = 'hex';
/**
* Specifies the value of the initially selected color.
*/
set value(value) {
this._value = parseColor(value, this.format);
}
get value() {
return this._value;
}
/**
* Specifies the number of columns that will be displayed.
* Defaults to `10`.
*/
set columns(value) {
const minColumnsCount = 1;
this._columns = value > minColumnsCount ? value : minColumnsCount;
}
get columns() {
return this._columns;
}
/**
* The color palette that will be displayed.
*
* The supported values are:
* * The name of the predefined palette preset (for example, `office`, `basic`, and `apex`).
* * A string with comma-separated colors.
* * A string array.
*/
set palette(value) {
if (!isPresent(value)) {
value = DEFAULT_PRESET;
}
if (typeof value === 'string' && isPresent(PALETTEPRESETS[value])) {
this.columns = this.columns || PALETTEPRESETS[value].columns;
value = PALETTEPRESETS[value].colors;
}
const colors = (typeof value === 'string') ? value.split(',') : value;
this._palette = colors.map(color => parseColor(color, this.format, false, false));
}
get palette() {
return this._palette;
}
/**
* The size property specifies the padding of the ColorPalette internal elements.
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size || DEFAULT_SIZE$6;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*/
set tabindex(value) {
const tabindex = Number(value);
const defaultValue = 0;
this._tabindex = !isNaN(tabindex) ? tabindex : defaultValue;
}
get tabindex() {
return !this.disabled ? this._tabindex : undefined;
}
/**
* Sets the disabled state of the ColorPalette. To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_colorpalette#toc-managing-the-colorpalette-disabled-state-in-reactive-forms).
*/
disabled = false;
/**
* Sets the read-only state of the ColorPalette.
*
* @default false
*/
readonly = false;
/**
* Specifies the size of a color cell. The default tile size depends on the `size` of the component.
*/
tileSize;
/**
* @hidden
*/
get tileLayout() {
if (typeof this.tileSize !== 'number') {
return this.tileSize;
}
return { width: this.tileSize, height: this.tileSize };
}
/**
* Fires each time the color selection is changed.
*/
selectionChange = new EventEmitter();
/**
* Fires each time the value is changed.
*/
valueChange = new EventEmitter();
/**
* Fires each time the user selects a cell with the mouse or presses `Enter`.
*
* @hidden
*/
cellSelection = new EventEmitter();
/**
* @hidden
*/
get colorRows() {
return this.service.colorRows;
}
/**
* @hidden
*/
get hostTabindex() { return this.tabindex; }
/**
* @hidden
*/
hostClasses = true;
/**
* @hidden
*/
get disabledClass() { return this.disabled; }
/**
* @hidden
*/
get readonlyAttribute() { return this.readonly; }
/**
* @hidden
*/
activeCellId;
/**
* @hidden
*/
focusedCell;
/**
* @hidden
*/
selectedCell;
/**
* @hidden
*/
focusInComponent;
/**
* @hidden
*/
uniqueId = guid();
selection;
_size = 'medium';
_value;
_columns;
_palette;
_tabindex = 0;
subs = new Subscription();
dynamicRTLSubscription;
constructor(host, service, cdr, renderer, localizationService, ngZone) {
this.host = host;
this.service = service;
this.cdr = cdr;
this.renderer = renderer;
this.localizationService = localizationService;
this.ngZone = ngZone;
validatePackage(packageMetadata);
this.dynamicRTLSubscription = localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
}
ngOnInit() {
if (this.colorRows.length === 0) {
const defaultPreset = (this.format !== 'name') ? DEFAULT_PRESET : DEFAULT_ACCESSIBLE_PRESET;
this.palette = this.palette || defaultPreset;
this.setRows();
}
const elem = this.host.nativeElement;
this.subs.add(this.renderer.listen(elem, 'keydown', event => this.handleKeydown(event)));
this.subs.add(this.renderer.listen(elem, 'focus', () => this.handleFocus()));
this.subs.add(this.renderer.listen(elem, 'blur', () => this.handleHostBlur()));
}
ngAfterViewInit() {
const stylingInputs = ['size'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
this.setHostElementAriaLabel();
if (this.value) {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.selectCell(this.value);
});
}
}
ngOnDestroy() {
this.subs.unsubscribe();
if (this.dynamicRTLSubscription) {
this.dynamicRTLSubscription.unsubscribe();
}
}
ngOnChanges(changes) {
if (changes['palette'] || changes['columns']) {
this.setRows();
}
if (changes['palette'] || changes['value'] || changes['columns']) {
this.selectCell(this.value);
this.setHostElementAriaLabel();
}
}
/**
* @hidden
*/
handleKeydown(event) {
const isRTL = this.direction === 'rtl';
switch (event.keyCode) {
case Keys.ArrowDown:
this.handleCellNavigation(0, 1);
break;
case Keys.ArrowUp:
this.handleCellNavigation(0, -1);
break;
case Keys.ArrowRight:
this.handleCellNavigation(isRTL ? -1 : 1, 0);
break;
case Keys.ArrowLeft:
this.handleCellNavigation(isRTL ? 1 : -1, 0);
break;
case Keys.Enter:
this.handleEnter();
break;
default: return;
}
event.preventDefault();
}
/**
* @hidden
*/
handleFocus() {
if (!this.focusInComponent) {
this.focus();
}
}
/**
* @hidden
*/
handleHostBlur() {
this.notifyNgTouched();
this.handleCellFocusOnBlur();
}
/**
* @hidden
*/
handleCellSelection(value, focusedCell) {
if (this.readonly) {
return;
}
this.selectedCell = focusedCell;
this.focusedCell = this.selectedCell;
this.focusInComponent = true;
const parsedColor = parseColor(value, this.format, false, false);
this.cellSelection.emit(parsedColor);
this.handleValueChange(parsedColor);
if (this.selection !== parsedColor) {
this.selection = parsedColor;
this.selectionChange.emit(parsedColor);
}
if (focusedCell) {
this.activeCellId = `k-${this.selectedCell.row}-${this.selectedCell.col}-${this.uniqueId}`;
}
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
this.selectCell(value);
}
/**
* @hidden
*/
registerOnChange(fn) {
this.notifyNgChanged = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.notifyNgTouched = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled) {
this.cdr.markForCheck();
this.disabled = isDisabled;
}
/**
* @hidden
*/
focus() {
this.host.nativeElement.focus();
if (!this.focusedCell && !this.readonly && !this.disabled) {
this.focusedCell = {
row: 0,
col: 0
};
this.activeCellId = `k-${this.focusedCell.row}-${this.focusedCell.col}-${this.uniqueId}`;
}
}
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
/**
* Clears the color value of the ColorPalette.
*/
reset() {
this.focusedCell = null;
if (isPresent(this.value)) {
this.handleValueChange(undefined);
}
this.selectedCell = undefined;
}
handleValueChange(color) {
if (this.value === color) {
return;
}
this.value = color;
this.valueChange.emit(color);
this.notifyNgChanged(color);
this.setHostElementAriaLabel();
}
handleCellFocusOnBlur() {
this.focusInComponent = false;
this.focusedCell = this.selectedCell;
}
selectCell(value) {
const parsedColor = parseColor(value, 'hex');
this.selectedCell = this.service.getCellCoordsFor(parsedColor);
this.focusedCell = this.selectedCell;
}
setRows() {
if (!isPresent(this.palette)) {
return;
}
this.columns = this.columns || DEFAULT_COLUMNS_COUNT;
this.service.setColorMatrix(this.palette, this.columns);
}
handleCellNavigation(horizontalStep, verticalStep) {
if (this.readonly) {
return;
}
this.focusedCell = this.service.getNextCell(this.focusedCell, horizontalStep, verticalStep);
this.focusInComponent = true;
if (this.focusedCell) {
this.activeCellId = `k-${this.focusedCell.row}-${this.focusedCell.col}-${this.uniqueId}`;
}
}
setHostElementAriaLabel() {
const parsed = parseColor(this.value, this.format);
this.renderer.setAttribute(this.host.nativeElement, 'aria-label', `${this.value ? parsed : this.localizationService.get('colorPaletteNoColor')}`);
}
handleEnter() {
if (!isPresent(this.focusedCell)) {
return;
}
const selectedColor = this.service.getColorAt(this.focusedCell);
this.handleCellSelection(selectedColor, this.focusedCell);
}
handleClasses(value, input) {
const elem = this.host.nativeElement;
const classes = getStylingClasses('colorpalette', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
notifyNgTouched = () => { };
notifyNgChanged = () => { };
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteComponent, deps: [{ token: i0.ElementRef }, { token: ColorPaletteService }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColorPaletteComponent, isStandalone: true, selector: "kendo-colorpalette", inputs: { id: "id", format: "format", value: "value", columns: "columns", palette: "palette", size: "size", tabindex: "tabindex", disabled: "disabled", readonly: "readonly", tileSize: "tileSize" }, outputs: { selectionChange: "selectionChange", valueChange: "valueChange", cellSelection: "cellSelection" }, host: { properties: { "attr.dir": "this.direction", "attr.role": "this.role", "attr.aria-activedescendant": "this.activeDescendant", "attr.id": "this.paletteId", "class.k-readonly": "this.readonly", "attr.tabindex": "this.hostTabindex", "class.k-colorpalette": "this.hostClasses", "attr.aria-disabled": "this.disabledClass", "class.k-disabled": "this.disabledClass", "attr.aria-readonly": "this.readonlyAttribute" } }, providers: [
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ColorPaletteComponent)
}, {
provide: KendoInput,
useExisting: forwardRef(() => ColorPaletteComponent)
},
ColorPaletteService,
ColorPaletteLocalizationService,
{
provide: LocalizationService,
useExisting: ColorPaletteLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.colorpalette'
}
], exportAs: ["kendoColorPalette"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoColorPaletteLocalizedMessages
i18n-colorPaletteNoColor="kendo.colorpalette.colorPaletteNoColor|The aria-label applied to the ColorPalette component when the value is empty."
colorPaletteNoColor="Colorpalette no color chosen">
</ng-container>
<table role="presentation" class="k-colorpalette-table">
<tbody>
<tr *ngFor="let row of colorRows; let rowIndex = index" role="row">
<td *ngFor="let color of row; let colIndex = index"
role="gridcell"
[class.k-selected]="selectedCell?.row === rowIndex && selectedCell?.col === colIndex"
[class.k-focus]="focusInComponent && focusedCell?.row === rowIndex && focusedCell?.col === colIndex"
[attr.aria-selected]="selectedCell?.row === rowIndex && selectedCell?.col === colIndex ? 'true' : undefined"
[attr.aria-label]="color"
class="k-colorpalette-tile"
[id]="'k-' + rowIndex + '-' + colIndex + '-' + uniqueId"
[attr.value]="color"
(click)="handleCellSelection(color, { row: rowIndex, col: colIndex })"
[ngStyle]="{
backgroundColor: color,
width: tileLayout?.width + 'px',
height: tileLayout?.height + 'px',
minWidth: tileLayout?.width + 'px'
}">
</td>
</tr>
</tbody>
</table>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedColorPickerMessagesDirective, selector: "[kendoColorPickerLocalizedMessages], [kendoFlatColorPickerLocalizedMessages], [kendoColorGradientLocalizedMessages], [kendoColorPaletteLocalizedMessages]" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPaletteComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoColorPalette',
selector: 'kendo-colorpalette',
providers: [
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ColorPaletteComponent)
}, {
provide: KendoInput,
useExisting: forwardRef(() => ColorPaletteComponent)
},
ColorPaletteService,
ColorPaletteLocalizationService,
{
provide: LocalizationService,
useExisting: ColorPaletteLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.colorpalette'
}
],
template: `
<ng-container kendoColorPaletteLocalizedMessages
i18n-colorPaletteNoColor="kendo.colorpalette.colorPaletteNoColor|The aria-label applied to the ColorPalette component when the value is empty."
colorPaletteNoColor="Colorpalette no color chosen">
</ng-container>
<table role="presentation" class="k-colorpalette-table">
<tbody>
<tr *ngFor="let row of colorRows; let rowIndex = index" role="row">
<td *ngFor="let color of row; let colIndex = index"
role="gridcell"
[class.k-selected]="selectedCell?.row === rowIndex && selectedCell?.col === colIndex"
[class.k-focus]="focusInComponent && focusedCell?.row === rowIndex && focusedCell?.col === colIndex"
[attr.aria-selected]="selectedCell?.row === rowIndex && selectedCell?.col === colIndex ? 'true' : undefined"
[attr.aria-label]="color"
class="k-colorpalette-tile"
[id]="'k-' + rowIndex + '-' + colIndex + '-' + uniqueId"
[attr.value]="color"
(click)="handleCellSelection(color, { row: rowIndex, col: colIndex })"
[ngStyle]="{
backgroundColor: color,
width: tileLayout?.width + 'px',
height: tileLayout?.height + 'px',
minWidth: tileLayout?.width + 'px'
}">
</td>
</tr>
</tbody>
</table>
`,
standalone: true,
imports: [LocalizedColorPickerMessagesDirective, NgFor, NgStyle]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ColorPaletteService }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1.LocalizationService }, { type: i0.NgZone }]; }, propDecorators: { direction: [{
type: HostBinding,
args: ['attr.dir']
}], role: [{
type: HostBinding,
args: ['attr.role']
}], activeDescendant: [{
type: HostBinding,
args: ['attr.aria-activedescendant']
}], paletteId: [{
type: HostBinding,
args: ['attr.id']
}], id: [{
type: Input
}], format: [{
type: Input
}], value: [{
type: Input
}], columns: [{
type: Input
}], palette: [{
type: Input
}], size: [{
type: Input
}], tabindex: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], tileSize: [{
type: Input
}], selectionChange: [{
type: Output
}], valueChange: [{
type: Output
}], cellSelection: [{
type: Output
}], hostTabindex: [{
type: HostBinding,
args: ['attr.tabindex']
}], hostClasses: [{
type: HostBinding,
args: ['class.k-colorpalette']
}], disabledClass: [{
type: HostBinding,
args: ['attr.aria-disabled']
}, {
type: HostBinding,
args: ['class.k-disabled']
}], readonlyAttribute: [{
type: HostBinding,
args: ['attr.aria-readonly']
}] } });
/**
* @hidden
*/
class FlatColorPickerService {
getPaletteSettings(settings, format) {
const defaultPreset = (format !== 'name') ? DEFAULT_PRESET$1 : DEFAULT_ACCESSIBLE_PRESET$1;
const settingsPalette = settings.palette;
const presetColumns = typeof settingsPalette === 'string' && PALETTEPRESETS[settingsPalette] ?
PALETTEPRESETS[settingsPalette].columns :
undefined;
return {
palette: settingsPalette || defaultPreset,
tileSize: settings.tileSize,
columns: settings.columns || presetColumns || 10
};
}
paletteTileLayout(tileSize) {
if (typeof tileSize === 'number') {
return { width: tileSize, height: tileSize };
}
return {
width: tileSize?.width ? tileSize?.width : tileSize?.height,
height: tileSize?.height ? tileSize?.height : tileSize?.width
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerService, decorators: [{
type: Injectable
}] });
/**
* Arguments for the `cancel` event of the ColorPicker and FlatColorPicker components.
*/
class ColorPickerCancelEvent extends PreventableEvent {
/**
* The DOM event that triggered the `cancel` event.
*/
originalEvent;
constructor(originalEvent) {
super();
this.originalEvent = originalEvent;
}
}
/**
* Arguments for the `close` event of the ColorPicker component.
*/
class ColorPickerCloseEvent extends PreventableEvent {
}
/**
* Arguments for the `open` event of the ColorPicker component.
*/
class ColorPickerOpenEvent extends PreventableEvent {
}
/**
* 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.
*
* Provides information about the current active color and gives the option to prevent the opening of the popup.
*
* @example
*
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-colorpicker
* [icon]="'edit-tools'"
* [value]="'#900'"
* (activeColorClick)="handleActiveColorClick($event)"
* >
* </kendo-colorpicker>
* `
* })
* class AppComponent {
* public handleActiveColorClick(event: ActiveColorClickEvent): void {
* event.preventOpen();
*
* console.log('Open prevented:', event.isOpenPrevented());
* console.log('Current color:', event.color);
* }
* }
* ```
*/
class ActiveColorClickEvent {
color;
openPrevented = false;
/**
* @hidden
* @param color Represents the current value of the ColorPicker.
*/
constructor(color) {
this.color = color;
}
/**
* Prevents the opening of the popup.
*/
preventOpen() {
this.openPrevented = true;
}
/**
* Returns `true` if the popup opening is prevented by any of its subscribers.
*
* @returns - Returns `true` if the open action was prevented. Otherwise, returns `false`.
*/
isOpenPrevented() {
return this.openPrevented;
}
}
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* @hidden
*/
class FlatColorPickerHeaderComponent {
localizationService;
renderer;
hostClasses = true;
clearButton;
activeView;
views;
preview;
innerTabIndex = -1;
value;
selection;
size;
viewChange = new EventEmitter();
valuePaneClick = new EventEmitter();
clearButtonClick = new EventEmitter();
tabOut = new EventEmitter();
viewButtonsCollection;
clearButtonElement;
dropletSliderIcon = dropletSliderIcon;
paletteIcon = paletteIcon;
dropletSlashIcon = dropletSlashIcon;
constructor(localizationService, renderer) {
this.localizationService = localizationService;
this.renderer = renderer;
}
ngAfterViewInit() {
if (this.viewButtonsCollection.length > 0) {
this.viewButtonsCollection.forEach((button) => {
const buttonElem = button.nativeElement;
const isViewActive = buttonElem.getAttribute('aria-pressed') === 'true';
if (isViewActive) {
this.renderer.addClass(buttonElem, 'k-selected');
}
});
}
}
onViewButtonClick(view) {
this.activeView = view;
this.viewChange.emit(view);
}
get viewButtons() {
return this.views && this.views.indexOf('gradient') >= 0 && this.views.indexOf('palette') >= 0;
}
getViewButtonIcon(view) {
return view === 'gradient' ? 'color-canvas' : 'palette';
}
getViewButtonsSVGIcon(view) {
return view === 'gradient' ? this.dropletSliderIcon : this.paletteIcon;
}
getText(text) {
return this.localizationService.get(text);
}
onHeaderTabOut(ev, index) {
if (index === 0) {
ev.preventDefault();
this.tabOut.emit(ev);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerHeaderComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FlatColorPickerHeaderComponent, isStandalone: true, selector: "[kendoFlatColorPickerHeader]", inputs: { clearButton: "clearButton", activeView: "activeView", views: "views", preview: "preview", innerTabIndex: "innerTabIndex", value: "value", selection: "selection", size: "size" }, outputs: { viewChange: "viewChange", valuePaneClick: "valuePaneClick", clearButtonClick: "clearButtonClick", tabOut: "tabOut" }, host: { properties: { "class.k-coloreditor-header": "this.hostClasses", "class.k-hstack": "this.hostClasses" } }, viewQueries: [{ propertyName: "clearButtonElement", first: true, predicate: ["clearButton"], descendants: true, read: ElementRef }, { propertyName: "viewButtonsCollection", predicate: ["viewButtons"], descendants: true, read: ElementRef }], ngImport: i0, template: `
<div class="k-coloreditor-header-actions k-hstack">
<div
*ngIf="viewButtons"
class="k-button-group k-button-group-flat"
role="group"
>
<button
*ngFor="let view of views; let i = index;"
kendoButton
type="button"
#viewButtons
fillMode="flat"
[tabindex]="innerTabIndex.toString()"
(click)="onViewButtonClick(view)"
[icon]="getViewButtonIcon(view)"
[svgIcon]="getViewButtonsSVGIcon(view)"
(keydown.shift.tab)="onHeaderTabOut($event, i)"
[size]="size"
[attr.title]="getText(view === 'gradient' ? 'gradientView' : 'paletteView')"
[attr.aria-label]="getText(view === 'gradient' ? 'gradientView' : 'paletteView')"
[attr.aria-pressed]="activeView === view"
[ngClass]="activeView === view ? 'k-selected' : ''">
</button>
</div>
</div>
<div class="k-spacer"></div>
<div class="k-coloreditor-header-actions k-hstack">
<button
kendoButton
type="button"
[tabindex]="innerTabIndex.toString()"
*ngIf="clearButton"
#clearButton
[size]="size"
fillMode="flat"
icon="reset-color"
[svgIcon]="dropletSlashIcon"
class="k-coloreditor-reset"
[attr.aria-label]="getText('clearButton')"
[attr.title]="getText('clearButton')"
(click)="clearButtonClick.emit()">
</button>
<div class="k-coloreditor-preview k-vstack" *ngIf="preview" aria-hidden="true">
<span
class="k-coloreditor-preview-color k-color-preview"
[attr.title]="getText('previewColor')"
[style.background-color]="selection">
</span>
<span class="k-coloreditor-current-color k-color-preview"
[style.background-color]="value"
[attr.title]="getText('revertSelection')"
(click)="valuePaneClick.emit($event)">
</span>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerHeaderComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoFlatColorPickerHeader]',
template: `
<div class="k-coloreditor-header-actions k-hstack">
<div
*ngIf="viewButtons"
class="k-button-group k-button-group-flat"
role="group"
>
<button
*ngFor="let view of views; let i = index;"
kendoButton
type="button"
#viewButtons
fillMode="flat"
[tabindex]="innerTabIndex.toString()"
(click)="onViewButtonClick(view)"
[icon]="getViewButtonIcon(view)"
[svgIcon]="getViewButtonsSVGIcon(view)"
(keydown.shift.tab)="onHeaderTabOut($event, i)"
[size]="size"
[attr.title]="getText(view === 'gradient' ? 'gradientView' : 'paletteView')"
[attr.aria-label]="getText(view === 'gradient' ? 'gradientView' : 'paletteView')"
[attr.aria-pressed]="activeView === view"
[ngClass]="activeView === view ? 'k-selected' : ''">
</button>
</div>
</div>
<div class="k-spacer"></div>
<div class="k-coloreditor-header-actions k-hstack">
<button
kendoButton
type="button"
[tabindex]="innerTabIndex.toString()"
*ngIf="clearButton"
#clearButton
[size]="size"
fillMode="flat"
icon="reset-color"
[svgIcon]="dropletSlashIcon"
class="k-coloreditor-reset"
[attr.aria-label]="getText('clearButton')"
[attr.title]="getText('clearButton')"
(click)="clearButtonClick.emit()">
</button>
<div class="k-coloreditor-preview k-vstack" *ngIf="preview" aria-hidden="true">
<span
class="k-coloreditor-preview-color k-color-preview"
[attr.title]="getText('previewColor')"
[style.background-color]="selection">
</span>
<span class="k-coloreditor-current-color k-color-preview"
[style.background-color]="value"
[attr.title]="getText('revertSelection')"
(click)="valuePaneClick.emit($event)">
</span>
</div>
</div>
`,
standalone: true,
imports: [NgIf, NgFor, ButtonComponent, NgClass]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Renderer2 }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-coloreditor-header']
}, {
type: HostBinding,
args: ['class.k-hstack']
}], clearButton: [{
type: Input
}], activeView: [{
type: Input
}], views: [{
type: Input
}], preview: [{
type: Input
}], innerTabIndex: [{
type: Input
}], value: [{
type: Input
}], selection: [{
type: Input
}], size: [{
type: Input
}], viewChange: [{
type: Output
}], valuePaneClick: [{
type: Output
}], clearButtonClick: [{
type: Output
}], tabOut: [{
type: Output
}], viewButtonsCollection: [{
type: ViewChildren,
args: ['viewButtons', { read: ElementRef }]
}], clearButtonElement: [{
type: ViewChild,
args: ['clearButton', { read: ElementRef }]
}] } });
/**
* @hidden
*/
class FlatColorPickerActionButtonsComponent {
localizationService;
hostClasses = true;
innerTabIndex = -1;
size;
actionButtonClick = new EventEmitter();
tabOut = new EventEmitter();
firstButton;
lastButton;
constructor(localizationService) {
this.localizationService = localizationService;
}
getText(text) {
return this.localizationService.get(text);
}
onActionButtonClick(type, ev) {
const args = {
target: type,
originalEvent: ev
};
this.actionButtonClick.emit(args);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerActionButtonsComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FlatColorPickerActionButtonsComponent, isStandalone: true, selector: "[kendoFlatColorPickerActionButtons]", inputs: { innerTabIndex: "innerTabIndex", size: "size" }, outputs: { actionButtonClick: "actionButtonClick", tabOut: "tabOut" }, host: { properties: { "class.k-coloreditor-footer": "this.hostClasses", "class.k-actions": "this.hostClasses", "class.k-actions-horizontal": "this.hostClasses" } }, viewQueries: [{ propertyName: "firstButton", first: true, predicate: ["first"], descendants: true, read: ElementRef }, { propertyName: "lastButton", first: true, predicate: ["last"], descendants: true, read: ElementRef }], ngImport: i0, template: `
<button #first
kendoButton
class="k-coloreditor-cancel"
[size]="size"
[attr.title]="getText('cancelButton')"
(click)="onActionButtonClick('cancel', $event)"
type="button"
[tabindex]="innerTabIndex.toString()"
>{{getText('cancelButton')}}</button>
<button #last
kendoButton
themeColor="primary"
[size]="size"
class="k-coloreditor-apply"
[attr.title]="getText('applyButton')"
(click)="onActionButtonClick('apply', $event)"
type="button"
[tabindex]="innerTabIndex.toString()"
(keydown.tab)="$event.preventDefault(); tabOut.emit();"
>{{getText('applyButton')}}</button>
`, 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"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerActionButtonsComponent, decorators: [{
type: Component,
args: [{
// eslint-disable-next-line @angular-eslint/component-selector
selector: '[kendoFlatColorPickerActionButtons]',
template: `
<button #first
kendoButton
class="k-coloreditor-cancel"
[size]="size"
[attr.title]="getText('cancelButton')"
(click)="onActionButtonClick('cancel', $event)"
type="button"
[tabindex]="innerTabIndex.toString()"
>{{getText('cancelButton')}}</button>
<button #last
kendoButton
themeColor="primary"
[size]="size"
class="k-coloreditor-apply"
[attr.title]="getText('applyButton')"
(click)="onActionButtonClick('apply', $event)"
type="button"
[tabindex]="innerTabIndex.toString()"
(keydown.tab)="$event.preventDefault(); tabOut.emit();"
>{{getText('applyButton')}}</button>
`,
standalone: true,
imports: [ButtonComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-coloreditor-footer']
}, {
type: HostBinding,
args: ['class.k-actions']
}, {
type: HostBinding,
args: ['class.k-actions-horizontal']
}], innerTabIndex: [{
type: Input
}], size: [{
type: Input
}], actionButtonClick: [{
type: Output
}], tabOut: [{
type: Output
}], firstButton: [{
type: ViewChild,
args: ['first', { read: ElementRef }]
}], lastButton: [{
type: ViewChild,
args: ['last', { read: ElementRef }]
}] } });
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-unused-expressions */
const DEFAULT_SIZE$5 = 'medium';
/**
* Represents the [Kendo UI FlatColorPicker component for Angular]({% slug overview_flatcolorpicker %}).
*
* The FlatColorPicker is a powerful tool which allows the user to choose colors through palettes with predefined sets of colors and
* through a gradient that renders an hsv canvas. It supports previewing the selected color, reverting it to its previous state or clearing it completely.
*/
class FlatColorPickerComponent {
host;
service;
localizationService;
cdr;
renderer;
ngZone;
injector;
hostClasses = true;
get disabledClass() {
return this.disabled;
}
get ariaReadonly() {
return this.readonly;
}
direction;
get hostTabindex() {
return this.tabindex?.toString() || '0';
}
ariaRole = 'textbox';
get isControlInvalid() {
return (this.control?.invalid)?.toString();
}
get isDisabled() {
return this.disabled?.toString() || undefined;
}
/**
* @hidden
*/
enterHandler(event) {
if (event.target !== this.host.nativeElement) {
return;
}
event.preventDefault();
this.internalNavigation = true;
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.firstFocusable?.focus());
}
/**
* @hidden
*/
escapeHandler() {
this.internalNavigation = false;
this.host.nativeElement.focus();
}
/**
* @hidden
*/
focusHandler(ev) {
this.internalNavigation = ev.target !== this.host.nativeElement;
}
/**
* Sets the read-only state of the FlatColorPicker.
*
* @default false
*/
readonly = false;
/**
* Sets the disabled state of the FlatColorPicker. To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_flatcolorpicker#toc-managing-the-flatcolorpicker-disabled-state-in-reactive-forms).
*
* @default false
*/
disabled = false;
/**
* Specifies the output format of the FlatColorPicker.
*
* 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 initially selected color.
*/
set value(value) {
this._value = parseColor(value, this.format, this.gradientSettings.opacity);
}
get value() {
return this._value;
}
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*
* @default 0
*/
set tabindex(value) {
if (isPresent(value)) {
const tabindex = Number(value);
this._tabindex = !isNaN(tabindex) ? tabindex : 0;
}
else {
// Allows removal of the tabindex attribute
this._tabindex = value;
}
}
get tabindex() {
return !this.disabled ? this._tabindex : undefined;
}
/**
* Specifies whether the FlatColorPicker should display a 'Clear color' button.
*
* @default true
*/
clearButton = true;
/**
* Displays `Apply` and `Cancel` action buttons and a color preview pane.
*
* 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
* initial state i.e. to the current value.
*
* @default true
*/
preview = true;
/**
* Configures the layout of the `Apply` and `Cancel` action buttons.
* * `start`
* * `center`
* * `end` (default)
* * `stretch`
*/
actionsLayout = 'end';
/**
* Sets the initially active view in the FlatColorPicker. The property supports two-way binding.
* * `gradient` (default)
* * `palette`
*/
activeView;
/**
* Specifies the views that will be rendered. Default value is gradient and palette.
*/
views = ['gradient', 'palette'];
/**
* Configures the gradient view.
*/
set gradientSettings(value) {
Object.assign(this._gradientSettings, value);
}
get gradientSettings() {
return this._gradientSettings;
}
/**
* @hidden
*/
adaptiveMode = false;
/**
* Configures the palette view.
*/
set paletteSettings(value) {
Object.assign(this._paletteSettings, value);
}
get paletteSettings() {
return this._paletteSettings;
}
/**
* The size property specifies the padding of the FlatColorPicker internal elements.
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size || DEFAULT_SIZE$5;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* Fires each time the component value is changed.
*/
valueChange = new EventEmitter();
/**
* Fires when the user cancels the current color selection.
*
* The event is emitted on preview pane or on 'Cancel' button click.
*/
cancel = 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();
/**
* @hidden
* Fires each time the clear button is clicked.
*/
clearButtonClick = new EventEmitter();
/**
* @hidden
*/
actionButtonClick = new EventEmitter();
header;
headerElement;
gradient;
gradientElement;
palette;
footer;
/**
* @hidden
*/
selection;
focused;
_value;
_tabindex = 0;
_gradientSettings = {
opacity: true,
delay: 0,
gradientSliderStep: DRAGHANDLE_MOVE_SPEED,
gradientSliderSmallStep: DRAGHANDLE_MOVE_SPEED_SMALL_STEP
};
_paletteSettings = {};
dynamicRTLSubscription;
subscriptions = new Subscription();
internalNavigation = false;
_size = 'medium';
control;
/**
* @hidden
*/
get innerTabIndex() {
return this.internalNavigation ? 0 : -1;
}
/**
* @hidden
*/
get firstFocusable() {
if (this.headerHasContent) {
return this.headerElement.nativeElement.querySelector('.k-button');
}
return this.activeView === 'gradient' ? this.gradient : this.palette;
}
constructor(host, service, localizationService, cdr, renderer, ngZone, injector) {
this.host = host;
this.service = service;
this.localizationService = localizationService;
this.cdr = cdr;
this.renderer = renderer;
this.ngZone = ngZone;
this.injector = injector;
validatePackage(packageMetadata);
this.dynamicRTLSubscription = this.localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
}
ngOnInit() {
this.selection = this.value;
this.control = this.injector.get(NgControl, null);
this._paletteSettings = this.service.getPaletteSettings(this._paletteSettings, this.format);
this.setActiveView();
}
ngAfterViewInit() {
const stylingInputs = ['size'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
this.setHostElementAriaLabel();
this.initDomEvents();
this.setSizingVariables();
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.removeGradientAttributes());
}
ngOnChanges(changes) {
if (isChanged('value', changes)) {
this.selection = this.value;
this.setHostElementAriaLabel();
}
if (isChanged('paletteSettings', changes)) {
this.setSizingVariables();
}
}
ngOnDestroy() {
if (this.dynamicRTLSubscription) {
this.dynamicRTLSubscription.unsubscribe();
}
this.subscriptions.unsubscribe();
}
/**
* @hidden
*/
focusFirstHeaderButton() {
if (this.gradientElement.nativeElement === document.activeElement) {
if (this.headerHasContent && !this.preview) {
const firstHeaderButton = this.headerElement.nativeElement.querySelector('.k-button');
firstHeaderButton.focus();
}
}
}
/**
* @hidden
*/
lastFocusable(event) {
if (this.preview) {
this.footer.lastButton.nativeElement.focus();
return;
}
event.stopImmediatePropagation();
const gradient = this.gradientElement?.nativeElement;
const palette = this.palette?.host.nativeElement;
this.activeView === 'gradient' ? gradient.focus() : palette.focus();
}
/**
* @hidden
*/
onTab(ev) {
const { shiftKey } = ev;
const nextTabStop = this.preview ? this.footer.firstButton.nativeElement : this.headerHasContent ? findFocusableChild(this.headerElement.nativeElement) : null;
const previousTabStop = this.headerHasContent ? findFocusableChild(this.headerElement.nativeElement) : this.preview ? this.footer.lastButton.nativeElement : null;
if (!nextTabStop && !previousTabStop) {
return;
}
ev.preventDefault();
// eslint-disable-next-line no-unused-expressions
shiftKey ? previousTabStop?.focus() : nextTabStop?.focus();
}
/**
* @hidden
*/
get headerHasContent() {
return this.preview || this.views.length > 1 || this.clearButton;
}
/**
* @hidden
* Used by the FloatingLabel to determine if the component is empty.
*/
isEmpty() {
return false;
}
/**
* Focuses the wrapper of the FlatColorPicker.
*/
focus() {
if (this.disabled || this.focused) {
return;
}
this.host.nativeElement.focus();
this.focused = true;
}
/**
* Blurs the wrapper of the FlatColorPicker.
*/
blur() {
if (!this.focused) {
return;
}
this.notifyNgTouched();
this.host.nativeElement.blur();
this.focused = false;
}
/**
* Clears the value of the FlatColorPicker.
*/
reset() {
if (!isPresent(this.value)) {
return;
}
this.value = undefined;
this.notifyNgChanged(undefined);
this.setHostElementAriaLabel();
}
/**
* @hidden
*/
onViewChange(view) {
if (this.activeView === view) {
return;
}
this.activeView = view;
this.activeViewChange.emit(view);
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this[this.activeView]?.focus();
});
});
if (this.activeView === 'gradient') {
this.removeGradientAttributes();
}
}
/**
* @hidden
*/
onClearButtonClick() {
this.resetInnerComponentValue();
this.clearButtonClick.emit();
}
/**
* @hidden
*/
handleValueChange(color) {
// eslint-disable-next-line no-unused-expressions
this.preview ? this.changeCurrentValue(color) : this.setFlatColorPickerValue(color);
}
/**
* @hidden
*/
onAction(ev) {
// eslint-disable-next-line no-unused-expressions
ev.target === 'apply' ? this.setFlatColorPickerValue(this.selection) : this.resetSelection(ev.originalEvent);
this.actionButtonClick.emit();
}
/**
* @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
*/
resetSelection(ev) {
const eventArgs = new ColorPickerCancelEvent(ev);
this.cancel.emit(eventArgs);
if (!eventArgs.isDefaultPrevented()) {
this.selection = this.value;
}
this.notifyNgTouched();
}
setHostElementAriaLabel() {
const parsed = parseColor(this.value, this.format, this.gradientSettings.opacity);
const ariaLabelValue = `${this.value ? parsed : this.localizationService.get('flatColorPickerNoColor')}`;
this.renderer.setAttribute(this.host.nativeElement, 'aria-label', ariaLabelValue);
}
setSizingVariables() {
const paletteTileSize = this.service.paletteTileLayout(this.paletteSettings.tileSize);
const element = this.host.nativeElement.querySelector('.k-coloreditor-views.k-vstack');
const cssProperties = [`--kendo-color-preview-columns: ${this.paletteSettings.columns};`];
if (paletteTileSize.width) {
cssProperties.push(`--kendo-color-preview-width: ${paletteTileSize.width}px;`);
}
if (paletteTileSize.height) {
cssProperties.push(`--kendo-color-preview-height: ${paletteTileSize.height}px;`);
}
this.renderer.setProperty(element, 'style', cssProperties.join(' '));
}
changeCurrentValue(color) {
this.selection = color;
this.notifyNgTouched();
}
resetInnerComponentValue() {
this.selection = null;
if (this.gradient) {
this.gradient.reset();
return;
}
this.palette.reset();
}
setFlatColorPickerValue(color) {
if (this.value === color) {
return;
}
this.value = color;
this.valueChange.emit(color);
this.notifyNgChanged(color);
this.setHostElementAriaLabel();
}
setActiveView() {
if (!isPresent(this.activeView)) {
this.activeView = this.views[0];
return;
}
if (isDevMode() && this.views.indexOf(this.activeView) === -1) {
throw new Error("Invalid configuration: The current activeView is not present in the views collection");
}
}
notifyNgChanged = () => { };
notifyNgTouched = () => { };
initDomEvents() {
if (!this.host) {
return;
}
const hostElement = this.host.nativeElement;
this.ngZone.runOutsideAngular(() => {
this.subscriptions.add(this.renderer.listen(hostElement, 'focus', () => {
this.focused = true;
}));
this.subscriptions.add(this.renderer.listen(hostElement, 'blur', () => {
this.focused = false;
this.notifyNgTouched();
}));
});
}
removeGradientAttributes() {
this.gradientElement && this.renderer.removeAttribute(this.gradientElement.nativeElement, 'role');
this.gradientElement && this.renderer.removeAttribute(this.gradientElement.nativeElement, 'aria-label');
}
handleClasses(value, input) {
const elem = this.host.nativeElement;
const classes = getStylingClasses('coloreditor', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerComponent, deps: [{ token: i0.ElementRef }, { token: FlatColorPickerService }, { token: i1.LocalizationService }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FlatColorPickerComponent, isStandalone: true, selector: "kendo-flatcolorpicker", inputs: { readonly: "readonly", disabled: "disabled", format: "format", value: "value", tabindex: "tabindex", clearButton: "clearButton", preview: "preview", actionsLayout: "actionsLayout", activeView: "activeView", views: "views", gradientSettings: "gradientSettings", adaptiveMode: "adaptiveMode", paletteSettings: "paletteSettings", size: "size" }, outputs: { valueChange: "valueChange", cancel: "cancel", activeViewChange: "activeViewChange", clearButtonClick: "clearButtonClick", actionButtonClick: "actionButtonClick" }, host: { listeners: { "keydown.enter": "enterHandler($event)", "keydown.escape": "escapeHandler()", "focusin": "focusHandler($event)" }, properties: { "class.k-flatcolorpicker": "this.hostClasses", "class.k-coloreditor": "this.hostClasses", "class.k-disabled": "this.disabledClass", "attr.aria-disabled": "this.isDisabled", "attr.aria-readonly": "this.ariaReadonly", "attr.dir": "this.direction", "attr.tabindex": "this.hostTabindex", "attr.role": "this.ariaRole", "attr.aria-invalid": "this.isControlInvalid", "class.k-readonly": "this.readonly" } }, providers: [
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FlatColorPickerComponent)
},
{
provide: KendoInput,
useExisting: forwardRef(() => FlatColorPickerComponent)
},
FlatColorPickerService,
FlatColorPickerLocalizationService,
{
provide: LocalizationService,
useExisting: FlatColorPickerLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.flatcolorpicker'
}
], viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "headerElement", first: true, predicate: ["header"], descendants: true, read: ElementRef }, { propertyName: "gradient", first: true, predicate: ["gradient"], descendants: true }, { propertyName: "gradientElement", first: true, predicate: ["gradient"], descendants: true, read: ElementRef }, { propertyName: "palette", first: true, predicate: ["palette"], descendants: true }, { propertyName: "footer", first: true, predicate: ["footer"], descendants: true }], exportAs: ["kendoFlatColorPicker"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoFlatColorPickerLocalizedMessages
i18n-flatColorPickerNoColor="kendo.flatcolorpicker.flatColorPickerNoColor|The aria-label applied to the FlatColorPicker component when the value is empty."
flatColorPickerNoColor="Flatcolorpicker no color chosen"
i18n-colorGradientNoColor="kendo.flatcolorpicker.colorGradientNoColor|The aria-label applied to the ColorGradient component when the value is empty."
colorGradientNoColor="Colorgradient no color chosen"
i18n-colorPaletteNoColor="kendo.flatcolorpicker.colorPaletteNoColor|The aria-label applied to the ColorPalette component when the value is empty."
colorPaletteNoColor="Colorpalette no color chosen"
i18n-colorGradientHandle="kendo.flatcolorpicker.colorGradientHandle|The title for the gradient color drag handle chooser."
colorGradientHandle="Choose color"
i18n-clearButton="kendo.flatcolorpicker.clearButton|The title for the clear button."
clearButton="Clear value"
i18n-hueSliderHandle="kendo.flatcolorpicker.hueSliderHandle|The title for the hue slider handle."
hueSliderHandle="Set hue"
i18n-opacitySliderHandle="kendo.flatcolorpicker.opacitySliderHandle|The title for the opacity slider handle."
opacitySliderHandle="Set opacity"
i18n-contrastRatio="kendo.flatcolorpicker.contrastRatio|The contrast ratio message for the contrast tool."
contrastRatio="Contrast ratio"
i18n-previewColor="kendo.flatcolorpicker.previewColor|The message for the color preview pane."
previewColor="Color preview"
i18n-revertSelection="kendo.flatcolorpicker.revertSelection|The message for the selected color pane."
revertSelection="Revert selection"
i18n-gradientView="kendo.flatcolorpicker.gradientView|The message for the gradient view button."
gradientView="Gradient view"
i18n-paletteView="kendo.flatcolorpicker.paletteView|The message for the palette view button."
paletteView="Palette view"
i18n-formatButton="kendo.flatcolorpicker.formatButton|The message for the input format toggle button."
formatButton="Change color format"
i18n-applyButton="kendo.flatcolorpicker.applyButton|The message for the Apply action button."
applyButton="Apply"
i18n-cancelButton="kendo.flatcolorpicker.cancelButton|The message for the Cancel action button."
cancelButton="Cancel"
i18n-redChannelLabel="kendo.flatcolorpicker.redChannelLabel|The label of the NumericTextBox representing the red color channel."
redChannelLabel="Red channel"
i18n-greenChannelLabel="kendo.flatcolorpicker.greenChannelLabel|The label of the NumericTextBox representing the green color channel."
greenChannelLabel="Green channel"
i18n-blueChannelLabel="kendo.flatcolorpicker.blueChannelLabel|The label of the NumericTextBox representing the blue color channel."
blueChannelLabel="Blue channel"
i18n-alphaChannelLabel="kendo.flatcolorpicker.alphaChannelLabel|The label of the NumericTextBox representing the alpha color channel."
alphaChannelLabel="Alpha channel"
i18n-redInputPlaceholder="kendo.flatcolorpicker.redInputPlaceholder|The placeholder for the red color input."
redChannelLabel="R"
i18n-greenInputPlaceholder="kendo.flatcolorpicker.greenInputPlaceholder|The placeholder for the green color input."
greenInputPlaceholder="G"
i18n-blueInputPlaceholder="kendo.flatcolorpicker.blueInputPlaceholder|The placeholder for the blue color input."
blueInputPlaceholder="B"
i18n-hexInputPlaceholder="kendo.flatcolorpicker.hexInputPlaceholder|The placeholder for the HEX color input."
hexInputPlaceholder="HEX">
</ng-container>
<div kendoFlatColorPickerHeader
[innerTabIndex]="innerTabIndex"
*ngIf="headerHasContent"
#header
[clearButton]="clearButton"
[activeView]="activeView"
[views]="views"
[size]="size"
[value]="value"
[selection]="selection"
[preview]="preview"
(clearButtonClick)="onClearButtonClick()"
(viewChange)="onViewChange($event)"
(valuePaneClick)="resetSelection($event)"
(tabOut)="lastFocusable($event)"></div>
<div class="k-coloreditor-views k-vstack">
<kendo-colorgradient #gradient
[tabindex]="innerTabIndex"
*ngIf="activeView === 'gradient'"
[value]="selection"
[size]="size"
[adaptiveMode]="adaptiveMode"
[format]="format"
[opacity]="gradientSettings.opacity"
[delay]="gradientSettings.delay"
[contrastTool]="gradientSettings.contrastTool"
[gradientSliderSmallStep]="gradientSettings.gradientSliderSmallStep"
[gradientSliderStep]="gradientSettings.gradientSliderStep"
[readonly]="readonly"
(keydown.tab)="focusFirstHeaderButton()"
(valueChange)="handleValueChange($event)"
></kendo-colorgradient>
<kendo-colorpalette #palette
[tabindex]="innerTabIndex"
*ngIf="activeView === 'palette'"
[palette]="paletteSettings.palette"
[size]="size"
[columns]="paletteSettings.columns"
[tileSize]="paletteSettings.tileSize"
[format]="format"
[value]="selection"
[readonly]="readonly"
(valueChange)="handleValueChange($event)"
></kendo-colorpalette>
</div>
<div *ngIf="preview && !adaptiveMode"
#footer
kendoFlatColorPickerActionButtons
[innerTabIndex]="innerTabIndex"
[size]="size"
[ngClass]="'k-justify-content-' + actionsLayout"
(actionButtonClick)="onAction($event)"
(tabOut)="firstFocusable.focus()">
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedColorPickerMessagesDirective, selector: "[kendoColorPickerLocalizedMessages], [kendoFlatColorPickerLocalizedMessages], [kendoColorGradientLocalizedMessages], [kendoColorPaletteLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FlatColorPickerHeaderComponent, selector: "[kendoFlatColorPickerHeader]", inputs: ["clearButton", "activeView", "views", "preview", "innerTabIndex", "value", "selection", "size"], outputs: ["viewChange", "valuePaneClick", "clearButtonClick", "tabOut"] }, { kind: "component", type: ColorGradientComponent, selector: "kendo-colorgradient", inputs: ["adaptiveMode", "id", "opacity", "size", "disabled", "readonly", "clearButton", "delay", "value", "contrastTool", "tabindex", "format", "gradientSliderStep", "gradientSliderSmallStep"], outputs: ["valueChange"], exportAs: ["kendoColorGradient"] }, { kind: "component", type: ColorPaletteComponent, selector: "kendo-colorpalette", inputs: ["id", "format", "value", "columns", "palette", "size", "tabindex", "disabled", "readonly", "tileSize"], outputs: ["selectionChange", "valueChange", "cellSelection"], exportAs: ["kendoColorPalette"] }, { kind: "component", type: FlatColorPickerActionButtonsComponent, selector: "[kendoFlatColorPickerActionButtons]", inputs: ["innerTabIndex", "size"], outputs: ["actionButtonClick", "tabOut"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatColorPickerComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoFlatColorPicker',
selector: 'kendo-flatcolorpicker',
providers: [
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FlatColorPickerComponent)
},
{
provide: KendoInput,
useExisting: forwardRef(() => FlatColorPickerComponent)
},
FlatColorPickerService,
FlatColorPickerLocalizationService,
{
provide: LocalizationService,
useExisting: FlatColorPickerLocalizationService
},
{
provide: L10N_PREFIX,
useValue: 'kendo.flatcolorpicker'
}
],
template: `
<ng-container kendoFlatColorPickerLocalizedMessages
i18n-flatColorPickerNoColor="kendo.flatcolorpicker.flatColorPickerNoColor|The aria-label applied to the FlatColorPicker component when the value is empty."
flatColorPickerNoColor="Flatcolorpicker no color chosen"
i18n-colorGradientNoColor="kendo.flatcolorpicker.colorGradientNoColor|The aria-label applied to the ColorGradient component when the value is empty."
colorGradientNoColor="Colorgradient no color chosen"
i18n-colorPaletteNoColor="kendo.flatcolorpicker.colorPaletteNoColor|The aria-label applied to the ColorPalette component when the value is empty."
colorPaletteNoColor="Colorpalette no color chosen"
i18n-colorGradientHandle="kendo.flatcolorpicker.colorGradientHandle|The title for the gradient color drag handle chooser."
colorGradientHandle="Choose color"
i18n-clearButton="kendo.flatcolorpicker.clearButton|The title for the clear button."
clearButton="Clear value"
i18n-hueSliderHandle="kendo.flatcolorpicker.hueSliderHandle|The title for the hue slider handle."
hueSliderHandle="Set hue"
i18n-opacitySliderHandle="kendo.flatcolorpicker.opacitySliderHandle|The title for the opacity slider handle."
opacitySliderHandle="Set opacity"
i18n-contrastRatio="kendo.flatcolorpicker.contrastRatio|The contrast ratio message for the contrast tool."
contrastRatio="Contrast ratio"
i18n-previewColor="kendo.flatcolorpicker.previewColor|The message for the color preview pane."
previewColor="Color preview"
i18n-revertSelection="kendo.flatcolorpicker.revertSelection|The message for the selected color pane."
revertSelection="Revert selection"
i18n-gradientView="kendo.flatcolorpicker.gradientView|The message for the gradient view button."
gradientView="Gradient view"
i18n-paletteView="kendo.flatcolorpicker.paletteView|The message for the palette view button."
paletteView="Palette view"
i18n-formatButton="kendo.flatcolorpicker.formatButton|The message for the input format toggle button."
formatButton="Change color format"
i18n-applyButton="kendo.flatcolorpicker.applyButton|The message for the Apply action button."
applyButton="Apply"
i18n-cancelButton="kendo.flatcolorpicker.cancelButton|The message for the Cancel action button."
cancelButton="Cancel"
i18n-redChannelLabel="kendo.flatcolorpicker.redChannelLabel|The label of the NumericTextBox representing the red color channel."
redChannelLabel="Red channel"
i18n-greenChannelLabel="kendo.flatcolorpicker.greenChannelLabel|The label of the NumericTextBox representing the green color channel."
greenChannelLabel="Green channel"
i18n-blueChannelLabel="kendo.flatcolorpicker.blueChannelLabel|The label of the NumericTextBox representing the blue color channel."
blueChannelLabel="Blue channel"
i18n-alphaChannelLabel="kendo.flatcolorpicker.alphaChannelLabel|The label of the NumericTextBox representing the alpha color channel."
alphaChannelLabel="Alpha channel"
i18n-redInputPlaceholder="kendo.flatcolorpicker.redInputPlaceholder|The placeholder for the red color input."
redChannelLabel="R"
i18n-greenInputPlaceholder="kendo.flatcolorpicker.greenInputPlaceholder|The placeholder for the green color input."
greenInputPlaceholder="G"
i18n-blueInputPlaceholder="kendo.flatcolorpicker.blueInputPlaceholder|The placeholder for the blue color input."
blueInputPlaceholder="B"
i18n-hexInputPlaceholder="kendo.flatcolorpicker.hexInputPlaceholder|The placeholder for the HEX color input."
hexInputPlaceholder="HEX">
</ng-container>
<div kendoFlatColorPickerHeader
[innerTabIndex]="innerTabIndex"
*ngIf="headerHasContent"
#header
[clearButton]="clearButton"
[activeView]="activeView"
[views]="views"
[size]="size"
[value]="value"
[selection]="selection"
[preview]="preview"
(clearButtonClick)="onClearButtonClick()"
(viewChange)="onViewChange($event)"
(valuePaneClick)="resetSelection($event)"
(tabOut)="lastFocusable($event)"></div>
<div class="k-coloreditor-views k-vstack">
<kendo-colorgradient #gradient
[tabindex]="innerTabIndex"
*ngIf="activeView === 'gradient'"
[value]="selection"
[size]="size"
[adaptiveMode]="adaptiveMode"
[format]="format"
[opacity]="gradientSettings.opacity"
[delay]="gradientSettings.delay"
[contrastTool]="gradientSettings.contrastTool"
[gradientSliderSmallStep]="gradientSettings.gradientSliderSmallStep"
[gradientSliderStep]="gradientSettings.gradientSliderStep"
[readonly]="readonly"
(keydown.tab)="focusFirstHeaderButton()"
(valueChange)="handleValueChange($event)"
></kendo-colorgradient>
<kendo-colorpalette #palette
[tabindex]="innerTabIndex"
*ngIf="activeView === 'palette'"
[palette]="paletteSettings.palette"
[size]="size"
[columns]="paletteSettings.columns"
[tileSize]="paletteSettings.tileSize"
[format]="format"
[value]="selection"
[readonly]="readonly"
(valueChange)="handleValueChange($event)"
></kendo-colorpalette>
</div>
<div *ngIf="preview && !adaptiveMode"
#footer
kendoFlatColorPickerActionButtons
[innerTabIndex]="innerTabIndex"
[size]="size"
[ngClass]="'k-justify-content-' + actionsLayout"
(actionButtonClick)="onAction($event)"
(tabOut)="firstFocusable.focus()">
</div>
`,
standalone: true,
imports: [LocalizedColorPickerMessagesDirective, NgIf, FlatColorPickerHeaderComponent, ColorGradientComponent, ColorPaletteComponent, FlatColorPickerActionButtonsComponent, NgClass]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: FlatColorPickerService }, { type: i1.LocalizationService }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.Injector }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-flatcolorpicker']
}, {
type: HostBinding,
args: ['class.k-coloreditor']
}], disabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}, {
type: HostBinding,
args: ['attr.aria-disabled']
}], ariaReadonly: [{
type: HostBinding,
args: ['attr.aria-readonly']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], hostTabindex: [{
type: HostBinding,
args: ['attr.tabindex']
}], ariaRole: [{
type: HostBinding,
args: ['attr.role']
}], isControlInvalid: [{
type: HostBinding,
args: ['attr.aria-invalid']
}], isDisabled: [{
type: HostBinding,
args: ['attr.aria-disabled']
}], enterHandler: [{
type: HostListener,
args: ['keydown.enter', ['$event']]
}], escapeHandler: [{
type: HostListener,
args: ['keydown.escape']
}], focusHandler: [{
type: HostListener,
args: ['focusin', ['$event']]
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], disabled: [{
type: Input
}], format: [{
type: Input
}], value: [{
type: Input
}], tabindex: [{
type: Input
}], clearButton: [{
type: Input
}], preview: [{
type: Input
}], actionsLayout: [{
type: Input
}], activeView: [{
type: Input
}], views: [{
type: Input
}], gradientSettings: [{
type: Input
}], adaptiveMode: [{
type: Input
}], paletteSettings: [{
type: Input
}], size: [{
type: Input
}], valueChange: [{
type: Output
}], cancel: [{
type: Output
}], activeViewChange: [{
type: Output
}], clearButtonClick: [{
type: Output
}], actionButtonClick: [{
type: Output
}], header: [{
type: ViewChild,
args: ['header']
}], headerElement: [{
type: ViewChild,
args: ['header', { read: ElementRef }]
}], gradient: [{
type: ViewChild,
args: ['gradient']
}], gradientElement: [{
type: ViewChild,
args: ['gradient', { read: ElementRef }]
}], palette: [{
type: ViewChild,
args: ['palette']
}], footer: [{
type: ViewChild,
args: ['footer']
}] } });
/**
* @hidden
*/
const animationDuration = 300;
/**
* @hidden
*/
const updateActionSheetAdaptiveAppearance = (actionSheet, windowSize, renderer) => {
const element = actionSheet['element'].nativeElement.querySelector('.k-actionsheet');
const animationContainer = actionSheet['element'].nativeElement.querySelector('.k-child-animation-container');
renderer.addClass(element, 'k-adaptive-actionsheet');
renderer.setStyle(animationContainer, 'width', '100%');
if (windowSize === 'medium') {
renderer.removeClass(element, 'k-actionsheet-fullscreen');
renderer.addClass(element, 'k-actionsheet-bottom');
renderer.setStyle(animationContainer, 'bottom', '0px');
}
else if (windowSize === 'small') {
renderer.removeClass(element, 'k-actionsheet-bottom');
renderer.addClass(element, 'k-actionsheet-fullscreen');
renderer.setStyle(animationContainer, 'height', '100%');
}
};
/**
* @hidden
*/
class AdaptiveCloseButtonComponent {
title;
icon;
svgIcon;
color;
close = new EventEmitter();
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveCloseButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AdaptiveCloseButtonComponent, isStandalone: true, selector: "kendo-adaptive-close-button", inputs: { title: "title", icon: "icon", svgIcon: "svgIcon", color: "color" }, outputs: { close: "close" }, ngImport: i0, template: `
<button kendoButton
type="button"
[title]="title"
[icon]="icon"
[svgIcon]="svgIcon"
[themeColor]="color"
fillMode="flat"
size="large"
[tabIndex]="-1"
(click)="close.emit($event)"
></button>
`, 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"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveCloseButtonComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-adaptive-close-button',
template: `
<button kendoButton
type="button"
[title]="title"
[icon]="icon"
[svgIcon]="svgIcon"
[themeColor]="color"
fillMode="flat"
size="large"
[tabIndex]="-1"
(click)="close.emit($event)"
></button>
`,
standalone: true,
imports: [ButtonComponent]
}]
}], propDecorators: { title: [{
type: Input
}], icon: [{
type: Input
}], svgIcon: [{
type: Input
}], color: [{
type: Input
}], close: [{
type: Output
}] } });
/**
* @hidden
*/
class AdaptiveRendererComponent {
localization;
title;
subtitle;
actionSheetTemplate;
isActionSheetExpanded;
preview;
actionSheetClose = new EventEmitter();
onExpand = new EventEmitter();
onCollapse = new EventEmitter();
onApply = new EventEmitter();
onCancel = new EventEmitter();
actionSheet;
actionSheetSearchBar;
cancelButton;
applyButton;
constructor(localization) {
this.localization = localization;
}
animationDuration = animationDuration;
xIcon = xIcon;
checkIcon = checkIcon;
messageFor(key) {
return this.localization.get(key);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveRendererComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AdaptiveRendererComponent, isStandalone: true, selector: "kendo-adaptive-renderer", inputs: { title: "title", subtitle: "subtitle", actionSheetTemplate: "actionSheetTemplate", isActionSheetExpanded: "isActionSheetExpanded", preview: "preview" }, outputs: { actionSheetClose: "actionSheetClose", onExpand: "onExpand", onCollapse: "onCollapse", onApply: "onApply", onCancel: "onCancel" }, viewQueries: [{ propertyName: "actionSheet", first: true, predicate: ActionSheetComponent, descendants: true }, { propertyName: "actionSheetSearchBar", first: true, predicate: ["actionSheetSearchBar"], descendants: true }, { propertyName: "cancelButton", first: true, predicate: ["cancel"], descendants: true }, { propertyName: "applyButton", first: true, predicate: ["apply"], descendants: true }], ngImport: i0, template: `
<kendo-actionsheet
#actionSheet
[animation]="{ duration: animationDuration }"
[expanded]="isActionSheetExpanded"
(overlayClick)="actionSheetClose.emit()"
(expand)="onExpand.emit()"
(collapse)="onCollapse.emit()"
>
<ng-template kendoActionSheetTemplate>
<div class="k-text-center k-actionsheet-titlebar">
<div class="k-actionsheet-titlebar-group k-hbox">
<div class="k-actionsheet-title">
<div class="k-text-center">{{ messageFor('adaptiveTitle') }}</div>
<div class="k-actionsheet-subtitle k-text-center"></div>
</div>
<div *ngIf="!preview" class="k-actionsheet-actions">
<kendo-adaptive-close-button
icon="check"
color="primary"
[title]="messageFor('closeButton')"
[svgIcon]="checkIcon"
(close)="onApply.emit($event)">
</kendo-adaptive-close-button>
</div>
<div *ngIf="preview" class="k-actionsheet-actions">
<kendo-adaptive-close-button
icon="x"
[title]="messageFor('closeButton')"
[svgIcon]="xIcon"
(close)="actionSheetClose.emit($event)">
</kendo-adaptive-close-button>
</div>
</div>
</div>
<div class="k-actionsheet-content !k-overflow-hidden">
<ng-container *ngTemplateOutlet="actionSheetTemplate"></ng-container>
</div>
<div *ngIf="preview" class="k-actions k-actions-stretched k-actions-horizontal k-actionsheet-footer">
<button
#cancel
kendoButton
size="large"
(click)="onCancel.emit($event)"
[title]="messageFor('cancelButton')">
{{messageFor('cancelButton')}}
</button>
<button
#apply
kendoButton
size="large"
themeColor="primary"
(click)="onApply.emit()"
[title]="messageFor('applyButton')">
{{messageFor('applyButton')}}
</button>
</div>
</ng-template>
</kendo-actionsheet>
`, isInline: true, dependencies: [{ kind: "component", type: ActionSheetComponent, selector: "kendo-actionsheet", inputs: ["title", "subtitle", "items", "cssClass", "animation", "expanded", "titleId"], outputs: ["expandedChange", "expand", "collapse", "itemClick", "overlayClick"], exportAs: ["kendoActionSheet"] }, { kind: "directive", type: ActionSheetTemplateDirective, selector: "[kendoActionSheetTemplate]" }, { 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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AdaptiveCloseButtonComponent, selector: "kendo-adaptive-close-button", inputs: ["title", "icon", "svgIcon", "color"], outputs: ["close"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveRendererComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-adaptive-renderer',
template: `
<kendo-actionsheet
#actionSheet
[animation]="{ duration: animationDuration }"
[expanded]="isActionSheetExpanded"
(overlayClick)="actionSheetClose.emit()"
(expand)="onExpand.emit()"
(collapse)="onCollapse.emit()"
>
<ng-template kendoActionSheetTemplate>
<div class="k-text-center k-actionsheet-titlebar">
<div class="k-actionsheet-titlebar-group k-hbox">
<div class="k-actionsheet-title">
<div class="k-text-center">{{ messageFor('adaptiveTitle') }}</div>
<div class="k-actionsheet-subtitle k-text-center"></div>
</div>
<div *ngIf="!preview" class="k-actionsheet-actions">
<kendo-adaptive-close-button
icon="check"
color="primary"
[title]="messageFor('closeButton')"
[svgIcon]="checkIcon"
(close)="onApply.emit($event)">
</kendo-adaptive-close-button>
</div>
<div *ngIf="preview" class="k-actionsheet-actions">
<kendo-adaptive-close-button
icon="x"
[title]="messageFor('closeButton')"
[svgIcon]="xIcon"
(close)="actionSheetClose.emit($event)">
</kendo-adaptive-close-button>
</div>
</div>
</div>
<div class="k-actionsheet-content !k-overflow-hidden">
<ng-container *ngTemplateOutlet="actionSheetTemplate"></ng-container>
</div>
<div *ngIf="preview" class="k-actions k-actions-stretched k-actions-horizontal k-actionsheet-footer">
<button
#cancel
kendoButton
size="large"
(click)="onCancel.emit($event)"
[title]="messageFor('cancelButton')">
{{messageFor('cancelButton')}}
</button>
<button
#apply
kendoButton
size="large"
themeColor="primary"
(click)="onApply.emit()"
[title]="messageFor('applyButton')">
{{messageFor('applyButton')}}
</button>
</div>
</ng-template>
</kendo-actionsheet>
`,
standalone: true,
imports: [ActionSheetComponent, ActionSheetTemplateDirective, ButtonComponent, NgIf, NgTemplateOutlet, AdaptiveCloseButtonComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { title: [{
type: Input
}], subtitle: [{
type: Input
}], actionSheetTemplate: [{
type: Input
}], isActionSheetExpanded: [{
type: Input
}], preview: [{
type: Input
}], actionSheetClose: [{
type: Output
}], onExpand: [{
type: Output
}], onCollapse: [{
type: Output
}], onApply: [{
type: Output
}], onCancel: [{
type: Output
}], actionSheet: [{
type: ViewChild,
args: [ActionSheetComponent]
}], actionSheetSearchBar: [{
type: ViewChild,
args: ['actionSheetSearchBar']
}], cancelButton: [{
type: ViewChild,
args: ['cancel']
}], applyButton: [{
type: ViewChild,
args: ['apply']
}] } });
/* eslint-disable @typescript-eslint/no-explicit-any */
const DOM_FOCUS_EVENTS = ['focus', 'blur'];
const DEFAULT_SIZE$4 = 'medium';
const DEFAULT_ROUNDED$3 = 'medium';
const DEFAULT_FILL_MODE$3 = '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.
*/
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$4;
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$3;
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$3;
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$1 : DEFAULT_ACCESSIBLE_PRESET$1;
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$1(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$1(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$1(event.relatedTarget, (element) => element === this.flatColorPicker.host.nativeElement) :
false;
const closestWrapper = closest$1(event.relatedTarget, (element) => element === this.host.nativeElement);
const closestActionSheet = this.isActionSheetExpanded ? closest$1(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$2.PopupService }, { token: i0.ChangeDetectorRef }, { token: i1.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 () { return [{ type: i0.ElementRef }, { type: i1$2.PopupService }, { type: i0.ChangeDetectorRef }, { type: i1.LocalizationService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i0.Injector }, { type: i3.AdaptiveService }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-colorpicker']
}, {
type: HostBinding,
args: ['class.k-icon-picker']
}, {
type: HostBinding,
args: ['class.k-picker']
}], focusedClass: [{
type: HostBinding,
args: ['class.k-focus']
}], disabledClass: [{
type: HostBinding,
args: ['attr.aria-disabled']
}, {
type: HostBinding,
args: ['class.k-disabled']
}], ariaReadonly: [{
type: HostBinding,
args: ['attr.aria-readonly']
}], ariaExpanded: [{
type: HostBinding,
args: ['attr.aria-expanded']
}], hostTabindex: [{
type: HostBinding,
args: ['attr.tabindex']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], role: [{
type: HostBinding,
args: ['attr.role']
}], hasPopup: [{
type: HostBinding,
args: ['attr.aria-haspopup']
}], isControlInvalid: [{
type: HostBinding,
args: ['attr.aria-invalid']
}], views: [{
type: Input
}], view: [{
type: Input
}], adaptiveMode: [{
type: Input
}], activeView: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], disabled: [{
type: Input
}], format: [{
type: Input
}], value: [{
type: Input
}], popupSettings: [{
type: Input
}], paletteSettings: [{
type: Input
}], gradientSettings: [{
type: Input
}], icon: [{
type: Input
}], iconClass: [{
type: Input
}], svgIcon: [{
type: Input
}], clearButton: [{
type: Input
}], tabindex: [{
type: Input
}], preview: [{
type: Input
}], actionsLayout: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], valueChange: [{
type: Output
}], open: [{
type: Output
}], close: [{
type: Output
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], cancel: [{
type: Output
}], activeColorClick: [{
type: Output
}], clearButtonClick: [{
type: Output
}], activeViewChange: [{
type: Output
}], container: [{
type: ViewChild,
args: ['container', { read: ViewContainerRef, static: true }]
}], activeColor: [{
type: ViewChild,
args: ['activeColor', { static: true }]
}], popupTemplate: [{
type: ViewChild,
args: ['popupTemplate', { static: true }]
}], flatColorPicker: [{
type: ViewChild,
args: ['flatColorPicker', { static: false }]
}], adaptiveRenderer: [{
type: ViewChild,
args: [AdaptiveRendererComponent]
}] } });
/**
* Custom component messages override default component messages.
*/
class ColorPickerCustomMessagesComponent extends ColorPickerMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColorPickerCustomMessagesComponent, isStandalone: true, selector: "kendo-colorpicker-messages, kendo-flatcolorpicker-messages, kendo-colorgradient-messages, kendo-colorpalette-messages", providers: [
{
provide: ColorPickerMessages,
useExisting: forwardRef(() => ColorPickerCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: ColorPickerMessages,
useExisting: forwardRef(() => ColorPickerCustomMessagesComponent)
}
],
selector: 'kendo-colorpicker-messages, kendo-flatcolorpicker-messages, kendo-colorgradient-messages, kendo-colorpalette-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
let serial$1 = 0;
/**
* Represents an error message that will be shown underneath
* a Kendo control or native HTML form-bound component after a validation.
*/
class ErrorComponent {
hostClass = true;
/**
* Specifies the alignment of the Error message.
*
* The possible values are:
* * (Default) `start`
* * `end`
*/
align = 'start';
/**
* @hidden
*/
id = `kendo-error-${serial$1++}`;
roleAttribute = 'alert';
get startClass() {
return this.align === 'start';
}
get endClass() {
return this.align === 'end';
}
get idAttribute() {
return this.id;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ErrorComponent, isStandalone: true, selector: "kendo-formerror", inputs: { align: "align" }, host: { properties: { "class.k-form-error": "this.hostClass", "attr.role": "this.roleAttribute", "class.k-text-start": "this.startClass", "class.k-text-end": "this.endClass", "attr.id": "this.idAttribute" } }, ngImport: i0, template: `
<ng-content></ng-content>
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-formerror',
template: `
<ng-content></ng-content>
`,
standalone: true
}]
}], propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-form-error']
}], align: [{
type: Input
}], roleAttribute: [{
type: HostBinding,
args: ['attr.role']
}], startClass: [{
type: HostBinding,
args: ['class.k-text-start']
}], endClass: [{
type: HostBinding,
args: ['class.k-text-end']
}], idAttribute: [{
type: HostBinding,
args: ['attr.id']
}] } });
let serial = 0;
/**
* Represents a hint message that will be shown underneath a form-bound component.
*/
class HintComponent {
/**
* Specifies the alignment of the Hint message.
*
* The possible values are:
* * (Default) `start`
* * `end`
*/
align = 'start';
/**
* @hidden
*/
id = `kendo-hint-${serial++}`;
hostClass = true;
get startClass() {
return this.align === 'start';
}
get endClass() {
return this.align === 'end';
}
get idAttribute() {
return this.id;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HintComponent, isStandalone: true, selector: "kendo-formhint", inputs: { align: "align" }, host: { properties: { "class.k-form-hint": "this.hostClass", "class.k-text-start": "this.startClass", "class.k-text-end": "this.endClass", "attr.id": "this.idAttribute" } }, ngImport: i0, template: `
<ng-content></ng-content>
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HintComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-formhint',
template: `
<ng-content></ng-content>
`,
standalone: true
}]
}], propDecorators: { align: [{
type: Input
}], hostClass: [{
type: HostBinding,
args: ['class.k-form-hint']
}], startClass: [{
type: HostBinding,
args: ['class.k-text-start']
}], endClass: [{
type: HostBinding,
args: ['class.k-text-end']
}], idAttribute: [{
type: HostBinding,
args: ['attr.id']
}] } });
/**
* Specifies a container for form-bound controls (Kendo controls or native HTML controls).
* Applies styling and behavior rules.
*/
class FormFieldComponent {
renderer;
localizationService;
hostElement;
hostClass = true;
/**
* @hidden
*/
direction;
get errorClass() {
if (!this.control) {
return false;
}
return this.control.invalid && (this.control.touched || this.control.dirty);
}
get disabledClass() {
if (!this.control) {
return false;
}
// radiobutton group
if (this.isRadioControl(this.control)) {
return false;
}
return this.disabledControl() ||
this.disabledElement() ||
this.disabledKendoInput();
}
set formControls(formControls) {
this.validateFormControl(formControls);
this.control = formControls.first;
}
controlElementRefs;
kendoInput;
errorChildren;
hintChildren;
/**
*
* Specifies when the Hint messages will be shown.
*
* The possible values are:
*
* * (Default) `initial`—Allows displaying hints when the form-bound component state is
* `valid` or `untouched` and `pristine`.
* * `always`—Allows full control over the visibility of the hints.
*
*/
showHints = 'initial';
/**
* Specifies the layout orientation of the form field.
*
* * The possible values are:
*
* * (Default) `vertical`
* * `horizontal`
*/
orientation = 'vertical';
/**
* Specifies when the Error messages will be shown.
*
* The possible values are:
*
* * (Default) `initial`—Allows displaying errors when the form-bound component state is
* `invalid` and `touched` or `dirty`.
* * `always`—Allows full control over the visibility of the errors.
*
*/
showErrors = 'initial';
/**
* @hidden
*/
get horizontal() {
return this.orientation === 'horizontal';
}
/**
* @hidden
*/
get hasHints() {
return this.showHints === 'always' ? true : this.showHintsInitial();
}
/**
* @hidden
*/
get hasErrors() {
return this.showErrors === 'always' ? true : this.showErrorsInitial();
}
control;
subscriptions = new Subscription();
rtl = false;
constructor(renderer, localizationService, hostElement) {
this.renderer = renderer;
this.localizationService = localizationService;
this.hostElement = hostElement;
validatePackage(packageMetadata);
this.subscriptions.add(this.localizationService.changes.subscribe(({ rtl }) => {
this.rtl = rtl;
this.direction = this.rtl ? 'rtl' : 'ltr';
}));
}
ngAfterViewInit() {
this.setDescription();
}
ngAfterViewChecked() {
this.updateDescription();
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
disabledKendoInput() {
return this.kendoInput && this.kendoInput.disabled;
}
disabledControl() {
return this.control.disabled;
}
disabledElement() {
const elements = this.controlElementRefs.toArray();
return elements.every(e => e.nativeElement.hasAttribute('disabled'));
}
validateFormControl(formControls) {
if (isDevMode() && formControls.length !== 1 && !this.isControlGroup(formControls)) {
throw new Error('The `kendo-formfield` component should contain ' +
'only one control of type NgControl with a formControlName(https://angular.io/api/forms/FormControlName)' +
'or an ngModel(https://angular.io/api/forms/NgModel) binding.');
}
}
isControlGroup(formControls) {
if (!formControls.length) {
return false;
}
const name = formControls.first.name;
return formControls.toArray().every(c => c.name === name && (this.isRadioControl(c)));
}
isRadioControl(control) {
return control.valueAccessor instanceof RadioControlValueAccessor;
}
updateDescription() {
const controls = this.findControlElements().filter(c => !!c);
if (!controls) {
return;
}
controls.forEach((control) => {
if (this.errorChildren.length > 0 || this.hintChildren.length > 0) {
const ariaIds = this.generateDescriptionIds(control);
if (ariaIds !== '') {
this.renderer.setAttribute(control, 'aria-describedby', ariaIds);
}
else {
this.renderer.removeAttribute(control, 'aria-describedby');
}
}
});
}
findControlElements() {
if (!this.controlElementRefs) {
return;
}
// the control is KendoInput and has focusableId - dropdowns, dateinputs, editor
if (this.kendoInput && this.kendoInput.focusableId && isDocumentAvailable()) {
// Editor requires special treatment when in iframe mode
const isEditor = this.kendoInput.focusableId.startsWith('k-editor');
return isEditor ? [this.kendoInput.viewMountElement] : [this.hostElement.nativeElement.querySelector(`#${this.kendoInput.focusableId}`)];
}
return this.controlElementRefs.map(el => el.nativeElement);
}
generateDescriptionIds(control) {
const ids = new Set();
let errorAttribute = '';
if (control.hasAttribute('aria-describedby')) {
const attributes = control.getAttribute('aria-describedby').split(' ');
errorAttribute = attributes.filter(attr => attr.includes('kendo-error-'))[0];
attributes.forEach((attr) => {
if (attr.includes('kendo-hint-') || attr.includes('kendo-error-')) {
return;
}
ids.add(attr);
});
}
this.hintChildren.forEach((hint) => {
ids.add(hint.id);
});
if (this.hasErrors) {
this.errorChildren.forEach((error) => {
ids.add(error.id);
});
}
else {
ids.delete(errorAttribute);
}
return Array.from(ids).join(' ');
}
showHintsInitial() {
if (!this.control) {
return true;
}
const { valid, untouched, pristine } = this.control;
return valid || (untouched && pristine);
}
showErrorsInitial() {
if (!this.control) {
return false;
}
const { invalid, dirty, touched } = this.control;
return invalid && (dirty || touched);
}
setDescription() {
this.updateDescription();
this.subscriptions.add(this.errorChildren.changes.subscribe(() => this.updateDescription()));
this.subscriptions.add(this.hintChildren.changes.subscribe(() => this.updateDescription()));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFieldComponent, deps: [{ token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FormFieldComponent, isStandalone: true, selector: "kendo-formfield", inputs: { showHints: "showHints", orientation: "orientation", showErrors: "showErrors" }, host: { properties: { "class.k-form-field": "this.hostClass", "attr.dir": "this.direction", "class.k-form-field-error": "this.errorClass", "class.k-form-field-disabled": "this.disabledClass" } }, providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.formfield'
}
], queries: [{ propertyName: "kendoInput", first: true, predicate: KendoInput, descendants: true, static: true }, { propertyName: "formControls", predicate: NgControl, descendants: true }, { propertyName: "controlElementRefs", predicate: NgControl, descendants: true, read: ElementRef }, { propertyName: "errorChildren", predicate: ErrorComponent, descendants: true }, { propertyName: "hintChildren", predicate: HintComponent, descendants: true }], ngImport: i0, template: `
<ng-content select="label, kendo-label"></ng-content>
<div class="k-form-field-wrap">
<ng-content></ng-content>
<ng-content select="kendo-formhint" *ngIf="hasHints"></ng-content>
<ng-content select="kendo-formerror" *ngIf="hasErrors"></ng-content>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFieldComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-formfield',
template: `
<ng-content select="label, kendo-label"></ng-content>
<div class="k-form-field-wrap">
<ng-content></ng-content>
<ng-content select="kendo-formhint" *ngIf="hasHints"></ng-content>
<ng-content select="kendo-formerror" *ngIf="hasErrors"></ng-content>
</div>
`,
providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.formfield'
}
],
standalone: true,
imports: [NgIf]
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i1.LocalizationService }, { type: i0.ElementRef }]; }, propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-form-field']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], errorClass: [{
type: HostBinding,
args: ['class.k-form-field-error']
}], disabledClass: [{
type: HostBinding,
args: ['class.k-form-field-disabled']
}], formControls: [{
type: ContentChildren,
args: [NgControl, { descendants: true }]
}], controlElementRefs: [{
type: ContentChildren,
args: [NgControl, { read: ElementRef, descendants: true }]
}], kendoInput: [{
type: ContentChild,
args: [KendoInput, { static: true }]
}], errorChildren: [{
type: ContentChildren,
args: [ErrorComponent, { descendants: true }]
}], hintChildren: [{
type: ContentChildren,
args: [HintComponent, { descendants: true }]
}], showHints: [{
type: Input
}], orientation: [{
type: Input
}], showErrors: [{
type: Input
}] } });
class RadioButtonComponent extends RadioCheckBoxBase {
renderer;
hostElement;
cdr;
ngZone;
injector;
localizationService;
hostClass = true;
direction;
/**
* Specifies the checked state of the RadioButton.
*
* @default false
*/
checked = false;
/**
* Fires each time the checked state is changed.
* When the state of the component is programmatically changed to `ngModel` or `formControl`
* through its API or form binding, the `checkedStateChange` event is not triggered because it
* might cause a mix-up with the built-in mechanisms of the `ngModel` or `formControl` bindings.
*
* Used to provide a two-way binding for the `checked` property.
*/
checkedChange = new EventEmitter();
subs = new Subscription();
get defaultAttributes() {
return {
type: 'radio',
id: this.focusableId,
title: this.title,
tabindex: this.tabindex,
tabIndex: this.tabindex,
disabled: this.disabled ? '' : null,
value: this.value,
checked: this.checked,
name: this.name,
'aria-invalid': this.isControlInvalid
};
}
constructor(renderer, hostElement, cdr, ngZone, injector, localizationService) {
super('radio', hostElement, renderer, cdr, ngZone, injector);
this.renderer = renderer;
this.hostElement = hostElement;
this.cdr = cdr;
this.ngZone = ngZone;
this.injector = injector;
this.localizationService = localizationService;
validatePackage(packageMetadata);
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
}
ngOnInit() {
super.ngOnInit();
this.subs.add(this.localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
}));
}
ngAfterViewInit() {
const stylingInputs = ['size'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
// Otherwise the view is not updated in Reactive Forms - https://github.com/angular/angular/issues/13792
if (this.control) {
this.subs.add(this.control.valueChanges.subscribe(e => {
this.control.control.setValue(e, { emitEvent: false });
}));
}
}
ngOnDestroy() {
this.subs.unsubscribe();
}
/**
* @hidden
*/
handleChange = ($event) => {
this.ngZone.run(() => {
this.checked = $event.target.checked;
this.checkedChange.emit(this.checked);
this.ngChange($event.target.value);
});
};
/**
* @hidden
*/
writeValue(value) {
this.checked = value === this.value;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RadioButtonComponent, isStandalone: true, selector: "kendo-radiobutton", inputs: { checked: "checked" }, outputs: { checkedChange: "checkedChange" }, host: { properties: { "class.k-radio-wrap": "this.hostClass", "attr.dir": "this.direction" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.radiobutton' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioButtonComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => RadioButtonComponent) }
], exportAs: ["kendoRadioButton"], usesInheritance: true, ngImport: i0, template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<input #input
type="radio"
class="k-radio"
[id]="focusableId"
[attr.title]="title"
[disabled]="disabled"
[class.k-disabled]="disabled"
[attr.tabindex]="disabled ? undefined : tabindex"
[value]="value"
[name]="name"
[checked]="checked"
[class.k-checked]="checked"
[attr.aria-invalid]="isControlInvalid"
[class.k-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
blur: handleInputBlur,
change: handleChange
}"
/>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoRadioButton',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.radiobutton' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioButtonComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => RadioButtonComponent) }
],
selector: 'kendo-radiobutton',
template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<input #input
type="radio"
class="k-radio"
[id]="focusableId"
[attr.title]="title"
[disabled]="disabled"
[class.k-disabled]="disabled"
[attr.tabindex]="disabled ? undefined : tabindex"
[value]="value"
[name]="name"
[checked]="checked"
[class.k-checked]="checked"
[attr.aria-invalid]="isControlInvalid"
[class.k-invalid]="isControlInvalid"
[attr.required]="isControlRequired ? '' : null"
[kendoEventsOutsideAngular]="{
blur: handleInputBlur,
change: handleChange
}"
/>
</ng-container>
`,
standalone: true,
imports: [SharedInputEventsDirective, EventsOutsideAngularDirective]
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }, { type: i1.LocalizationService }]; }, propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-radio-wrap']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], checked: [{
type: Input
}], checkedChange: [{
type: Output
}] } });
const DEFAULT_SIZE$3 = 'medium';
/**
* Represents the directive that renders the [Kendo UI RadioButton]({% slug overview_checkbox %}) input component.
* The directive is placed on input type="radio" elements.
*
* @example
* ```ts-no-run
* <input type="radio" kendoRadioButton />
* ```
*/
class RadioButtonDirective {
renderer;
hostElement;
kendoClass = true;
/**
* The size property specifies the width and height of the RadioButton
* ([see example]({% slug appearance_radiobuttondirective %}#toc-size)).
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$3;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
_size = 'medium';
constructor(renderer, hostElement) {
this.renderer = renderer;
this.hostElement = hostElement;
validatePackage(packageMetadata);
}
ngAfterViewInit() {
// kept in sync with other inputs for easier refactoring
// to a common base class
const stylingInputs = ['size'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('radio', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RadioButtonDirective, isStandalone: true, selector: "input[kendoRadioButton]", inputs: { size: "size" }, host: { properties: { "class.k-radio": "this.kendoClass" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[kendoRadioButton]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { kendoClass: [{
type: HostBinding,
args: ['class.k-radio']
}], size: [{
type: Input
}] } });
/**
* Custom component messages override default component messages.
*/
class RangeSliderCustomMessagesComponent extends RangeSliderMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RangeSliderCustomMessagesComponent, isStandalone: true, selector: "kendo-rangeslider-messages", providers: [
{
provide: RangeSliderMessages,
useExisting: forwardRef(() => RangeSliderCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: RangeSliderMessages,
useExisting: forwardRef(() => RangeSliderCustomMessagesComponent)
}
],
selector: 'kendo-rangeslider-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Renders the hovered rating item content. To define an item template, nest an `<ng-template>` tag
* with the `kendoRatingHoveredItemTemplate` directive inside the `<kendo-rating>` tag
* [see example](slug:templates_rating).
* The index of the currently hovered item is available as an implicit context using the `let-index="index"` syntax.
*/
class RatingHoveredItemTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingHoveredItemTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RatingHoveredItemTemplateDirective, isStandalone: true, selector: "[kendoRatingHoveredItemTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingHoveredItemTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoRatingHoveredItemTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* Renders the rating item content. To define an item template, nest an `<ng-template>` tag
* with the `kendoRatingItemTemplate` directive inside the `<kendo-rating>` tag
* [see example](slug:templates_rating).
* The index of the current item is available as an implicit context using the `let-index="index"` syntax.
*/
class RatingItemTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingItemTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RatingItemTemplateDirective, isStandalone: true, selector: "[kendoRatingItemTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingItemTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoRatingItemTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* Renders the selected rating item content. To define an item template, nest an `<ng-template>` tag
* with the `kendoRatingSelectedItemTemplate` directive inside the `<kendo-rating>` tag
* [see example](slug:templates_rating).
* The index of the currently selected item is available as an implicit context using the `let-index="index"` syntax.
*/
class RatingSelectedItemTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingSelectedItemTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RatingSelectedItemTemplateDirective, isStandalone: true, selector: "[kendoRatingSelectedItemTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingSelectedItemTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoRatingSelectedItemTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* Represents the [Kendo UI Rating component for Angular]({% slug overview_rating %}).
*/
class RatingComponent {
element;
renderer;
localizationService;
cdr;
zone;
itemTemplate;
hoveredItemTemplate;
selectedItemTemplate;
/**
* Determines whether the Rating is disabled ([see example]({% slug disabledstate_rating %})). To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_rating#toc-managing-the-rating-disabled-state-in-reactive-forms).
*
* @default false
*
*/
disabled = false;
/**
* Determines whether the Rating is in its read-only state ([see example]({% slug readonly_rating %})).
*
* @default false
*
*/
readonly = false;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the Rating.
*
* @default 0
*
*/
tabindex = 0;
/**
* Sets the number of rating items ([see example]({% slug itemscount_rating %})).
*
* @default 5
*
*/
itemsCount = 5;
/**
* The initial value of the Rating component.
* The component can use either NgModel or the `value` binding but not both of them at the same time.
*
*/
set value(value) {
this._value = value;
this.updateRatingItems();
}
get value() {
return this._value;
}
/**
* Sets the selection mode of the Rating ([see example]({% slug selection_rating %})).
*
* @default 'continuous'
*
*/
set selection(selection) {
this._selection = selection;
this.updateRatingItems();
}
get selection() {
return this._selection;
}
/**
* Determines the precision of the Rating ([see example]({% slug precision_rating %})).
*
* @default 'item'
*
*/
set precision(precision) {
this._precision = precision;
this.updateRatingItems();
}
get precision() {
return this._precision;
}
/**
* Sets the Rating label. It is not the native HTML `label` element, it is just a `span` element with the provided text ([see example]({% slug label_rating %})).
*/
label;
/**
* Sets custom Rating font icon ([see example]({% slug icon_rating %})).
*/
icon;
/**
* Sets custom Rating SVG icon. It is the icon that is used for selected/hovered state ([see example]({% slug icon_rating %})).
*/
svgIcon = starIcon;
/**
* Sets custom Rating SVG icon. It is the icon that is used for not selected/hovered state ([see example]({% slug icon_rating %})).
*/
svgIconOutline = starOutlineIcon;
/**
* Fires each time the user selects a new value.
*/
valueChange = new EventEmitter();
hostClass = true;
direction;
get isControlInvalid() {
return (this.control?.invalid)?.toString();
}
valueMin = 0;
get valueMax() {
return this.itemsCount;
}
get valueNow() {
return this.value;
}
ariaRole = 'slider';
/**
* @hidden
*/
ratingItems = [];
control;
ngChange = (_) => { };
ngTouched = () => { };
rect;
_value;
_selection = 'continuous';
_precision = 'item';
subscriptions = new Subscription();
constructor(element, renderer, localizationService, cdr, zone) {
this.element = element;
this.renderer = renderer;
this.localizationService = localizationService;
this.cdr = cdr;
this.zone = zone;
validatePackage(packageMetadata);
}
ngOnInit() {
this.subscriptions.add(this.localizationService
.changes
.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
}));
this.subscriptions.add(this.renderer.listen(this.element.nativeElement, 'blur', () => this.ngTouched()));
this.subscriptions.add(this.renderer.listen(this.element.nativeElement, 'keydown', event => this.onKeyDown(event)));
this.createRatingItems();
}
ngAfterViewInit() {
const items = this.element.nativeElement.querySelectorAll('.k-rating-item');
this.zone.runOutsideAngular(() => {
items.forEach((item, index) => this.subscriptions.add(this.renderer.listen(item, 'mousemove', (event) => this.onMouseMove(index, event))));
});
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
/**
* Focuses the Rating component.
*/
focus() {
if (isDocumentAvailable() && !this.disabled) {
this.element.nativeElement.focus();
}
}
/**
* Blurs the Rating component.
*/
blur() {
if (isDocumentAvailable()) {
this.element.nativeElement.blur();
}
}
/**
* @hidden
*/
createRatingItems() {
for (let i = 0; i < this.itemsCount; i++) {
const item = {
title: this.isHalf(i, this.value) ? String(i + 0.5) : String(i + 1),
selected: this.isSelected(i, this.value),
selectedIndicator: false,
hovered: false,
half: this.isHalf(i, this.value)
};
this.ratingItems.push(item);
}
}
/**
* @hidden
*/
onMouseEnter(event) {
this.rect = event.target.getBoundingClientRect();
}
/**
* @hidden
*/
onMouseMove(value, event) {
const halfPrecision = this.precision === 'half';
const isFirstHalf = halfPrecision && this.isFirstHalf(this.rect, event.clientX);
this.zone.run(() => this.ratingItems.forEach((item, index) => {
item.title = (halfPrecision && value === index && isFirstHalf) ? String(index + 0.5) : String(index + 1);
item.selected = item.hovered = this.isSelected(index, value + 1);
item.selectedIndicator = this.isSelected(index, this.value);
item.half = (halfPrecision && value === index) ? isFirstHalf : false;
}));
}
/**
* @hidden
*/
onMouseOut() {
this.rect = null;
this.updateRatingItems();
}
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this.cdr.markForCheck();
}
/**
* @hidden
*/
changeValue(index, event) {
const rect = event.target.getBoundingClientRect();
const isFirstHalf = this.isFirstHalf(rect, event.clientX);
const value = (this.precision === 'half' && isFirstHalf) ? index + 0.5 : index + 1;
if (!areSame(this.value, value)) {
this.value = value;
this.ngChange(this.value);
this.valueChange.emit(this.value);
this.updateRatingItems();
this.cdr.markForCheck();
}
}
/**
* @hidden
*/
updateRatingItems() {
this.ratingItems.forEach((item, index) => {
item.title = this.isHalf(index, this.value) ? String(index + 0.5) : String(index + 1);
item.selected = this.isSelected(index, this.value);
item.selectedIndicator = this.isSelected(index, this.value);
item.hovered = false;
item.half = this.isHalf(index, this.value);
});
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
this.updateRatingItems();
this.cdr.markForCheck();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
isSelected(index, value) {
return this.selection === 'single' ? index === Math.ceil(value - 1) : index <= Math.ceil(value - 1);
}
isHalf(index, value) {
return (this.precision === 'half' && (value > index) && (value < index + 1));
}
isFirstHalf(rect, clientX) {
const elementPosition = rect.x + (rect.width / 2);
return this.direction === 'ltr' ? clientX < elementPosition : clientX > elementPosition;
}
onKeyDown(event) {
const decreaseValue = () => {
if (this.value <= 0) {
return;
}
this.value = (this.precision === 'half') ? this.value - 0.5 : this.value - 1;
this.ngChange(this.value);
this.valueChange.emit(this.value);
this.updateRatingItems();
this.cdr.markForCheck();
};
const increaseValue = () => {
if (this.value >= this.itemsCount) {
return;
}
this.value = (this.precision === 'half') ? this.value + 0.5 : this.value + 1;
this.ngChange(this.value);
this.valueChange.emit(this.value);
this.updateRatingItems();
this.cdr.markForCheck();
};
const setMinValue = () => {
if (!areSame(this.value, this.valueMin)) {
this.value = this.valueMin;
this.ngChange(this.value);
this.valueChange.emit(this.value);
this.updateRatingItems();
this.cdr.markForCheck();
}
};
const setMaxValue = () => {
if (!areSame(this.value, this.valueMax)) {
this.value = this.valueMax;
this.ngChange(this.value);
this.valueChange.emit(this.value);
this.updateRatingItems();
this.cdr.markForCheck();
}
};
if (event.keyCode === Keys.ArrowDown) {
decreaseValue();
}
if (event.keyCode === Keys.ArrowLeft) {
if (this.direction === 'ltr') {
decreaseValue();
}
else {
increaseValue();
}
}
if (event.keyCode === Keys.ArrowUp) {
increaseValue();
}
if (event.keyCode === Keys.ArrowRight) {
if (this.direction === 'ltr') {
increaseValue();
}
else {
decreaseValue();
}
}
if (event.keyCode === Keys.Home) {
setMinValue();
}
if (event.keyCode === Keys.End) {
setMaxValue();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RatingComponent, isStandalone: true, selector: "kendo-rating", inputs: { disabled: "disabled", readonly: "readonly", tabindex: "tabindex", itemsCount: "itemsCount", value: "value", selection: "selection", precision: "precision", label: "label", icon: "icon", svgIcon: "svgIcon", svgIconOutline: "svgIconOutline" }, outputs: { valueChange: "valueChange" }, host: { properties: { "attr.aria-disabled": "this.disabled", "class.k-disabled": "this.disabled", "attr.aria-readonly": "this.readonly", "class.k-readonly": "this.readonly", "attr.tabindex": "this.tabindex", "class.k-rating": "this.hostClass", "attr.dir": "this.direction", "attr.aria-invalid": "this.isControlInvalid", "attr.aria-valuemin": "this.valueMin", "attr.aria-valuemax": "this.valueMax", "attr.aria-valuenow": "this.valueNow", "attr.role": "this.ariaRole" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.rating' },
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RatingComponent) /* eslint-disable-line*/
},
{
provide: KendoInput,
useExisting: forwardRef(() => RatingComponent)
}
], queries: [{ propertyName: "itemTemplate", first: true, predicate: RatingItemTemplateDirective, descendants: true }, { propertyName: "hoveredItemTemplate", first: true, predicate: RatingHoveredItemTemplateDirective, descendants: true }, { propertyName: "selectedItemTemplate", first: true, predicate: RatingSelectedItemTemplateDirective, descendants: true }], exportAs: ["kendoRating"], ngImport: i0, template: `
<span class="k-rating-container">
<span
*ngFor="let item of ratingItems; index as i"
class="k-rating-item"
[title]="item.title"
[ngClass]="{
'k-selected': item.selected || item.selectedIndicator,
'k-hover': item.hovered
}"
(mouseenter)="onMouseEnter($event)"
(mouseout)="onMouseOut()"
(click)="changeValue(i, $event)"
>
<ng-container *ngIf="!item.half">
<ng-container *ngIf="!itemTemplate">
<kendo-icon-wrapper
*ngIf="!icon"
size="xlarge"
[name]="item.selected || item.hovered ? 'star' : 'star-outline'"
[svgIcon]="item.selected || item.hovered ? svgIcon : svgIconOutline"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="icon"
size="xlarge"
[name]="item.selected || item.hovered ? icon : icon + '-outline'"
>
</kendo-icon-wrapper>
</ng-container>
<ng-template
*ngIf="itemTemplate && (!item.selected && !item.hovered)"
[ngTemplateOutlet]="itemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
<ng-template
*ngIf="hoveredItemTemplate && item.hovered"
[ngTemplateOutlet]="hoveredItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
<ng-template
*ngIf="selectedItemTemplate && (item.selected && !item.hovered)"
[ngTemplateOutlet]="selectedItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</ng-container>
<ng-container *ngIf="item.half">
<ng-container *ngIf="!itemTemplate">
<span class="k-rating-precision-complement">
<kendo-icon-wrapper
*ngIf="!icon"
size="xlarge"
[name]="'star-outline'"
[svgIcon]="svgIconOutline"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="icon"
size="xlarge"
[name]="icon + '-outline'"
>
</kendo-icon-wrapper>
</span>
<span
class="k-rating-precision-part"
[ngStyle]="{'clipPath': direction === 'rtl' ? 'inset(0 0 0 50%)' : 'inset(0 50% 0 0)'}"
>
<kendo-icon-wrapper
*ngIf="!icon"
size="xlarge"
[name]="'star'"
[svgIcon]="svgIcon"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="icon"
size="xlarge"
[name]="icon"
>
</kendo-icon-wrapper>
</span>
</ng-container>
<span
class="k-rating-precision-complement"
>
<ng-template
[ngTemplateOutlet]="itemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</span>
<span
*ngIf="hoveredItemTemplate && item.hovered"
class="k-rating-precision-part"
[ngStyle]="{'clipPath': direction === 'rtl' ? 'inset(0 0 0 50%)' : 'inset(0 50% 0 0)'}"
>
<ng-template
[ngTemplateOutlet]="hoveredItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</span>
<span
*ngIf="selectedItemTemplate && (item.selected && !item.hovered)"
class="k-rating-precision-part"
[ngStyle]="{'clipPath': direction === 'rtl' ? 'inset(0 0 0 50%)' : 'inset(0 50% 0 0)'}"
>
<ng-template
[ngTemplateOutlet]="selectedItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</span>
<span [style.width.px]="24" [style.height.px]="24" [style.display]="'block'"></span>
</ng-container>
</span>
</span>
<span
*ngIf="label"
class="k-rating-label"
>{{ label }}</span>
`, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoRating',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.rating' },
{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RatingComponent) /* eslint-disable-line*/
},
{
provide: KendoInput,
useExisting: forwardRef(() => RatingComponent)
}
],
selector: 'kendo-rating',
template: `
<span class="k-rating-container">
<span
*ngFor="let item of ratingItems; index as i"
class="k-rating-item"
[title]="item.title"
[ngClass]="{
'k-selected': item.selected || item.selectedIndicator,
'k-hover': item.hovered
}"
(mouseenter)="onMouseEnter($event)"
(mouseout)="onMouseOut()"
(click)="changeValue(i, $event)"
>
<ng-container *ngIf="!item.half">
<ng-container *ngIf="!itemTemplate">
<kendo-icon-wrapper
*ngIf="!icon"
size="xlarge"
[name]="item.selected || item.hovered ? 'star' : 'star-outline'"
[svgIcon]="item.selected || item.hovered ? svgIcon : svgIconOutline"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="icon"
size="xlarge"
[name]="item.selected || item.hovered ? icon : icon + '-outline'"
>
</kendo-icon-wrapper>
</ng-container>
<ng-template
*ngIf="itemTemplate && (!item.selected && !item.hovered)"
[ngTemplateOutlet]="itemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
<ng-template
*ngIf="hoveredItemTemplate && item.hovered"
[ngTemplateOutlet]="hoveredItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
<ng-template
*ngIf="selectedItemTemplate && (item.selected && !item.hovered)"
[ngTemplateOutlet]="selectedItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</ng-container>
<ng-container *ngIf="item.half">
<ng-container *ngIf="!itemTemplate">
<span class="k-rating-precision-complement">
<kendo-icon-wrapper
*ngIf="!icon"
size="xlarge"
[name]="'star-outline'"
[svgIcon]="svgIconOutline"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="icon"
size="xlarge"
[name]="icon + '-outline'"
>
</kendo-icon-wrapper>
</span>
<span
class="k-rating-precision-part"
[ngStyle]="{'clipPath': direction === 'rtl' ? 'inset(0 0 0 50%)' : 'inset(0 50% 0 0)'}"
>
<kendo-icon-wrapper
*ngIf="!icon"
size="xlarge"
[name]="'star'"
[svgIcon]="svgIcon"
>
</kendo-icon-wrapper>
<kendo-icon-wrapper
*ngIf="icon"
size="xlarge"
[name]="icon"
>
</kendo-icon-wrapper>
</span>
</ng-container>
<span
class="k-rating-precision-complement"
>
<ng-template
[ngTemplateOutlet]="itemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</span>
<span
*ngIf="hoveredItemTemplate && item.hovered"
class="k-rating-precision-part"
[ngStyle]="{'clipPath': direction === 'rtl' ? 'inset(0 0 0 50%)' : 'inset(0 50% 0 0)'}"
>
<ng-template
[ngTemplateOutlet]="hoveredItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</span>
<span
*ngIf="selectedItemTemplate && (item.selected && !item.hovered)"
class="k-rating-precision-part"
[ngStyle]="{'clipPath': direction === 'rtl' ? 'inset(0 0 0 50%)' : 'inset(0 50% 0 0)'}"
>
<ng-template
[ngTemplateOutlet]="selectedItemTemplate?.templateRef"
[ngTemplateOutletContext]="{index: i}"
>
</ng-template>
</span>
<span [style.width.px]="24" [style.height.px]="24" [style.display]="'block'"></span>
</ng-container>
</span>
</span>
<span
*ngIf="label"
class="k-rating-label"
>{{ label }}</span>
`,
standalone: true,
imports: [NgFor, NgClass, NgIf, IconWrapperComponent, NgTemplateOutlet, NgStyle]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.LocalizationService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }]; }, propDecorators: { itemTemplate: [{
type: ContentChild,
args: [RatingItemTemplateDirective]
}], hoveredItemTemplate: [{
type: ContentChild,
args: [RatingHoveredItemTemplateDirective]
}], selectedItemTemplate: [{
type: ContentChild,
args: [RatingSelectedItemTemplateDirective]
}], disabled: [{
type: Input
}, {
type: HostBinding,
args: ['attr.aria-disabled']
}, {
type: HostBinding,
args: ['class.k-disabled']
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['attr.aria-readonly']
}, {
type: HostBinding,
args: ['class.k-readonly']
}], tabindex: [{
type: Input
}, {
type: HostBinding,
args: ['attr.tabindex']
}], itemsCount: [{
type: Input
}], value: [{
type: Input
}], selection: [{
type: Input
}], precision: [{
type: Input
}], label: [{
type: Input
}], icon: [{
type: Input
}], svgIcon: [{
type: Input
}], svgIconOutline: [{
type: Input
}], valueChange: [{
type: Output
}], hostClass: [{
type: HostBinding,
args: ['class.k-rating']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], isControlInvalid: [{
type: HostBinding,
args: ['attr.aria-invalid']
}], valueMin: [{
type: HostBinding,
args: ['attr.aria-valuemin']
}], valueMax: [{
type: HostBinding,
args: ['attr.aria-valuemax']
}], valueNow: [{
type: HostBinding,
args: ['attr.aria-valuenow']
}], ariaRole: [{
type: HostBinding,
args: ['attr.role']
}] } });
/**
* @hidden
*/
class SignatureMessages extends ComponentMessages {
/**
* The title of the Clear button of the Signature.
*/
clear;
/**
* The title of the Minimize button of the Signature.
*/
minimize;
/**
* The title of the Maximize button of the Signature.
*/
maximize;
/**
* The value of the Signature canvas element aria-label attribute.
*/
canvasLabel;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SignatureMessages, selector: "kendo-signature-messages-base", inputs: { clear: "clear", minimize: "minimize", maximize: "maximize", canvasLabel: "canvasLabel" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-signature-messages-base'
}]
}], propDecorators: { clear: [{
type: Input
}], minimize: [{
type: Input
}], maximize: [{
type: Input
}], canvasLabel: [{
type: Input
}] } });
/**
* Custom component messages override default component messages.
*/
class SignatureCustomMessagesComponent extends SignatureMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SignatureCustomMessagesComponent, isStandalone: true, selector: "kendo-signature-messages", providers: [
{
provide: SignatureMessages,
useExisting: forwardRef(() => SignatureCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: SignatureMessages,
useExisting: forwardRef(() => SignatureCustomMessagesComponent)
}
],
selector: 'kendo-signature-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Arguments for the `close` event of the Signature component.
*/
class SignatureCloseEvent extends PreventableEvent {
}
/**
* Arguments for the `open` event of the Signature component.
*/
class SignatureOpenEvent extends PreventableEvent {
}
/**
* @hidden
*/
class LocalizedSignatureMessagesDirective extends SignatureMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedSignatureMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedSignatureMessagesDirective, isStandalone: true, selector: "[kendoSignatureLocalizedMessages]", providers: [
{
provide: SignatureMessages,
useExisting: forwardRef(() => LocalizedSignatureMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedSignatureMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: SignatureMessages,
useExisting: forwardRef(() => LocalizedSignatureMessagesDirective)
}
],
selector: '[kendoSignatureLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/* eslint-disable @typescript-eslint/no-explicit-any */
const noop = () => { };
let _id = 0;
const nextId = () => 'k-signature-focusable-' + _id++;
const FOCUSED_CLASS = 'k-focus';
const DEFAULT_SIZE$2 = 'medium';
const DEFAULT_ROUNDED$2 = 'medium';
const DEFAULT_FILL_MODE$2 = 'solid';
const DEFAULT_POPUP_SCALE = 3;
const DEFAULT_EXPORT_SCALE = 2;
const DEFAULT_COLOR = '#000000';
const DEFAULT_BACKGROUND_COLOR = '#ffffff';
const iconsMap = { xIcon, hyperlinkOpenIcon };
/**
* Represents the [Kendo UI Signature component for Angular]({% slug overview_signature %}).
*
* The Signature allows users to add a hand-drawn signature to forms.
*/
class SignatureComponent {
element;
renderer;
ngZone;
cd;
localization;
cdr;
staticHostClasses = true;
/**
* @hidden
*/
focusableId = nextId();
direction;
/**
* Sets the read-only state of the Signature.
*
* @default false
*/
readonly = false;
/**
* Sets the disabled state of the Signature. To disable the component in reactive forms, visit the following [article](slug:formssupport_signature#toc-managing-the-signature-disabled-state-in-reactive-forms)
*
* @default false
*/
disabled = false;
/**
* Sets the width of the signature in pixels.
*
* The width can also be set using inline styles and CSS.
*/
width;
/**
* The height of the signature in pixels.
*
* The height can also be set using inline styles and CSS.
*/
height;
/**
* Gets or sets the value of the signature.
*
* The value is a Base64-encoded PNG image.
*/
set value(value) {
if (value !== this._value) {
this._value = value;
if (this.instance) {
this.instance.loadImage(value);
}
}
}
get value() {
return this._value;
}
/**
* @hidden
*/
svgIcon(name) {
return iconsMap[name];
}
/**
* 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;
}
/**
* The size property specifies the padding of the Signature internal controls
* ([see example]({% slug appearance_signature %}#toc-size)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
size = DEFAULT_SIZE$2;
/**
* The `rounded` property specifies the border radius of the signature
* ([see example](slug:appearance_signature#rounded-corners)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `full` (not supported by the Signature)
* * `none`
*/
rounded = DEFAULT_ROUNDED$2;
/**
* The `fillMode` property specifies the background and border styles of the signature
* ([see example](slug:appearance_signature#toc-fill-mode)).
*
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
fillMode = DEFAULT_FILL_MODE$2;
/**
* The stroke color of the signature.
*
* Accepts CSS color names and hex values.
*
* The default value is determined by the theme `$kendo-input-text` variable.
*/
color;
/**
* The background color of the signature.
*
* Accepts CSS color names and hex values.
*
* The default value is determined by the theme `$kendo-input-bg` variable.
*/
backgroundColor;
/**
* The stroke width of the signature.
*
* @default 1
*/
strokeWidth = 1;
/**
* A flag indicating whether to smooth out signature lines.
*
* @default false
*/
smooth = false;
/**
* A flag indicating if the signature can be maximized.
*
* @default true
*/
maximizable = true;
/**
* @hidden
*/
maximized = false;
/**
* The scale factor for the popup.
*
* The Signature width and height will be multiplied by the scale when showing the popup.
*
* @default 3
*/
popupScale = DEFAULT_POPUP_SCALE;
/**
* The scale factor for the exported image.
*
* The Signature width and height will be multiplied by the scale when converting the signature to an image.
*
* @default 2
*/
exportScale = DEFAULT_EXPORT_SCALE;
/**
* @hidden
*/
parentLocalization;
/**
* A flag indicating whether the dotted line should be displayed in the background.
*
* @default false
*/
hideLine = false;
/**
* Fires each time the signature value is changed.
*/
valueChange = new EventEmitter();
/**
* Fires each time the popup is about to open.
* This event is preventable. If you cancel it, the popup will remain closed.
*/
open = new EventEmitter();
/**
* Fires each time the popup is about to close.
* This event is preventable. If you cancel it, the popup will remain open.
*/
close = new EventEmitter();
/**
* Fires each time Signature is focused.
*/
onFocus = new EventEmitter();
/**
* Fires each time the Signature is blurred.
*/
onBlur = new EventEmitter();
/**
* @hidden
*/
minimize = new EventEmitter();
canvas;
minimizeButton;
maximizeButton;
/**
* Indicates whether the Signature wrapper is focused.
*/
isFocused = false;
/**
* Indicates whether the Signature popup is open.
*/
isOpen;
/**
* @hidden
*/
get isEmpty() {
return !this.value;
}
/**
* @hidden
*/
get canvasLabel() {
return this.getMessage('canvasLabel');
}
/**
* @hidden
*/
get clearTitle() {
return this.getMessage('clear');
}
/**
* @hidden
*/
get minimizeTitle() {
return this.getMessage('minimize');
}
/**
* @hidden
*/
get maximizeTitle() {
return this.getMessage('maximize');
}
/**
* @hidden
*/
get baseWidth() {
return this.width || this.element.nativeElement.offsetWidth;
}
/**
* @hidden
*/
get baseHeight() {
return this.height || this.element.nativeElement.offsetHeight;
}
/**
* @hidden
*/
get popupWidth() {
return this.baseWidth * this.popupScale;
}
/**
* @hidden
*/
get popupHeight() {
return this.baseHeight * this.popupScale;
}
/**
* @hidden
*/
isDrawing = false;
/**
* @hidden
*/
get showMaximize() {
return !(this.maximized || this.isDrawing || !this.maximizable || this.disabled);
}
/**
* @hidden
*/
get showMinimize() {
return this.maximized && !this.isDrawing;
}
/**
* @hidden
*/
get showClear() {
return !(this.isEmpty || this.isDrawing || this.readonly || this.disabled);
}
/**
* @hidden
*/
get focused() {
return this.isFocused;
}
set focused(value) {
if (this.isFocused !== value && this.element) {
const wrap = this.element.nativeElement;
if (value && !this.maximized) {
this.renderer.addClass(wrap, FOCUSED_CLASS);
}
else {
this.renderer.removeClass(wrap, FOCUSED_CLASS);
}
this.isFocused = value;
}
}
get options() {
return {
scale: this.maximized ? this.popupScale : 1,
color: this.color,
backgroundColor: this.backgroundColor,
strokeWidth: this.strokeWidth,
smooth: this.smooth,
readonly: this.readonly
};
}
notifyNgTouched = noop;
notifyNgChanged = noop;
instance;
_value;
_tabindex = 0;
subscriptions;
unsubscribe;
hostClasses = [];
constructor(element, renderer, ngZone, cd, localization, cdr) {
this.element = element;
this.renderer = renderer;
this.ngZone = ngZone;
this.cd = cd;
this.localization = localization;
this.cdr = cdr;
validatePackage(packageMetadata);
this.direction = localization.rtl ? 'rtl' : 'ltr';
}
ngOnInit() {
this.subscriptions = this.localization
.changes
.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
}
ngAfterViewInit() {
if (!isDocumentAvailable()) {
return;
}
this.applyHostClasses();
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.readThemeColors();
this.instance.setOptions(this.options);
});
this.ngZone.runOutsideAngular(() => {
const element = this.canvas.nativeElement;
this.instance = new SignaturePad(element, {
...this.options,
onChange: () => this.onValueChange(),
onDraw: () => this.onDraw(),
onDrawEnd: () => this.onDrawEnd()
});
if (this.value) {
this.instance.loadImage(this.value);
}
if (this.maximized) {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.minimizeButton?.nativeElement.focus();
});
}
this.addEventListeners();
});
}
ngOnChanges(changes) {
if (anyChanged(['readonly', 'color', 'backgroundColor', 'strokeWidth', 'smooth'], changes, true)) {
this.instance.setOptions(this.options);
}
this.applyHostClasses();
}
ngOnDestroy() {
if (this.instance) {
this.instance.destroy();
this.instance = null;
}
if (this.subscriptions) {
this.subscriptions.unsubscribe();
this.subscriptions = null;
}
if (this.unsubscribe) {
this.unsubscribe();
this.unsubscribe = null;
}
}
/**
* @hidden
*/
onClear() {
this.reset();
this.valueChange.emit(undefined);
this.canvas.nativeElement.focus();
}
/**
* @hidden
*/
async onValueChange() {
const value = await this.instance.exportImage({
width: this.baseWidth * this.exportScale,
height: this.baseHeight * this.exportScale
});
this._value = value;
this.cd.markForCheck();
this.ngZone.run(() => {
this.valueChange.emit(value);
this.notifyNgChanged(value);
});
}
/**
* @hidden
*/
onDialogValueChange(value) {
this.value = value;
this.valueChange.emit(value);
this.notifyNgTouched();
this.notifyNgChanged(value);
}
/**
* @hidden
*/
onDialogClick(e) {
if (e.target.classList.contains('k-overlay')) {
this.isOpen = false;
this.maximizeButton?.nativeElement.focus();
}
}
/**
* @hidden
*/
onDialogKeydown(e) {
if (e.keyCode === Keys.Escape) {
this.isOpen = false;
this.cd.detectChanges();
this.maximizeButton?.nativeElement.focus();
}
}
/**
* @hidden
*/
onDialogClose() {
const args = new SignatureCloseEvent();
this.close.next(args);
if (!args.isDefaultPrevented()) {
this.isOpen = false;
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
(this.maximizeButton || this.element)?.nativeElement?.focus();
});
}
}
/**
* Clears the value of the Signature.
*/
reset() {
if (!isPresent(this.value)) {
return;
}
this.instance?.clear();
this.value = this._value = undefined;
this.notifyNgChanged(undefined);
}
/**
* Toggles the popup of the Signature.
* 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) {
if (this.disabled || this.readonly) {
return;
}
open = isPresent(open) ? open : !this.isOpen;
this.isOpen = open;
}
/**
* @hidden
*/
async onMaximize() {
const args = new SignatureOpenEvent();
this.open.next(args);
if (!args.isDefaultPrevented()) {
this.popupValue = await this.instance.exportImage({
width: this.popupWidth * this.exportScale,
height: this.popupHeight * this.exportScale
});
this.isOpen = true;
this.cd.detectChanges();
}
}
/**
* @hidden
*/
onMinimize() {
this.minimize.next();
}
applyHostClasses() {
const classList = this.element.nativeElement.classList;
this.hostClasses.forEach(([name]) => classList.remove(name));
this.hostClasses = [
[`k-signature-${SIZE_MAP[this.size || DEFAULT_SIZE$2]}`, !isNone(this.size)],
[`k-input-${this.fillMode || DEFAULT_FILL_MODE$2}`, !isNone(this.fillMode)],
[`k-rounded-${ROUNDED_MAP[this.rounded || DEFAULT_ROUNDED$2]}`, !isNone(this.rounded)]
];
this.hostClasses.forEach(([name, enabled]) => classList.toggle(name, enabled));
}
readThemeColors() {
let defaultColor = DEFAULT_COLOR;
let defaultBackgroundColor = DEFAULT_BACKGROUND_COLOR;
if (isDocumentAvailable()) {
const el = this.element.nativeElement;
defaultColor = getComputedStyle(el).color;
defaultBackgroundColor = getComputedStyle(el).backgroundColor;
}
this.color = this.color || defaultColor;
this.backgroundColor = this.backgroundColor || defaultBackgroundColor;
}
/**
* Focuses the wrapper of the Signature.
*/
focus() {
this.focused = true;
this.element.nativeElement.focus();
}
/**
* @hidden
*/
onWrapperFocus() {
if (this.focused) {
return;
}
this.ngZone.run(() => {
this.focus();
this.onFocus.emit();
});
}
/**
* Blurs the Signature.
*/
blur() {
this.focused = false;
this.element.nativeElement.blur();
this.notifyNgTouched();
}
/**
* @hidden
*/
onWrapperBlur() {
if (this.isOpen) {
return;
}
this.ngZone.run(() => {
this.onBlur.emit();
this.focused = false;
this.notifyNgTouched();
});
}
/**
* @hidden
*/
onWrapperClick(_event) {
if (this.disabled) {
return;
}
this.focus();
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
}
/**
* @hidden
*/
registerOnChange(fn) {
this.notifyNgChanged = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.notifyNgTouched = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this.cdr.markForCheck();
}
/**
* @hidden
*/
popupValue;
onDraw() {
this.isDrawing = true;
this.cd.markForCheck();
}
onDrawEnd() {
this.isDrawing = false;
this.cd.markForCheck();
}
addEventListeners() {
const element = this.element.nativeElement;
const focusIn = this.renderer.listen(element, 'focusin', () => this.onWrapperFocus());
const focusOut = this.renderer.listen(element, 'focusout', (e) => {
const insideWrapper = closest$1(e.relatedTarget, element => element === this.element.nativeElement);
if (!insideWrapper) {
this.onWrapperBlur();
}
});
const click = this.renderer.listen(element, 'click', () => {
this.ngZone.run((e) => {
this.onWrapperClick(e);
});
});
this.unsubscribe = () => {
focusIn();
focusOut();
click();
};
}
getMessage(key) {
if (this.maximized && this.parentLocalization) {
return this.parentLocalization.get(key);
}
return this.localization.get(key);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SignatureComponent, isStandalone: true, selector: "kendo-signature", inputs: { focusableId: "focusableId", readonly: "readonly", disabled: "disabled", width: "width", height: "height", value: "value", tabindex: "tabindex", size: "size", rounded: "rounded", fillMode: "fillMode", color: "color", backgroundColor: "backgroundColor", strokeWidth: "strokeWidth", smooth: "smooth", maximizable: "maximizable", maximized: "maximized", popupScale: "popupScale", exportScale: "exportScale", parentLocalization: "parentLocalization", hideLine: "hideLine" }, outputs: { valueChange: "valueChange", open: "open", close: "close", onFocus: "focus", onBlur: "blur", minimize: "minimize" }, host: { properties: { "class.k-signature": "this.staticHostClasses", "class.k-input": "this.staticHostClasses", "attr.dir": "this.direction", "class.k-readonly": "this.readonly", "class.k-disabled": "this.disabled", "style.width.px": "this.width", "style.height.px": "this.height" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.signature' },
{ multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SignatureComponent) }
], viewQueries: [{ propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true }, { propertyName: "minimizeButton", first: true, predicate: ["minimize"], descendants: true, read: ElementRef }, { propertyName: "maximizeButton", first: true, predicate: ["maximize"], descendants: true, read: ElementRef }], exportAs: ["kendoSignature"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoSignatureLocalizedMessages
i18n-clear="kendo.signature.clear|The message for the Clear button."
clear="Clear"
i18n-maximize="kendo.signature.maximize|The message for the Maximize button."
maximize="Maximize"
i18n-minimize="kendo.signature.minimize|The message for the Minimize button."
minimize="Minimize"
i18n-canvasLabel="kendo.signature.canvasLabel|The message for the Canvas element aria-label."
canvasLabel="Signature canvas">
</ng-container>
<div
#canvas
class="k-signature-canvas"
[attr.tabindex]="tabindex"
[id]="focusableId"
role="img"
[attr.aria-label]="canvasLabel"
></div>
<div class="k-signature-actions k-signature-actions-top">
<button
#maximize
*ngIf="showMaximize"
kendoButton
type="button"
class="k-signature-action k-signature-maximize"
icon="hyperlink-open"
[svgIcon]="svgIcon('hyperlinkOpenIcon')"
fillMode="flat"
[size]="size"
(click)="onMaximize()"
[attr.aria-label]="maximizeTitle"
[title]="maximizeTitle">
</button>
<button
#minimize
*ngIf="showMinimize"
kendoButton
type="button"
class="k-signature-action k-signature-minimize k-rotate-180"
icon="hyperlink-open"
[svgIcon]="svgIcon('hyperlinkOpenIcon')"
fillMode="flat"
[size]="size"
(click)="onMinimize()"
[attr.aria-label]="minimizeTitle"
[title]="minimizeTitle">
</button>
</div>
<div
*ngIf="!hideLine"
class="k-signature-line"
></div>
<div class="k-signature-actions k-signature-actions-bottom">
<button
*ngIf="showClear"
kendoButton
class="k-signature-action k-signature-clear"
icon="close"
type="button"
[svgIcon]="svgIcon('xIcon')"
fillMode="flat"
[size]="size"
[attr.aria-label]="clearTitle"
[title]="clearTitle"
(click)="onClear()" >
</button>
</div>
<kendo-dialog
*ngIf="isOpen"
autoFocusedElement=".k-signature-action.k-signature-minimize"
(click)="onDialogClick($event)"
(keydown)="onDialogKeydown($event)">
<kendo-signature
[readonly]="readonly"
[disabled]="disabled"
[size]="size"
[rounded]="rounded"
[fillMode]="fillMode"
[color]="color"
[backgroundColor]="backgroundColor"
[strokeWidth]="strokeWidth"
[smooth]="smooth"
[value]="popupValue"
(valueChange)="onDialogValueChange($event)"
[hideLine]="hideLine"
[class.k-signature-maximized]="true"
[maximized]="true"
(minimize)="onDialogClose()"
[width]="popupWidth"
[height]="popupHeight"
[popupScale]="popupScale"
[exportScale]="(1 / popupScale) * exportScale"
[parentLocalization]="localization">
</kendo-signature>
</kendo-dialog>
`, isInline: true, dependencies: [{ kind: "component", type: SignatureComponent, selector: "kendo-signature", inputs: ["focusableId", "readonly", "disabled", "width", "height", "value", "tabindex", "size", "rounded", "fillMode", "color", "backgroundColor", "strokeWidth", "smooth", "maximizable", "maximized", "popupScale", "exportScale", "parentLocalization", "hideLine"], outputs: ["valueChange", "open", "close", "focus", "blur", "minimize"], exportAs: ["kendoSignature"] }, { kind: "directive", type: LocalizedSignatureMessagesDirective, selector: "[kendoSignatureLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: DialogComponent, selector: "kendo-dialog", inputs: ["actions", "actionsLayout", "autoFocusedElement", "title", "width", "minWidth", "maxWidth", "height", "minHeight", "maxHeight", "animation", "themeColor"], outputs: ["action", "close"], exportAs: ["kendoDialog"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoSignature',
selector: 'kendo-signature',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.signature' },
{ multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SignatureComponent) }
],
template: `
<ng-container kendoSignatureLocalizedMessages
i18n-clear="kendo.signature.clear|The message for the Clear button."
clear="Clear"
i18n-maximize="kendo.signature.maximize|The message for the Maximize button."
maximize="Maximize"
i18n-minimize="kendo.signature.minimize|The message for the Minimize button."
minimize="Minimize"
i18n-canvasLabel="kendo.signature.canvasLabel|The message for the Canvas element aria-label."
canvasLabel="Signature canvas">
</ng-container>
<div
#canvas
class="k-signature-canvas"
[attr.tabindex]="tabindex"
[id]="focusableId"
role="img"
[attr.aria-label]="canvasLabel"
></div>
<div class="k-signature-actions k-signature-actions-top">
<button
#maximize
*ngIf="showMaximize"
kendoButton
type="button"
class="k-signature-action k-signature-maximize"
icon="hyperlink-open"
[svgIcon]="svgIcon('hyperlinkOpenIcon')"
fillMode="flat"
[size]="size"
(click)="onMaximize()"
[attr.aria-label]="maximizeTitle"
[title]="maximizeTitle">
</button>
<button
#minimize
*ngIf="showMinimize"
kendoButton
type="button"
class="k-signature-action k-signature-minimize k-rotate-180"
icon="hyperlink-open"
[svgIcon]="svgIcon('hyperlinkOpenIcon')"
fillMode="flat"
[size]="size"
(click)="onMinimize()"
[attr.aria-label]="minimizeTitle"
[title]="minimizeTitle">
</button>
</div>
<div
*ngIf="!hideLine"
class="k-signature-line"
></div>
<div class="k-signature-actions k-signature-actions-bottom">
<button
*ngIf="showClear"
kendoButton
class="k-signature-action k-signature-clear"
icon="close"
type="button"
[svgIcon]="svgIcon('xIcon')"
fillMode="flat"
[size]="size"
[attr.aria-label]="clearTitle"
[title]="clearTitle"
(click)="onClear()" >
</button>
</div>
<kendo-dialog
*ngIf="isOpen"
autoFocusedElement=".k-signature-action.k-signature-minimize"
(click)="onDialogClick($event)"
(keydown)="onDialogKeydown($event)">
<kendo-signature
[readonly]="readonly"
[disabled]="disabled"
[size]="size"
[rounded]="rounded"
[fillMode]="fillMode"
[color]="color"
[backgroundColor]="backgroundColor"
[strokeWidth]="strokeWidth"
[smooth]="smooth"
[value]="popupValue"
(valueChange)="onDialogValueChange($event)"
[hideLine]="hideLine"
[class.k-signature-maximized]="true"
[maximized]="true"
(minimize)="onDialogClose()"
[width]="popupWidth"
[height]="popupHeight"
[popupScale]="popupScale"
[exportScale]="(1 / popupScale) * exportScale"
[parentLocalization]="localization">
</kendo-signature>
</kendo-dialog>
`,
standalone: true,
imports: [LocalizedSignatureMessagesDirective, NgIf, ButtonComponent, DialogComponent]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1.LocalizationService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { staticHostClasses: [{
type: HostBinding,
args: ['class.k-signature']
}, {
type: HostBinding,
args: ['class.k-input']
}], focusableId: [{
type: Input
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], readonly: [{
type: HostBinding,
args: ['class.k-readonly']
}, {
type: Input
}], disabled: [{
type: HostBinding,
args: ['class.k-disabled']
}, {
type: Input
}], width: [{
type: Input
}, {
type: HostBinding,
args: ['style.width.px']
}], height: [{
type: Input
}, {
type: HostBinding,
args: ['style.height.px']
}], value: [{
type: Input
}], tabindex: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], color: [{
type: Input
}], backgroundColor: [{
type: Input
}], strokeWidth: [{
type: Input
}], smooth: [{
type: Input
}], maximizable: [{
type: Input
}], maximized: [{
type: Input
}], popupScale: [{
type: Input
}], exportScale: [{
type: Input
}], parentLocalization: [{
type: Input
}], hideLine: [{
type: Input
}], valueChange: [{
type: Output
}], open: [{
type: Output
}], close: [{
type: Output
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], minimize: [{
type: Output
}], canvas: [{
type: ViewChild,
args: ['canvas']
}], minimizeButton: [{
type: ViewChild,
args: ['minimize', { read: ElementRef }]
}], maximizeButton: [{
type: ViewChild,
args: ['maximize', { read: ElementRef }]
}] } });
/**
* Custom component messages override default component messages.
*/
class SliderCustomMessagesComponent extends SliderMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SliderCustomMessagesComponent, isStandalone: true, selector: "kendo-slider-messages", providers: [
{
provide: SliderMessages,
useExisting: forwardRef(() => SliderCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: SliderMessages,
useExisting: forwardRef(() => SliderCustomMessagesComponent)
}
],
selector: 'kendo-slider-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Custom component messages override default component messages.
*/
class SwitchCustomMessagesComponent extends Messages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SwitchCustomMessagesComponent, isStandalone: true, selector: "kendo-switch-messages", providers: [
{
provide: Messages,
useExisting: forwardRef(() => SwitchCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: Messages,
useExisting: forwardRef(() => SwitchCustomMessagesComponent)
}
],
selector: 'kendo-switch-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Specifies the adornments in the prefix container ([see example]({% slug textarea_adornments %})).
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textarea>
* <kendo-textarea-prefix>
* <button kendoButton look="clear" icon="image"></button>
* </kendo-textarea-prefix>
* </kendo-textarea>
* `
* })
* class AppComponent {}
* ```
*/
class TextAreaPrefixComponent {
/**
* @hidden
*/
flow = 'vertical';
/**
* @hidden
*/
orientation = 'horizontal';
hostClass = true;
get verticalOrientation() {
return this.orientation === 'vertical';
}
get horizontalOrientation() {
return this.orientation === 'horizontal';
}
get alignItems() {
return this.flow === this.orientation;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaPrefixComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TextAreaPrefixComponent, isStandalone: true, selector: "kendo-textarea-prefix", inputs: { flow: "flow", orientation: "orientation" }, host: { properties: { "class.k-input-prefix": "this.hostClass", "class.k-input-prefix-vertical": "this.verticalOrientation", "class.k-input-prefix-horizontal": "this.horizontalOrientation", "class.!k-align-items-start": "this.alignItems" } }, exportAs: ["kendoTextAreaPrefix"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaPrefixComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoTextAreaPrefix',
selector: 'kendo-textarea-prefix',
template: `<ng-content></ng-content>`,
standalone: true
}]
}], propDecorators: { flow: [{
type: Input
}], orientation: [{
type: Input
}], hostClass: [{
type: HostBinding,
args: ['class.k-input-prefix']
}], verticalOrientation: [{
type: HostBinding,
args: ['class.k-input-prefix-vertical']
}], horizontalOrientation: [{
type: HostBinding,
args: ['class.k-input-prefix-horizontal']
}], alignItems: [{
type: HostBinding,
args: ['class.!k-align-items-start']
}] } });
/**
* Specifies the adornments in the suffix container ([see example]({% slug textarea_adornments %})).
* ```ts-no-run
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textarea>
* <kendo-textarea-suffix>
* <button kendoButton look="clear" icon="image"></button>
* </kendo-textarea-suffix>
* </kendo-textarea>
* `
* })
* class AppComponent {}
* ```
*/
class TextAreaSuffixComponent {
/**
* @hidden
*/
flow = 'vertical';
/**
* @hidden
*/
orientation = 'horizontal';
hostClass = true;
get verticalOrientation() {
return this.orientation === 'vertical';
}
get horizontalOrientation() {
return this.orientation === 'horizontal';
}
get alignItems() {
return this.flow === this.orientation;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaSuffixComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TextAreaSuffixComponent, isStandalone: true, selector: "kendo-textarea-suffix", inputs: { flow: "flow", orientation: "orientation" }, host: { properties: { "class.k-input-suffix": "this.hostClass", "class.k-input-suffix-vertical": "this.verticalOrientation", "class.k-input-suffix-horizontal": "this.horizontalOrientation", "class.!k-align-items-start": "this.alignItems" } }, exportAs: ["kendoTextAreaSuffix"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaSuffixComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoTextAreaSuffix',
selector: 'kendo-textarea-suffix',
template: `<ng-content></ng-content>`,
standalone: true
}]
}], propDecorators: { flow: [{
type: Input
}], orientation: [{
type: Input
}], hostClass: [{
type: HostBinding,
args: ['class.k-input-suffix']
}], verticalOrientation: [{
type: HostBinding,
args: ['class.k-input-suffix-vertical']
}], horizontalOrientation: [{
type: HostBinding,
args: ['class.k-input-suffix-horizontal']
}], alignItems: [{
type: HostBinding,
args: ['class.!k-align-items-start']
}] } });
/**
* @hidden
*/
class TextFieldsBase {
localizationService;
ngZone;
changeDetector;
renderer;
injector;
hostElement;
/**
* Sets the `title` attribute of the internal textarea input element of the component.
*/
title = '';
/**
* Sets the disabled state of the TextArea component. To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_textarea#toc-managing-the-textarea-disabled-state-in-reactive-forms).
*
* @default false
*/
disabled = false;
/**
* Sets the read-only state of the TextArea component.
*
* @default false
*/
readonly = false;
/**
* Provides a value for the TextArea component.
*/
value = null;
/**
* Determines whether the whole value will be selected when the TextArea is clicked. Defaults to `false`.
*
* @default false
*/
selectOnFocus = false;
/**
* The hint, which is displayed when the Textarea is empty.
*/
placeholder;
/**
* Fires each time the user focuses the internal textarea element of the component.
* This event is useful when you need to distinguish between focusing the textarea element and focusing one of its adornments.
*/
inputFocus = new EventEmitter();
/**
* Fires each time the internal textarea element gets blurred.
* This event is useful when adornments are used, in order to distinguish between blurring the textarea element and blurring the whole TextArea component.
*/
inputBlur = new EventEmitter();
/**
* Represents the visible textarea element of the component.
*/
input;
get disabledClass() {
return this.disabled;
}
direction;
/**
* @hidden
*/
control;
subscriptions = new Subscription();
_isFocused = false;
focusChangedProgrammatically = false;
constructor(localizationService, ngZone, changeDetector, renderer, injector, hostElement) {
this.localizationService = localizationService;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.renderer = renderer;
this.injector = injector;
this.hostElement = hostElement;
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
/**
* @hidden
*/
handleInputBlur = () => {
this.changeDetector.markForCheck();
if (hasObservers(this.inputBlur) || requiresZoneOnBlur(this.control)) {
this.ngZone.run(() => {
this.ngTouched();
this.inputBlur.emit();
});
}
};
/**
* @hidden
* Called when the status of the component changes to or from `disabled`.
* Depending on the value, it enables or disables the appropriate DOM element.
*
* @param isDisabled
*/
setDisabledState(isDisabled) {
this.changeDetector.markForCheck();
this.disabled = isDisabled;
}
ngChange = (_) => { };
ngTouched = () => { };
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextFieldsBase, deps: [{ token: i1.LocalizationService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.Injector }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TextFieldsBase, selector: "kendo-textfield-base", inputs: { title: "title", disabled: "disabled", readonly: "readonly", value: "value", selectOnFocus: "selectOnFocus", placeholder: "placeholder" }, outputs: { inputFocus: "inputFocus", inputBlur: "inputBlur" }, host: { properties: { "class.k-readonly": "this.readonly", "class.k-disabled": "this.disabledClass", "attr.dir": "this.direction" } }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }], ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextFieldsBase, decorators: [{
type: Component,
args: [{
selector: 'kendo-textfield-base',
template: ``
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i0.Injector }, { type: i0.ElementRef }]; }, propDecorators: { title: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-readonly']
}], value: [{
type: Input
}], selectOnFocus: [{
type: Input
}], placeholder: [{
type: Input
}], inputFocus: [{
type: Output
}], inputBlur: [{
type: Output
}], input: [{
type: ViewChild,
args: ['input', { static: true }]
}], disabledClass: [{
type: HostBinding,
args: ['class.k-disabled']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}] } });
const resizeClasses = {
'vertical': 'k-resize-y',
'horizontal': 'k-resize-x',
'both': 'k-resize',
'none': 'k-resize-none',
'auto': 'k-resize-none'
};
const FOCUSED = 'k-focus';
const DEFAULT_SIZE$1 = 'medium';
const DEFAULT_ROUNDED$1 = 'medium';
const DEFAULT_FILL_MODE$1 = 'solid';
/**
* Represents the [Kendo UI TextArea component for Angular]({% slug overview_textarea %}).
*/
class TextAreaComponent extends TextFieldsBase {
localizationService;
ngZone;
changeDetector;
renderer;
injector;
hostElement;
/**
* @hidden
*/
focusableId = `k-${guid()}`;
hostClasses = true;
get flowCol() {
return this.flow === 'vertical';
}
get flowRow() {
return this.flow === 'horizontal';
}
_flow = 'vertical';
/**
* Specifies the flow direction of the TextArea sections. This property is useful when adornments are used, in order to specify
* their position in relation to the textarea element.
*
* The possible values are:
* * `vertical`(Default) —TextArea sections are placed from top to bottom.
* * `horizontal`—TextArea sections are placed from left to right in `ltr`, and from right to left in `rtl` mode.
*/
set flow(flow) {
this._flow = flow;
if (this.prefix) {
this.prefix.flow = flow;
}
if (this.suffix) {
this.suffix.flow = flow;
}
}
get flow() {
return this._flow;
}
/**
* Sets the HTML attributes of the inner focusable input element. Attributes which are essential for certain component functionalities cannot be changed.
*/
set inputAttributes(attributes) {
if (isObjectPresent(this.parsedAttributes)) {
removeHTMLAttributes(this.parsedAttributes, this.renderer, this.input.nativeElement);
}
this._inputAttributes = attributes;
this.parsedAttributes = this.inputAttributes ?
parseAttributes(this.inputAttributes, this.defaultAttributes) :
this.inputAttributes;
this.setInputAttributes();
}
get inputAttributes() {
return this._inputAttributes;
}
/**
* Specifies the orientation of the TextArea adornments. This property is used in order to specify
* the adornments' position relative to themselves.
*
* The possible values are:
* * `horizontal`(Default) —TextArea adornments are placed from left to right in `ltr`, and from right to left in `rtl` mode.
* * `vertical`—TextArea adornments are placed from top to bottom.
*/
set adornmentsOrientation(orientation) {
this._adornmentsOrientation = orientation;
if (this.prefix) {
this.prefix.orientation = orientation;
}
if (this.suffix) {
this.suffix.orientation = orientation;
}
}
get adornmentsOrientation() {
return this._adornmentsOrientation;
}
/**
* Specifies the visible height of the textarea element in lines.
*/
rows;
/**
* Specifies the visible width of the textarea element (in average character width).
*/
cols;
/**
* Specifies the maximum number of characters that the user can enter in the TextArea component.
*/
maxlength;
/**
* Specifies the [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*/
tabindex = 0;
/**
* @hidden
*/
set tabIndex(tabIndex) {
this.tabindex = tabIndex;
}
get tabIndex() {
return this.tabindex;
}
/**
* Configures the resize behavior of the TextArea.
*
* The possible values are:
* * `vertical`(Default)—The TextArea component can be resized only vertically.
* * `horizontal`—The TextArea component can be resized only horizontally.
* * `both`—The TextArea component can be resized in both (horizontal and vertical) directions.
* * `auto`—Specifies whether the TextArea component will adjust its height automatically, based on the content.
* * `none`—The TextArea cannot be resized.
*
*/
resizable = 'vertical';
/**
* The size property specifies the padding of the internal textarea element
* ([see example]({% slug appearance_textarea %}#toc-size)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size ? size : DEFAULT_SIZE$1;
this.handleClasses(newSize, 'size');
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The `rounded` property specifies the border radius of the TextArea
* ([see example](slug:appearance_textarea#toc-roundness)).
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set rounded(rounded) {
const newRounded = rounded ? rounded : DEFAULT_ROUNDED$1;
this.handleClasses(newRounded, 'rounded');
this._rounded = newRounded;
}
get rounded() {
return this._rounded;
}
/**
* The `fillMode` property specifies the background and border styles of the TextArea
* ([see example](slug:appearance_textarea#toc-fill-mode)).
*
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
set fillMode(fillMode) {
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE$1;
this.handleClasses(newFillMode, 'fillMode');
this._fillMode = newFillMode;
}
get fillMode() {
return this._fillMode;
}
/**
* Specifies whether the prefix separator of the TextArea is rendered.
* If a prefix template is not declared, the separator will not be rendered, regardless of the parameter value.
*
* @default false
*/
showPrefixSeparator = false;
/**
* Specifies whether the suffix separator of the TextArea is rendered.
* If a suffix template is not declared, the separator will not be rendered, regardless of the parameter value.
*
* @default false
*/
showSuffixSeparator = false;
/**
* Fires each time the user focuses the TextArea component.
*
* > To wire the event programmatically, use the `onFocus` property.
*
* @example
* ```ts
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textarea (focus)="handleFocus()"></kendo-textarea>
* `
* })
* class AppComponent {
* public handleFocus(): void {
* console.log('Component is focused.');
* }
* }
* ```
*/
onFocus = new EventEmitter();
/**
* Fires each time the TextArea component gets blurred.
*
* > To wire the event programmatically, use the `onBlur` property.
*
* @example
* ```ts
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-textarea (blur)="handleBlur()"></kendo-textarea>
* `
* })
* class AppComponent {
* public handleBlur(): void {
* console.log('Component is blurred');
* }
* }
* ```
*/
onBlur = new EventEmitter();
/**
* Fires each time the value is changed or the component is blurred
* ([see example](slug:events_textarea)).
* When the component value is changed programmatically or via its form control binding, the valueChange event is not emitted.
*/
valueChange = new EventEmitter();
initialHeight;
resizeSubscription;
_size = 'medium';
_rounded = 'medium';
_fillMode = 'solid';
_adornmentsOrientation = 'horizontal';
_inputAttributes;
parsedAttributes = {};
get defaultAttributes() {
return {
id: this.focusableId,
disabled: this.disabled ? '' : null,
readonly: this.readonly ? '' : null,
tabindex: this.disabled ? undefined : this.tabIndex,
placeholder: this.placeholder,
title: this.title,
maxlength: this.maxlength,
rows: this.rows,
cols: this.cols,
'aria-disabled': this.disabled ? true : undefined,
'aria-readonly': this.readonly ? true : undefined,
'aria-invalid': this.isControlInvalid,
required: this.isControlRequired ? '' : null
};
}
get mutableAttributes() {
return {
'aria-multiline': 'true'
};
}
constructor(localizationService, ngZone, changeDetector, renderer, injector, hostElement) {
super(localizationService, ngZone, changeDetector, renderer, injector, hostElement);
this.localizationService = localizationService;
this.ngZone = ngZone;
this.changeDetector = changeDetector;
this.renderer = renderer;
this.injector = injector;
this.hostElement = hostElement;
validatePackage(packageMetadata);
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
}
ngAfterViewInit() {
this.ngZone.runOutsideAngular(() => {
this.handleFlow();
});
const stylingInputs = ['size', 'rounded', 'fillMode'];
stylingInputs.forEach(input => {
this.handleClasses(this[input], input);
});
}
ngOnInit() {
this.control = this.injector.get(NgControl, null);
if (isDocumentAvailable() && this.resizable === 'auto') {
this.resizeSubscription = fromEvent(window, 'resize')
.pipe((debounceTime(50)))
.subscribe(() => this.resize());
}
if (this.hostElement) {
this.renderer.removeAttribute(this.hostElement.nativeElement, "tabindex");
}
this.subscriptions = this.localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
}
ngOnChanges(changes) {
const hostElement = this.hostElement.nativeElement;
const element = this.input.nativeElement;
if (changes.flow) {
this.handleFlow();
}
if (changes.resizable) {
if (this.resizable === 'auto') {
this.renderer.removeClass(element, '\!k-overflow-y-auto');
this.initialHeight = element.offsetHeight;
}
else if (this.resizable !== 'both') {
this.renderer.addClass(element, '\!k-overflow-y-auto');
element.style.height = `${this.initialHeight}px`;
}
}
if (changes.cols) {
if (isPresent(changes.cols.currentValue)) {
this.renderer.setStyle(hostElement, 'width', 'auto');
}
else {
this.renderer.removeStyle(hostElement, 'width');
}
}
if (changes.value) {
this.resize();
}
}
/**
* @hidden
*/
prefix;
/**
* @hidden
*/
suffix;
/**
* @hidden
*/
writeValue(value) {
this.value = value;
this.resize();
this.changeDetector.markForCheck();
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
updateValue(value) {
if (!areSame(this.value, value)) {
this.ngZone.run(() => {
this.value = value;
this.ngChange(value);
this.valueChange.emit(value);
this.changeDetector.markForCheck();
});
}
}
ngOnDestroy() {
super.ngOnDestroy();
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
}
/**
* @hidden
*/
get resizableClass() {
return resizeClasses[this.resizable];
}
/**
* @hidden
*/
get isControlInvalid() {
return this.control && this.control.touched && !this.control.valid;
}
/**
* @hidden
*/
get isControlRequired() {
return isControlRequired(this.control?.control);
}
/**
* @hidden
*/
get separatorOrientation() {
return this.flow === 'horizontal' ? 'vertical' : 'horizontal';
}
/**
* @hidden
*/
get isFocused() {
return this._isFocused;
}
/**
* @hidden
*/
set isFocused(value) {
if (this._isFocused !== value && this.hostElement) {
const element = this.hostElement.nativeElement;
if (value && !this.disabled) {
this.renderer.addClass(element, FOCUSED);
}
else {
this.renderer.removeClass(element, FOCUSED);
}
this._isFocused = value;
}
}
/**
* @hidden
*/
handleInput = (ev) => {
const incomingValue = ev.target.value;
this.updateValue(incomingValue);
this.resize();
};
/**
* @hidden
*/
handleInputFocus = () => {
if (!this.disabled) {
if (this.selectOnFocus && this.value) {
this.ngZone.run(() => {
setTimeout(() => { this.selectAll(); });
});
}
if (!this.isFocused) {
this.handleFocus();
}
if (hasObservers(this.inputFocus)) {
if (!this.focusChangedProgrammatically) {
this.ngZone.run(() => {
this.inputFocus.emit();
});
}
}
}
};
/**
* Focuses the TextArea component.
*
* @example
* ```ts
* _@Component({
* selector: 'my-app',
* template: `
* <button (click)="textarea.focus()">Focus the textarea</button>
* <kendo-textarea #textarea></kendo-textarea>
* `
* })
* class AppComponent { }
* ```
*/
focus() {
if (!this.input) {
return;
}
this.focusChangedProgrammatically = true;
this.isFocused = true;
this.input.nativeElement.focus();
this.focusChangedProgrammatically = false;
}
/**
* Blurs the TextArea component.
*/
blur() {
this.focusChangedProgrammatically = true;
const isFocusedElement = this.hostElement.nativeElement.querySelector(':focus');
if (isFocusedElement) {
isFocusedElement.blur();
}
this.isFocused = false;
this.focusChangedProgrammatically = false;
}
resize() {
if (this.resizable !== 'auto') {
return;
}
// The logic of the resize method, does not depend on Angular and thus moving it outisde of it
// We need to ensure that the resizing logic runs after the value is updated thus the setTimout
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
const hostElement = this.hostElement.nativeElement;
const element = this.input.nativeElement;
this.renderer.setStyle(element, 'height', `${this.initialHeight}px`);
const scrollHeight = element.scrollHeight;
this.renderer.setStyle(hostElement, 'min-height', `${scrollHeight}px`);
if (scrollHeight > this.initialHeight) {
this.renderer.setStyle(element, 'height', `${scrollHeight}px`);
}
}, 0);
});
}
/**
* @hidden
*/
handleFocus() {
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically && hasObservers(this.onFocus)) {
this.onFocus.emit();
}
this.isFocused = true;
});
}
/**
* @hidden
*/
handleBlur() {
this.changeDetector.markForCheck();
this.ngZone.run(() => {
if (!this.focusChangedProgrammatically) {
this.onBlur.emit();
}
this.isFocused = false;
});
}
setSelection(start, end) {
if (this.isFocused) {
invokeElementMethod(this.input, 'setSelectionRange', start, end);
}
}
selectAll() {
if (this.value) {
this.setSelection(0, this.value.length);
}
}
handleClasses(value, input) {
const elem = this.hostElement.nativeElement;
const classes = getStylingClasses('input', input, this[input], value);
if (classes.toRemove) {
this.renderer.removeClass(elem, classes.toRemove);
}
if (classes.toAdd) {
this.renderer.addClass(elem, classes.toAdd);
}
}
handleFlow() {
const isVertical = this.flow === 'vertical';
const element = this.input.nativeElement;
this.renderer[isVertical ? 'addClass' : 'removeClass'](element, '\!k-flex-none');
}
setInputAttributes() {
const attributesToRender = Object.assign({}, this.mutableAttributes, this.parsedAttributes);
setHTMLAttributes(attributesToRender, this.renderer, this.input.nativeElement, this.ngZone);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaComponent, deps: [{ token: i1.LocalizationService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.Injector }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TextAreaComponent, isStandalone: true, selector: "kendo-textarea", inputs: { focusableId: "focusableId", flow: "flow", inputAttributes: "inputAttributes", adornmentsOrientation: "adornmentsOrientation", rows: "rows", cols: "cols", maxlength: "maxlength", tabindex: "tabindex", tabIndex: "tabIndex", resizable: "resizable", size: "size", rounded: "rounded", fillMode: "fillMode", showPrefixSeparator: "showPrefixSeparator", showSuffixSeparator: "showSuffixSeparator" }, outputs: { onFocus: "focus", onBlur: "blur", valueChange: "valueChange" }, host: { properties: { "class.k-textarea": "this.hostClasses", "class.k-input": "this.hostClasses", "class.!k-flex-col": "this.flowCol", "class.!k-flex-row": "this.flowRow" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.textarea' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextAreaComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => TextAreaComponent) }
], queries: [{ propertyName: "prefix", first: true, predicate: TextAreaPrefixComponent, descendants: true }, { propertyName: "suffix", first: true, predicate: TextAreaSuffixComponent, descendants: true }], exportAs: ["kendoTextArea"], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<ng-content select="kendo-textarea-prefix"></ng-content>
<kendo-input-separator
*ngIf="prefix && showPrefixSeparator"
[orientation]="separatorOrientation"
></kendo-input-separator>
<textarea #input
class="k-input-inner !k-overflow-auto"
[attr.aria-multiline]="true"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-invalid]="isControlInvalid"
[id]="focusableId"
[attr.required]="isControlRequired ? '' : null"
[ngClass]="resizableClass"
[value]="value"
[attr.placeholder]="placeholder"
[disabled]="disabled"
[readonly]="readonly"
[attr.rows]="rows"
[attr.cols]="cols"
[attr.tabindex]="tabIndex"
[attr.title]="title"
[attr.maxlength]="maxlength"
[attr.aria-invalid]="isControlInvalid"
[kendoEventsOutsideAngular]="{
focus: handleInputFocus,
blur: handleInputBlur,
input: handleInput}"
></textarea>
<kendo-input-separator
*ngIf="suffix && showSuffixSeparator"
[orientation]="separatorOrientation"
></kendo-input-separator>
<ng-content select="kendo-textarea-suffix"></ng-content>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: InputSeparatorComponent, selector: "kendo-input-separator, kendo-textbox-separator", inputs: ["orientation"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoTextArea',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.textarea' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextAreaComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => TextAreaComponent) }
],
selector: 'kendo-textarea',
template: `
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<ng-content select="kendo-textarea-prefix"></ng-content>
<kendo-input-separator
*ngIf="prefix && showPrefixSeparator"
[orientation]="separatorOrientation"
></kendo-input-separator>
<textarea #input
class="k-input-inner !k-overflow-auto"
[attr.aria-multiline]="true"
[attr.aria-disabled]="disabled ? true : undefined"
[attr.aria-readonly]="readonly ? true : undefined"
[attr.aria-invalid]="isControlInvalid"
[id]="focusableId"
[attr.required]="isControlRequired ? '' : null"
[ngClass]="resizableClass"
[value]="value"
[attr.placeholder]="placeholder"
[disabled]="disabled"
[readonly]="readonly"
[attr.rows]="rows"
[attr.cols]="cols"
[attr.tabindex]="tabIndex"
[attr.title]="title"
[attr.maxlength]="maxlength"
[attr.aria-invalid]="isControlInvalid"
[kendoEventsOutsideAngular]="{
focus: handleInputFocus,
blur: handleInputBlur,
input: handleInput}"
></textarea>
<kendo-input-separator
*ngIf="suffix && showSuffixSeparator"
[orientation]="separatorOrientation"
></kendo-input-separator>
<ng-content select="kendo-textarea-suffix"></ng-content>
</ng-container>
`,
standalone: true,
imports: [SharedInputEventsDirective, NgIf, InputSeparatorComponent, NgClass, EventsOutsideAngularDirective]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i0.Injector }, { type: i0.ElementRef }]; }, propDecorators: { focusableId: [{
type: Input
}], hostClasses: [{
type: HostBinding,
args: ['class.k-textarea']
}, {
type: HostBinding,
args: ['class.k-input']
}], flowCol: [{
type: HostBinding,
args: ['class.\!k-flex-col']
}], flowRow: [{
type: HostBinding,
args: ['class.\!k-flex-row']
}], flow: [{
type: Input
}], inputAttributes: [{
type: Input
}], adornmentsOrientation: [{
type: Input
}], rows: [{
type: Input
}], cols: [{
type: Input
}], maxlength: [{
type: Input
}], tabindex: [{
type: Input
}], tabIndex: [{
type: Input
}], resizable: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], showPrefixSeparator: [{
type: Input
}], showSuffixSeparator: [{
type: Input
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], valueChange: [{
type: Output
}], prefix: [{
type: ContentChild,
args: [TextAreaPrefixComponent]
}], suffix: [{
type: ContentChild,
args: [TextAreaSuffixComponent]
}] } });
/**
* Custom component messages override default component messages.
*/
class TextBoxCustomMessagesComponent extends TextBoxMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TextBoxCustomMessagesComponent, isStandalone: true, selector: "kendo-textbox-messages", providers: [
{
provide: TextBoxMessages,
useExisting: forwardRef(() => TextBoxCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: TextBoxMessages,
useExisting: forwardRef(() => TextBoxCustomMessagesComponent)
}
],
selector: 'kendo-textbox-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* @hidden
*/
class OTPInputSeparatorComponent {
set separator(otpSeparator) {
this._separator = otpSeparator;
this.clearSeparator();
if (!isPresent$1(otpSeparator)) {
return;
}
if (typeof otpSeparator === 'string') {
this.hasText = true;
return;
}
if (typeof otpSeparator.value !== 'string') {
this.hasSVGIcon = otpSeparator?.type === 'svgIcon';
this.separatorSVGIcon = otpSeparator.value;
return;
}
this.hasIconClass = otpSeparator?.type === 'iconClass';
this.hasFontIcon = otpSeparator?.type === 'fontIcon';
this.separatorIconString = otpSeparator.value;
}
get separator() {
return this._separator;
}
wrapperClass = true;
hasText;
hasIconClass;
hasSVGIcon;
hasFontIcon;
separatorIconString;
separatorSVGIcon;
_separator;
clearSeparator() {
this.hasText = false;
this.hasFontIcon = false;
this.hasIconClass = false;
this.hasSVGIcon = false;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: OTPInputSeparatorComponent, isStandalone: true, selector: "kendo-otpinput-separator", inputs: { separator: "separator" }, host: { properties: { "class.k-otp-separator": "this.wrapperClass" } }, exportAs: ["kendoOTPInputSeparator"], ngImport: i0, template: `
<ng-container *ngIf="hasText">{{this.separator}}</ng-container>
<span *ngIf="hasIconClass" [ngClass]="separatorIconString"></span>
<kendo-icon-wrapper
*ngIf="hasFontIcon || hasSVGIcon"
[name]="separatorIconString"
[svgIcon]="separatorSVGIcon"
></kendo-icon-wrapper>
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputSeparatorComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoOTPInputSeparator',
selector: 'kendo-otpinput-separator',
template: `
<ng-container *ngIf="hasText">{{this.separator}}</ng-container>
<span *ngIf="hasIconClass" [ngClass]="separatorIconString"></span>
<kendo-icon-wrapper
*ngIf="hasFontIcon || hasSVGIcon"
[name]="separatorIconString"
[svgIcon]="separatorSVGIcon"
></kendo-icon-wrapper>
`,
standalone: true,
imports: [NgIf, NgClass, IconWrapperComponent]
}]
}], propDecorators: { separator: [{
type: Input
}], wrapperClass: [{
type: HostBinding,
args: ['class.k-otp-separator']
}] } });
/**
* @hidden
*/
class OTPInputMessages extends ComponentMessages {
/**
* The aria-label of the OTP Input. Follows the pattern **Input {currentInput} of {totalInputs}, current value {value}** by default.
* Тhe default label text when the current input is 1, and the total number of inputs is 4 will be
* **Input 1 of 4, current value null**.
*
* The message consists of several parts - the current input number, the total number of inputs, the current value and a localizable string.
* To allow for reordering its parts, the `ariaLabel` input accepts a string with placeholders for the current input,
* total number of inputs and current value. The `{currentInput}`, `{totalInputs}` and `{currentValue}` placeholders will be
* replaced internally with the respective actual values.
*/
ariaLabel;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputMessages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: OTPInputMessages, selector: "kendo-otpinput-messages-base", inputs: { ariaLabel: "ariaLabel" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputMessages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-otpinput-messages-base'
}]
}], propDecorators: { ariaLabel: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedOTPInputMessagesDirective extends OTPInputMessages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedOTPInputMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedOTPInputMessagesDirective, isStandalone: true, selector: "[kendoOTPInputLocalizedMessages]", providers: [
{
provide: OTPInputMessages,
useExisting: forwardRef(() => LocalizedOTPInputMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedOTPInputMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: OTPInputMessages,
useExisting: forwardRef(() => LocalizedOTPInputMessagesDirective)
}
],
selector: '[kendoOTPInputLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
const DEFAULT_SIZE = 'medium';
const DEFAULT_ROUNDED = 'medium';
const DEFAULT_FILL_MODE = 'solid';
const DEFAULT_OTPINPUT_LENGTH = 4;
class OTPInputComponent {
hostElement;
cdr;
injector;
renderer;
localizationService;
zone;
/**
* Configures the total number of input fields.
*
* @default 4
*/
set length(value) {
if (value < 1 || this._length === value) {
return;
}
this._length = value;
this.inputsArray = new Array(this._length);
}
get length() {
return this._length;
}
/**
* Configures the input type.
*
* * The possible values are:
* * `text` (default)
* * `number`
* * `password`
*
* @default 'text'
*/
type = 'text';
/**
* Configures whether the input fields are separate or adjacent to each other.
*
* @default true
*/
spacing = true;
/**
* Specifies the separator between groups of input fields.
*
* > The configuration can only be applied when `groupLength` is set.
*/
separator;
/**
* Configures whether the component is enabled or disabled.
*
* @default false
*/
disabled = false;
/**
* Configures whether the component is readonly.
*
* @default false
*/
readonly = false;
/**
* Configures the placeholder of the input fields.
*/
placeholder;
/**
* Configures the length of the groups. If `groupLength` is a number, all groups will have the same length. If it's an array, each group can have a different length.
*/
get groupLength() {
return this._groupLength;
}
set groupLength(length) {
const isNumber = typeof length === 'number';
if (this._groupLength === length ||
isPresent$1(length) &&
((isNumber && (length < 1 || length > this.length)) ||
(!isNumber && !this.isValidGroupArray(length)))) {
return;
}
if (!isPresent$1(length)) {
this.clearGroups();
}
else if (isNumber) {
this.populateGroupArray(length);
}
else {
this.groupLengthArray = length;
if (!this.spacing) {
this.adjacentGroups = this.groupLengthArray;
}
}
this._groupLength = length;
this.populateSeparatorPositions();
}
/**
* Configures the value of the component. Unfilled input fields are represented with space.
*/
get value() {
return this._value;
}
set value(input) {
const isInvalidInput = this.type === 'number' && isPresent$1(input) && !this.containsDigitsOrSpaces(input);
if (this._value === input || isInvalidInput) {
return;
}
if (!isPresent$1(input)) {
this.clearInputValues();
this._value = null;
}
else {
this._value = input.slice(0, this.length);
if (!this.inputFieldValueChanged) {
this.fillInputs(input, 0, true);
}
}
if (this.inputAttributes) {
this.setInputAttributes();
}
else {
this.setDefaultAttributes();
}
}
/**
* The `size` property specifies the padding of the input fields.
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `none`
*/
set size(size) {
const newSize = size || DEFAULT_SIZE;
const elem = this.hostElement.nativeElement;
this.renderer.removeClass(elem, `k-otp-${SIZE_MAP[this._size]}`);
this.renderer.addClass(elem, `k-otp-${SIZE_MAP[newSize]}`);
this._size = newSize;
}
get size() {
return this._size;
}
/**
* The `rounded` property specifies the border radius of the OTP Input.
*
* The possible values are:
* * `small`
* * `medium` (default)
* * `large`
* * `full`
* * `none`
*/
set rounded(rounded) {
this._rounded = rounded || DEFAULT_ROUNDED;
}
get rounded() {
return this._rounded;
}
/**
* The `fillMode` property specifies the background and border styles of the OTP Input.
*
* The possible values are:
* * `flat`
* * `solid` (default)
* * `outline`
* * `none`
*/
set fillMode(fillMode) {
const newFillMode = fillMode || DEFAULT_FILL_MODE;
this.setGroupFillMode(newFillMode, this._fillMode);
this._fillMode = newFillMode;
}
get fillMode() {
return this._fillMode;
}
/**
* Sets the HTML attributes of the inner focusable input element. Attributes which are essential for certain component functionalities cannot be changed.
*/
set inputAttributes(attributes) {
this._inputAttributes = attributes;
this.parsedAttributes = this.inputAttributes ?
{ ...this.defaultAttributes, ...this.inputAttributes } :
this.inputAttributes;
this.setInputAttributes();
}
get inputAttributes() {
return this._inputAttributes;
}
/**
* Fires each time the value is changed by the user—
* When the value of the component is programmatically changed to `ngModel` or `formControl`
* through its API or form binding, the `valueChange` event is not triggered because it
* might cause a mix-up with the built-in `valueChange` mechanisms of the `ngModel` or `formControl` bindings.
*/
valueChange = new EventEmitter();
/**
* Fires each time the user focuses the OTP Input.
*/
onFocus = new EventEmitter();
/**
* Fires each time the user blurs the OTP Input.
*/
onBlur = new EventEmitter();
wrapperClass = true;
get invalidClass() {
return this.isControlInvalid;
}
direction;
role = 'group';
/**
* @hidden
*/
inputFields;
/**
* @hidden
*/
set inputGroups(elements) {
this._inputGroups = elements;
this.setGroupFillMode(this.fillMode);
}
get inputGroups() {
return this._inputGroups;
}
/**
* @hidden
*/
groupLengthArray;
/**
* @hidden
*/
inputsArray;
/**
* @hidden
*/
inputsValues = [].constructor(DEFAULT_OTPINPUT_LENGTH);
/**
* @hidden
*/
adjacentGroups;
_length = DEFAULT_OTPINPUT_LENGTH;
_groupLength;
_inputGroups;
separatorPositions = new Set();
_value = null;
_size = DEFAULT_SIZE;
_rounded = DEFAULT_ROUNDED;
_fillMode = DEFAULT_FILL_MODE;
_isFocused = false;
focusChangedProgrammatically = false;
inputFieldValueChanged = false;
focusedInput;
_inputAttributes;
parsedAttributes = {};
get defaultAttributes() {
return {
autocomplete: 'off'
};
}
subscriptions;
ngChange = (_) => { };
ngTouched = () => { };
constructor(hostElement, cdr, injector, renderer, localizationService, zone) {
this.hostElement = hostElement;
this.cdr = cdr;
this.injector = injector;
this.renderer = renderer;
this.localizationService = localizationService;
this.zone = zone;
this.direction = localizationService.rtl ? 'rtl' : 'ltr';
}
ngOnInit() {
this.inputsArray = Array.from({ length: this._length });
this.subscriptions = this.localizationService.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
});
this.zone.runOutsideAngular(() => {
this.subscriptions.add(this.renderer.listen(this.hostElement.nativeElement, 'paste', this.handlePaste.bind(this)));
this.subscriptions.add(this.renderer.listen(this.hostElement.nativeElement, 'keydown', this.handleKeydown.bind(this)));
});
}
ngAfterViewInit() {
this.subscriptions.add(this.inputFields.changes.subscribe(this.handleInputChanges.bind(this)));
this.handleInputChanges();
this.renderer.addClass(this.hostElement.nativeElement, `k-otp-${SIZE_MAP[this._size]}`);
this.setGroupFillMode(this.fillMode);
this.zone.onStable.pipe(take(1)).subscribe(() => {
this.fillInputs(this.value);
});
}
ngOnChanges(changes) {
if (changes.length) {
if (typeof this.groupLength === 'number') {
this.populateGroupArray(this.groupLength);
}
this.populateSeparatorPositions();
}
if (changes.spacing) {
if (this.spacing === true) {
this.adjacentGroups = null;
}
else {
this.adjacentGroups = this.groupLengthArray ?? [this.length];
}
}
if (changes.type && this.type === 'number') {
if (isPresent$1(this.value) && !this.containsDigitsOrSpaces(this.value)) {
this.value = null;
this.zone.runOutsideAngular(() => setTimeout(() => this.zone.run(() => {
this.ngChange(null);
this.cdr.markForCheck();
})));
}
}
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
/**
* @hidden
*/
get formControl() {
const ngControl = this.injector.get(NgControl, null);
return ngControl?.control || null;
}
/**
* @hidden
*/
writeValue(value) {
this.value = value;
}
/**
* @hidden
*/
registerOnChange(fn) {
this.ngChange = fn;
}
/**
* @hidden
*/
registerOnTouched(fn) {
this.ngTouched = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled) {
this.cdr.markForCheck();
this.disabled = isDisabled;
}
/**
* @hidden
*/
get isControlInvalid() {
return this.formControl?.touched && this.formControl.invalid;
}
/**
* @hidden
*/
get isFocused() {
return this._isFocused;
}
/**
* @hidden
*/
set isFocused(value) {
if (this._isFocused !== value && this.hostElement) {
this._isFocused = value;
}
}
/**
* @hidden
*/
get hasGroups() {
if (!this.spacing && isPresent$1(this.groupLength)) {
return true;
}
}
/**
* @hidden
*/
showGroupSeparator(index) {
return this.groupLengthArray && index < this.groupLengthArray.length - 1;
}
/**
* @hidden
*/
showSeparator(index) {
return this.groupLength ? this.separatorPositions.has(index) : false;
}
/**
* @hidden
*/
handleValueChange(index, groupIndex) {
this.inputFieldValueChanged = true;
if (groupIndex) {
index = this.getIndexByGroup(groupIndex, index);
}
let newValue = '';
this.inputFields.forEach((input) => newValue = newValue.concat(input.value?.toString() || ' '));
if (!areSame(this.value, newValue)) {
this.zone.run(() => {
this.value = newValue;
this.ngChange(newValue);
this.valueChange.emit(newValue);
this.cdr.markForCheck();
});
}
this.inputFieldValueChanged = false;
if (isPresent$1(index) && isPresent$1(this.inputFields?.get(index).value)) {
this.focusNext();
}
}
/**
* @hidden
*/
handleInputFocus(index, groupIndex) {
if (this.focusChangedProgrammatically) {
return;
}
if (groupIndex) {
index = this.getIndexByGroup(groupIndex, index);
}
this.focusedInput = index;
}
/**
* @hidden
*/
handleInput(event, index, groupIndex) {
if (this.type === 'number' && !this.isValidNumber(event?.data)) {
const inputIndex = groupIndex ? this.getIndexByGroup(groupIndex, index) : index;
const textbox = this.inputFields.get(inputIndex);
if (this.value && this.isValidNumber(this.value[inputIndex])) {
textbox.value = this.value[inputIndex];
}
else {
textbox.value = null;
}
this.showInvalidInput(inputIndex);
return;
}
this.handleValueChange(index, groupIndex);
}
/**
* @hidden
*/
fillInputs(text, start = 0, replaceLast = false) {
if (!isPresent$1(text)) {
return;
}
let charCounter = 0;
this.inputFields?.forEach((otpInput, i) => {
if (i < start) {
return;
}
if (charCounter < text.length) {
if (text[charCounter] === ' ') {
otpInput.value = null;
}
else {
otpInput.value = text[charCounter];
}
charCounter++;
}
else if (replaceLast) {
otpInput.value = null;
}
});
}
/**
* Focuses the OTP Input.
*/
focus(index) {
if (!this.inputFields || index < 0 || index >= this.length) {
return;
}
this.focusChangedProgrammatically = true;
this.isFocused = true;
this.inputFields.get(index || 0).focus();
this.focusedInput = index || 0;
this.focusChangedProgrammatically = false;
}
/**
* Blurs the OTP Input.
*/
blur() {
this.focusChangedProgrammatically = true;
const isFocusedElement = this.hostElement.nativeElement.querySelector(':focus');
if (isFocusedElement) {
isFocusedElement.blur();
}
this.isFocused = false;
this.focusChangedProgrammatically = false;
}
/**
* @hidden
*/
handleFocus() {
this.zone.run(() => {
if (!this.focusChangedProgrammatically && hasObservers(this.onFocus)) {
this.onFocus.emit();
}
this.isFocused = true;
});
}
/**
* @hidden
*/
handleBlur() {
this.zone.run(() => {
if (!this.focusChangedProgrammatically) {
this.ngTouched();
this.onBlur.emit();
}
this.isFocused = false;
});
}
getIndexByGroup(groupIndex, itemIndex) {
return this.groupLengthArray.slice(0, groupIndex).reduce((sum, current) => sum + current, 0) + itemIndex;
}
focusNext() {
if (!this.inputFields || this.focusedInput === this.length - 1) {
return;
}
this.focusChangedProgrammatically = true;
this.isFocused = true;
this.inputFields.get(this.focusedInput).blur();
this.inputFields.get(this.focusedInput + 1).focus();
this.focusedInput++;
this.focusChangedProgrammatically = false;
}
focusPrevious() {
if (!this.inputFields || this.focusedInput === 0) {
return;
}
this.focusChangedProgrammatically = true;
this.isFocused = true;
this.inputFields.get(this.focusedInput).blur();
this.inputFields.get(this.focusedInput - 1).focus();
this.focusedInput--;
this.focusChangedProgrammatically = false;
}
handlePaste(event) {
event.preventDefault();
const text = event.clipboardData.getData('text').trim();
if (text === '') {
return;
}
if (this.type === 'number' && !this.isValidNumber(text)) {
this.showInvalidInput(this.focusedInput);
return;
}
this.inputFieldValueChanged = true;
this.fillInputs(text, this.focusedInput);
this.handleValueChange();
this.inputFieldValueChanged = false;
const focusedInput = this.focusedInput + text.length < this.inputFields?.length ?
this.focusedInput + text.length :
this.inputFields.length - 1;
this.inputFields.get(this.focusedInput).blur();
this.focusedInput = focusedInput;
this.inputFields.get(this.focusedInput).focus();
}
handleKeydown(event) {
if (this.readonly) {
const isCopyCommand = (event.ctrlKey || event.metaKey) && event.keyCode === Keys.KeyC;
if (!(event.keyCode === Keys.Tab || isCopyCommand)) {
event.preventDefault();
return;
}
}
switch (event.keyCode) {
case Keys.ArrowRight:
event.preventDefault();
this.direction === 'ltr' ? this.focusNext() : this.focusPrevious();
break;
case Keys.ArrowLeft:
event.preventDefault();
this.direction === 'ltr' ? this.focusPrevious() : this.focusNext();
break;
case Keys.Backspace:
event.preventDefault();
this.inputFields.get(this.focusedInput).value = null;
this.handleValueChange();
this.focusPrevious();
break;
case Keys.Delete:
event.preventDefault();
this.inputFields.get(this.focusedInput).value = null;
this.handleValueChange();
break;
default:
break;
}
}
isValidGroupArray(groups) {
if (!isPresent$1(groups)) {
return;
}
const sum = groups.reduce((sum, current) => sum + current, 0);
return sum === this.length;
}
populateGroupArray(length) {
const groupsCount = Math.floor(this.length / length);
const remainder = this.length % length;
const result = Array(groupsCount).fill(length);
if (remainder > 0) {
result.push(remainder);
}
this.groupLengthArray = [...result];
// groups with spacing shouldn't be wrapped in `k-input-group`
if (!this.spacing) {
this.adjacentGroups = [...this.groupLengthArray];
}
}
populateSeparatorPositions() {
let itemIndex = 0;
this.separatorPositions.clear();
if (!isPresent$1(this.groupLengthArray)) {
return;
}
for (let i = 0; i < this.groupLengthArray.length - 1; i++) {
itemIndex += this.groupLengthArray[i];
this.separatorPositions.add(itemIndex - 1);
}
}
clearGroups() {
this.groupLengthArray = null;
if (!this.spacing) {
this.adjacentGroups = [this.length];
}
else {
this.adjacentGroups = null;
}
this.separatorPositions.clear();
}
clearInputValues() {
this.inputFields?.forEach((input) => input.value = null);
}
handleInputChanges() {
this.zone.onStable.pipe(take(1)).subscribe(() => {
this.fillInputs(this.value?.trim());
if (this.inputAttributes) {
this.setInputAttributes();
}
else {
this.setDefaultAttributes();
}
this.cdr.detectChanges();
});
}
setGroupFillMode(fillMode, previousFillMode) {
this.inputGroups?.forEach(element => {
if (previousFillMode !== 'none') {
this.renderer.removeClass(element.nativeElement, `k-input-group-${previousFillMode}`);
}
if (fillMode !== 'none') {
this.renderer.addClass(element.nativeElement, `k-input-group-${fillMode}`);
}
});
}
setInputAttributes() {
this.inputFields?.forEach((input, index) => {
if (!this.parsedAttributes || !this.parsedAttributes?.['aria-label']) {
input.inputAttributes = { ...this.parsedAttributes, 'aria-label': this.ariaLabel(index) };
}
else {
input.inputAttributes = this.parsedAttributes;
}
});
}
setDefaultAttributes() {
this.inputFields?.forEach((input, index) => {
input.inputAttributes = {
autocomplete: 'off',
'aria-label': this.ariaLabel(index)
};
});
}
ariaLabel(index) {
const localizationMsg = this.localizationService.get('ariaLabel') || '';
return replaceMessagePlaceholder(replaceMessagePlaceholder(replaceMessagePlaceholder(localizationMsg, 'currentInput', (index + 1).toString()), 'totalInputs', this.length.toString()), 'value', this.value);
}
isValidNumber(value) {
if (!isPresent$1(value)) {
return;
}
const trimmedValue = value.trim();
return trimmedValue !== '' &&
trimmedValue !== 'Infinity' &&
trimmedValue !== '-Infinity' &&
!isNaN(Number(trimmedValue));
}
showInvalidInput(index) {
const textbox = this.inputFields.get(index);
const textboxElement = this.inputFields.get(index).hostElement.nativeElement;
const inputElement = textbox.input.nativeElement;
this.renderer.addClass(textboxElement, 'k-invalid');
if (textbox.value && this.isValidNumber(textbox.value)) {
this.zone.onStable.pipe(take(1)).subscribe(() => inputElement.select());
}
this.zone.runOutsideAngular(() => {
setTimeout(() => {
if (!this.isControlInvalid && textboxElement) {
this.renderer.removeClass(textboxElement, 'k-invalid');
}
}, 300);
});
}
containsDigitsOrSpaces(value) {
// @ts-expect-error TS does not allow comparing string with number
const isDigitOrSpace = (char) => (char == +char) || char === ' ';
for (let i = 0; i < value.length; i++) {
if (!isDigitOrSpace(value[i])) {
return false;
}
}
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: OTPInputComponent, isStandalone: true, selector: "kendo-otpinput", inputs: { length: "length", type: "type", spacing: "spacing", separator: "separator", disabled: "disabled", readonly: "readonly", placeholder: "placeholder", groupLength: "groupLength", value: "value", size: "size", rounded: "rounded", fillMode: "fillMode", inputAttributes: "inputAttributes" }, outputs: { valueChange: "valueChange", onFocus: "focus", onBlur: "blur" }, host: { properties: { "class.k-otp": "this.wrapperClass", "class.k-invalid": "this.invalidClass", "attr.dir": "this.direction", "attr.role": "this.role" } }, providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.otpinput' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => OTPInputComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => OTPInputComponent) }
], viewQueries: [{ propertyName: "inputFields", predicate: TextBoxComponent, descendants: true }, { propertyName: "inputGroups", predicate: ["inputGroup"], descendants: true }], exportAs: ["kendoOTPInput"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoOTPInputLocalizedMessages
i18n-ariaLabel="kendo.otpinput.ariaLabel|The value of the aria-label attribute of the input fields."
ariaLabel="{{ 'Input {currentInput} of {totalInputs}, current value {value}' }}"
></ng-container>
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<ng-container *ngIf="spacing; else groups">
<ng-container *ngFor="let input of inputsArray; let i = index">
<kendo-textbox
class="k-otp-input"
[class.k-invalid]="isControlInvalid"
[selectOnFocus]="true"
[maxlength]="1"
[type]="type !== 'number' ? type : null"
[placeholder]="placeholder"
[size]="size"
[rounded]="rounded"
[fillMode]="fillMode"
[disabled]="disabled"
[readonly]="readonly"
(focus)="handleInputFocus(i)"
(input)="handleInput($event, i)"
></kendo-textbox>
<kendo-otpinput-separator *ngIf="showSeparator(i)" [separator]="separator"></kendo-otpinput-separator>
</ng-container>
</ng-container>
<ng-template #groups>
<ng-container *ngFor="let group of adjacentGroups; let i = index">
<div #inputGroup class="k-input-group">
<kendo-textbox
*ngFor="let input of [].constructor(group); let j = index"
class="k-otp-input"
[class.k-invalid]="isControlInvalid"
[selectOnFocus]="true"
[maxlength]="1"
[type]="type !== 'number' ? type : null"
[placeholder]="placeholder"
[size]="size"
[rounded]="rounded"
[fillMode]="fillMode"
[disabled]="disabled"
[readonly]="readonly"
(focus)="handleInputFocus(j, i)"
(input)="handleInput($event, j, i)"
></kendo-textbox>
</div>
<kendo-otpinput-separator *ngIf="showGroupSeparator(i)" [separator]="separator"></kendo-otpinput-separator>
</ng-container>
</ng-template>
<ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { 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: "component", type: OTPInputSeparatorComponent, selector: "kendo-otpinput-separator", inputs: ["separator"], exportAs: ["kendoOTPInputSeparator"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: LocalizedOTPInputMessagesDirective, selector: "[kendoOTPInputLocalizedMessages]" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoOTPInput',
providers: [
LocalizationService,
{ provide: L10N_PREFIX, useValue: 'kendo.otpinput' },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => OTPInputComponent),
multi: true
},
{ provide: KendoInput, useExisting: forwardRef(() => OTPInputComponent) }
],
selector: 'kendo-otpinput',
template: `
<ng-container kendoOTPInputLocalizedMessages
i18n-ariaLabel="kendo.otpinput.ariaLabel|The value of the aria-label attribute of the input fields."
ariaLabel="{{ 'Input {currentInput} of {totalInputs}, current value {value}' }}"
></ng-container>
<ng-container
kendoInputSharedEvents
[hostElement]="hostElement"
[(isFocused)]="isFocused"
(handleBlur)="handleBlur()"
(onFocus)="handleFocus()"
>
<ng-container *ngIf="spacing; else groups">
<ng-container *ngFor="let input of inputsArray; let i = index">
<kendo-textbox
class="k-otp-input"
[class.k-invalid]="isControlInvalid"
[selectOnFocus]="true"
[maxlength]="1"
[type]="type !== 'number' ? type : null"
[placeholder]="placeholder"
[size]="size"
[rounded]="rounded"
[fillMode]="fillMode"
[disabled]="disabled"
[readonly]="readonly"
(focus)="handleInputFocus(i)"
(input)="handleInput($event, i)"
></kendo-textbox>
<kendo-otpinput-separator *ngIf="showSeparator(i)" [separator]="separator"></kendo-otpinput-separator>
</ng-container>
</ng-container>
<ng-template #groups>
<ng-container *ngFor="let group of adjacentGroups; let i = index">
<div #inputGroup class="k-input-group">
<kendo-textbox
*ngFor="let input of [].constructor(group); let j = index"
class="k-otp-input"
[class.k-invalid]="isControlInvalid"
[selectOnFocus]="true"
[maxlength]="1"
[type]="type !== 'number' ? type : null"
[placeholder]="placeholder"
[size]="size"
[rounded]="rounded"
[fillMode]="fillMode"
[disabled]="disabled"
[readonly]="readonly"
(focus)="handleInputFocus(j, i)"
(input)="handleInput($event, j, i)"
></kendo-textbox>
</div>
<kendo-otpinput-separator *ngIf="showGroupSeparator(i)" [separator]="separator"></kendo-otpinput-separator>
</ng-container>
</ng-template>
<ng-container>
`,
standalone: true,
imports: [SharedInputEventsDirective, TextBoxComponent, OTPInputSeparatorComponent, NgFor, NgIf, LocalizedOTPInputMessagesDirective]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: i0.Renderer2 }, { type: i1.LocalizationService }, { type: i0.NgZone }]; }, propDecorators: { length: [{
type: Input
}], type: [{
type: Input
}], spacing: [{
type: Input
}], separator: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}], placeholder: [{
type: Input
}], groupLength: [{
type: Input
}], value: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], fillMode: [{
type: Input
}], inputAttributes: [{
type: Input
}], valueChange: [{
type: Output
}], onFocus: [{
type: Output,
args: ['focus']
}], onBlur: [{
type: Output,
args: ['blur']
}], wrapperClass: [{
type: HostBinding,
args: ['class.k-otp']
}], invalidClass: [{
type: HostBinding,
args: ['class.k-invalid']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], role: [{
type: HostBinding,
args: ['attr.role']
}], inputFields: [{
type: ViewChildren,
args: [TextBoxComponent]
}], inputGroups: [{
type: ViewChildren,
args: ['inputGroup']
}] } });
/**
* Custom component messages override default component messages.
*/
class OTPInputCustomMessagesComponent extends OTPInputMessages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputCustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: OTPInputCustomMessagesComponent, isStandalone: true, selector: "kendo-otpinput-messages", providers: [
{
provide: OTPInputMessages,
useExisting: forwardRef(() => OTPInputCustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OTPInputCustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: OTPInputMessages,
useExisting: forwardRef(() => OTPInputCustomMessagesComponent)
}
],
selector: 'kendo-otpinput-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Utility array that contains all `TextBox` related components and directives
*/
const KENDO_TEXTBOX = [
TextBoxDirective,
TextBoxComponent,
InputSeparatorComponent,
TextBoxSuffixTemplateDirective,
TextBoxPrefixTemplateDirective,
TextBoxCustomMessagesComponent,
PrefixTemplateDirective,
SuffixTemplateDirective,
SeparatorComponent
];
/**
* Utility array that contains all `NumericTextBox` related components and directives
*/
const KENDO_NUMERICTEXTBOX = [
NumericTextBoxComponent,
NumericTextBoxCustomMessagesComponent,
PrefixTemplateDirective,
SuffixTemplateDirective,
SeparatorComponent
];
/**
* Utility array that contains all `MaskedTextBox` related components and directives
*/
const KENDO_MASKEDTEXTBOX = [
MaskedTextBoxComponent,
PrefixTemplateDirective,
SuffixTemplateDirective,
SeparatorComponent
];
/**
* Utility array that contains all `OTP` related components and directives
*/
const KENDO_OTPINPUT = [
OTPInputComponent,
OTPInputCustomMessagesComponent
];
/**
* Utility array that contains all `TextArea` related components and directives
*/
const KENDO_TEXTAREA = [
TextAreaComponent,
TextAreaDirective,
TextAreaPrefixComponent,
TextAreaSuffixComponent,
SeparatorComponent
];
/**
* Utility array that contains all `CheckBox` related components and directives
*/
const KENDO_CHECKBOX = [
CheckBoxComponent,
CheckBoxDirective
];
/**
* Utility array that contains all `RadioButton` related components and directives
*/
const KENDO_RADIOBUTTON = [
RadioButtonComponent,
RadioButtonDirective
];
/**
* Utility array that contains all `Switch` related components and directives
*/
const KENDO_SWITCH = [
SwitchComponent,
SwitchCustomMessagesComponent
];
/**
* Utility array that contains all `FormField` related components and directives
*/
const KENDO_FORMFIELD = [
FormFieldComponent,
HintComponent,
ErrorComponent
];
/**
* Utility array that contains all `Slider` related components and directives
*/
const KENDO_SLIDER = [
SliderComponent,
SliderCustomMessagesComponent,
LabelTemplateDirective,
];
/**
* Utility array that contains all `RangeSlider` related components and directives
*/
const KENDO_RANGESLIDER = [
RangeSliderComponent,
RangeSliderCustomMessagesComponent,
LabelTemplateDirective
];
/**
* Utility array that contains all `Rating` related components and directives
*/
const KENDO_RATING = [
RatingComponent,
RatingItemTemplateDirective,
RatingHoveredItemTemplateDirective,
RatingSelectedItemTemplateDirective
];
/**
* Utility array that contains all `Signature` related components and directives
*/
const KENDO_SIGNATURE = [
SignatureComponent,
SignatureCustomMessagesComponent
];
/**
* Utility array that contains all `ColorPicker` related components and directives
*/
const KENDO_COLORPICKER = [
ColorPickerComponent,
ColorPickerCustomMessagesComponent
];
/**
* Utility array that contains all `FlatColorPicker` related components and directives
*/
const KENDO_FLATCOLORPICKER = [
FlatColorPickerComponent,
ColorPickerCustomMessagesComponent
];
/**
* Utility array that contains all `ColorPallete` related components and directives
*/
const KENDO_COLORPALETTE = [
ColorPaletteComponent,
ColorPickerCustomMessagesComponent
];
/**
* Utility array that contains all `ColorGradient` related components and directives
*/
const KENDO_COLORGRADIENT = [
ColorGradientComponent,
ColorPickerCustomMessagesComponent
];
/**
* Utility array that contains all `@progress/kendo-angular-inputs` related components and directives
*/
const KENDO_INPUTS = [
...KENDO_TEXTBOX,
...KENDO_NUMERICTEXTBOX,
...KENDO_MASKEDTEXTBOX,
...KENDO_TEXTAREA,
...KENDO_CHECKBOX,
...KENDO_RADIOBUTTON,
...KENDO_SWITCH,
...KENDO_FORMFIELD,
...KENDO_SLIDER,
...KENDO_RANGESLIDER,
...KENDO_RATING,
...KENDO_SIGNATURE,
...KENDO_COLORPICKER,
...KENDO_FLATCOLORPICKER,
...KENDO_COLORGRADIENT,
...KENDO_COLORPALETTE,
...KENDO_OTPINPUT
];
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the Inputs components.
*
* @example
*
* ```ts-no-run
* // Import the Inputs module
* import { InputsModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
* import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, BrowserAnimationsModule, InputsModule], // import Inputs module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class InputsModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: InputsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: InputsModule, imports: [TextBoxDirective, TextBoxComponent, InputSeparatorComponent, TextBoxSuffixTemplateDirective, TextBoxPrefixTemplateDirective, TextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, MaskedTextBoxComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, TextAreaComponent, TextAreaDirective, TextAreaPrefixComponent, TextAreaSuffixComponent, i7.SeparatorComponent, CheckBoxComponent, CheckBoxDirective, RadioButtonComponent, RadioButtonDirective, SwitchComponent, SwitchCustomMessagesComponent, FormFieldComponent, HintComponent, ErrorComponent, SliderComponent, SliderCustomMessagesComponent, LabelTemplateDirective, RangeSliderComponent, RangeSliderCustomMessagesComponent, LabelTemplateDirective, RatingComponent, RatingItemTemplateDirective, RatingHoveredItemTemplateDirective, RatingSelectedItemTemplateDirective, SignatureComponent, SignatureCustomMessagesComponent, ColorPickerComponent, ColorPickerCustomMessagesComponent, FlatColorPickerComponent, ColorPickerCustomMessagesComponent, ColorGradientComponent, ColorPickerCustomMessagesComponent, ColorPaletteComponent, ColorPickerCustomMessagesComponent, OTPInputComponent, OTPInputCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent], exports: [TextBoxDirective, TextBoxComponent, InputSeparatorComponent, TextBoxSuffixTemplateDirective, TextBoxPrefixTemplateDirective, TextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, MaskedTextBoxComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, TextAreaComponent, TextAreaDirective, TextAreaPrefixComponent, TextAreaSuffixComponent, i7.SeparatorComponent, CheckBoxComponent, CheckBoxDirective, RadioButtonComponent, RadioButtonDirective, SwitchComponent, SwitchCustomMessagesComponent, FormFieldComponent, HintComponent, ErrorComponent, SliderComponent, SliderCustomMessagesComponent, LabelTemplateDirective, RangeSliderComponent, RangeSliderCustomMessagesComponent, LabelTemplateDirective, RatingComponent, RatingItemTemplateDirective, RatingHoveredItemTemplateDirective, RatingSelectedItemTemplateDirective, SignatureComponent, SignatureCustomMessagesComponent, ColorPickerComponent, ColorPickerCustomMessagesComponent, FlatColorPickerComponent, ColorPickerCustomMessagesComponent, ColorGradientComponent, ColorPickerCustomMessagesComponent, ColorPaletteComponent, ColorPickerCustomMessagesComponent, OTPInputComponent, OTPInputCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: InputsModule, providers: [IconsService, PopupService, ResizeBatchService, DialogContainerService, DialogService, WindowService, WindowContainerService, AdaptiveService], imports: [TextBoxComponent, i7.SeparatorComponent, NumericTextBoxComponent, i7.SeparatorComponent, i7.SeparatorComponent, i7.SeparatorComponent, SliderComponent, RangeSliderComponent, RatingComponent, SignatureComponent, ColorPickerComponent, FlatColorPickerComponent, ColorGradientComponent, OTPInputComponent, i7.SeparatorComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: InputsModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_INPUTS, ...KENDO_ADORNMENTS],
exports: [...KENDO_INPUTS, ...KENDO_ADORNMENTS],
providers: [IconsService, PopupService, ResizeBatchService, DialogContainerService, DialogService, WindowService, WindowContainerService, AdaptiveService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the Slider component.
*
* @example
*
* ```ts-no-run
* // Import the Inputs module
* import { SliderModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
* import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, BrowserAnimationsModule, SliderModule], // import Slider module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class SliderModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: SliderModule, imports: [SliderComponent, SliderCustomMessagesComponent, LabelTemplateDirective], exports: [SliderComponent, SliderCustomMessagesComponent, LabelTemplateDirective] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderModule, providers: [IconsService, PopupService, ResizeBatchService], imports: [SliderComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SliderModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_SLIDER],
exports: [...KENDO_SLIDER],
providers: [IconsService, PopupService, ResizeBatchService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the RangeSlider component.
*
* @example
*
* ```ts-no-run
* // Import the Inputs module
* import { RangeSliderModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
* import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, BrowserAnimationsModule, RangeSliderModule], // import RangeSlider module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class RangeSliderModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderModule, imports: [RangeSliderComponent, RangeSliderCustomMessagesComponent, LabelTemplateDirective], exports: [RangeSliderComponent, RangeSliderCustomMessagesComponent, LabelTemplateDirective] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderModule, providers: [ResizeBatchService], imports: [RangeSliderComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RangeSliderModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_RANGESLIDER],
exports: [...KENDO_RANGESLIDER],
providers: [ResizeBatchService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the Switch component.
*
* @example
*
* ```ts-no-run
* // Import the Switch module
* import { SwitchModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, SwitchModule], // import Switch module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class SwitchModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: SwitchModule, imports: [SwitchComponent, SwitchCustomMessagesComponent], exports: [SwitchComponent, SwitchCustomMessagesComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchModule, providers: [ResizeBatchService] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SwitchModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_SWITCH],
exports: [...KENDO_SWITCH],
providers: [ResizeBatchService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the NumericTextBox component.
*
* @example
*
* ```ts-no-run
* // Import the NumericTextBox module
* import { NumericTextBoxModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, NumericTextBoxModule], // import NumericTextBox module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class NumericTextBoxModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxModule, imports: [NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent], exports: [NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxModule, providers: [IconsService], imports: [NumericTextBoxComponent, i7.SeparatorComponent, i7.SeparatorComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NumericTextBoxModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_NUMERICTEXTBOX, ...KENDO_ADORNMENTS],
exports: [...KENDO_NUMERICTEXTBOX, ...KENDO_ADORNMENTS],
providers: [IconsService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the MaskedTextBox component.
*
* @example
*
* ```ts-no-run
* // Import the MaskedTextBox module
* import { MaskedTextBoxModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, MaskedTextBoxModule], // import MaskedTextBox module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class MaskedTextBoxModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskedTextBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: MaskedTextBoxModule, imports: [MaskedTextBoxComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent], exports: [MaskedTextBoxComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskedTextBoxModule, imports: [i7.SeparatorComponent, i7.SeparatorComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MaskedTextBoxModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_MASKEDTEXTBOX, ...KENDO_ADORNMENTS],
exports: [...KENDO_MASKEDTEXTBOX, ...KENDO_ADORNMENTS]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the TextBox directive.
*
* @example
*
* ```ts-no-run
* // Import the TextBox module
* import { TextBoxModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, TextBoxModule], // import TextBox module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class TextBoxModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: TextBoxModule, imports: [TextBoxDirective, TextBoxComponent, InputSeparatorComponent, TextBoxSuffixTemplateDirective, TextBoxPrefixTemplateDirective, TextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent], exports: [TextBoxDirective, TextBoxComponent, InputSeparatorComponent, TextBoxSuffixTemplateDirective, TextBoxPrefixTemplateDirective, TextBoxCustomMessagesComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxModule, providers: [IconsService], imports: [TextBoxComponent, i7.SeparatorComponent, i7.SeparatorComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextBoxModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_TEXTBOX, ...KENDO_ADORNMENTS],
exports: [...KENDO_TEXTBOX, ...KENDO_ADORNMENTS],
providers: [IconsService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the TextArea component.
*
* @example
*
* ```ts-no-run
* // Import the TextArea module
* import { TextAreaModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, TextAreaModule], // import TextArea module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class TextAreaModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: TextAreaModule, imports: [TextAreaComponent, TextAreaDirective, TextAreaPrefixComponent, TextAreaSuffixComponent, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent], exports: [TextAreaComponent, TextAreaDirective, TextAreaPrefixComponent, TextAreaSuffixComponent, i7.SeparatorComponent, i7.PrefixTemplateDirective, i7.SuffixTemplateDirective, i7.SeparatorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaModule, imports: [i7.SeparatorComponent, i7.SeparatorComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextAreaModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_TEXTAREA, ...KENDO_ADORNMENTS],
exports: [...KENDO_TEXTAREA, ...KENDO_ADORNMENTS]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the CheckBox directive and CheckBoxComponent.
*
* @example
*
* ```ts-no-run
* // Import the CheckBox module
* import { CheckBoxModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, CheckBoxModule], // import CheckBox module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class CheckBoxModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxModule, imports: [CheckBoxComponent, CheckBoxDirective], exports: [CheckBoxComponent, CheckBoxDirective] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CheckBoxModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_CHECKBOX],
exports: [...KENDO_CHECKBOX]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the RadioButton directive and RadioButtonComponent.
*
* @example
*
* ```ts-no-run
* // Import the RadioButton module
* import { RadioButtonModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, RadioButtonModule], // import RadioButton module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class RadioButtonModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonModule, imports: [RadioButtonComponent, RadioButtonDirective], exports: [RadioButtonComponent, RadioButtonDirective] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RadioButtonModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_RADIOBUTTON],
exports: [...KENDO_RADIOBUTTON]
}]
}] });
/**
* Arguments for the `blur` event of the Switch component.
*/
class SwitchBlurEvent {
/**
* The original DOM [`blur`](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event) event.
*/
originalEvent;
}
/**
* Arguments for the `focus` event of the Switch component.
*/
class SwitchFocusEvent {
/**
* The original DOM [`focus`](https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event) event.
*/
originalEvent;
}
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the ColorPicker.
*/
class ColorPickerModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerModule, imports: [ColorPickerComponent, ColorPickerCustomMessagesComponent, FlatColorPickerComponent, ColorPickerCustomMessagesComponent, ColorGradientComponent, ColorPickerCustomMessagesComponent, ColorPaletteComponent, ColorPickerCustomMessagesComponent], exports: [ColorPickerComponent, ColorPickerCustomMessagesComponent, FlatColorPickerComponent, ColorPickerCustomMessagesComponent, ColorGradientComponent, ColorPickerCustomMessagesComponent, ColorPaletteComponent, ColorPickerCustomMessagesComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerModule, providers: [PopupService, IconsService, ResizeBatchService, AdaptiveService], imports: [ColorPickerComponent, FlatColorPickerComponent, ColorGradientComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPickerModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_COLORPICKER, ...KENDO_FLATCOLORPICKER, ...KENDO_COLORGRADIENT, ...KENDO_COLORPALETTE],
exports: [...KENDO_COLORPICKER, ...KENDO_FLATCOLORPICKER, ...KENDO_COLORGRADIENT, ...KENDO_COLORPALETTE],
providers: [PopupService, IconsService, ResizeBatchService, AdaptiveService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the FormField, Error and Hint components.
*
* @example
*
* ```ts-no-run
* // Import the FormField module
* import { FormFieldModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, FormFieldModule], // import FormField module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class FormFieldModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FormFieldModule, imports: [FormFieldComponent, HintComponent, ErrorComponent], exports: [FormFieldComponent, HintComponent, ErrorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFieldModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FormFieldModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_FORMFIELD],
exports: [...KENDO_FORMFIELD]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the Signature component.
*
* @example
*
* ```ts-no-run
* // Import the Signature module
* import { SignatureModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, SignatureModule], // import Signature module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class SignatureModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: SignatureModule, imports: [SignatureComponent, SignatureCustomMessagesComponent], exports: [SignatureComponent, SignatureCustomMessagesComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureModule, providers: [IconsService, PopupService, ResizeBatchService, DialogContainerService, DialogService, WindowService, WindowContainerService], imports: [SignatureComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SignatureModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_SIGNATURE],
exports: [...KENDO_SIGNATURE],
providers: [IconsService, PopupService, ResizeBatchService, DialogContainerService, DialogService, WindowService, WindowContainerService]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
* definition for the Rating component.
*
* @example
*
* ```ts-no-run
* // Import the Rating module
* import { RatingModule } from '@progress/kendo-angular-inputs';
*
* // The browser platform with a compiler
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
*
* import { NgModule } from '@angular/core';
*
* // Import the app component
* import { AppComponent } from './app.component';
*
* // Define the app module
* _@NgModule({
* declarations: [AppComponent], // declare app component
* imports: [BrowserModule, RatingModule], // import Rating module
* bootstrap: [AppComponent]
* })
* export class AppModule {}
*
* // Compile and launch the module
* platformBrowserDynamic().bootstrapModule(AppModule);
*
* ```
*/
class RatingModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: RatingModule, imports: [RatingComponent, RatingItemTemplateDirective, RatingHoveredItemTemplateDirective, RatingSelectedItemTemplateDirective], exports: [RatingComponent, RatingItemTemplateDirective, RatingHoveredItemTemplateDirective, RatingSelectedItemTemplateDirective] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingModule, providers: [IconsService], imports: [RatingComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RatingModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_RATING],
exports: [...KENDO_RATING],
providers: [IconsService]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { ActiveColorClickEvent, CheckBoxComponent, CheckBoxDirective, CheckBoxModule, ColorGradientComponent, ColorPaletteComponent, ColorPickerCancelEvent, ColorPickerCloseEvent, ColorPickerComponent, ColorPickerCustomMessagesComponent, ColorPickerModule, ColorPickerOpenEvent, ErrorComponent, FlatColorPickerComponent, FormFieldComponent, FormFieldModule, HintComponent, InputSeparatorComponent, InputsModule, KENDO_CHECKBOX, KENDO_COLORGRADIENT, KENDO_COLORPALETTE, KENDO_COLORPICKER, KENDO_FLATCOLORPICKER, KENDO_FORMFIELD, KENDO_INPUTS, KENDO_MASKEDTEXTBOX, KENDO_NUMERICTEXTBOX, KENDO_OTPINPUT, KENDO_RADIOBUTTON, KENDO_RANGESLIDER, KENDO_RATING, KENDO_SIGNATURE, KENDO_SLIDER, KENDO_SWITCH, KENDO_TEXTAREA, KENDO_TEXTBOX, LabelTemplateDirective, LocalizedColorPickerMessagesDirective, LocalizedNumericTextBoxMessagesDirective, LocalizedRangeSliderMessagesDirective, LocalizedSignatureMessagesDirective, LocalizedSliderMessagesDirective, LocalizedSwitchMessagesDirective, LocalizedTextBoxMessagesDirective, MaskedTextBoxComponent, MaskedTextBoxModule, MaskingService, NumericLabelDirective, NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent, NumericTextBoxModule, OTPInputComponent, OTPInputCustomMessagesComponent, RadioButtonComponent, RadioButtonDirective, RadioButtonModule, RangeSliderComponent, RangeSliderCustomMessagesComponent, RangeSliderModule, RatingComponent, RatingHoveredItemTemplateDirective, RatingItemTemplateDirective, RatingModule, RatingSelectedItemTemplateDirective, SignatureCloseEvent, SignatureComponent, SignatureCustomMessagesComponent, SignatureMessages, SignatureModule, SignatureOpenEvent, SliderComponent, SliderCustomMessagesComponent, SliderModule, SliderTicksComponent, SwitchBlurEvent, SwitchComponent, SwitchCustomMessagesComponent, SwitchFocusEvent, SwitchModule, TextAreaComponent, TextAreaDirective, TextAreaModule, TextAreaPrefixComponent, TextAreaSuffixComponent, TextBoxComponent, TextBoxCustomMessagesComponent, TextBoxDirective, TextBoxModule, TextBoxPrefixTemplateDirective, TextBoxSuffixTemplateDirective };