@coreui/angular-pro 5.3.0 → 5.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,19 +25,12 @@
25
25
 
26
26
  ## Status
27
27
 
28
- ![angular][angular-badge]
29
28
  [![npm-coreui-angular-v5-ng19][npm-coreui-angular-badge-v5-ng19]][npm-coreui-angular]
30
29
  [![npm-coreui-angular-latest][npm-coreui-angular-badge-latest]][npm-coreui-angular]
31
30
  [![npm-coreui-angular-next][npm-coreui-angular-badge-next]][npm-coreui-angular]
32
31
  [![NPM downloads][npm-coreui-angular-download]][npm-coreui-angular]
33
- [![Build](https://github.com/coreui/coreui-angular/actions/workflows/build-check.yml/badge.svg)](https://github.com/coreui/coreui-angular/actions/workflows/build-check.yml)
32
+ ![angular][angular-badge] [![Build](https://github.com/coreui/coreui-angular/actions/workflows/build-check.yml/badge.svg)](https://github.com/coreui/coreui-angular/actions/workflows/build-check.yml)
34
33
 
35
- [npm-coreui-angular-badge-v5-ng19]: https://img.shields.io/npm/v/@coreui/angular-pro/v5-ng19?style=flat-square&color=brightgreen
36
- [npm-coreui-angular-badge-latest]: https://img.shields.io/npm/v/@coreui/angular-pro/latest?style=flat-square&color=blue
37
- [npm-coreui-angular-badge-next]: https://img.shields.io/npm/v/@coreui/angular-pro/next?style=flat-square&color=yellow
38
- [npm-coreui-angular]: https://www.npmjs.com/package/@coreui/angular-pro
39
- [npm-coreui-angular-download]: https://img.shields.io/npm/dm/@coreui/angular.svg?style=flat-square
40
- [angular-badge]: https://img.shields.io/badge/angular-^19.0.0-lightgrey.svg?style=flat-square&logo=angular
41
34
 
42
35
  ## Table of contents
43
36
 
@@ -70,7 +63,7 @@
70
63
  Before you begin, make sure your development environment includes `Node.js®` and `npm` package manager.
71
64
 
72
65
  ###### Node.js
73
- [**Angular 19**](https://angular.dev/overview) requires `Node.js` LTS version `^18.19.1` or `^20.11.1`.
66
+ [**Angular 19**](https://angular.dev/overview) requires `Node.js` LTS version `^18.19`, `^20.11` or `^22.0`.
74
67
 
75
68
  - To check your version, run `node -v` in a terminal/console window.
76
69
  - To get `Node.js`, go to [nodejs.org](https://nodejs.org/).
@@ -186,3 +179,10 @@ Copyright 2017-2024 creativeLabs Łukasz Holeczek.
186
179
 
187
180
  This is proprietary software. To use it, you have to obtain a commercial license.
188
181
 
182
+
183
+ [npm-coreui-angular-badge-v5-ng19]: https://img.shields.io/npm/v/@coreui/angular-pro/v5-ng19?style=flat-square&color=brightgreen
184
+ [npm-coreui-angular-badge-latest]: https://img.shields.io/npm/v/@coreui/angular-pro/latest?style=flat-square&color=blue
185
+ [npm-coreui-angular-badge-next]: https://img.shields.io/npm/v/@coreui/angular-pro/next?style=flat-square&color=yellow
186
+ [npm-coreui-angular]: https://www.npmjs.com/package/@coreui/angular-pro
187
+ [npm-coreui-angular-download]: https://img.shields.io/npm/dm/@coreui/angular.svg?style=flat-square
188
+ [angular-badge]: https://img.shields.io/badge/angular-^19.0.0-lightgrey.svg?style=flat-square&logo=angular
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, ElementRef, Directive, input, Renderer2, effect, TemplateRef, Input, booleanAttribute, NgModule, computed, Injectable, Component, signal, output, contentChildren, EventEmitter, HostBinding, Output, ContentChildren, HostListener, DestroyRef, RendererFactory2, numberAttribute, Pipe, ViewChildren, model, PLATFORM_ID, Inject, afterNextRender, ViewChild, forwardRef, ContentChild, Optional, viewChild, ChangeDetectionStrategy, ChangeDetectorRef, NgZone, contentChild, afterRender, ViewContainerRef, viewChildren, untracked, Injector, runInInjectionContext } from '@angular/core';
3
- import { NgTemplateOutlet, DOCUMENT, NgClass, NgOptimizedImage, AsyncPipe, NgStyle, isPlatformServer, isPlatformBrowser, formatDate, I18nPluralPipe, JsonPipe } from '@angular/common';
3
+ import { NgTemplateOutlet, DOCUMENT, NgClass, AsyncPipe, NgStyle, isPlatformServer, isPlatformBrowser, formatDate, I18nPluralPipe, JsonPipe } from '@angular/common';
4
4
  import { animation, animate, style, AnimationBuilder, useAnimation, trigger, state, transition, group, query, animateChild } from '@angular/animations';
5
5
  import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
6
6
  import { fromEvent, Subject, BehaviorSubject, Observable, skip, merge, takeWhile, distinctUntilChanged as distinctUntilChanged$1, map as map$1, debounceTime as debounceTime$1 } from 'rxjs';
@@ -218,14 +218,14 @@ class AccordionService {
218
218
  }
219
219
  }
220
220
  toggleItem(item) {
221
- item.visible = !item.visible;
221
+ item.itemVisible.update((value) => !value);
222
222
  this.closeOtherItems(item);
223
223
  }
224
224
  closeOtherItems(openItem) {
225
225
  if (!this.alwaysOpen) {
226
226
  this.items.forEach((item) => {
227
227
  if (item !== openItem) {
228
- item.visible = false;
228
+ item.itemVisible.set(false);
229
229
  }
230
230
  });
231
231
  }
@@ -441,7 +441,14 @@ class AccordionItemComponent {
441
441
  * @type boolean
442
442
  * @default false
443
443
  */
444
- this.visible = false;
444
+ // eslint-disable-next-line @angular-eslint/no-input-rename
445
+ this.visibleInput = input(false, { transform: booleanAttribute, alias: 'visible' });
446
+ this.itemVisible = signal(false);
447
+ this.visibleInputChange = effect(() => {
448
+ setTimeout(() => {
449
+ this.itemVisible.set(this.visibleInput());
450
+ });
451
+ });
445
452
  this.contentId = `accordion-item-${nextId$2++}`;
446
453
  this.contentTemplates = contentChildren(TemplateIdDirective, { descendants: true });
447
454
  this.templates = computed(() => {
@@ -452,15 +459,14 @@ class AccordionItemComponent {
452
459
  });
453
460
  }
454
461
  #accordionService;
455
- set open(value) {
456
- console.warn('c-accordion-item "open" prop is deprecated, use "visible" prop instead.');
457
- this.visible = value || this.visible;
462
+ set visible(value) {
463
+ this.itemVisible.set(value);
458
464
  }
459
- get open() {
460
- return this.visible;
465
+ get visible() {
466
+ return this.itemVisible();
461
467
  }
462
468
  get itemContext() {
463
- return { $implicit: this.visible };
469
+ return { $implicit: this.itemVisible() };
464
470
  }
465
471
  ngOnInit() {
466
472
  this.#accordionService.addItem(this);
@@ -472,17 +478,12 @@ class AccordionItemComponent {
472
478
  this.#accordionService.toggleItem(this);
473
479
  }
474
480
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: AccordionItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
475
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.1", type: AccordionItemComponent, isStandalone: true, selector: "c-accordion-item", inputs: { visible: ["visible", "visible", booleanAttribute], open: "open" }, host: { classAttribute: "accordion-item" }, queries: [{ propertyName: "contentTemplates", predicate: TemplateIdDirective, descendants: true, isSignal: true }], exportAs: ["cAccordionItem"], ngImport: i0, template: "@let tmpl = templates();\n<ng-container>\n <div class=\"accordion-header\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionHeaderTemplate'] || defaultAccordionHeaderTemplate; context: itemContext\" />\n </div>\n <div class=\"accordion-collapse\" cCollapse [visible]=\"visible\" [attr.aria-expanded]=\"visible\" [id]=\"contentId\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionBodyTemplate'] || defaultAccordionBodyTemplate; context: itemContext\" />\n </div>\n</ng-container>\n\n<ng-template #defaultAccordionHeaderTemplate>\n <button cAccordionButton [collapsed]=\"!visible\" [attr.aria-controls]=\"contentId\" (click)=\"toggleItem()\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionHeader'] || defaultAccordionHeaderContentTemplate; context: itemContext\">\n </ng-container>\n </button>\n</ng-template>\n\n<ng-template #defaultAccordionHeaderContentTemplate>\n <ng-content />\n</ng-template>\n\n<ng-template #defaultAccordionBodyTemplate>\n <div class=\"accordion-body\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionBody'] || defaultAccordionBodyContentTemplate; context: itemContext\">\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultAccordionBodyContentTemplate>\n <ng-content />\n</ng-template>\n", styles: [":host{display:block;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: AccordionButtonDirective, selector: "[cAccordionButton]", inputs: ["collapsed", "type"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CollapseDirective, selector: "[cCollapse]", inputs: ["animate", "horizontal", "visible", "navbar", "duration", "transition"], outputs: ["visibleChange", "collapseChange"], exportAs: ["cCollapse"] }] }); }
481
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.1", type: AccordionItemComponent, isStandalone: true, selector: "c-accordion-item", inputs: { visibleInput: { classPropertyName: "visibleInput", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "accordion-item" }, queries: [{ propertyName: "contentTemplates", predicate: TemplateIdDirective, descendants: true, isSignal: true }], exportAs: ["cAccordionItem"], ngImport: i0, template: "@let tmpl = templates();\n<ng-container>\n <div class=\"accordion-header\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionHeaderTemplate'] || defaultAccordionHeaderTemplate; context: itemContext\" />\n </div>\n <div class=\"accordion-collapse\" cCollapse [visible]=\"itemVisible()\" [attr.aria-expanded]=\"itemVisible()\" [id]=\"contentId\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionBodyTemplate'] || defaultAccordionBodyTemplate; context: itemContext\" />\n </div>\n</ng-container>\n\n<ng-template #defaultAccordionHeaderTemplate>\n <button cAccordionButton [collapsed]=\"!itemVisible()\" [attr.aria-controls]=\"contentId\" (click)=\"toggleItem()\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionHeader'] || defaultAccordionHeaderContentTemplate; context: itemContext\">\n </ng-container>\n </button>\n</ng-template>\n\n<ng-template #defaultAccordionHeaderContentTemplate>\n <ng-content />\n</ng-template>\n\n<ng-template #defaultAccordionBodyTemplate>\n <div class=\"accordion-body\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionBody'] || defaultAccordionBodyContentTemplate; context: itemContext\">\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultAccordionBodyContentTemplate>\n <ng-content />\n</ng-template>\n", styles: [":host{display:block;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: AccordionButtonDirective, selector: "[cAccordionButton]", inputs: ["collapsed", "type"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CollapseDirective, selector: "[cCollapse]", inputs: ["animate", "horizontal", "visible", "navbar", "duration", "transition"], outputs: ["visibleChange", "collapseChange"], exportAs: ["cCollapse"] }] }); }
476
482
  }
477
483
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: AccordionItemComponent, decorators: [{
478
484
  type: Component,
479
- args: [{ selector: 'c-accordion-item', exportAs: 'cAccordionItem', imports: [AccordionButtonDirective, NgTemplateOutlet, CollapseDirective], host: { class: 'accordion-item' }, template: "@let tmpl = templates();\n<ng-container>\n <div class=\"accordion-header\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionHeaderTemplate'] || defaultAccordionHeaderTemplate; context: itemContext\" />\n </div>\n <div class=\"accordion-collapse\" cCollapse [visible]=\"visible\" [attr.aria-expanded]=\"visible\" [id]=\"contentId\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionBodyTemplate'] || defaultAccordionBodyTemplate; context: itemContext\" />\n </div>\n</ng-container>\n\n<ng-template #defaultAccordionHeaderTemplate>\n <button cAccordionButton [collapsed]=\"!visible\" [attr.aria-controls]=\"contentId\" (click)=\"toggleItem()\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionHeader'] || defaultAccordionHeaderContentTemplate; context: itemContext\">\n </ng-container>\n </button>\n</ng-template>\n\n<ng-template #defaultAccordionHeaderContentTemplate>\n <ng-content />\n</ng-template>\n\n<ng-template #defaultAccordionBodyTemplate>\n <div class=\"accordion-body\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionBody'] || defaultAccordionBodyContentTemplate; context: itemContext\">\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultAccordionBodyContentTemplate>\n <ng-content />\n</ng-template>\n", styles: [":host{display:block;overflow:hidden}\n"] }]
480
- }], propDecorators: { visible: [{
481
- type: Input,
482
- args: [{ transform: booleanAttribute }]
483
- }], open: [{
484
- type: Input
485
- }] } });
485
+ args: [{ selector: 'c-accordion-item', exportAs: 'cAccordionItem', imports: [AccordionButtonDirective, NgTemplateOutlet, CollapseDirective], host: { class: 'accordion-item' }, template: "@let tmpl = templates();\n<ng-container>\n <div class=\"accordion-header\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionHeaderTemplate'] || defaultAccordionHeaderTemplate; context: itemContext\" />\n </div>\n <div class=\"accordion-collapse\" cCollapse [visible]=\"itemVisible()\" [attr.aria-expanded]=\"itemVisible()\" [id]=\"contentId\">\n <ng-container *ngTemplateOutlet=\"tmpl['accordionBodyTemplate'] || defaultAccordionBodyTemplate; context: itemContext\" />\n </div>\n</ng-container>\n\n<ng-template #defaultAccordionHeaderTemplate>\n <button cAccordionButton [collapsed]=\"!itemVisible()\" [attr.aria-controls]=\"contentId\" (click)=\"toggleItem()\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionHeader'] || defaultAccordionHeaderContentTemplate; context: itemContext\">\n </ng-container>\n </button>\n</ng-template>\n\n<ng-template #defaultAccordionHeaderContentTemplate>\n <ng-content />\n</ng-template>\n\n<ng-template #defaultAccordionBodyTemplate>\n <div class=\"accordion-body\">\n <ng-container\n *ngTemplateOutlet=\"tmpl['accordionBody'] || defaultAccordionBodyContentTemplate; context: itemContext\">\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultAccordionBodyContentTemplate>\n <ng-content />\n</ng-template>\n", styles: [":host{display:block;overflow:hidden}\n"] }]
486
+ }] });
486
487
 
487
488
  class AccordionModule {
488
489
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: AccordionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
@@ -1225,16 +1226,16 @@ class AvatarComponent {
1225
1226
  });
1226
1227
  }
1227
1228
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1228
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.1", type: AvatarComponent, isStandalone: true, selector: "c-avatar", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" }, classAttribute: "avatar" }, hostDirectives: [{ directive: TextColorDirective, inputs: ["cTextColor", "textColor"] }], ngImport: i0, template: "<ng-content>\n @if (src()) {\n @defer (prefetch on idle) {\n <img [ngSrc]=\"src() ?? ''\" fill=\"\" class=\"avatar-img\" alt=\"{{alt()}}\" />\n } @placeholder () {\n <svg aria-label=\"Avatar placeholder\"\n focusable=\"false\"\n preserveAspectRatio=\"xMidYMid slice\"\n role=\"img\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"avatar-img\"\n style=\"position: absolute; width: 100%; height: 100%; inset: 0;\">\n <rect fill=\"#868e96\" height=\"100%\" width=\"100%\"></rect>\n </svg>\n }\n }\n</ng-content>\n@if (!!status()) {\n <span [ngClass]=\"statusClass()\"></span>\n}\n\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], deferBlockDependencies: [() => [NgOptimizedImage]] }); }
1229
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.1", type: AvatarComponent, isStandalone: true, selector: "c-avatar", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" }, classAttribute: "avatar" }, hostDirectives: [{ directive: TextColorDirective, inputs: ["cTextColor", "textColor"] }], ngImport: i0, template: "<ng-content>\n @if (src()) {\n @defer (prefetch on idle) {\n <img src=\"{{src() ?? ''}}\" class=\"avatar-img\" alt=\"{{alt()}}\" />\n } @placeholder () {\n <svg aria-label=\"Avatar placeholder\"\n focusable=\"false\"\n preserveAspectRatio=\"xMidYMid slice\"\n role=\"img\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"avatar-img\"\n style=\"position: absolute; width: 100%; height: 100%; inset: 0;\">\n <rect fill=\"#868e96\" height=\"100%\" width=\"100%\"></rect>\n </svg>\n }\n }\n</ng-content>\n@if (!!status()) {\n <span [ngClass]=\"statusClass()\"></span>\n}\n\n", styles: [":host .avatar-img{object-fit:cover}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
1229
1230
  }
