igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,147 lines (1,140 loc) • 46.2 kB
JavaScript
import * as i3 from 'igniteui-angular/input-group';
import { IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-group';
import * as i0 from '@angular/core';
import { inject, ChangeDetectorRef, ElementRef, Renderer2, DOCUMENT, EventEmitter, TemplateRef, booleanAttribute, HostListener, ViewChild, HostBinding, Output, Input, Component, IterableDiffers, ContentChildren, NgModule } from '@angular/core';
import { IgxDropDirective, IgxDragDirective } from 'igniteui-angular/directives';
import { getCurrentResourceStrings, ChipResourceStringsEN, ɵSize as _Size, rem } from 'igniteui-angular/core';
import { Subject } from 'rxjs';
import { IgxIconComponent } from 'igniteui-angular/icon';
import { NgClass, NgTemplateOutlet } from '@angular/common';
import { takeUntil } from 'rxjs/operators';
const IgxChipTypeVariant = {
PRIMARY: 'primary',
INFO: 'info',
SUCCESS: 'success',
WARNING: 'warning',
DANGER: 'danger'
};
let CHIP_ID = 0;
/**
* Chip is compact visual component that displays information in an obround.
*
* @igxModule IgxChipsModule
*
* @igxTheme igx-chip-theme
*
* @igxKeywords chip
*
* @igxGroup display
*
* @remarks
* The Ignite UI Chip can be templated, deleted, and selected.
* Multiple chips can be reordered and visually connected to each other.
* Chips reside in a container called chips area which is responsible for managing the interactions between the chips.
*
* @example
* ```html
* <igx-chip class="chipStyle" [id]="901" [draggable]="true" [removable]="true" (remove)="chipRemoved($event)">
* <igx-avatar class="chip-avatar-resized" igxPrefix></igx-avatar>
* </igx-chip>
* ```
*/
class IgxChipComponent {
constructor() {
this.cdr = inject(ChangeDetectorRef);
this.ref = inject(ElementRef);
this.renderer = inject(Renderer2);
this.document = inject(DOCUMENT);
/**
* Sets the value of `id` attribute. If not provided it will be automatically generated.
*
* @example
* ```html
* <igx-chip [id]="'igx-chip-1'"></igx-chip>
* ```
*/
this.id = `igx-chip-${CHIP_ID++}`;
/**
* Returns the `role` attribute of the chip.
*
* @example
* ```typescript
* let chipRole = this.chip.role;
* ```
*/
this.role = 'option';
/**
* Defines if the `IgxChipComponent` can be dragged in order to change it's position.
* By default it is set to false.
*
* @example
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true"></igx-chip>
* ```
*/
this.draggable = false;
/**
* Enables/disables the draggable element animation when the element is released.
* By default it's set to true.
*
* @example
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true" [animateOnRelease]="false"></igx-chip>
* ```
*/
this.animateOnRelease = true;
/**
* Enables/disables the hiding of the base element that has been dragged.
* By default it's set to true.
*
* @example
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true" [hideBaseOnDrag]="false"></igx-chip>
* ```
*/
this.hideBaseOnDrag = true;
/**
* Defines if the `IgxChipComponent` should render remove button and throw remove events.
* By default it is set to false.
*
* @example
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true" [removable]="true"></igx-chip>
* ```
*/
this.removable = false;
/**
* Defines if the `IgxChipComponent` can be selected on click or through navigation,
* By default it is set to false.
*
* @example
* ```html
* <igx-chip [id]="chip.id" [draggable]="true" [removable]="true" [selectable]="true"></igx-chip>
* ```
*/
this.selectable = false;
/**
* @hidden
* @internal
*/
this.class = '';
/**
* Disables the `IgxChipComponent`. When disabled it restricts user interactions
* like focusing on click or tab, selection on click or Space, dragging.
* By default it is set to false.
*
* @example
* ```html
* <igx-chip [id]="chip.id" [disabled]="true"></igx-chip>
* ```
*/
this.disabled = false;
/**
* @hidden
* @internal
*/
this.selectedChange = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` moving starts.
* Returns the moving `IgxChipComponent`.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (moveStart)="moveStarted($event)">
* ```
*/
this.moveStart = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` moving ends.
* Returns the moved `IgxChipComponent`.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (moveEnd)="moveEnded($event)">
* ```
*/
this.moveEnd = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` is removed.
* Returns the removed `IgxChipComponent`.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (remove)="remove($event)">
* ```
*/
this.remove = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` is clicked.
* Returns the clicked `IgxChipComponent`, whether the event should be canceled.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (click)="chipClick($event)">
* ```
*/
this.chipClick = new EventEmitter();
/**
* Emits event when the `IgxChipComponent` is selected/deselected.
* Returns the selected chip reference, whether the event should be canceled, what is the next selection state and
* when the event is triggered by interaction `originalEvent` is provided, otherwise `originalEvent` is `null`.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [selectable]="true" (selectedChanging)="chipSelect($event)">
* ```
*/
this.selectedChanging = new EventEmitter();
/**
* Emits event when the `IgxChipComponent` is selected/deselected and any related animations and transitions also end.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [selectable]="true" (selectedChanged)="chipSelectEnd($event)">
* ```
*/
this.selectedChanged = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` keyboard navigation is being used.
* Returns the focused/selected `IgxChipComponent`, whether the event should be canceled,
* if the `alt`, `shift` or `control` key is pressed and the pressed key name.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (keyDown)="chipKeyDown($event)">
* ```
*/
this.keyDown = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` has entered the `IgxChipsAreaComponent`.
* Returns the target `IgxChipComponent`, the drag `IgxChipComponent`, as well as
* the original drop event arguments.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (dragEnter)="chipEnter($event)">
* ```
*/
this.dragEnter = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` has left the `IgxChipsAreaComponent`.
* Returns the target `IgxChipComponent`, the drag `IgxChipComponent`, as well as
* the original drop event arguments.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (dragLeave)="chipLeave($event)">
* ```
*/
this.dragLeave = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` is over the `IgxChipsAreaComponent`.
* Returns the target `IgxChipComponent`, the drag `IgxChipComponent`, as well as
* the original drop event arguments.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (dragOver)="chipOver($event)">
* ```
*/
this.dragOver = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` has been dropped in the `IgxChipsAreaComponent`.
* Returns the target `IgxChipComponent`, the drag `IgxChipComponent`, as well as
* the original drop event arguments.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (dragDrop)="chipLeave($event)">
* ```
*/
this.dragDrop = new EventEmitter();
this.defaultClass = 'igx-chip';
/**
* @hidden
* @internal
*/
this.hideBaseElement = false;
/**
* @hidden
* @internal
*/
this.destroy$ = new Subject();
this._tabIndex = null;
this._selected = false;
this._selectedItemClass = 'igx-chip__item--selected';
this._movedWhileRemoving = false;
this._resourceStrings = getCurrentResourceStrings(ChipResourceStringsEN);
}
/**
* Sets the value of `tabindex` attribute. If not provided it will use the element's tabindex if set.
*
* @example
* ```html
* <igx-chip [id]="'igx-chip-1'" [tabIndex]="1"></igx-chip>
* ```
*/
set tabIndex(value) {
this._tabIndex = value;
}
get tabIndex() {
if (this._tabIndex !== null) {
return this._tabIndex;
}
return !this.disabled ? 0 : null;
}
/**
* Sets the `IgxChipComponent` selected state.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [selectable]="true" [selected]="true">
* ```
*
* Two-way data binding:
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [selectable]="true" [(selected)]="model.isSelected">
* ```
*/
set selected(newValue) {
this.changeSelection(newValue);
}
/**
* Returns if the `IgxChipComponent` is selected.
*
* @example
* ```typescript
* @ViewChild('myChip')
* public chip: IgxChipComponent;
* selectedChip(){
* let selectedChip = this.chip.selected;
* }
* ```
*/
get selected() {
return this._selected;
}
/**
* Sets the `IgxChipComponent` background color.
* The `color` property supports string, rgb, hex.
*
* @example
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [color]="'#ff0000'"></igx-chip>
* ```
*/
set color(newColor) {
this.chipArea.nativeElement.style.backgroundColor = newColor;
}
/**
* Returns the background color of the `IgxChipComponent`.
*
* @example
* ```typescript
* @ViewChild('myChip')
* public chip: IgxChipComponent;
* ngAfterViewInit(){
* let chipColor = this.chip.color;
* }
* ```
*/
get color() {
return this.chipArea.nativeElement.style.backgroundColor;
}
/**
* An accessor that sets the resource strings.
* By default it uses EN resources.
*/
set resourceStrings(value) {
this._resourceStrings = Object.assign({}, this._resourceStrings, value);
}
/**
* An accessor that returns the resource strings.
*/
get resourceStrings() {
return this._resourceStrings;
}
get isPrimary() {
return this.variant === IgxChipTypeVariant.PRIMARY;
}
get isInfo() {
return this.variant === IgxChipTypeVariant.INFO;
}
get isSuccess() {
return this.variant === IgxChipTypeVariant.SUCCESS;
}
get isWarning() {
return this.variant === IgxChipTypeVariant.WARNING;
}
get isDanger() {
return this.variant === IgxChipTypeVariant.DANGER;
}
/**
* @hidden
* @internal
*/
get removeButtonTemplate() {
if (!this.disabled) {
return this.removeIcon || this.defaultRemoveIcon;
}
}
/**
* @hidden
* @internal
*/
get selectIconTemplate() {
return this.selectIcon || this.defaultSelectIcon;
}
/**
* @hidden
* @internal
*/
get ghostStyles() {
return { '--ig-size': `${this.chipSize}` };
}
/** @hidden @internal */
get nativeElement() {
return this.ref.nativeElement;
}
get chipSize() {
return this.computedStyles?.getPropertyValue('--ig-size') || _Size.Medium;
}
/**
* @hidden
* @internal
*/
keyEvent(event) {
this.onChipKeyDown(event);
}
/**
* @hidden
* @internal
*/
selectClass(condition) {
const SELECT_CLASS = 'igx-chip__select';
return {
[SELECT_CLASS]: condition,
[`${SELECT_CLASS}--hidden`]: !condition
};
}
onSelectTransitionDone(event) {
if (event.target.tagName) {
// Trigger onSelectionDone on when `width` property is changed and the target is valid element(not comment).
this.selectedChanged.emit({
owner: this,
originalEvent: event
});
}
}
/**
* @hidden
* @internal
*/
onChipKeyDown(event) {
const keyDownArgs = {
originalEvent: event,
owner: this,
cancel: false
};
this.keyDown.emit(keyDownArgs);
if (keyDownArgs.cancel) {
return;
}
if ((event.key === 'Delete' || event.key === 'Del') && this.removable) {
this.remove.emit({
originalEvent: event,
owner: this
});
}
if ((event.key === ' ' || event.key === 'Spacebar') && this.selectable && !this.disabled) {
this.changeSelection(!this.selected, event);
}
if (event.key !== 'Tab') {
event.preventDefault();
}
}
/**
* @hidden
* @internal
*/
onRemoveBtnKeyDown(event) {
if (event.key === ' ' || event.key === 'Spacebar' || event.key === 'Enter') {
this.remove.emit({
originalEvent: event,
owner: this
});
event.preventDefault();
event.stopPropagation();
}
}
onRemoveMouseDown(event) {
event.stopPropagation();
}
/**
* @hidden
* @internal
*/
onRemoveClick(event) {
this.remove.emit({
originalEvent: event,
owner: this
});
}
/**
* @hidden
* @internal
*/
onRemoveTouchMove() {
// We don't remove chip if user starting touch interacting on the remove button moves the chip
this._movedWhileRemoving = true;
}
/**
* @hidden
* @internal
*/
onRemoveTouchEnd(event) {
if (!this._movedWhileRemoving) {
this.onRemoveClick(event);
}
this._movedWhileRemoving = false;
}
/**
* @hidden
* @internal
*/
// -----------------------------
// Start chip igxDrag behavior
onChipDragStart(event) {
this.moveStart.emit({
originalEvent: event,
owner: this
});
event.cancel = !this.draggable || this.disabled;
}
/**
* @hidden
* @internal
*/
onChipDragEnd() {
if (this.animateOnRelease) {
this.dragDirective.transitionToOrigin();
}
}
/**
* @hidden
* @internal
*/
onChipMoveEnd(event) {
// moveEnd is triggered after return animation has finished. This happen when we drag and release the chip.
this.moveEnd.emit({
originalEvent: event,
owner: this
});
if (this.selected) {
this.chipArea.nativeElement.focus();
}
}
/**
* @hidden
* @internal
*/
onChipGhostCreate() {
this.hideBaseElement = this.hideBaseOnDrag;
}
/**
* @hidden
* @internal
*/
onChipGhostDestroy() {
this.hideBaseElement = false;
}
/**
* @hidden
* @internal
*/
onChipDragClicked(event) {
const clickEventArgs = {
originalEvent: event,
owner: this,
cancel: false
};
this.chipClick.emit(clickEventArgs);
if (!clickEventArgs.cancel && this.selectable && !this.disabled) {
this.changeSelection(!this.selected, event);
}
}
// End chip igxDrag behavior
/**
* @hidden
* @internal
*/
// -----------------------------
// Start chip igxDrop behavior
onChipDragEnterHandler(event) {
if (this.dragDirective === event.drag) {
return;
}
const eventArgs = {
owner: this,
dragChip: event.drag.data?.chip,
originalEvent: event
};
this.dragEnter.emit(eventArgs);
}
/**
* @hidden
* @internal
*/
onChipDragLeaveHandler(event) {
if (this.dragDirective === event.drag) {
return;
}
const eventArgs = {
owner: this,
dragChip: event.drag.data?.chip,
originalEvent: event
};
this.dragLeave.emit(eventArgs);
}
/**
* @hidden
* @internal
*/
onChipDrop(event) {
// Cancel the default drop logic
event.cancel = true;
if (this.dragDirective === event.drag) {
return;
}
const eventArgs = {
owner: this,
dragChip: event.drag.data?.chip,
originalEvent: event
};
this.dragDrop.emit(eventArgs);
}
/**
* @hidden
* @internal
*/
onChipOverHandler(event) {
if (this.dragDirective === event.drag) {
return;
}
const eventArgs = {
owner: this,
dragChip: event.drag.data?.chip,
originalEvent: event
};
this.dragOver.emit(eventArgs);
}
// End chip igxDrop behavior
changeSelection(newValue, srcEvent = null) {
const onSelectArgs = {
originalEvent: srcEvent,
owner: this,
selected: false,
cancel: false
};
if (newValue && !this._selected) {
onSelectArgs.selected = true;
this.selectedChanging.emit(onSelectArgs);
if (!onSelectArgs.cancel) {
this.renderer.addClass(this.chipArea.nativeElement, this._selectedItemClass);
this._selected = newValue;
this.selectedChange.emit(this._selected);
this.selectedChanged.emit({
owner: this,
originalEvent: srcEvent
});
}
}
else if (!newValue && this._selected) {
this.selectedChanging.emit(onSelectArgs);
if (!onSelectArgs.cancel) {
this.renderer.removeClass(this.chipArea.nativeElement, this._selectedItemClass);
this._selected = newValue;
this.selectedChange.emit(this._selected);
this.selectedChanged.emit({
owner: this,
originalEvent: srcEvent
});
}
}
}
ngOnInit() {
this.computedStyles = this.document.defaultView.getComputedStyle(this.nativeElement);
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxChipComponent, isStandalone: true, selector: "igx-chip", inputs: { variant: "variant", id: "id", tabIndex: "tabIndex", data: "data", draggable: ["draggable", "draggable", booleanAttribute], animateOnRelease: ["animateOnRelease", "animateOnRelease", booleanAttribute], hideBaseOnDrag: ["hideBaseOnDrag", "hideBaseOnDrag", booleanAttribute], removable: ["removable", "removable", booleanAttribute], removeIcon: "removeIcon", selectable: ["selectable", "selectable", booleanAttribute], selectIcon: "selectIcon", class: "class", disabled: ["disabled", "disabled", booleanAttribute], selected: ["selected", "selected", booleanAttribute], color: "color", resourceStrings: "resourceStrings" }, outputs: { selectedChange: "selectedChange", moveStart: "moveStart", moveEnd: "moveEnd", remove: "remove", chipClick: "chipClick", selectedChanging: "selectedChanging", selectedChanged: "selectedChanged", keyDown: "keyDown", dragEnter: "dragEnter", dragLeave: "dragLeave", dragOver: "dragOver", dragDrop: "dragDrop" }, host: { listeners: { "keydown": "keyEvent($event)" }, properties: { "attr.id": "this.id", "attr.role": "this.role", "attr.tabIndex": "this.tabIndex", "class.igx-chip--disabled": "this.disabled", "attr.aria-selected": "this.selected", "class.igx-chip": "this.defaultClass", "class.igx-chip--primary": "this.isPrimary", "class.igx-chip--info": "this.isInfo", "class.igx-chip--success": "this.isSuccess", "class.igx-chip--warning": "this.isWarning", "class.igx-chip--danger": "this.isDanger" } }, viewQueries: [{ propertyName: "dragDirective", first: true, predicate: ["chipArea"], descendants: true, read: IgxDragDirective, static: true }, { propertyName: "chipArea", first: true, predicate: ["chipArea"], descendants: true, read: ElementRef, static: true }, { propertyName: "defaultRemoveIcon", first: true, predicate: ["defaultRemoveIcon"], descendants: true, read: TemplateRef, static: true }, { propertyName: "defaultSelectIcon", first: true, predicate: ["defaultSelectIcon"], descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: "<div #chipArea class=\"igx-chip__item\"\n [igxDrag]=\"{chip: this}\"\n [style.visibility]='hideBaseElement ? \"hidden\" : \"visible\"'\n ghostClass=\"igx-chip__ghost\"\n [ghostStyle]=\"ghostStyles\"\n (dragStart)=\"onChipDragStart($event)\"\n (ghostCreate)=\"onChipGhostCreate()\"\n (ghostDestroy)=\"onChipGhostDestroy()\"\n (dragEnd)=\"onChipDragEnd()\"\n (transitioned)=\"onChipMoveEnd($event)\"\n (dragClick)=\"onChipDragClicked($event)\"\n igxDrop\n (enter)=\"onChipDragEnterHandler($event)\"\n (leave)=\"onChipDragLeaveHandler($event)\"\n (over)=\"onChipOverHandler($event)\"\n (dropped)=\"onChipDrop($event)\">\n\n <div class=\"igx-chip__start\" #selectContainer>\n @if (selected) {\n <div [ngClass]=\"selectClass(selected)\">\n <ng-container *ngTemplateOutlet=\"selectIconTemplate\"></ng-container>\n </div>\n }\n\n <ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n </div>\n\n <div class=\"igx-chip__content\">\n <ng-content></ng-content>\n </div>\n\n <div class=\"igx-chip__end\">\n <ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n\n @if (removable) {\n <div class=\"igx-chip__remove\"\n [attr.tabIndex]=\"tabIndex\"\n (keydown)=\"onRemoveBtnKeyDown($event)\"\n (pointerdown)=\"onRemoveMouseDown($event)\"\n (mousedown)=\"onRemoveMouseDown($event)\"\n (click)=\"onRemoveClick($event)\"\n (touchmove)=\"onRemoveTouchMove()\"\n (touchend)=\"onRemoveTouchEnd($event)\">\n <ng-container *ngTemplateOutlet=\"removeButtonTemplate\"></ng-container>\n </div>\n }\n </div>\n</div>\n\n<ng-template #defaultSelectIcon>\n <igx-icon\n [attr.aria-label]=\"resourceStrings.igx_chip_select\"\n family=\"default\"\n name=\"selected\"\n ></igx-icon>\n</ng-template>\n\n<ng-template #defaultRemoveIcon>\n <igx-icon\n [attr.aria-label]=\"resourceStrings.igx_chip_remove\"\n family=\"default\"\n name=\"remove\"\n ></igx-icon>\n</ng-template>\n", dependencies: [{ kind: "directive", type: IgxDropDirective, selector: "[igxDrop]", inputs: ["igxDrop", "dropChannel", "dropStrategy"], outputs: ["enter", "over", "leave", "dropped"], exportAs: ["drop"] }, { kind: "directive", type: IgxDragDirective, selector: "[igxDrag]", inputs: ["igxDrag", "dragTolerance", "dragDirection", "dragChannel", "ghost", "ghostClass", "ghostStyle", "ghostTemplate", "ghostHost", "scrollContainer", "ghostOffsetX", "ghostOffsetY"], outputs: ["dragStart", "dragMove", "dragEnd", "dragClick", "ghostCreate", "ghostDestroy", "transitioned"], exportAs: ["drag"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IgxIconComponent, selector: "igx-icon", inputs: ["ariaHidden", "family", "name", "active"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipComponent, decorators: [{
type: Component,
args: [{ selector: 'igx-chip', imports: [IgxDropDirective, IgxDragDirective, NgClass, NgTemplateOutlet, IgxIconComponent], template: "<div #chipArea class=\"igx-chip__item\"\n [igxDrag]=\"{chip: this}\"\n [style.visibility]='hideBaseElement ? \"hidden\" : \"visible\"'\n ghostClass=\"igx-chip__ghost\"\n [ghostStyle]=\"ghostStyles\"\n (dragStart)=\"onChipDragStart($event)\"\n (ghostCreate)=\"onChipGhostCreate()\"\n (ghostDestroy)=\"onChipGhostDestroy()\"\n (dragEnd)=\"onChipDragEnd()\"\n (transitioned)=\"onChipMoveEnd($event)\"\n (dragClick)=\"onChipDragClicked($event)\"\n igxDrop\n (enter)=\"onChipDragEnterHandler($event)\"\n (leave)=\"onChipDragLeaveHandler($event)\"\n (over)=\"onChipOverHandler($event)\"\n (dropped)=\"onChipDrop($event)\">\n\n <div class=\"igx-chip__start\" #selectContainer>\n @if (selected) {\n <div [ngClass]=\"selectClass(selected)\">\n <ng-container *ngTemplateOutlet=\"selectIconTemplate\"></ng-container>\n </div>\n }\n\n <ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n </div>\n\n <div class=\"igx-chip__content\">\n <ng-content></ng-content>\n </div>\n\n <div class=\"igx-chip__end\">\n <ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n\n @if (removable) {\n <div class=\"igx-chip__remove\"\n [attr.tabIndex]=\"tabIndex\"\n (keydown)=\"onRemoveBtnKeyDown($event)\"\n (pointerdown)=\"onRemoveMouseDown($event)\"\n (mousedown)=\"onRemoveMouseDown($event)\"\n (click)=\"onRemoveClick($event)\"\n (touchmove)=\"onRemoveTouchMove()\"\n (touchend)=\"onRemoveTouchEnd($event)\">\n <ng-container *ngTemplateOutlet=\"removeButtonTemplate\"></ng-container>\n </div>\n }\n </div>\n</div>\n\n<ng-template #defaultSelectIcon>\n <igx-icon\n [attr.aria-label]=\"resourceStrings.igx_chip_select\"\n family=\"default\"\n name=\"selected\"\n ></igx-icon>\n</ng-template>\n\n<ng-template #defaultRemoveIcon>\n <igx-icon\n [attr.aria-label]=\"resourceStrings.igx_chip_remove\"\n family=\"default\"\n name=\"remove\"\n ></igx-icon>\n</ng-template>\n" }]
}], propDecorators: { variant: [{
type: Input
}], id: [{
type: HostBinding,
args: ['attr.id']
}, {
type: Input
}], role: [{
type: HostBinding,
args: ['attr.role']
}], tabIndex: [{
type: HostBinding,
args: ['attr.tabIndex']
}, {
type: Input
}], data: [{
type: Input
}], draggable: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], animateOnRelease: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], hideBaseOnDrag: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], removable: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], removeIcon: [{
type: Input
}], selectable: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], selectIcon: [{
type: Input
}], class: [{
type: Input
}], disabled: [{
type: HostBinding,
args: ['class.igx-chip--disabled']
}, {
type: Input,
args: [{ transform: booleanAttribute }]
}], selected: [{
type: HostBinding,
args: ['attr.aria-selected']
}, {
type: Input,
args: [{ transform: booleanAttribute }]
}], selectedChange: [{
type: Output
}], color: [{
type: Input
}], resourceStrings: [{
type: Input
}], moveStart: [{
type: Output
}], moveEnd: [{
type: Output
}], remove: [{
type: Output
}], chipClick: [{
type: Output
}], selectedChanging: [{
type: Output
}], selectedChanged: [{
type: Output
}], keyDown: [{
type: Output
}], dragEnter: [{
type: Output
}], dragLeave: [{
type: Output
}], dragOver: [{
type: Output
}], dragDrop: [{
type: Output
}], defaultClass: [{
type: HostBinding,
args: ['class.igx-chip']
}], isPrimary: [{
type: HostBinding,
args: ['class.igx-chip--primary']
}], isInfo: [{
type: HostBinding,
args: ['class.igx-chip--info']
}], isSuccess: [{
type: HostBinding,
args: ['class.igx-chip--success']
}], isWarning: [{
type: HostBinding,
args: ['class.igx-chip--warning']
}], isDanger: [{
type: HostBinding,
args: ['class.igx-chip--danger']
}], dragDirective: [{
type: ViewChild,
args: ['chipArea', { read: IgxDragDirective, static: true }]
}], chipArea: [{
type: ViewChild,
args: ['chipArea', { read: ElementRef, static: true }]
}], defaultRemoveIcon: [{
type: ViewChild,
args: ['defaultRemoveIcon', { read: TemplateRef, static: true }]
}], defaultSelectIcon: [{
type: ViewChild,
args: ['defaultSelectIcon', { read: TemplateRef, static: true }]
}], keyEvent: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
/**
* The chip area allows you to perform more complex scenarios with chips that require interaction,
* like dragging, selection, navigation, etc.
*
* @igxModule IgxChipsModule
*
* @igxTheme igx-chip-theme
*
* @igxKeywords chip area, chip
*
* @igxGroup display
*
* @example
* ```html
* <igx-chips-area>
* <igx-chip *ngFor="let chip of chipList" [id]="chip.id">
* <span>{{chip.text}}</span>
* </igx-chip>
* </igx-chips-area>
* ```
*/
class IgxChipsAreaComponent {
/** @hidden @internal */
get _widthToRem() {
return rem(this.width);
}
/** @hidden @internal */
get _heightToRem() {
return rem(this.height);
}
constructor() {
this.cdr = inject(ChangeDetectorRef);
this.element = inject(ElementRef);
this._iterableDiffers = inject(IterableDiffers);
/**
* Returns the `role` attribute of the chips area.
*
* @example
* ```typescript
* let chipsAreaRole = this.chipsArea.role;
* ```
*/
this.role = 'listbox';
/**
* Returns the `aria-label` attribute of the chips area.
*
* @example
* ```typescript
* let ariaLabel = this.chipsArea.ariaLabel;
* ```
*
*/
this.ariaLabel = 'chip area';
/**
* Emits an event when `IgxChipComponent`s in the `IgxChipsAreaComponent` should be reordered.
* Returns an array of `IgxChipComponent`s.
*
* @example
* ```html
* <igx-chips-area #chipsArea [width]="'300'" [height]="'10'" (onReorder)="changedOrder($event)"></igx-chips-area>
* ```
*/
this.reorder = new EventEmitter();
/**
* Emits an event when an `IgxChipComponent` in the `IgxChipsAreaComponent` is selected/deselected.
* Fired after the chips area is initialized if there are initially selected chips as well.
* Returns an array of selected `IgxChipComponent`s and the `IgxChipAreaComponent`.
*
* @example
* ```html
* <igx-chips-area #chipsArea [width]="'300'" [height]="'10'" (selectionChange)="selection($event)"></igx-chips-area>
* ```
*/
this.selectionChange = new EventEmitter();
/**
* Emits an event when an `IgxChipComponent` in the `IgxChipsAreaComponent` is moved.
*
* @example
* ```html
* <igx-chips-area #chipsArea [width]="'300'" [height]="'10'" (moveStart)="moveStart($event)"></igx-chips-area>
* ```
*/
this.moveStart = new EventEmitter();
/**
* Emits an event after an `IgxChipComponent` in the `IgxChipsAreaComponent` is moved.
*
* @example
* ```html
* <igx-chips-area #chipsArea [width]="'300'" [height]="'10'" (moveEnd)="moveEnd($event)"></igx-chips-area>
* ```
*/
this.moveEnd = new EventEmitter();
this.destroy$ = new Subject();
this.hostClass = 'igx-chip-area';
this._differ = null;
this._differ = this._iterableDiffers.find([]).create(null);
}
/**
* @hidden
* @internal
*/
ngAfterViewInit() {
// If we have initially selected chips through their inputs, we need to get them, because we cannot listen to their events yet.
if (this.chipsList.length) {
const selectedChips = this.chipsList.filter((item) => item.selected);
if (selectedChips.length) {
this.selectionChange.emit({
originalEvent: null,
newSelection: selectedChips,
owner: this
});
}
}
}
/**
* @hidden
* @internal
*/
ngDoCheck() {
if (this.chipsList) {
const changes = this._differ.diff(this.chipsList.toArray());
if (changes) {
changes.forEachAddedItem((addedChip) => {
addedChip.item.moveStart.pipe(takeUntil(addedChip.item.destroy$)).subscribe((args) => {
this.onChipMoveStart(args);
});
addedChip.item.moveEnd.pipe(takeUntil(addedChip.item.destroy$)).subscribe((args) => {
this.onChipMoveEnd(args);
});
addedChip.item.dragEnter.pipe(takeUntil(addedChip.item.destroy$)).subscribe((args) => {
this.onChipDragEnter(args);
});
addedChip.item.keyDown.pipe(takeUntil(addedChip.item.destroy$)).subscribe((args) => {
this.onChipKeyDown(args);
});
if (addedChip.item.selectable) {
addedChip.item.selectedChanging.pipe(takeUntil(addedChip.item.destroy$)).subscribe((args) => {
this.onChipSelectionChange(args);
});
}
});
this.modifiedChipsArray = this.chipsList.toArray();
}
}
}
/**
* @hidden
* @internal
*/
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
/**
* @hidden
* @internal
*/
onChipKeyDown(event) {
let orderChanged = false;
const chipsArray = this.chipsList.toArray();
const dragChipIndex = chipsArray.findIndex((el) => el === event.owner);
if (event.originalEvent.shiftKey === true) {
if (event.originalEvent.key === 'ArrowLeft' || event.originalEvent.key === 'Left') {
orderChanged = this.positionChipAtIndex(dragChipIndex, dragChipIndex - 1, false, event.originalEvent);
if (orderChanged) {
setTimeout(() => {
this.chipsList.get(dragChipIndex - 1).nativeElement.focus();
});
}
}
else if (event.originalEvent.key === 'ArrowRight' || event.originalEvent.key === 'Right') {
orderChanged = this.positionChipAtIndex(dragChipIndex, dragChipIndex + 1, true, event.originalEvent);
}
}
else {
if ((event.originalEvent.key === 'ArrowLeft' || event.originalEvent.key === 'Left') && dragChipIndex > 0) {
chipsArray[dragChipIndex - 1].nativeElement.focus();
}
else if ((event.originalEvent.key === 'ArrowRight' || event.originalEvent.key === 'Right') &&
dragChipIndex < chipsArray.length - 1) {
chipsArray[dragChipIndex + 1].nativeElement.focus();
}
}
}
/**
* @hidden
* @internal
*/
onChipMoveStart(event) {
this.moveStart.emit({
originalEvent: event.originalEvent,
owner: this
});
}
/**
* @hidden
* @internal
*/
onChipMoveEnd(event) {
this.moveEnd.emit({
originalEvent: event.originalEvent,
owner: this
});
}
/**
* @hidden
* @internal
*/
onChipDragEnter(event) {
const dropChipIndex = this.chipsList.toArray().findIndex((el) => el === event.owner);
const dragChipIndex = this.chipsList.toArray().findIndex((el) => el === event.dragChip);
if (dragChipIndex < dropChipIndex) {
// from the left to right
this.positionChipAtIndex(dragChipIndex, dropChipIndex, true, event.originalEvent);
}
else {
// from the right to left
this.positionChipAtIndex(dragChipIndex, dropChipIndex, false, event.originalEvent);
}
}
/**
* @hidden
* @internal
*/
positionChipAtIndex(chipIndex, targetIndex, shiftRestLeft, originalEvent) {
if (chipIndex < 0 || this.chipsList.length <= chipIndex ||
targetIndex < 0 || this.chipsList.length <= targetIndex) {
return false;
}
const chipsArray = this.chipsList.toArray();
const result = [];
for (let i = 0; i < chipsArray.length; i++) {
if (shiftRestLeft) {
if (chipIndex <= i && i < targetIndex) {
result.push(chipsArray[i + 1]);
}
else if (i === targetIndex) {
result.push(chipsArray[chipIndex]);
}
else {
result.push(chipsArray[i]);
}
}
else {
if (targetIndex < i && i <= chipIndex) {
result.push(chipsArray[i - 1]);
}
else if (i === targetIndex) {
result.push(chipsArray[chipIndex]);
}
else {
result.push(chipsArray[i]);
}
}
}
this.modifiedChipsArray = result;
const eventData = {
chipsArray: this.modifiedChipsArray,
originalEvent,
owner: this
};
this.reorder.emit(eventData);
return true;
}
/**
* @hidden
* @internal
*/
onChipSelectionChange(event) {
let selectedChips = this.chipsList.filter((chip) => chip.selected);
if (event.selected && !selectedChips.includes(event.owner)) {
selectedChips.push(event.owner);
}
else if (!event.selected && selectedChips.includes(event.owner)) {
selectedChips = selectedChips.filter((chip) => chip.id !== event.owner.id);
}
this.selectionChange.emit({
originalEvent: event.originalEvent,
newSelection: selectedChips,
owner: this
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipsAreaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.2", type: IgxChipsAreaComponent, isStandalone: true, selector: "igx-chips-area", inputs: { width: "width", height: "height" }, outputs: { reorder: "reorder", selectionChange: "selectionChange", moveStart: "moveStart", moveEnd: "moveEnd" }, host: { properties: { "attr.role": "this.role", "attr.aria-label": "this.ariaLabel", "style.width.rem": "this._widthToRem", "style.height.rem": "this._heightToRem", "class": "this.hostClass" } }, queries: [{ propertyName: "chipsList", predicate: IgxChipComponent, descendants: true }], ngImport: i0, template: "<ng-content></ng-content>\n" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipsAreaComponent, decorators: [{
type: Component,
args: [{ selector: 'igx-chips-area', standalone: true, template: "<ng-content></ng-content>\n" }]
}], ctorParameters: () => [], propDecorators: { role: [{
type: HostBinding,
args: ['attr.role']
}], ariaLabel: [{
type: HostBinding,
args: ['attr.aria-label']
}], width: [{
type: Input
}], _widthToRem: [{
type: HostBinding,
args: ['style.width.rem']
}], height: [{
type: Input
}], _heightToRem: [{
type: HostBinding,
args: ['style.height.rem']
}], reorder: [{
type: Output
}], selectionChange: [{
type: Output
}], moveStart: [{
type: Output
}], moveEnd: [{
type: Output
}], chipsList: [{
type: ContentChildren,
args: [IgxChipComponent, { descendants: true }]
}], hostClass: [{
type: HostBinding,
args: ['class']
}] } });
/* NOTE: Chips directives collection for ease-of-use import in standalone components scenario */
const IGX_CHIPS_DIRECTIVES = [
IgxChipsAreaComponent,
IgxChipComponent,
IgxPrefixDirective,
IgxSuffixDirective
];
/**
* @hidden
* IMPORTANT: The following is NgModule exported for backwards-compatibility before standalone components
*/
class IgxChipsModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.2", ngImport: i0, type: IgxChipsModule, imports: [IgxChipsAreaComponent, IgxChipComponent, i3.IgxPrefixDirective, i3.IgxSuffixDirective], exports: [IgxChipsAreaComponent, IgxChipComponent, i3.IgxPrefixDirective, i3.IgxSuffixDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipsModule, imports: [IgxChipComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxChipsModule, decorators: [{
type: NgModule,
args: [{
exports: [
...IGX_CHIPS_DIRECTIVES
],
imports: [
...IGX_CHIPS_DIRECTIVES
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { IGX_CHIPS_DIRECTIVES, IgxChipComponent, IgxChipTypeVariant, IgxChipsAreaComponent, IgxChipsModule };
//# sourceMappingURL=igniteui-angular-chips.mjs.map