@engie-group/fluid-design-system-angular
Version:
Fluid Design System Angular
839 lines (821 loc) • 388 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, TemplateRef, Directive, Input, booleanAttribute, input, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, ContentChildren, HostBinding, ContentChild, DestroyRef, EventEmitter, contentChild, signal, effect, Output, ViewChild, forwardRef, ChangeDetectorRef, HostListener, ViewChildren, Inject, output, contentChildren, Pipe, Attribute, Optional, model, Self, Host, Injectable } from '@angular/core';
import * as i1 from '@angular/common';
import { NgTemplateOutlet, CommonModule, DOCUMENT } from '@angular/common';
import { ICON_ENGIE_PREFIX } from '@engie-group/fluid-types';
export * from '@engie-group/fluid-types';
import * as i2 from '@angular/forms';
import { NgModel, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
import { Subject, merge, fromEvent, takeUntil, race, BehaviorSubject } from 'rxjs';
import { trigger, state, transition, style, animate } from '@angular/animations';
import { njSemanticMotionEasingLinearOutSlowIn } from '@engie-group/fluid-design-tokens';
import { ComponentPortal, DomPortalOutlet, TemplatePortal } from '@angular/cdk/portal';
import * as i1$1 from '@angular/cdk/overlay';
import * as i1$2 from '@angular/cdk/dialog';
import * as i1$3 from '@angular/platform-browser';
const ThemeComponentsVariantsArray = [
'grey',
'brand',
'teal',
'pink',
'orange',
'red',
'green',
'ultramarine',
'yellow',
'purple',
'blue',
'lime'
];
class CustomIconDirective {
constructor() {
this.templateRef = inject(TemplateRef);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CustomIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.13", type: CustomIconDirective, isStandalone: true, selector: "[njCustomIcon]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CustomIconDirective, decorators: [{
type: Directive,
args: [{
selector: '[njCustomIcon]',
standalone: true
}]
}] });
class EngieTemplateDirective {
constructor() {
this.templateRef = inject(TemplateRef);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: EngieTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.13", type: EngieTemplateDirective, isStandalone: true, selector: "[njTemplate]", inputs: { selector: ["njTemplate", "selector"] }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: EngieTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[njTemplate]',
standalone: true
}]
}], propDecorators: { selector: [{
type: Input,
args: ['njTemplate']
}] } });
class HeadingDirective {
get classes() {
return {
'nj-heading': true,
'nj-heading--not-invertible': this.isNotInvertible,
[`nj-heading--${this.scale}`]: !!this.scale,
[`nj-heading--${this.variant}`]: !!this.variant
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HeadingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.13", type: HeadingDirective, isStandalone: true, selector: "[njHeading]", inputs: { scale: "scale", variant: "variant", isNotInvertible: ["isNotInvertible", "isNotInvertible", booleanAttribute] }, host: { properties: { "class": "classes" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HeadingDirective, decorators: [{
type: Directive,
args: [{
selector: '[njHeading]',
standalone: true,
host: {
'[class]': 'classes'
}
}]
}], propDecorators: { scale: [{
type: Input
}], variant: [{
type: Input
}], isNotInvertible: [{
type: Input,
args: [{ transform: booleanAttribute }]
}] } });
class TextDirective {
get classes() {
return {
'nj-text': true,
'nj-text--not-invertible': this.isNotInvertible,
'nj-text--monospace': this.isMono,
[`nj-text--${this.scale}`]: !!this.scale,
[`nj-text--${this.variant}`]: !!this.variant
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: TextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.13", type: TextDirective, isStandalone: true, selector: "[njText]", inputs: { scale: "scale", variant: "variant", isNotInvertible: ["isNotInvertible", "isNotInvertible", booleanAttribute], isMono: ["isMono", "isMono", booleanAttribute] }, host: { properties: { "class.nj-text": "true", "class.nj-text--not-invertible": "isNotInvertible", "class.nj-text--monospace": "isMono", "class": "classes" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: TextDirective, decorators: [{
type: Directive,
args: [{
selector: '[njText]',
standalone: true,
host: {
'[class.nj-text]': 'true',
'[class.nj-text--not-invertible]': 'isNotInvertible',
'[class.nj-text--monospace]': 'isMono',
'[class]': 'classes'
}
}]
}], propDecorators: { scale: [{
type: Input
}], variant: [{
type: Input
}], isNotInvertible: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], isMono: [{
type: Input,
args: [{ transform: booleanAttribute }]
}] } });
class IconComponent {
constructor() {
this.ICON_MATERIAL_CLASS = 'nj-icon-material';
/**
* Icon name
*/
this.name = input.required(...(ngDevMode ? [{ debugName: "name" }] : []));
/**
* Icon size
*/
this.scale = input(...(ngDevMode ? [undefined, { debugName: "scale" }] : []));
/**
* Icon variant theme
*/
this.variant = input(...(ngDevMode ? [undefined, { debugName: "variant" }] : []));
/**
* Icon style
*/
this.iconStyle = input(...(ngDevMode ? [undefined, { debugName: "iconStyle" }] : []));
/**
* Text alternative for assistive technologies.
* When provided, removes `aria-hidden` and exposes the icon to screen readers.
*/
this.ariaLabel = input(undefined, ...(ngDevMode ? [{ debugName: "ariaLabel", alias: 'aria-label' }] : [{ alias: 'aria-label' }]));
this.classes = computed(() => {
const base = this.ICON_MATERIAL_CLASS;
const scale = this.scale();
const variant = this.variant();
const iconStyle = this.iconStyle();
const name = this.name();
const isEngie = name.startsWith(ICON_ENGIE_PREFIX);
return {
[base]: true,
[`${base}--${scale === 'inherit' ? 'size-inherit' : scale}`]: !!scale && scale !== 'md',
[`${base}--${variant === 'inherit' ? 'color-inherit' : variant}`]: !!variant && variant !== 'primary',
[`${base}--${iconStyle}`]: !!iconStyle && iconStyle !== 'filled' && !isEngie,
[`${base}--engie`]: isEngie
};
}, ...(ngDevMode ? [{ debugName: "classes" }] : []));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.13", type: IconComponent, isStandalone: true, selector: "nj-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, iconStyle: { classPropertyName: "iconStyle", publicName: "iconStyle", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.aria-hidden": "ariaLabel() ? null : \"true\"", "attr.role": "ariaLabel() ? \"img\" : null" } }, ngImport: i0, template: "{{ name() }}\n", styles: [":host,nj-icon{display:inline-flex}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IconComponent, decorators: [{
type: Component,
args: [{ selector: 'nj-icon', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
'[class]': 'classes()',
'[attr.aria-hidden]': 'ariaLabel() ? null : "true"',
'[attr.role]': 'ariaLabel() ? "img" : null'
}, template: "{{ name() }}\n", styles: [":host,nj-icon{display:inline-flex}\n"] }]
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], iconStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconStyle", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }] } });
class AccordionItemComponent {
constructor() {
this.element = inject(ElementRef);
this.accordion = inject(AccordionComponent);
}
get classes() {
const classes = ['nj-accordion-item'];
if (this.scale && this.scale !== 'md') {
classes.push(`nj-accordion-item--${this.scale}`);
}
if (this.hasLeadingToggleIcon) {
classes.push('nj-accordion-item--leading-toggle');
}
return classes;
}
ngAfterContentInit() {
this.templateDirectives?.forEach((templateDirective) => {
if (templateDirective?.selector === 'icon') {
this.iconTemplate = templateDirective.templateRef;
}
if (templateDirective?.selector === 'header') {
this.headerTemplate = templateDirective.templateRef;
}
});
}
handleClick(event) {
if (this.name && !this.element.nativeElement.open) {
event.preventDefault();
this.accordion.collapseAllItems(this.name);
this.expand();
}
}
/**
* Expand the accordion item programmatically
*/
expand() {
if (this.element) {
this.element.nativeElement.open = true;
}
}
/**
* Collapse the accordion item programmatically
*/
collapse() {
if (this.element) {
this.element.nativeElement.open = false;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: AccordionItemComponent, isStandalone: true, selector: "details[nj-accordion-item]", inputs: { scale: "scale", hasLeadingToggleIcon: ["hasLeadingToggleIcon", "hasLeadingToggleIcon", booleanAttribute], useAlternativeToggleIcon: ["useAlternativeToggleIcon", "useAlternativeToggleIcon", booleanAttribute], name: "name", label: "label" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "classes" } }, queries: [{ propertyName: "templateDirectives", predicate: EngieTemplateDirective }], ngImport: i0, template: "@if (label || headerTemplate) {\n <summary>\n @if (iconTemplate) {\n <ng-container [ngTemplateOutlet]=\"iconTemplate\"></ng-container>\n }\n <span class=\"nj-accordion-item__label\">\n @if (label) {\n {{ label }}\n } @else {\n <ng-template [ngTemplateOutlet]=\"headerTemplate\"></ng-template>\n }\n </span>\n @if (!useAlternativeToggleIcon) {\n <nj-icon name=\"expand_more\" class=\"nj-accordion-item__toggle\" variant=\"inherit\" scale=\"inherit\"></nj-icon>\n } @else {\n <nj-icon\n name=\"add\"\n class=\"nj-accordion-item__toggle nj-accordion-item__toggle--closed\"\n variant=\"inherit\"\n scale=\"inherit\"\n ></nj-icon>\n <nj-icon\n name=\"remove\"\n class=\"nj-accordion-item__toggle nj-accordion-item__toggle--opened\"\n variant=\"inherit\"\n scale=\"inherit\"\n ></nj-icon>\n }\n </summary>\n}\n<p class=\"nj-accordion-item__content\">\n <ng-content></ng-content>\n</p>\n", styles: ["details[nj-accordion-item][open] nj-icon.nj-accordion-item__toggle.nj-accordion-item__toggle--opened{display:inline-flex}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "nj-icon", inputs: ["name", "scale", "variant", "iconStyle", "aria-label"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionItemComponent, decorators: [{
type: Component,
args: [{ selector: 'details[nj-accordion-item]', encapsulation: ViewEncapsulation.None, imports: [IconComponent, NgTemplateOutlet], host: {
'[class]': 'classes',
'(click)': 'handleClick($event)'
}, template: "@if (label || headerTemplate) {\n <summary>\n @if (iconTemplate) {\n <ng-container [ngTemplateOutlet]=\"iconTemplate\"></ng-container>\n }\n <span class=\"nj-accordion-item__label\">\n @if (label) {\n {{ label }}\n } @else {\n <ng-template [ngTemplateOutlet]=\"headerTemplate\"></ng-template>\n }\n </span>\n @if (!useAlternativeToggleIcon) {\n <nj-icon name=\"expand_more\" class=\"nj-accordion-item__toggle\" variant=\"inherit\" scale=\"inherit\"></nj-icon>\n } @else {\n <nj-icon\n name=\"add\"\n class=\"nj-accordion-item__toggle nj-accordion-item__toggle--closed\"\n variant=\"inherit\"\n scale=\"inherit\"\n ></nj-icon>\n <nj-icon\n name=\"remove\"\n class=\"nj-accordion-item__toggle nj-accordion-item__toggle--opened\"\n variant=\"inherit\"\n scale=\"inherit\"\n ></nj-icon>\n }\n </summary>\n}\n<p class=\"nj-accordion-item__content\">\n <ng-content></ng-content>\n</p>\n", styles: ["details[nj-accordion-item][open] nj-icon.nj-accordion-item__toggle.nj-accordion-item__toggle--opened{display:inline-flex}\n"] }]
}], propDecorators: { scale: [{
type: Input
}], hasLeadingToggleIcon: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], useAlternativeToggleIcon: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], name: [{
type: Input
}], label: [{
type: Input
}], templateDirectives: [{
type: ContentChildren,
args: [EngieTemplateDirective]
}] } });
class AccordionComponent {
get classes() {
const classes = ['nj-accordion'];
if (this.noBorder) {
classes.push('nj-accordion--no-border');
}
if (this.separated) {
classes.push('nj-accordion--separated');
}
return classes;
}
/**
* Expand all children items programmatically
*/
expandAllItems() {
const openedGroup = new Set();
this.accordions?.forEach((accordion) => {
// Firefox doesn't currently support grouping accordion items with `name` property.
// So we replicate the behavior here to have it on all browsers.
//
// As explained in the MDN documentation, when the `name` property is set, only the first details
// element with the `open` property should be opened.
if (!accordion.name || !openedGroup.has(accordion.name)) {
accordion.expand();
}
else {
accordion.collapse();
}
if (accordion.name) {
openedGroup.add(accordion.name);
}
});
}
/**
* Collapse all children items programmatically
*/
collapseAllItems(name) {
this.accordions?.forEach((accordion) => {
if (name && accordion.name !== name) {
return;
}
accordion.collapse();
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.3.13", type: AccordionComponent, isStandalone: true, selector: "nj-accordion", inputs: { noBorder: ["noBorder", "noBorder", booleanAttribute], separated: ["separated", "separated", booleanAttribute] }, host: { properties: { "class": "classes" } }, queries: [{ propertyName: "accordions", predicate: AccordionItemComponent }], ngImport: i0, template: "<ng-content></ng-content>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionComponent, decorators: [{
type: Component,
args: [{ selector: 'nj-accordion', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
'[class]': 'classes'
}, template: "<ng-content></ng-content>\n" }]
}], propDecorators: { noBorder: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], separated: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], accordions: [{
type: ContentChildren,
args: [AccordionItemComponent]
}] } });
class AccordionActionsComponent {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.13", type: AccordionActionsComponent, isStandalone: true, selector: "nj-accordion-actions", host: { classAttribute: "nj-accordion__actions" }, ngImport: i0, template: "<ng-content></ng-content>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionActionsComponent, decorators: [{
type: Component,
args: [{ selector: 'nj-accordion-actions', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: {
class: 'nj-accordion__actions'
}, template: "<ng-content></ng-content>\n" }]
}] });
class AccordionActionDirective {
constructor() {
this.accordion = inject(AccordionComponent);
}
handleClicked() {
if (this.type === 'expand') {
this.accordion?.expandAllItems();
}
if (this.type === 'collapse') {
this.accordion?.collapseAllItems();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionActionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.13", type: AccordionActionDirective, isStandalone: true, selector: "[njAccordionAction]", inputs: { type: ["njAccordionAction", "type"] }, host: { listeners: { "click": "handleClicked()" }, properties: { "attr.data-accordion-expand": "type === 'expand'", "attr.data-accordion-collapse": "type === 'collapse'" }, classAttribute: "njAccordionAction" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: AccordionActionDirective, decorators: [{
type: Directive,
args: [{
selector: '[njAccordionAction]',
standalone: true,
host: {
class: 'njAccordionAction',
'[attr.data-accordion-expand]': "type === 'expand'",
'[attr.data-accordion-collapse]': "type === 'collapse'",
'(click)': 'handleClicked()'
}
}]
}], propDecorators: { type: [{
type: Input,
args: ['njAccordionAction']
}] } });
const selectAnimations = {
transformList: trigger('transformList', [
state('void', style({
transform: 'scaleY(0.8)',
opacity: 0
})),
state('*', style({
opacity: 1,
transform: 'scaleY(1)'
})),
transition('void => *', animate(`120ms ${njSemanticMotionEasingLinearOutSlowIn}`)),
transition('* => void', animate(`100ms 25ms ${njSemanticMotionEasingLinearOutSlowIn}`, style({ opacity: 0 })))
])
};
// Ignore https://angular.io/guide/angular-compiler-options#strictmetadataemit
// @dynamic
class Utils {
static { this.MAX_UID = 1000000; }
static isUndefinedOrNull(value) {
return typeof value === 'undefined' || value === null;
}
static normalizeString(text) {
return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
static normalizeAndSearchInText(text, search) {
if (Utils.isUndefinedOrNull(text) || Utils.isUndefinedOrNull(search)) {
return false;
}
const normalizedText = Utils.normalizeString(text);
let normalizedSearch = Utils.escapeRegExp(Utils.normalizeString(search));
const regExp = new RegExp(normalizedSearch, 'gi');
return normalizedText.search(regExp) !== -1;
}
static escapeRegExp(string) {
return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
}
static getUID(prefix) {
do {
// eslint-disable-next-line no-bitwise
prefix += ~~(Math.random() * Utils.MAX_UID); // "~~" acts like a faster Math.floor() here
} while (document.getElementById(prefix));
return prefix;
}
}
class FormFieldDirective {
constructor(el) {
this.el = el;
this.class = 'nj-form-item__field';
this.setPlaceholder();
}
setPlaceholder() {
if (this.tagName.toLowerCase() === 'select') {
return;
}
const placeholder = this.el?.nativeElement?.placeholder;
this.el.nativeElement.placeholder =
Utils.isUndefinedOrNull(placeholder) || placeholder?.trim() === ''
? ' ' // Placeholder must be " " because of webkit browser behavior with floating labels
: placeholder;
}
get type() {
return this.el?.nativeElement?.type;
}
set type(value) {
if (this.el?.nativeElement) {
this.el.nativeElement.type = value;
}
}
get tagName() {
return this.el?.nativeElement?.tagName;
}
get element() {
return this.el?.nativeElement;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: FormFieldDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.13", type: FormFieldDirective, isStandalone: true, selector: "input[njFormField], textarea[njFormField], select[njFormField], nj-select[njFormField], div[njFormField]", host: { properties: { "class": "this.class" } }, exportAs: ["njFormField"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: FormFieldDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[njFormField], textarea[njFormField], select[njFormField], nj-select[njFormField], div[njFormField]',
exportAs: 'njFormField',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { class: [{
type: HostBinding,
args: ['class']
}] } });
class IconButtonIconDirective {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IconButtonIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.13", type: IconButtonIconDirective, isStandalone: true, selector: "[njIconButtonIcon]", host: { classAttribute: "nj-icon-btn__icon" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IconButtonIconDirective, decorators: [{
type: Directive,
args: [{
selector: '[njIconButtonIcon]',
standalone: true,
host: {
class: 'nj-icon-btn__icon'
}
}]
}] });
const rootClassName = 'nj-icon-btn';
class IconButtonComponent {
constructor() {
/**
* Whether button has custom icon
*/
this.hasCustomIcon = false;
}
ngAfterContentInit() {
if (this.template?.selector === 'icon') {
this.iconTemplateRef = this.template.templateRef;
}
}
get classes() {
const classes = [rootClassName];
if (this.variant) {
classes.push(`${rootClassName}--${this.variant}`);
}
const scale = this.scale ?? this.size;
if (scale) {
classes.push(`${rootClassName}--${scale}`);
}
return classes;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IconButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: IconButtonComponent, isStandalone: true, selector: "button[nj-icon-button]", inputs: { variant: "variant", size: "size", scale: "scale", hasCustomIcon: "hasCustomIcon", icon: "icon", altLabel: "altLabel" }, host: { properties: { "class": "classes" } }, queries: [{ propertyName: "template", first: true, predicate: EngieTemplateDirective, descendants: true }], ngImport: i0, template: "@if (altLabel) {\n <span class=\"nj-sr-only\">{{ altLabel }}</span>\n}\n@if (icon) {\n <nj-icon njIconButtonIcon [name]=\"icon\"></nj-icon>\n} @else if (iconTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"iconTemplateRef\"></ng-container>\n}\n", dependencies: [{ kind: "component", type: IconComponent, selector: "nj-icon", inputs: ["name", "scale", "variant", "iconStyle", "aria-label"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconButtonIconDirective, selector: "[njIconButtonIcon]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IconButtonComponent, decorators: [{
type: Component,
args: [{ selector: 'button[nj-icon-button]', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [IconComponent, CommonModule, IconButtonIconDirective], host: {
'[class]': 'classes'
}, template: "@if (altLabel) {\n <span class=\"nj-sr-only\">{{ altLabel }}</span>\n}\n@if (icon) {\n <nj-icon njIconButtonIcon [name]=\"icon\"></nj-icon>\n} @else if (iconTemplateRef) {\n <ng-container [ngTemplateOutlet]=\"iconTemplateRef\"></ng-container>\n}\n" }]
}], propDecorators: { variant: [{
type: Input
}], size: [{
type: Input
}], scale: [{
type: Input
}], hasCustomIcon: [{
type: Input
}], icon: [{
type: Input
}], altLabel: [{
type: Input
}], template: [{
type: ContentChild,
args: [EngieTemplateDirective]
}] } });
class FormItemComponent {
constructor() {
this.destroyRef = inject(DestroyRef);
this.formItemClassName = 'nj-form-item';
/**
* @ignore
*/
this.isVisible = false;
/**
* @ignore
*/
this.passwordNotice = '';
/**
* @ignore
*/
this.passwordButtonLabel = '';
/**
* @ignore
*/
this.isMultiline = false;
/**
* Form item size
*
* @deprecated Use `scale` instead. This property will be removed in future releases.
*/
this.size = 'medium';
/**
* Whether the form-item label is floating
*/
this.isFloatingLabel = true;
/**
* Whether the form-item's icon (or custom icon) is clickable
*/
this.isIconClickable = true;
/**
* Additional form-item css classes
*/
this.additionalClass = '';
/**
* Outputs icon click
*/
this.iconClick = new EventEmitter();
/**
* Outputs icon keydown
*/
this.iconKeydown = new EventEmitter();
/**
* Outputs icon click
*/
this.wrapperClick = new EventEmitter();
/**
* Outputs clear icon click
*/
this.clearIconClick = new EventEmitter();
this.formField = contentChild(FormFieldDirective, ...(ngDevMode ? [{ debugName: "formField" }] : []));
this.formFieldNgModel = contentChild(FormFieldDirective, ...(ngDevMode ? [{ debugName: "formFieldNgModel", read: NgModel }] : [{ read: NgModel }]));
this.formFieldValue = signal('', ...(ngDevMode ? [{ debugName: "formFieldValue" }] : []));
this.hasValue = computed(() => !!this.formFieldValue(), ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
this.cleanInputListener = null;
this.formFieldValueChangeEffect = effect(() => {
const value = this.formFieldValue();
const formField = this.formField();
if (formField?.element && formField.element.value !== value) {
formField.element.value = value;
}
}, ...(ngDevMode ? [{ debugName: "formFieldValueChangeEffect" }] : []));
this.handleFormFieldInputEffect = effect(() => {
this.cleanInputListener?.();
const input = this.formField()?.element;
if (!input) {
return;
}
this.formFieldValue.set(input.value);
const onInput = () => {
this.formFieldValue.set(input.value);
};
//Fixme: Necessary for clearable to works with autocomplete.
// Blocking for FLuid 6 release, will be reworked with form-item component redesign
this.formFieldNgModel()?.control.registerOnChange(onInput.bind(this));
input.addEventListener('input', onInput);
this.cleanInputListener = () => {
input.removeEventListener('input', onInput);
this.cleanInputListener = null;
};
this.destroyRef.onDestroy(() => this.cleanInputListener?.());
}, ...(ngDevMode ? [{ debugName: "handleFormFieldInputEffect" }] : []));
}
/**
* Whether form-item is in success state
*/
set hasSuccess(value) {
this._hasSuccess = value;
this.setAriaAttributes();
}
get hasSuccess() {
return !!this._hasSuccess;
}
/**
* Whether form-item is in error state
*/
set hasError(value) {
this._hasError = value;
this.setAriaAttributes();
}
get hasError() {
return !!this._hasError;
}
/**
* Whether the form-item has a hint substring
*/
set hasHint(value) {
this._hasHint = value;
this.setAriaAttributes();
}
get hasHint() {
return !!this._hasHint;
}
ngAfterContentInit() {
const tagName = this.formField()?.tagName?.toLowerCase();
this.isPassword = this.formField()?.type === 'password';
this.isMultiline = tagName === 'textarea';
this.passwordButtonLabel = this.passwordButtonLabelShow ?? '';
this.setAriaAttributes();
if (this.isRequired) {
this.formField()?.element.setAttribute('required', 'required');
}
}
/**
* @ignore
*/
iconClickHandler(event) {
if (!this.isIconClickable) {
return;
}
this.iconClick.emit(event);
}
/**
* @ignore
*/
iconKeydownHandler(event) {
event?.preventDefault();
if (!this.isIconClickable) {
return;
}
this.iconKeydown.emit(event);
}
/**
* @ignore
*/
toggleVisibility() {
const formField = this.formField();
if (this.isVisible) {
if (formField) {
formField.type = 'password';
}
this.passwordNotice = this.passwordNoticeIsHidden ?? '';
this.passwordButtonLabel = this.passwordButtonLabelShow ?? '';
}
else {
if (formField) {
formField.type = 'text';
}
this.passwordNotice = this.passwordNoticeIsVisible ?? '';
this.passwordButtonLabel = this.passwordButtonLabelHide ?? '';
}
this.isVisible = !this.isVisible;
}
/**
* @ignore
*/
getSubscriptId() {
return `${this.inputId}-subscript`;
}
/**
* @ignore
*/
setAriaAttributes() {
const formField = this.formField();
if (formField?.element) {
if (this.hasError) {
formField.element.setAttribute('aria-invalid', 'true');
}
if (this.hasError || this.hasSuccess || this.hasHint) {
formField.element.setAttribute('aria-describedby', this.getSubscriptId());
}
}
}
/**
* @ignore
*/
isCustomSelect() {
const type = this.formField()?.type;
return !!this.isSelect && type === 'text';
}
/**
* @ignore
*/
getFormItemSizeClass() {
let sizeModifier;
switch (this.size) {
case 'small':
sizeModifier = 'sm';
break;
case 'large':
sizeModifier = 'lg';
break;
case 'xlarge':
sizeModifier = 'xl';
break;
default:
break;
}
const scale = this.scale ?? sizeModifier;
return scale ? `${this.formItemClassName}--${scale}` : '';
}
clearInput(event) {
const formField = this.formField();
if (formField?.element) {
this.formFieldValue.set('');
}
this.clearIconClick.emit(event);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: FormItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: FormItemComponent, isStandalone: true, selector: "nj-form-item", inputs: { inputId: "inputId", size: "size", scale: "scale", isFloatingLabel: "isFloatingLabel", isDisabled: "isDisabled", isRequired: "isRequired", clearable: "clearable", hasSuccess: "hasSuccess", hasError: "hasError", hasHint: "hasHint", hasCustomIcon: "hasCustomIcon", isIconClickable: "isIconClickable", iconName: "iconName", additionalClass: "additionalClass", passwordButtonLabelShow: "passwordButtonLabelShow", passwordButtonLabelHide: "passwordButtonLabelHide", passwordNoticeIsVisible: "passwordNoticeIsVisible", passwordNoticeIsHidden: "passwordNoticeIsHidden", isSelect: "isSelect" }, outputs: { iconClick: "iconClick", iconKeydown: "iconKeydown", wrapperClick: "wrapperClick", clearIconClick: "clearIconClick" }, queries: [{ propertyName: "formField", first: true, predicate: FormFieldDirective, descendants: true, isSignal: true }, { propertyName: "formFieldNgModel", first: true, predicate: FormFieldDirective, descendants: true, read: NgModel, isSignal: true }], ngImport: i0, template: "<div\n class=\"nj-form-item\"\n [class.nj-form-item--static]=\"!isFloatingLabel\"\n [class.nj-form-item--disabled]=\"isDisabled\"\n [class.nj-form-item--error]=\"hasError\"\n [class.nj-form-item--success]=\"hasSuccess\"\n [class.nj-form-item--password]=\"isPassword\"\n [class.nj-form-item--select]=\"isSelect\"\n [class.nj-form-item--visible]=\"isVisible\"\n [class.nj-form-item--textarea]=\"isMultiline\"\n [ngClass]=\"[getFormItemSizeClass(), additionalClass]\"\n>\n <div class=\"nj-form-item__field-wrapper\" (click)=\"wrapperClick.emit($event)\">\n <ng-content select=\"[njFormField]\"></ng-content>\n <label class=\"nj-form-item__label\" [attr.for]=\"inputId\" [attr.aria-hidden]=\"isCustomSelect() ? 'true' : null\">\n <ng-content select=\"[njFormLabel]\"></ng-content>\n @if (isRequired) {\n <span class=\"nj-form-item__required-asterisk\">*</span>\n }\n </label>\n <ng-content select=\"[njFormAdditionalContent]\"></ng-content>\n @let hasIcon =\n isPassword || (!isMultiline && (iconName || hasCustomIcon)) || (clearable && hasValue() && !isDisabled);\n @if (hasIcon) {\n <div class=\"nj-form-item__trailing\">\n @if (clearable && hasValue() && !isDisabled) {\n <button\n nj-icon-button\n class=\"nj-form-item__clear-button\"\n scale=\"sm\"\n variant=\"tertiary\"\n [altLabel]=\"passwordButtonLabel\"\n (click)=\"clearInput($event)\"\n icon=\"cancel\"\n [attr.aria-pressed]=\"isVisible\"\n ></button>\n }\n @if (isPassword) {\n <button\n nj-icon-button\n class=\"nj-form-item__password-button\"\n scale=\"sm\"\n variant=\"tertiary\"\n [altLabel]=\"passwordButtonLabel\"\n [icon]=\"iconName || 'visibility'\"\n (click)=\"toggleVisibility()\"\n [attr.aria-pressed]=\"isVisible\"\n ></button>\n <p class=\"nj-sr-only\" aria-live=\"polite\" aria-atomic=\"true\">{{ passwordNotice }}</p>\n } @else if (!isMultiline && !hasCustomIcon && iconName) {\n <nj-icon\n class=\"nj-form-item__icon\"\n [name]=\"iconName\"\n (click)=\"iconClickHandler($event)\"\n (keydown)=\"iconKeydownHandler($event)\"\n >\n </nj-icon>\n } @else if (!isMultiline && hasCustomIcon) {\n <div\n class=\"nj-form-item__icon\"\n [attr.tabindex]=\"isIconClickable ? 0 : null\"\n (click)=\"iconClickHandler($event)\"\n (keydown)=\"iconKeydownHandler($event)\"\n >\n <ng-content select=\"[njFormCustomIcon]\"></ng-content>\n </div>\n }\n </div>\n }\n </div>\n @if (hasError || hasSuccess || hasHint) {\n <div class=\"nj-form-item__subscript\" [attr.id]=\"getSubscriptId()\">\n @if (hasError) {\n <nj-icon class=\"nj-form-item__subscript-icon\" name=\"warning\"></nj-icon>\n } @else if (hasSuccess) {\n <nj-icon class=\"nj-form-item__subscript-icon\" name=\"check\"></nj-icon>\n }\n <ng-content select=\"[njFormSubscript]\"></ng-content>\n </div>\n }\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "nj-icon", inputs: ["name", "scale", "variant", "iconStyle", "aria-label"] }, { kind: "component", type: IconButtonComponent, selector: "button[nj-icon-button]", inputs: ["variant", "size", "scale", "hasCustomIcon", "icon", "altLabel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: FormItemComponent, decorators: [{
type: Component,
args: [{ selector: 'nj-form-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [IconComponent, IconButtonComponent, CommonModule], template: "<div\n class=\"nj-form-item\"\n [class.nj-form-item--static]=\"!isFloatingLabel\"\n [class.nj-form-item--disabled]=\"isDisabled\"\n [class.nj-form-item--error]=\"hasError\"\n [class.nj-form-item--success]=\"hasSuccess\"\n [class.nj-form-item--password]=\"isPassword\"\n [class.nj-form-item--select]=\"isSelect\"\n [class.nj-form-item--visible]=\"isVisible\"\n [class.nj-form-item--textarea]=\"isMultiline\"\n [ngClass]=\"[getFormItemSizeClass(), additionalClass]\"\n>\n <div class=\"nj-form-item__field-wrapper\" (click)=\"wrapperClick.emit($event)\">\n <ng-content select=\"[njFormField]\"></ng-content>\n <label class=\"nj-form-item__label\" [attr.for]=\"inputId\" [attr.aria-hidden]=\"isCustomSelect() ? 'true' : null\">\n <ng-content select=\"[njFormLabel]\"></ng-content>\n @if (isRequired) {\n <span class=\"nj-form-item__required-asterisk\">*</span>\n }\n </label>\n <ng-content select=\"[njFormAdditionalContent]\"></ng-content>\n @let hasIcon =\n isPassword || (!isMultiline && (iconName || hasCustomIcon)) || (clearable && hasValue() && !isDisabled);\n @if (hasIcon) {\n <div class=\"nj-form-item__trailing\">\n @if (clearable && hasValue() && !isDisabled) {\n <button\n nj-icon-button\n class=\"nj-form-item__clear-button\"\n scale=\"sm\"\n variant=\"tertiary\"\n [altLabel]=\"passwordButtonLabel\"\n (click)=\"clearInput($event)\"\n icon=\"cancel\"\n [attr.aria-pressed]=\"isVisible\"\n ></button>\n }\n @if (isPassword) {\n <button\n nj-icon-button\n class=\"nj-form-item__password-button\"\n scale=\"sm\"\n variant=\"tertiary\"\n [altLabel]=\"passwordButtonLabel\"\n [icon]=\"iconName || 'visibility'\"\n (click)=\"toggleVisibility()\"\n [attr.aria-pressed]=\"isVisible\"\n ></button>\n <p class=\"nj-sr-only\" aria-live=\"polite\" aria-atomic=\"true\">{{ passwordNotice }}</p>\n } @else if (!isMultiline && !hasCustomIcon && iconName) {\n <nj-icon\n class=\"nj-form-item__icon\"\n [name]=\"iconName\"\n (click)=\"iconClickHandler($event)\"\n (keydown)=\"iconKeydownHandler($event)\"\n >\n </nj-icon>\n } @else if (!isMultiline && hasCustomIcon) {\n <div\n class=\"nj-form-item__icon\"\n [attr.tabindex]=\"isIconClickable ? 0 : null\"\n (click)=\"iconClickHandler($event)\"\n (keydown)=\"iconKeydownHandler($event)\"\n >\n <ng-content select=\"[njFormCustomIcon]\"></ng-content>\n </div>\n }\n </div>\n }\n </div>\n @if (hasError || hasSuccess || hasHint) {\n <div class=\"nj-form-item__subscript\" [attr.id]=\"getSubscriptId()\">\n @if (hasError) {\n <nj-icon class=\"nj-form-item__subscript-icon\" name=\"warning\"></nj-icon>\n } @else if (hasSuccess) {\n <nj-icon class=\"nj-form-item__subscript-icon\" name=\"check\"></nj-icon>\n }\n <ng-content select=\"[njFormSubscript]\"></ng-content>\n </div>\n }\n</div>\n", styles: [":host{display:block}\n"] }]
}], propDecorators: { inputId: [{
type: Input
}], size: [{
type: Input
}], scale: [{
type: Input
}], isFloatingLabel: [{
type: Input
}], isDisabled: [{
type: Input
}], isRequired: [{
type: Input
}], clearable: [{
type: Input
}], hasSuccess: [{
type: Input
}], hasError: [{
type: Input
}], hasHint: [{
type: Input
}], hasCustomIcon: [{
type: Input
}], isIconClickable: [{
type: Input
}], iconName: [{
type: Input
}], additionalClass: [{
type: Input
}], passwordButtonLabelShow: [{
type: Input
}], passwordButtonLabelHide: [{
type: Input
}], passwordNoticeIsVisible: [{
type: Input
}], passwordNoticeIsHidden: [{
type: Input
}], isSelect: [{
type: Input
}], iconClick: [{
type: Output
}], iconKeydown: [{
type: Output
}], wrapperClick: [{
type: Output
}], clearIconClick: [{
type: Output
}], formField: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FormFieldDirective), { isSignal: true }] }], formFieldNgModel: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FormFieldDirective), { ...{ read: NgModel }, isSignal: true }] }] } });
class HighlightDirective {
constructor(el) {
this.el = el;
/**
* Whether to escape accents or no
*/
this.escapeAccents = true;
/**
* Whether to take into account case or no
*/
this.caseSensitive = false;
this.OPENING_TAG = '<mark class="nj-highlight">';
this.CLOSING_TAG = '</mark>';
}
ngOnChanges(changes) {
this.highlightText();
}
highlightText() {
if (Utils.isUndefinedOrNull(this.content) || Utils.isUndefinedOrNull(this.el?.nativeElement)) {
return;
}
const regexFlags = this.caseSensitive ? 'g' : 'gi';
let innerHtml;
if (Utils.isUndefinedOrNull(this.textToHighlight)) {
innerHtml = this.content;
}
else {
if (this.escapeAccents) {
const escapedText = Utils.escapeRegExp(Utils.normalizeString(this.textToHighlight));
const regExp = new RegExp(escapedText, regexFlags);
const matches = Utils.normalizeString(this.content).matchAll(regExp);
let finalText = this.content;
let buffer = 0;
if (!Utils.isUndefinedOrNull(matches)) {
for (const match of matches) {
const updatedIndex = buffer + (match.index ?? 0);
const textBeforeOccurrence = finalText.slice(0, updatedIndex);
const occurrence = finalText.slice(updatedIndex, updatedIndex + this.textToHighlight.length);
const textAfterOccurrence = finalText.slice(updatedIndex + this.textToHighlight.length, finalText.length);
finalText = `${textBeforeOccurrence}${this.OPENING_TAG}${occurrence}${this.CLOSING_TAG}${textAfterOccurrence}`;
buffer = buffer + this.OPENING_TAG.length + this.CLOSING_TAG.length;
}
}
innerHtml = finalText;