1230
1231
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: AvatarComponent, decorators: [{
1231
1232
  type: Component,
1232
- args: [{ selector: 'c-avatar', imports: [NgClass, NgOptimizedImage], hostDirectives: [
1233
+ args: [{ selector: 'c-avatar', imports: [NgClass], hostDirectives: [
1233
1234
  {
1234
1235
  directive: TextColorDirective,
1235
1236
  inputs: ['cTextColor: textColor']
1236
1237
  }
1237
- ], host: { class: 'avatar', '[class]': 'hostClasses()' }, template: "<ng-content>\n @if (src()) {\n @defer (prefetch on idle) {\n <img [ngSrc]=\"src() ?? ''\" fill=\"\" class=\"avatar-img\" alt=\"{{alt()}}\" />\n } @placeholder () {\n <svg aria-label=\"Avatar placeholder\"\n focusable=\"false\"\n preserveAspectRatio=\"xMidYMid slice\"\n role=\"img\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"avatar-img\"\n style=\"position: absolute; width: 100%; height: 100%; inset: 0;\">\n <rect fill=\"#868e96\" height=\"100%\" width=\"100%\"></rect>\n </svg>\n }\n }\n</ng-content>\n@if (!!status()) {\n <span [ngClass]=\"statusClass()\"></span>\n}\n\n" }]
1238
+ ], host: { class: 'avatar', '[class]': 'hostClasses()' }, template: "<ng-content>\n @if (src()) {\n @defer (prefetch on idle) {\n <img src=\"{{src() ?? ''}}\" class=\"avatar-img\" alt=\"{{alt()}}\" />\n } @placeholder () {\n <svg aria-label=\"Avatar placeholder\"\n focusable=\"false\"\n preserveAspectRatio=\"xMidYMid slice\"\n role=\"img\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"avatar-img\"\n style=\"position: absolute; width: 100%; height: 100%; inset: 0;\">\n <rect fill=\"#868e96\" height=\"100%\" width=\"100%\"></rect>\n </svg>\n }\n }\n</ng-content>\n@if (!!status()) {\n <span [ngClass]=\"statusClass()\"></span>\n}\n\n", styles: [":host .avatar-img{object-fit:cover}\n"] }]
1238
1239
  }] });
1239
1240
 
1240
1241
  class AvatarModule {