igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1 lines • 637 kB
Source Map (JSON)
{"version":3,"file":"igniteui-angular-directives.mjs","sources":["../../../projects/igniteui-angular/directives/src/directives/button/button-base.ts","../../../projects/igniteui-angular/directives/src/directives/button/button.directive.ts","../../../projects/igniteui-angular/directives/src/directives/checkbox/checkbox-base.directive.ts","../../../projects/igniteui-angular/directives/src/directives/divider/divider.directive.ts","../../../projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.strategy.ts","../../../projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.directive.ts","../../../projects/igniteui-angular/directives/src/directives/drag-drop/public_api.ts","../../../projects/igniteui-angular/directives/src/directives/filter/filter.directive.ts","../../../projects/igniteui-angular/directives/src/directives/focus/focus.directive.ts","../../../projects/igniteui-angular/directives/src/directives/focus-trap/focus-trap.directive.ts","../../../projects/igniteui-angular/directives/src/directives/scroll-inertia/scroll_inertia.directive.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/display.container.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/base.helper.component.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/horizontal.virtual.helper.component.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/virtual.helper.component.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/for_of.sync.service.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts","../../../projects/igniteui-angular/directives/src/directives/button/icon-button.directive.ts","../../../projects/igniteui-angular/directives/src/directives/layout/layout.directive.ts","../../../projects/igniteui-angular/directives/src/directives/mask/mask-parsing.service.ts","../../../projects/igniteui-angular/directives/src/directives/mask/mask.directive.ts","../../../projects/igniteui-angular/directives/src/directives/ripple/ripple.directive.ts","../../../projects/igniteui-angular/directives/src/directives/size/ig-size.directive.ts","../../../projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.service.ts","../../../projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.directive.ts","../../../projects/igniteui-angular/directives/src/directives/text-selection/text-selection.directive.ts","../../../projects/igniteui-angular/directives/src/directives/template-outlet/template_outlet.directive.ts","../../../projects/igniteui-angular/directives/src/directives/toggle/toggle.directive.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip.component.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip.component.html","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip-close-button.component.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip.common.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip-target.directive.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/public_api.ts","../../../projects/igniteui-angular/directives/src/directives/date-time-editor/date-time-editor.directive.ts","../../../projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.ts","../../../projects/igniteui-angular/directives/src/directives/notification/notifications.directive.ts","../../../projects/igniteui-angular/directives/src/directives/button/button.module.ts","../../../projects/igniteui-angular/directives/src/directives/date-time-editor/date-time-editor.module.ts","../../../projects/igniteui-angular/directives/src/directives/divider/divider.module.ts","../../../projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.module.ts","../../../projects/igniteui-angular/directives/src/directives/filter/filter.module.ts","../../../projects/igniteui-angular/directives/src/directives/focus/focus.module.ts","../../../projects/igniteui-angular/directives/src/directives/focus-trap/focus-trap.module.ts","../../../projects/igniteui-angular/directives/src/directives/for-of/for_of.module.ts","../../../projects/igniteui-angular/directives/src/directives/form-control/form-control.module.ts","../../../projects/igniteui-angular/directives/src/directives/layout/layout.module.ts","../../../projects/igniteui-angular/directives/src/directives/mask/mask.module.ts","../../../projects/igniteui-angular/directives/src/directives/ripple/ripple.module.ts","../../../projects/igniteui-angular/directives/src/directives/scroll-inertia/scroll_inertia.module.ts","../../../projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.module.ts","../../../projects/igniteui-angular/directives/src/directives/text-selection/text-selection.module.ts","../../../projects/igniteui-angular/directives/src/directives/toggle/toggle.module.ts","../../../projects/igniteui-angular/directives/src/directives/tooltip/tooltip.module.ts","../../../projects/igniteui-angular/directives/src/public_api.ts","../../../projects/igniteui-angular/directives/src/igniteui-angular-directives.ts"],"sourcesContent":["import {\n Directive,\n ElementRef,\n EventEmitter,\n HostBinding,\n HostListener,\n Input,\n Output,\n booleanAttribute,\n inject,\n AfterViewInit,\n OnDestroy\n} from '@angular/core';\nimport { PlatformUtil } from 'igniteui-angular/core';\nimport { animationFrameScheduler, Subscription } from 'rxjs';\n\nexport const IgxBaseButtonType = {\n Flat: 'flat',\n Contained: 'contained',\n Outlined: 'outlined'\n} as const;\n\n\n@Directive()\nexport abstract class IgxButtonBaseDirective implements AfterViewInit, OnDestroy {\n private _platformUtil = inject(PlatformUtil);\n public element = inject(ElementRef);\n private _viewInit = false;\n private _animationScheduler: Subscription;\n\n /**\n * Emitted when the button is clicked.\n */\n @Output()\n public buttonClick = new EventEmitter<any>();\n\n /**\n * Sets/gets the `role` attribute.\n *\n * @example\n * ```typescript\n * this.button.role = 'navbutton';\n * let buttonRole = this.button.role;\n * ```\n */\n @HostBinding('attr.role')\n public role = 'button';\n\n /**\n * @hidden\n * @internal\n */\n @HostListener('click', ['$event'])\n public onClick(ev: MouseEvent) {\n this.buttonClick.emit(ev);\n this.focused = false;\n }\n\n /**\n * @hidden\n * @internal\n */\n @HostListener('blur')\n protected onBlur() {\n this.focused = false;\n }\n\n /**\n * Sets/gets whether the button component is on focus.\n * Default value is `false`.\n * ```typescript\n * this.button.focus = true;\n * ```\n * ```typescript\n * let isFocused = this.button.focused;\n * ```\n */\n @HostBinding('class.igx-button--focused')\n protected focused = false;\n\n /**\n * Enables/disables the button.\n *\n * @example\n * ```html\n * <button igxButton=\"fab\" disabled></button>\n * ```\n */\n @Input({ transform: booleanAttribute })\n @HostBinding('class.igx-button--disabled')\n public disabled = false;\n\n /**\n * @hidden\n * @internal\n */\n @HostBinding('attr.disabled')\n public get disabledAttribute() {\n return this.disabled || null;\n }\n\n protected constructor() {\n // In browser, set via native API for immediate effect (no-op on server).\n // In SSR there is no paint, so there’s no visual rendering or transitions to suppress.\n // Fix style flickering https://github.com/IgniteUI/igniteui-angular/issues/14759\n if (this._platformUtil.isBrowser) {\n this.element.nativeElement.style.setProperty('--_init-transition', '0s');\n }\n }\n\n public ngAfterViewInit(): void {\n if (this._platformUtil.isBrowser && !this._viewInit) {\n this._viewInit = true;\n\n this._animationScheduler = animationFrameScheduler.schedule(() => {\n this.element.nativeElement.style.removeProperty('--_init-transition');\n });\n }\n }\n\n public ngOnDestroy(): void {\n this._animationScheduler.unsubscribe();\n }\n\n /**\n * @hidden\n * @internal\n */\n @HostListener('keyup', ['$event'])\n protected updateOnKeyUp(event: KeyboardEvent) {\n if (event.key === \"Tab\") {\n this.focused = true;\n }\n }\n\n /**\n * Returns the underlying DOM element.\n */\n public get nativeElement() {\n return this.element.nativeElement;\n }\n}\n","import {\n Directive,\n EventEmitter,\n HostBinding,\n HostListener,\n Input,\n Output,\n Renderer2,\n booleanAttribute,\n inject\n} from '@angular/core';\nimport { IBaseEventArgs } from 'igniteui-angular/core';\nimport { IgxBaseButtonType, IgxButtonBaseDirective } from './button-base';\n\nconst IgxButtonType = {\n ...IgxBaseButtonType,\n FAB: 'fab'\n} as const;\n\n/**\n * Determines the Button type.\n */\nexport type IgxButtonType = typeof IgxButtonType[keyof typeof IgxButtonType];\n\n/**\n * The Button directive provides the Ignite UI Button functionality to every component that's intended to be used as a button.\n *\n * @igxModule IgxButtonModule\n *\n * @igxParent Data Entry & Display\n *\n * @igxTheme igx-button-theme\n *\n * @igxKeywords button, span, div, click\n *\n * @remarks\n * The Ignite UI Button directive is intended to be used by any button, span or div and turn it into a fully functional button.\n *\n * @example\n * ```html\n * <button type=\"button\" igxButton=\"outlined\">A Button</button>\n * ```\n */\n@Directive({\n selector: '[igxButton]',\n standalone: true\n})\nexport class IgxButtonDirective extends IgxButtonBaseDirective {\n private _renderer = inject(Renderer2);\n\n private static ngAcceptInputType_type: IgxButtonType | '';\n\n /**\n * Called when the button is selected.\n */\n @Output()\n public buttonSelected = new EventEmitter<IButtonEventArgs>();\n\n /**\n * @hidden\n * @internal\n */\n @HostBinding('class.igx-button')\n public _cssClass = 'igx-button';\n\n /**\n * @hidden\n * @internal\n */\n private _type: IgxButtonType;\n\n /**\n * @hidden\n * @internal\n */\n private _color: string;\n\n /**\n * @hidden\n * @internal\n */\n private _label: string;\n\n /**\n * @hidden\n * @internal\n */\n private _backgroundColor: string;\n\n /**\n * @hidden\n * @internal\n */\n private _selected = false;\n\n @HostListener('click')\n protected emitSelected() {\n this.buttonSelected.emit({\n button: this\n });\n }\n\n /**\n * Gets or sets whether the button is selected.\n * Mainly used in the IgxButtonGroup component and it will have no effect if set separately.\n *\n * @example\n * ```html\n * <button type=\"button\" igxButton=\"flat\" [selected]=\"button.selected\"></button>\n * ```\n */\n @Input({ transform: booleanAttribute })\n public set selected(value: boolean) {\n if (this._selected !== value) {\n this._selected = value;\n this._renderer.setAttribute(this.nativeElement, 'data-selected', value.toString());\n }\n }\n\n public get selected(): boolean {\n return this._selected;\n }\n\n constructor() {\n super();\n }\n\n /**\n * Sets the type of the button.\n *\n * @example\n * ```html\n * <button type=\"button\" igxButton=\"outlined\"></button>\n * ```\n */\n @Input('igxButton')\n public set type(type: IgxButtonType) {\n const t = type ? type : IgxButtonType.Flat;\n if (this._type !== t) {\n this._type = t;\n }\n }\n\n /**\n * Sets the `aria-label` attribute.\n *\n * @example\n * ```html\n * <button type=\"button\" igxButton=\"flat\" igxLabel=\"Label\"></button>\n * ```\n */\n @Input('igxLabel')\n public set label(value: string) {\n this._label = value || this._label;\n this._renderer.setAttribute(this.nativeElement, 'aria-label', this._label);\n }\n\n /**\n * @hidden\n * @internal\n */\n @HostBinding('class.igx-button--flat')\n public get flat(): boolean {\n return this._type === IgxButtonType.Flat;\n }\n\n /**\n * @hidden\n * @internal\n */\n @HostBinding('class.igx-button--contained')\n public get contained(): boolean {\n return this._type === IgxButtonType.Contained;\n }\n\n /**\n * @hidden\n * @internal\n */\n @HostBinding('class.igx-button--outlined')\n public get outlined(): boolean {\n return this._type === IgxButtonType.Outlined;\n }\n\n /**\n * @hidden\n * @internal\n */\n @HostBinding('class.igx-button--fab')\n public get fab(): boolean {\n return this._type === IgxButtonType.FAB;\n }\n\n /**\n * @hidden\n * @internal\n */\n public select() {\n this.selected = true;\n }\n\n /**\n * @hidden\n * @internal\n */\n public deselect() {\n this.selected = false;\n this.focused = false;\n }\n}\n\nexport interface IButtonEventArgs extends IBaseEventArgs {\n button: IgxButtonDirective;\n}\n","import { Directive, EventEmitter, HostListener, HostBinding, Input, Output, ViewChild, ElementRef, ChangeDetectorRef, booleanAttribute, inject, DestroyRef, AfterViewInit } from '@angular/core';\nimport { NgControl, Validators } from '@angular/forms';\nimport { IBaseEventArgs, getComponentTheme } from 'igniteui-angular/core';\nimport { noop, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport {\n IgxTheme,\n THEME_TOKEN,\n ThemeToken,\n} from 'igniteui-angular/core';\n\nexport const LabelPosition = {\n BEFORE: 'before',\n AFTER: 'after'\n} as const;\nexport type LabelPosition = typeof LabelPosition[keyof typeof LabelPosition];\n\nexport interface IChangeCheckboxEventArgs extends IBaseEventArgs {\n checked: boolean;\n value?: any;\n}\n\nlet nextId = 0;\n\n@Directive()\nexport class CheckboxBaseDirective implements AfterViewInit {\n protected cdr = inject(ChangeDetectorRef);\n protected themeToken = inject<ThemeToken>(THEME_TOKEN);\n public ngControl = inject(NgControl, { optional: true, self: true });\n\n /**\n * An event that is emitted after the checkbox state is changed.\n * Provides references to the `IgxCheckboxComponent` and the `checked` property as event arguments.\n */\n // eslint-disable-next-line @angular-eslint/no-output-native\n @Output() public readonly change: EventEmitter<IChangeCheckboxEventArgs> =\n new EventEmitter<IChangeCheckboxEventArgs>();\n\n /**\n * @hidden\n * @internal\n */\n public destroy$ = new Subject<boolean>();\n\n /**\n * Returns reference to the native checkbox element.\n *\n * @example\n * ```typescript\n * let checkboxElement = this.component.checkboxElement;\n * ```\n */\n @ViewChild('checkbox', { static: true })\n public nativeInput: ElementRef;\n\n /**\n * Returns reference to the native label element.\n * ```typescript\n *\n * @example\n * let labelElement = this.component.nativeLabel;\n * ```\n */\n @ViewChild('label', { static: true })\n public nativeLabel: ElementRef;\n\n public cssClass: string;\n public disabled: boolean;\n public readonly: boolean;\n public indeterminate: boolean;\n public focused: boolean;\n public invalid: boolean;\n\n @Input({ transform: booleanAttribute })\n public get checked() {\n return this._checked;\n }\n\n public set checked(value: boolean) {\n if (this._checked !== value) {\n this._checked = value;\n this._onChangeCallback(this._checked);\n }\n }\n\n /**\n * Returns reference to the `nativeElement` of the igx-checkbox/igx-switch.\n *\n * @example\n * ```typescript\n * let nativeElement = this.component.nativeElement;\n * ```\n */\n public get nativeElement() {\n return this.nativeInput.nativeElement;\n }\n\n /**\n * Returns reference to the label placeholder element.\n * ```typescript\n *\n * @example\n * let labelPlaceholder = this.component.placeholderLabel;\n * ```\n */\n @ViewChild('placeholderLabel', { static: true })\n public placeholderLabel: ElementRef;\n\n /**\n * Sets/gets the `id` of the checkbox component.\n * If not set, the `id` of the first checkbox component will be `\"igx-checkbox-0\"`.\n *\n * @example\n * ```html\n * <igx-checkbox id=\"my-first-checkbox\"></igx-checkbox>\n * ```\n * ```typescript\n * let checkboxId = this.checkbox.id;\n * ```\n */\n @HostBinding('attr.id')\n @Input()\n public id = `igx-checkbox-${nextId++}`;\n\n /**\n * Sets/gets the id of the `label` element.\n * If not set, the id of the `label` in the first checkbox component will be `\"igx-checkbox-0-label\"`.\n *\n * @example\n * ```html\n * <igx-checkbox labelId=\"Label1\"></igx-checkbox>\n * ```\n * ```typescript\n * let labelId = this.component.labelId;\n * ```\n */\n @Input() public labelId = `${this.id}-label`;\n\n /**\n * Sets/gets the `value` attribute.\n *\n * @example\n * ```html\n * <igx-checkbox [value]=\"'CheckboxValue'\"></igx-checkbox>\n * ```\n * ```typescript\n * let value = this.checkbox.value;\n * ```\n */\n @Input() public value: any;\n\n /**\n * Sets/gets the `name` attribute.\n *\n * @example\n * ```html\n * <igx-checkbox name=\"Checkbox1\"></igx-checkbox>\n * ```\n * ```typescript\n * let name = this.checkbox.name;\n * ```\n */\n @Input() public name: string;\n\n /**\n * Sets/gets the value of the `tabindex` attribute.\n *\n * @example\n * ```html\n * <igx-checkbox [tabindex]=\"1\"></igx-checkbox>\n * ```\n * ```typescript\n * let tabIndex = this.checkbox.tabindex;\n * ```\n */\n @Input() public tabindex: number = null;\n\n /**\n * Sets/gets the position of the `label`.\n * If not set, the `labelPosition` will have value `\"after\"`.\n *\n * @example\n * ```html\n * <igx-checkbox labelPosition=\"before\"></igx-checkbox>\n * ```\n * ```typescript\n * let labelPosition = this.checkbox.labelPosition;\n * ```\n */\n @Input()\n public labelPosition: LabelPosition | string = LabelPosition.AFTER;\n\n /**\n * Enables/Disables the ripple effect.\n * If not set, `disableRipple` will have value `false`.\n *\n * @example\n * ```html\n * <igx-checkbox [disableRipple]=\"true\"></igx-checkbox>\n * ```\n * ```typescript\n * let isRippleDisabled = this.checkbox.desableRipple;\n * ```\n */\n @Input({ transform: booleanAttribute })\n public disableRipple = false;\n\n /**\n * Sets/gets the `aria-labelledby` attribute.\n * If not set, the `aria-labelledby` will be equal to the value of `labelId` attribute.\n *\n * @example\n * ```html\n * <igx-checkbox aria-labelledby=\"Checkbox1\"></igx-checkbox>\n * ```\n * ```typescript\n * let ariaLabelledBy = this.checkbox.ariaLabelledBy;\n * ```\n */\n @Input('aria-labelledby')\n public ariaLabelledBy = this.labelId;\n\n /**\n * Sets/gets the value of the `aria-label` attribute.\n *\n * @example\n * ```html\n * <igx-checkbox aria-label=\"Checkbox1\"></igx-checkbox>\n * ```\n * ```typescript\n * let ariaLabel = this.checkbox.ariaLabel;\n * ```\n */\n @Input('aria-label')\n public ariaLabel: string | null = null;\n\n constructor() {\n if (this.ngControl !== null) {\n this.ngControl.valueAccessor = this;\n }\n\n this.theme = this.themeToken.theme;\n\n const themeChange = this.themeToken.onChange((theme) => {\n if (this.theme !== theme) {\n this.theme = theme;\n this.cdr.detectChanges();\n }\n });\n\n this.destroyRef.onDestroy(() => themeChange.unsubscribe());\n }\n\n /**\n * Sets/gets whether the checkbox is required.\n * If not set, `required` will have value `false`.\n *\n * @example\n * ```html\n * <igx-checkbox required></igx-checkbox>\n * ```\n * ```typescript\n * let isRequired = this.checkbox.required;\n * ```\n */\n @Input({ transform: booleanAttribute })\n public get required(): boolean {\n return this._required || this.nativeElement.hasAttribute('required');\n }\n public set required(value: boolean) {\n if (!value) {\n this.nativeElement.removeAttribute('required');\n }\n this._required = value;\n }\n\n /**\n * @hidden\n * @internal\n */\n public ngAfterViewInit() {\n if (this.ngControl) {\n this.ngControl.statusChanges\n .pipe(takeUntil(this.destroy$))\n .subscribe(this.updateValidityState.bind(this));\n\n if (\n this.ngControl.control.validator ||\n this.ngControl.control.asyncValidator\n ) {\n this._required = this.ngControl?.control?.hasValidator(\n Validators.required\n );\n this.cdr.detectChanges();\n }\n }\n\n this.setComponentTheme();\n }\n\n /**\n * @hidden\n * @internal\n */\n public inputId = `${this.id}-input`;\n\n /**\n * @hidden\n */\n protected _onChangeCallback: (_: any) => void = noop;\n\n /**\n * @hidden\n */\n private _onTouchedCallback: () => void = noop;\n\n /**\n * @hidden\n * @internal\n */\n protected _checked = false;\n\n /**\n * @hidden\n * @internal\n */\n protected theme: IgxTheme;\n\n /**\n * @hidden\n * @internal\n */\n public _required = false;\n private elRef = inject(ElementRef);\n protected destroyRef = inject(DestroyRef);\n\n private setComponentTheme() {\n if (!this.themeToken.preferToken) {\n const theme = getComponentTheme(this.elRef.nativeElement);\n\n if (theme && theme !== this.theme) {\n this.theme = theme;\n this.cdr.markForCheck();\n }\n }\n }\n\n /** @hidden @internal */\n @HostListener('keyup', ['$event'])\n public onKeyUp(event: KeyboardEvent) {\n event.stopPropagation();\n this.focused = true;\n }\n\n /** @hidden @internal */\n @HostListener('click', ['$event'])\n public _onCheckboxClick(event: PointerEvent | MouseEvent) {\n // Since the original checkbox is hidden and the label\n // is used for styling and to change the checked state of the checkbox,\n // we need to prevent the checkbox click event from bubbling up\n // as it gets triggered on label click\n // NOTE: The above is no longer valid, as the native checkbox is not labeled\n // by the SVG anymore.\n if (this.disabled || this.readonly) {\n // readonly prevents the component from changing state (see toggle() method).\n // However, the native checkbox can still be activated through user interaction (focus + space, label click)\n // Prevent the native change so the input remains in sync\n event.preventDefault();\n return;\n }\n\n this.nativeElement.focus();\n\n this.indeterminate = false;\n this.checked = !this.checked;\n this.updateValidityState();\n\n // K.D. March 23, 2021 Emitting on click and not on the setter because otherwise every component\n // bound on change would have to perform self checks for weather the value has changed because\n // of the initial set on initialization\n this.change.emit({\n checked: this.checked,\n value: this.value,\n owner: this,\n });\n }\n\n /**\n * @hidden\n * @internal\n */\n public get ariaChecked() {\n if (this.indeterminate) {\n return 'mixed';\n } else {\n return this.checked;\n }\n }\n\n /** @hidden @internal */\n public _onCheckboxChange(event: Event) {\n // We have to stop the original checkbox change event\n // from bubbling up since we emit our own change event\n event.stopPropagation();\n }\n\n /** @hidden @internal */\n @HostListener('blur')\n public onBlur() {\n this.focused = false;\n this._onTouchedCallback();\n this.updateValidityState();\n }\n\n /** @hidden @internal */\n public writeValue(value: boolean) {\n this._checked = value;\n }\n\n /** @hidden @internal */\n public get labelClass(): string {\n switch (this.labelPosition) {\n case LabelPosition.BEFORE:\n return `${this.cssClass}__label--before`;\n case LabelPosition.AFTER:\n default:\n return `${this.cssClass}__label`;\n }\n }\n\n /** @hidden @internal */\n public registerOnChange(fn: (_: any) => void) {\n this._onChangeCallback = fn;\n }\n\n /** @hidden @internal */\n public registerOnTouched(fn: () => void) {\n this._onTouchedCallback = fn;\n }\n\n /** @hidden @internal */\n public setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n\n /** @hidden @internal */\n public getEditElement() {\n return this.nativeInput.nativeElement;\n }\n\n /**\n * @hidden\n * @internal\n */\n protected updateValidityState() {\n if (this.ngControl) {\n if (\n !this.disabled &&\n !this.readonly &&\n (this.ngControl.control.touched || this.ngControl.control.dirty)\n ) {\n // the control is not disabled and is touched or dirty\n this.invalid = this.ngControl.invalid;\n } else {\n // if the control is untouched, pristine, or disabled, its state is initial. This is when the user did not interact\n // with the checkbox or when the form/control is reset\n this.invalid = false;\n }\n } else {\n this.checkNativeValidity();\n }\n }\n\n /**\n * A function to assign a native validity property of a checkbox.\n * This should be used when there's no ngControl\n *\n * @hidden\n * @internal\n */\n private checkNativeValidity() {\n if (\n !this.disabled &&\n this._required &&\n !this.checked &&\n !this.readonly\n ) {\n this.invalid = true;\n } else {\n this.invalid = false;\n }\n }\n}\n","import { Directive, HostBinding, Input, booleanAttribute } from '@angular/core';\n\nexport const IgxDividerType = {\n SOLID: 'solid',\n DASHED: 'dashed'\n} as const;\nexport type IgxDividerType = (typeof IgxDividerType)[keyof typeof IgxDividerType];\n\nlet NEXT_ID = 0;\n\n@Directive({\n selector: 'igx-divider',\n standalone: true\n})\nexport class IgxDividerDirective {\n /**\n * Sets/gets the `id` of the divider.\n * If not set, `id` will have value `\"igx-divider-0\"`;\n * ```html\n * <igx-divider id=\"my-divider\"></igx-divider>\n * ```\n * ```typescript\n * let dividerId = this.divider.id;\n * ```\n */\n @HostBinding('attr.id')\n @Input()\n public id = `igx-divider-${NEXT_ID++}`;\n\n /**\n * Sets the value of `role` attribute.\n * If not the default value of `separator` will be used.\n */\n @HostBinding('attr.role')\n @Input()\n public role = 'separator';\n\n /**\n * Sets the type of the divider. The default value\n * is `default`. The divider can also be `dashed`;\n * ```html\n * <igx-divider type=\"dashed\"></igx-divider>\n * ```\n */\n @HostBinding('class.igx-divider')\n @Input()\n public type: IgxDividerType | string = IgxDividerType.SOLID;\n\n @HostBinding('class.igx-divider--dashed')\n public get isDashed() {\n return this.type === IgxDividerType.DASHED;\n }\n\n /**\n * If set to `true` and an `inset` value has been provided,\n * the divider will start shrinking from both ends.\n * ```html\n * <igx-divider [middle]=\"true\"></igx-divider>\n * ```\n */\n @HostBinding('class.igx-divider--inset')\n @Input({ transform: booleanAttribute })\n public middle = false;\n\n /**\n * Sets the divider in vertical orientation.\n * ```html\n * <igx-divider [vertical]=\"true\"></igx-divider>\n * ```\n */\n @HostBinding('class.igx-divider--vertical')\n @Input({ transform: booleanAttribute })\n public vertical = false;\n\n /**\n * Sets the inset of the divider from the side(s).\n * If the divider attribute `middle` is set to `true`,\n * it will inset the divider on both sides.\n * ```typescript\n * this.divider.inset = '32px';\n * ```\n */\n @HostBinding('style.--inset')\n @Input()\n public set inset(value: string) {\n this._inset = value;\n }\n\n /**\n * Gets the current divider inset in terms of\n * inset-inline-start representation as applied to the divider.\n * ```typescript\n * const inset = this.divider.inset;\n * ```\n */\n public get inset() {\n return this._inset;\n }\n\n /**\n * Sets the value of the `inset` attribute.\n * If not provided it will be set to `'0'`.\n * ```html\n * <igx-divider inset=\"16px\"></igx-divider>\n * ```\n */\n private _inset = '0';\n\n /**\n * A getter that returns `true` if the type of the divider is `default`;\n * ```typescript\n * const isDefault = this.divider.isDefault;\n * ```\n */\n public get isSolid() {\n return this.type === IgxDividerType.SOLID;\n }\n\n}\n\n\n","import { Renderer2 } from '@angular/core';\nimport { IgxDragDirective, IgxDropDirective } from './drag-drop.directive';\n\n\nexport interface IDropStrategy {\n dropAction: (drag: IgxDragDirective, drop: IgxDropDirective, atIndex: number) => void;\n}\n\n// @dynamic\nexport class IgxDefaultDropStrategy implements IDropStrategy {\n\n public dropAction(_drag: IgxDragDirective, _drop: IgxDropDirective, _atIndex: number) { }\n}\n\n// @dynamic\nexport class IgxAppendDropStrategy implements IDropStrategy {\n\n constructor(private _renderer: Renderer2) { }\n\n public dropAction(drag: IgxDragDirective, drop: IgxDropDirective, _atIndex: number) {\n const dragElement = drag.element.nativeElement;\n const dropAreaElement = drop.element.nativeElement;\n this._renderer.removeChild(dragElement.parentNode, dragElement);\n this._renderer.appendChild(dropAreaElement, dragElement);\n }\n}\n\n// @dynamic\nexport class IgxPrependDropStrategy implements IDropStrategy {\n\n constructor(private _renderer: Renderer2) { }\n\n public dropAction(drag: IgxDragDirective, drop: IgxDropDirective, _atIndex: number) {\n const dragElement = drag.element.nativeElement;\n const dropAreaElement = drop.element.nativeElement;\n this._renderer.removeChild(dragElement.parentNode, dragElement);\n if (dropAreaElement.children.length) {\n this._renderer.insertBefore(dropAreaElement, dragElement, dropAreaElement.children[0]);\n } else {\n this._renderer.appendChild(dropAreaElement, dragElement);\n }\n }\n}\n\n// @dynamic\nexport class IgxInsertDropStrategy implements IDropStrategy {\n\n constructor(private _renderer: Renderer2) { }\n\n public dropAction(drag: IgxDragDirective, drop: IgxDropDirective, atIndex: number) {\n if (drag.element.nativeElement.parentElement === drop.element.nativeElement && atIndex === -1) {\n return;\n }\n\n const dragElement = drag.element.nativeElement;\n const dropAreaElement = drop.element.nativeElement;\n this._renderer.removeChild(dragElement.parentNode, dragElement);\n if (atIndex !== -1 && dropAreaElement.children.length > atIndex) {\n this._renderer.insertBefore(dropAreaElement, dragElement, dropAreaElement.children[atIndex]);\n } else {\n this._renderer.appendChild(dropAreaElement, dragElement);\n }\n }\n}\n","import {\n Directive,\n ElementRef,\n EventEmitter,\n HostBinding,\n HostListener,\n Input,\n NgZone,\n OnDestroy,\n OnInit,\n Output,\n Renderer2,\n ChangeDetectorRef,\n ViewContainerRef,\n AfterContentInit,\n TemplateRef,\n ContentChildren,\n QueryList,\n RendererStyleFlags2,\n booleanAttribute,\n EmbeddedViewRef,\n inject,\n DOCUMENT\n} from '@angular/core';\nimport { animationFrameScheduler, fromEvent, interval, Subject } from 'rxjs';\nimport { takeUntil, throttle } from 'rxjs/operators';\nimport { IBaseEventArgs, PlatformUtil } from 'igniteui-angular/core';\nimport { IDropStrategy, IgxDefaultDropStrategy } from './drag-drop.strategy';\n\nenum DragScrollDirection {\n UP,\n DOWN,\n LEFT,\n RIGHT\n}\n\nexport enum DragDirection {\n VERTICAL,\n HORIZONTAL,\n BOTH\n}\n\nexport interface IgxDragCustomEventDetails {\n startX: number;\n startY: number;\n pageX: number;\n pageY: number;\n owner: IgxDragDirective;\n originalEvent: any;\n}\n\nexport interface IDropBaseEventArgs extends IBaseEventArgs {\n /**\n * Reference to the original event that caused the draggable element to enter the igxDrop element.\n * Can be PointerEvent, TouchEvent or MouseEvent.\n */\n originalEvent: any;\n /** The owner igxDrop directive that triggered this event. */\n owner: IgxDropDirective;\n /** The igxDrag directive instanced on an element that entered the area of the igxDrop element */\n drag: IgxDragDirective;\n /** The data contained for the draggable element in igxDrag directive. */\n dragData: any;\n /** The initial position of the pointer on X axis when the dragged element began moving */\n startX: number;\n /** The initial position of the pointer on Y axis when the dragged element began moving */\n startY: number;\n /**\n * The current position of the pointer on X axis when the event was triggered.\n * Note: The browser might trigger the event with some delay and pointer would be already inside the igxDrop.\n */\n pageX: number;\n /**\n * The current position of the pointer on Y axis when the event was triggered.\n * Note: The browser might trigger the event with some delay and pointer would be already inside the igxDrop.\n */\n pageY: number;\n /**\n * The current position of the pointer on X axis relative to the container that initializes the igxDrop.\n * Note: The browser might trigger the event with some delay and pointer would be already inside the igxDrop.\n */\n offsetX: number;\n /**\n * The current position of the pointer on Y axis relative to the container that initializes the igxDrop.\n * Note: The browser might trigger the event with some delay and pointer would be already inside the igxDrop.\n */\n offsetY: number;\n}\n\nexport interface IDropDroppedEventArgs extends IDropBaseEventArgs {\n /** Specifies if the default drop logic related to the event should be canceled. */\n cancel: boolean;\n}\n\nexport interface IDragBaseEventArgs extends IBaseEventArgs {\n /**\n * Reference to the original event that caused the interaction with the element.\n * Can be PointerEvent, TouchEvent or MouseEvent.\n */\n originalEvent: PointerEvent | MouseEvent | TouchEvent;\n /** The owner igxDrag directive that triggered this event. */\n owner: IgxDragDirective;\n /** The initial position of the pointer on X axis when the dragged element began moving */\n startX: number;\n /** The initial position of the pointer on Y axis when the dragged element began moving */\n startY: number;\n /**\n * The current position of the pointer on X axis when the event was triggered.\n * Note: The browser might trigger the event with some delay and pointer would be already inside the igxDrop.\n */\n pageX: number;\n /**\n * The current position of the pointer on Y axis when the event was triggered.\n * Note: The browser might trigger the event with some delay and pointer would be already inside the igxDrop.\n */\n pageY: number;\n}\n\nexport interface IDragStartEventArgs extends IDragBaseEventArgs {\n /** Set if the the dragging should be canceled. */\n cancel: boolean;\n}\n\nexport interface IDragMoveEventArgs extends IDragStartEventArgs {\n /** The new pageX position of the pointer that the igxDrag will use. It can be overridden to limit dragged element X movement. */\n nextPageX: number;\n /** The new pageX position of the pointer that the igxDrag will use. It can be overridden to limit dragged element Y movement. */\n nextPageY: number;\n}\n\n\nexport interface IDragGhostBaseEventArgs extends IBaseEventArgs {\n /** The owner igxDrag directive that triggered this event. */\n owner: IgxDragDirective;\n /** Instance to the ghost element that is created when dragging starts. */\n ghostElement: any;\n /** Set if the ghost creation/destruction should be canceled. */\n cancel: boolean;\n}\n\nexport interface IDragCustomTransitionArgs {\n duration?: number;\n timingFunction?: string;\n delay?: number;\n}\n\nexport class IgxDragLocation {\n public pageX: number;\n public pageY: number;\n\n constructor(private _pageX, private _pageY) {\n this.pageX = parseFloat(_pageX);\n this.pageY = parseFloat(_pageY);\n }\n}\n\n@Directive({\n selector: '[igxDragHandle]',\n standalone: true\n})\nexport class IgxDragHandleDirective {\n public element = inject(ElementRef<any>);\n\n @HostBinding('class.igx-drag__handle')\n public baseClass = true;\n\n /**\n * @hidden\n */\n public parentDragElement: HTMLElement = null;\n}\n\n@Directive({\n selector: '[igxDragIgnore]',\n standalone: true\n})\nexport class IgxDragIgnoreDirective {\n public element = inject(ElementRef<any>);\n\n @HostBinding('class.igx-drag__ignore')\n public baseClass = true;\n}\n\n@Directive({\n exportAs: 'drag',\n selector: '[igxDrag]',\n standalone: true\n})\nexport class IgxDragDirective implements AfterContentInit, OnDestroy {\n /**\n * - Save data inside the `igxDrag` directive. This can be set when instancing `igxDrag` on an element.\n * ```html\n * <div [igxDrag]=\"{ source: myElement }\"></div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input('igxDrag')\n public set data(value: any) {\n this._data = value;\n }\n\n public get data(): any {\n return this._data;\n }\n\n /**\n * Sets the tolerance in pixels before drag starts.\n * By default the drag starts after the draggable element is moved by 5px.\n * ```html\n * <div igxDrag [dragTolerance]=\"100\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public dragTolerance = 5;\n\n /**\n * Sets the directions that the element can be dragged.\n * By default it is set to both horizontal and vertical directions.\n * ```html\n * <div igxDrag [dragDirection]=\"dragDir\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public dragDir = DragDirection.HORIZONTAL;\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public dragDirection = DragDirection.BOTH;\n\n /**\n * A property that provides a way for igxDrag and igxDrop to be linked through channels.\n * It accepts single value or an array of values and evaluates then using strict equality.\n * ```html\n * <div igxDrag [dragChannel]=\"'odd'\">\n * <span>95</span>\n * </div>\n * <div igxDrop [dropChannel]=\"['odd', 'irrational']\">\n * <span>Numbers drop area!</span>\n * </div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public dragChannel: number | string | number[] | string[];\n\n /**\n * Sets whether the base element should be moved, or a ghost element should be rendered that represents it instead.\n * By default it is set to `true`.\n * If it is set to `false` when dragging the base element is moved instead and no ghost elements are rendered.\n * ```html\n * <div igxDrag [ghost]=\"false\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input({ transform: booleanAttribute })\n public ghost = true;\n\n /**\n * Sets a custom class that will be added to the `ghostElement` element.\n * ```html\n * <div igxDrag [ghostClass]=\"'ghostElement'\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public ghostClass = '';\n\n /**\n * Set styles that will be added to the `ghostElement` element.\n * ```html\n * <div igxDrag [ghostStyle]=\"{'--ig-size': 'var(--ig-size-small)'}\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public ghostStyle = {};\n\n /**\n * Specifies a template for the ghost element created when dragging starts and `ghost` is true.\n * By default a clone of the base element the igxDrag is instanced is created.\n * ```html\n * <div igxDrag [ghostTemplate]=\"customGhost\">\n * <span>Drag Me!</span>\n * </div>\n * <ng-template #customGhost>\n * <div class=\"customGhostStyle\">\n * <span>I am being dragged!</span>\n * </div>\n * </ng-template>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public ghostTemplate: TemplateRef<any>;\n\n /**\n * Sets the element to which the dragged element will be appended.\n * By default it's set to null and the dragged element is appended to the body.\n * ```html\n * <div #hostDiv></div>\n * <div igxDrag [ghostHost]=\"hostDiv\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Input()\n public ghostHost;\n\n /**\n * Overrides the scroll container of the dragged element. By default its the window.\n */\n @Input()\n public scrollContainer: HTMLElement = null\n\n /**\n * Event triggered when the draggable element drag starts.\n * ```html\n * <div igxDrag (dragStart)=\"onDragStart()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public onDragStart(){\n * alert(\"The drag has stared!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public dragStart = new EventEmitter<IDragStartEventArgs>();\n\n /**\n * Event triggered when the draggable element has been moved.\n * ```html\n * <div igxDrag (dragMove)=\"onDragMove()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public onDragMove(){\n * alert(\"The element has moved!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public dragMove = new EventEmitter<IDragMoveEventArgs>();\n\n /**\n * Event triggered when the draggable element is released.\n * ```html\n * <div igxDrag (dragEnd)=\"onDragEnd()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public onDragEnd(){\n * alert(\"The drag has ended!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public dragEnd = new EventEmitter<IDragBaseEventArgs>();\n\n /**\n * Event triggered when the draggable element is clicked.\n * ```html\n * <div igxDrag (dragClick)=\"onDragClick()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public onDragClick(){\n * alert(\"The element has been clicked!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public dragClick = new EventEmitter<IDragBaseEventArgs>();\n\n /**\n * Event triggered when the drag ghost element is created.\n * ```html\n * <div igxDrag (ghostCreate)=\"ghostCreated()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public ghostCreated(){\n * alert(\"The ghost has been created!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public ghostCreate = new EventEmitter<IDragGhostBaseEventArgs>();\n\n /**\n * Event triggered when the drag ghost element is created.\n * ```html\n * <div igxDrag (ghostDestroy)=\"ghostDestroyed()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public ghostDestroyed(){\n * alert(\"The ghost has been destroyed!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public ghostDestroy = new EventEmitter<IDragGhostBaseEventArgs>();\n\n /**\n * Event triggered after the draggable element is released and after its animation has finished.\n * ```html\n * <div igxDrag (transitioned)=\"onMoveEnd()\">\n * <span>Drag Me!</span>\n * </div>\n * ```\n * ```typescript\n * public onMoveEnd(){\n * alert(\"The move has ended!\");\n * }\n * ```\n *\n * @memberof IgxDragDirective\n */\n @Output()\n public transitioned = new EventEmitter<IDragBaseEventArgs>();\n\n /**\n * @hidden\n */\n @ContentChildren(IgxDragHandleDirective, { descendants: true })\n public dragHandles: QueryList<IgxDragHandleDirective>;\n\n /**\n * @hidden\n */\n @ContentChildren(IgxDragIgnoreDirective, { descendants: true })\n public dragIgnoredElems: QueryList<IgxDragIgnoreDirective>;\n\n /**\n * @hidden\n */\n @HostBinding('class.igx-drag')\n public baseClass = true;\n\n /**\n * @hidden\n */\n @HostBinding('class.igx-drag--select-disabled')\n public selectDisabled = false;\n\n\n /**\n * Gets the current location of the element relative to the page.\n */\n public get location(): IgxDragLocation {\n return new IgxDragLocation(this.pageX, this.pageY);\n }\n\n /**\n * Gets the original location of the element before dragging started.\n */\n public get originLocation(): IgxDragLocation {\n return new IgxDragLocation(this.baseOriginLeft, this.baseOriginTop);\n }\n\n /**\n * @hidden\n */\n public get pointerEventsEnabled() {\n return typeof PointerEvent !== 'undefined';\n }\n\n /**\n * @hidden\n */\n public get touchEventsEnabled() {\n return 'ontouchstart' in window;\n }\n\n /**\n * @hidden\n */\n public get pageX() {\n if (this.ghost && this.ghostElement) {\n return this.ghostLeft;\n }\n return this.baseLeft + this.windowScrollLeft;\n }\n\n /**\n * @hidden\n */\n public get pageY() {\n if (this.ghost && this.ghostElement) {\n return this.ghostTop;\n }\n return this.baseTop + this.windowScrollTop;\n }\n\n protected get baseLeft(): number {\n return this.element.nativeElement.getBoundingClientRect().left;\n }\n\n protected get baseTop(): number {\n return this.element.nativeElement.getBoundingClientRect().top;\n }\n\n protected get baseOriginLeft(): number {\n return this.baseLeft - this.getTransformX(this.element.nativeElement);\n }\n\n protected get baseOriginTop(): number {\n return this.baseTop - this.getTransformY(this.element.nativeElement);\n }\n\n protected set ghostLeft(pageX: number) {\n if (this.ghostElement) {\n // We need to take into account marginLeft, since top style does not include margin, but pageX includes the margin.\n const ghostMarginLeft = parseInt(this.document.defaultView.getComputedStyle(this.ghostElement)['margin-left'], 10);\n // If ghost host is defined it needs to be taken into account.\n this.ghostElement.style.left = (pageX - ghostMarginLeft - this._ghostHostX) + 'px';\n }\n }\n\n protected get ghostLeft() {\n if (this.ghostElement) {\n return parseInt(this.ghostElement.style.left, 10) + this._ghostHostX;\n }\n }\n\n p