UNPKG

@clr/angular

Version:

Angular components for Clarity

991 lines (965 loc) 1.54 MB
import * as i0 from '@angular/core'; import { Directive, NgModule, Optional, Input, Injectable, Component, ChangeDetectionStrategy, EventEmitter, SkipSelf, HostBinding, Output, ContentChildren, PLATFORM_ID, Inject, ViewChild, HostListener, Renderer2, InjectionToken, ElementRef, NgZone, ChangeDetectorRef, ContentChild, ComponentFactoryResolver, KeyValueDiffers, Self, forwardRef, Attribute, TemplateRef, ViewContainerRef, LOCALE_ID, inject, Injector, VERSION, EnvironmentInjector, IterableDiffers, ViewChildren } from '@angular/core'; import * as i5 from '@angular/common'; import { CommonModule, isPlatformBrowser, DOCUMENT, NgForOf, getLocaleDayNames, FormStyle, TranslationWidth, getLocaleMonthNames, getLocaleFirstDayOfWeek, getLocaleDateFormat, FormatWidth } from '@angular/common'; import { ClarityIcons, angleIcon, exclamationCircleIcon, checkCircleIcon, ellipsisHorizontalIcon, windowCloseIcon, infoCircleIcon, timesIcon, angleDoubleIcon, eventIcon, calendarIcon, folderOpenIcon, minusIcon, plusIcon, eyeHideIcon, eyeIcon, ellipsisVerticalIcon, viewColumnsIcon, arrowIcon, stepForward2Icon, filterGridCircleIcon, filterGridIcon, errorStandardIcon, helpIcon, infoStandardIcon, noteIcon, successStandardIcon, warningStandardIcon, circleIcon, dotCircleIcon } from '@cds/core/icon'; import { map, tap, startWith, distinctUntilChanged, filter, skipUntil, debounceTime, takeUntil, take, first, switchMap as switchMap$1 } from 'rxjs/operators'; import * as i3 from 'rxjs'; import { Subject, BehaviorSubject, Observable, fromEvent, isObservable, of, shareReplay, combineLatest, startWith as startWith$1, switchMap, merge, map as map$1, EMPTY, ReplaySubject, tap as tap$1 } from 'rxjs'; import * as i2 from '@angular/animations'; import { animation, style, animate, trigger, transition, state, useAnimation, keyframes } from '@angular/animations'; import * as i1 from '@angular/forms'; import { FormControl, FormGroup, FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, SelectMultipleControlValueAccessor } from '@angular/forms'; import * as i1$1 from '@angular/router'; import { RouterModule } from '@angular/router'; import * as i1$2 from '@angular/cdk/a11y'; import { CdkTrapFocus } from '@angular/cdk/a11y'; import * as i2$1 from '@angular/cdk/drag-drop'; import { CdkDrag, CDK_DROP_LIST, CDK_DRAG_CONFIG } from '@angular/cdk/drag-drop'; import * as i1$3 from '@angular/cdk/bidi'; import { Directionality } from '@angular/cdk/bidi'; import { coerceNumberProperty } from '@angular/cdk/coercion'; import { _RecycleViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY } from '@angular/cdk/collections'; import * as i3$1 from '@angular/cdk/scrolling'; import { FixedSizeVirtualScrollStrategy, CdkVirtualScrollViewport, VIRTUAL_SCROLL_STRATEGY, ScrollDispatcher, ViewportRuler, CdkVirtualScrollable, CdkVirtualForOf } from '@angular/cdk/scrolling'; import '@cds/core/icon/register'; /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrIconCustomTag { } ClrIconCustomTag.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrIconCustomTag, deps: [], target: i0.ɵɵFactoryTarget.Directive }); ClrIconCustomTag.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: ClrIconCustomTag, selector: "clr-icon", ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrIconCustomTag, decorators: [{ type: Directive, args: [{ selector: 'clr-icon', }] }] }); class CdsIconCustomTag { } CdsIconCustomTag.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: CdsIconCustomTag, deps: [], target: i0.ɵɵFactoryTarget.Directive }); CdsIconCustomTag.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: CdsIconCustomTag, selector: "cds-icon", ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: CdsIconCustomTag, decorators: [{ type: Directive, args: [{ selector: 'cds-icon', }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ const CLR_ICON_DIRECTIVES = [ClrIconCustomTag, CdsIconCustomTag]; class ClrIconModule { } ClrIconModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrIconModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); ClrIconModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.2", ngImport: i0, type: ClrIconModule, declarations: [ClrIconCustomTag, CdsIconCustomTag], imports: [CommonModule], exports: [ClrIconCustomTag, CdsIconCustomTag] }); ClrIconModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrIconModule, imports: [CommonModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrIconModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule], declarations: [CLR_ICON_DIRECTIVES], exports: [CLR_ICON_DIRECTIVES], }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ /** * This is an abstract class because we need it to still be a valid token for dependency injection after transpiling. * This does not mean you should extend it, simply implementing it is fine. */ class LoadingListener { } /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ var ClrLoadingState; (function (ClrLoadingState) { ClrLoadingState[ClrLoadingState["DEFAULT"] = 0] = "DEFAULT"; ClrLoadingState[ClrLoadingState["LOADING"] = 1] = "LOADING"; ClrLoadingState[ClrLoadingState["SUCCESS"] = 2] = "SUCCESS"; ClrLoadingState[ClrLoadingState["ERROR"] = 3] = "ERROR"; })(ClrLoadingState || (ClrLoadingState = {})); class ClrLoading { // We find the first parent that handles something loading constructor(listener) { this.listener = listener; this._loadingState = ClrLoadingState.DEFAULT; } get loadingState() { return this._loadingState; } set loadingState(value) { if (value === true) { value = ClrLoadingState.LOADING; } else if (!value) { value = ClrLoadingState.DEFAULT; } if (value === this._loadingState) { return; } this._loadingState = value; if (this.listener) { this.listener.loadingStateChange(value); } } ngOnDestroy() { this.loadingState = ClrLoadingState.DEFAULT; } } ClrLoading.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrLoading, deps: [{ token: LoadingListener, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); ClrLoading.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: ClrLoading, selector: "[clrLoading]", inputs: { loadingState: ["clrLoading", "loadingState"] }, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrLoading, decorators: [{ type: Directive, args: [{ selector: '[clrLoading]', }] }], ctorParameters: function () { return [{ type: LoadingListener, decorators: [{ type: Optional }] }]; }, propDecorators: { loadingState: [{ type: Input, args: ['clrLoading'] }] } }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class IfExpandService { constructor() { this.expandable = 0; this.hasExpandTemplate = false; this._loading = false; this._expanded = false; this._expandChange = new Subject(); } get loading() { return this._loading; } set loading(value) { value = !!value; if (value !== this._loading) { this._loading = value; } } get expanded() { return this._expanded; } set expanded(value) { value = !!value; if (value !== this._expanded) { this._expanded = value; this._expandChange.next(value); } } get expandChange() { return this._expandChange.asObservable(); } toggle() { this.expanded = !this._expanded; } loadingStateChange(state) { switch (state) { case ClrLoadingState.LOADING: this.loading = true; break; default: this.loading = false; break; } } } IfExpandService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: IfExpandService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); IfExpandService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: IfExpandService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: IfExpandService, decorators: [{ type: Injectable }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ let NB_INSTANCES = 0; function uniqueIdFactory() { return 'clr-id-' + NB_INSTANCES++; } /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrAccordionDescription { } ClrAccordionDescription.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionDescription, deps: [], target: i0.ɵɵFactoryTarget.Component }); ClrAccordionDescription.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrAccordionDescription, selector: "clr-accordion-description, clr-step-description", host: { properties: { "class.clr-accordion-description": "true" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionDescription, decorators: [{ type: Component, args: [{ selector: 'clr-accordion-description, clr-step-description', template: `<ng-content></ng-content>`, host: { '[class.clr-accordion-description]': 'true' }, changeDetection: ChangeDetectionStrategy.OnPush, }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ const defaultAnimationTiming = '0.2s ease-in-out'; const defaultExpandAnimation = animation([style({ height: '{{ startHeight }}px' }), animate(defaultAnimationTiming, style({ height: '*' }))], { params: { startHeight: 0, // default }, }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ const panelAnimation = [ trigger('skipInitialRender', [transition(':enter', [])]), trigger('toggle', [ transition('void => *', [ style({ display: 'block', height: 0 }), animate(defaultAnimationTiming, style({ height: '*' })), ]), ]), ]; const stepAnimation = [ trigger('skipInitialRender', [transition(':enter', [])]), trigger('toggle', [ transition('void => *', [ style({ display: 'block', height: 0 }), animate(defaultAnimationTiming, style({ height: '*' })), ]), transition('* => void', [ style({ display: 'block' }), animate(defaultAnimationTiming, style({ height: 0, display: 'none' })), ]), ]), ]; /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ const commonStringsDefault = { open: 'Open', close: 'Close', show: 'Show', hide: 'Hide', apply: 'Apply', cancel: 'Cancel', expand: 'Expand', collapse: 'Collapse', more: 'More', select: 'Select', selectAll: 'Select All', previous: 'Previous', next: 'Next', current: 'Jump to current', info: 'Info', success: 'Success', warning: 'Warning', danger: 'Error', neutral: 'Neutral', unknown: 'Unknown', rowActions: 'Available actions', pickColumns: 'Manage Columns', showColumns: 'Show Columns', sortColumn: 'Sort Column', firstPage: 'First Page', lastPage: 'Last Page', nextPage: 'Next Page', previousPage: 'Previous Page', currentPage: 'Current Page', totalPages: 'Total Pages', filterItems: 'Filter items', minValue: 'Min value', maxValue: 'Max value', modalContentStart: 'Beginning of Modal Content', modalContentEnd: 'End of Modal Content', sidePanelPin: 'Pin Side Panel', showColumnsMenuDescription: 'Show or hide columns menu', allColumnsSelected: 'All columns selected', signpostToggle: 'Signpost Toggle', signpostClose: 'Close', loading: 'Loading', // Datagrid detailPaneStart: 'Start of row details', detailPaneEnd: 'End of row details', singleSelectionAriaLabel: 'Single selection header', singleActionableAriaLabel: 'Single actionable header', detailExpandableAriaLabel: 'Toggle more row content', datagridFilterAriaLabel: '{COLUMN} filter', datagridFilterLabel: '{COLUMN} filter', datagridFilterDialogAriaLabel: 'Filter dialog', columnSeparatorAriaLabel: 'Column resize handle', columnSeparatorDescription: 'Use left or right key to resize the column', fromLabel: 'From', toLabel: 'To', // Alert alertCloseButtonAriaLabel: 'Close alert', alertNextAlertAriaLabel: 'Next alert message, {CURRENT} of {COUNT}', alertPreviousAlertAriaLabel: 'Previous alert message, {CURRENT} of {COUNT}', // Date Picker datepickerDialogLabel: 'Choose date', datepickerToggleChooseDateLabel: 'Choose date', datepickerToggleChangeDateLabel: 'Change date, {SELECTED_DATE}', datepickerPreviousMonth: 'Previous month', datepickerCurrentMonth: 'Current month', datepickerNextMonth: 'Next month', datepickerPreviousDecade: 'Previous decade', datepickerNextDecade: 'Next decade', datepickerCurrentDecade: 'Current decade', datepickerSelectMonthText: 'Select month, the current month is {CALENDAR_MONTH}', datepickerSelectYearText: 'Select year, the current year is {CALENDAR_YEAR}', datepickerSelectedLabel: '{FULL_DATE} - Selected', // Stack View stackViewChanged: 'Value changed.', // Responsive Nav responsiveNavToggleOpen: 'Open navigation menu', responsiveNavToggleClose: 'Close navigation menu', responsiveNavOverflowOpen: 'Open navigation overflow menu', responsiveNavOverflowClose: 'Close navigation overflow menu', //Vertical Nav verticalNavToggle: 'Toggle vertical navigation', // Timeline steps timelineStepNotStarted: 'Not started', timelineStepCurrent: 'Current', timelineStepSuccess: 'Completed', timelineStepError: 'Error', timelineStepProcessing: 'In progress', // Combobox comboboxDelete: 'Delete selected option', comboboxSearching: 'Searching for matches for "{INPUT}"', comboboxSelection: 'Selection', comboboxSelected: 'Selected', comboboxNoResults: 'No results', comboboxOpen: 'Show options', // Datagrid expandable rows datagridExpandableBeginningOf: 'Beginning of', datagridExpandableEndOf: 'End of', datagridExpandableRowContent: 'Expandable row content', datagridExpandableRowsHelperText: `Screen reader table commands may not work for viewing expanded content, please use your screen reader's browse mode to read the content exposed by this button`, // Wizard wizardStep: 'Step', wizardStepCurrent: 'Current', wizardStepSuccess: 'Completed', wizardStepError: 'Error', wizardStepnavAriaLabel: 'Wizard steps', /** * Password Input * Screen-reader text for the hide/show password field button */ passwordHide: 'Hide password for {LABEL}', passwordShow: 'Show password for {LABEL}', /** * Datagrid footer; sr-only text after the number of selected rows. */ selectedRows: 'Selected rows', // Accordion/Stepper stepComplete: 'Step {STEP} complete', stepError: 'Error in step {STEP}', // File input browse: 'Browse', fileCount: '{COUNT} files', clearFile: 'Clear {FILE}', clearFiles: 'Clear {COUNT} files', // Tree selectedTreeNode: 'selected', unselectedTreeNode: 'unselected', // Breadcrumbs breadcrumbsLabel: 'breadcrumbs', expandBreadcrumbsLabel: 'Expand breadcrumbs', }; /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrCommonStringsService { constructor() { this._strings = commonStringsDefault; } /** * Access to all of the keys as strings */ get keys() { return this._strings; } /** * Allows you to pass in new overrides for localization */ localize(overrides) { this._strings = Object.assign(Object.assign({}, this._strings), overrides); } /** * Parse a string with a set of tokens to replace */ parse(source, tokens = {}) { const names = Object.keys(tokens); let output = source; if (names.length) { names.forEach(name => { output = output.replace(`{${name}}`, tokens[name]); }); } return output; } } ClrCommonStringsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrCommonStringsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); ClrCommonStringsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrCommonStringsService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrCommonStringsService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ var AccordionStatus; (function (AccordionStatus) { AccordionStatus["Inactive"] = "inactive"; AccordionStatus["Error"] = "error"; AccordionStatus["Complete"] = "complete"; })(AccordionStatus || (AccordionStatus = {})); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ var AccordionStrategy; (function (AccordionStrategy) { AccordionStrategy["Default"] = "default"; AccordionStrategy["Multi"] = "multi"; })(AccordionStrategy || (AccordionStrategy = {})); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ let accordionCount = 0; class AccordionPanelModel { constructor(id, accordionId) { this.id = id; this.accordionId = accordionId; this.status = AccordionStatus.Inactive; this.index = null; this.disabled = false; this.open = false; this.templateId = `${this.id}-${this.accordionId}`; } } class AccordionModel { constructor() { this.strategy = AccordionStrategy.Default; this.accordionCount = accordionCount++; this._panels = {}; } get panels() { return Object.keys(this._panels).map(id => this._panels[id]); } setStrategy(strategy) { this.strategy = strategy; } updatePanelOrder(ids) { ids.forEach((id, index) => (this._panels[id].index = index)); this.removeOldPanels(ids); } addPanel(id, open = false) { this._panels[id] = new AccordionPanelModel(id, this.accordionCount); this._panels[id].open = open; } togglePanel(panelId, open) { const panelIsOpen = this._panels[panelId].open; const newOpenState = open !== undefined ? open : !panelIsOpen; if (newOpenState && this.strategy === AccordionStrategy.Default) { this.closeAllPanels(); } this._panels[panelId].open = newOpenState; } disablePanel(panelId, disabled) { this._panels[panelId].disabled = disabled; } closeAllPanels() { this.panels.forEach(panel => (this._panels[panel.id].open = false)); } removeOldPanels(ids) { this.panels .filter(panel => ids.find(id => id === panel.id) === undefined) .forEach(panel => delete this._panels[panel.id]); } } /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class AccordionService { constructor() { this.accordion = new AccordionModel(); this._panelsChanges = new BehaviorSubject(this.accordion.panels); } getPanelChanges(panelId) { return this._panelsChanges.pipe(map(panels => panels.find(s => s.id === panelId))); } setStrategy(strategy) { this.accordion.setStrategy(strategy); } addPanel(panelId, open = false) { this.accordion.addPanel(panelId, open); this.emitUpdatedPanels(); } togglePanel(panelId, open) { this.accordion.togglePanel(panelId, open); this.emitUpdatedPanels(); } disablePanel(panelId, disabled) { this.accordion.disablePanel(panelId, disabled); this.emitUpdatedPanels(); } updatePanelOrder(ids) { this.accordion.updatePanelOrder(ids); this.emitUpdatedPanels(); } emitUpdatedPanels() { this._panelsChanges.next(this.accordion.panels); } } AccordionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); AccordionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionService, decorators: [{ type: Injectable }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrAccordionPanel { constructor(parent, commonStrings, accordionService, ifExpandService, cdr) { this.parent = parent; this.commonStrings = commonStrings; this.accordionService = accordionService; this.ifExpandService = ifExpandService; this.cdr = cdr; this.disabled = false; this.panelOpen = false; this.headingEnabled = false; this.panelOpenChange = new EventEmitter(); this._id = uniqueIdFactory(); } get id() { return this._id; } set id(value) { this._id = value; } get panelNumber() { return this._panelIndex + 1; } get headingLevel() { if (this.explicitHeadingLevel) { return this.explicitHeadingLevel; } return this.parent ? 4 : 3; } ngOnInit() { this.panel = this.accordionService.getPanelChanges(this.id).pipe(tap(panel => this.emitPanelChange(panel))); this.accordionService.addPanel(this.id, this.panelOpen); this.accordionService.togglePanel(this.id, this.panelOpen); this.accordionService.disablePanel(this.id, this.disabled); } ngOnChanges(changes) { if (this.panel && changes.panelOpen && changes.panelOpen.currentValue !== changes.panelOpen.previousValue) { this.accordionService.togglePanel(this.id, changes.panelOpen.currentValue); } if (this.panel && changes.disabled && changes.disabled.currentValue !== changes.disabled.previousValue) { this.accordionService.disablePanel(this.id, changes.disabled.currentValue); } } togglePanel() { this.accordionService.togglePanel(this.id); } collapsePanelOnAnimationDone(panel) { if (!panel.open) { this.ifExpandService.expanded = false; } } getPanelStateClasses(panel) { return `clr-accordion-panel-${panel.status} ${panel.open ? 'clr-accordion-panel-open' : ''}`; } getAccordionContentId(id) { return `clr-accordion-content-${id}'`; } getAccordionHeaderId(id) { return `clr-accordion-header-${id}`; } stepCompleteText(panelNumber) { return this.commonStrings.parse(this.commonStrings.keys.stepComplete, { STEP: panelNumber.toString() }); } stepErrorText(panelNumber) { return this.commonStrings.parse(this.commonStrings.keys.stepError, { STEP: panelNumber.toString() }); } emitPanelChange(panel) { if (panel.index !== this._panelIndex) { this._panelIndex = panel.index; // The whole chain of updates leading to this line starts in a ngAfterViewInit subscription in accordion.ts, // listening for DOM changes. It seems to only fails in tests, but as this is not a frequently called code, // I prefer to stay on the safe side and initiate a detection cycle here. this.cdr.detectChanges(); } if (panel.open !== this.panelOpen) { this.panelOpenChange.emit(panel.open); /** * @Note: this line below is needed because we don't want to use another value to track * for changes of the panel. Because we use BehaviorSubject this emit event is trigger on * init (that is not needed - there is no change of the original value) - in some cases this * lead to duplicate events. * * To prevent this we try to emit only when the value is changed and keep the value in sync * even that is used only into the Initial Lifecycle (ngOnInit). */ this.panelOpen = panel.open; } if (panel.open) { this.ifExpandService.expanded = true; } } } ClrAccordionPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionPanel, deps: [{ token: ClrAccordionPanel, optional: true, skipSelf: true }, { token: ClrCommonStringsService }, { token: AccordionService }, { token: IfExpandService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); ClrAccordionPanel.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrAccordionPanel, selector: "clr-accordion-panel", inputs: { disabled: ["clrAccordionPanelDisabled", "disabled"], panelOpen: ["clrAccordionPanelOpen", "panelOpen"], headingEnabled: ["clrAccordionPanelHeadingEnabled", "headingEnabled"], explicitHeadingLevel: ["clrAccordionPanelHeadingLevel", "explicitHeadingLevel"] }, outputs: { panelOpenChange: "clrAccordionPanelOpenChange" }, host: { properties: { "class.clr-accordion-panel": "true", "class.clr-accordion-panel-disabled": "this.disabled" } }, providers: [IfExpandService], queries: [{ propertyName: "accordionDescription", predicate: ClrAccordionDescription }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"panel | async; let panel\">\n <div [ngClass]=\"getPanelStateClasses(panel)\">\n <div\n class=\"clr-accordion-header\"\n [attr.role]=\"headingEnabled || explicitHeadingLevel ? 'heading' : null\"\n [attr.aria-level]=\"headingEnabled || explicitHeadingLevel ? headingLevel : null\"\n >\n <button\n type=\"button\"\n class=\"clr-accordion-header-button\"\n (click)=\"togglePanel()\"\n [id]=\"getAccordionHeaderId(panel.templateId)\"\n [disabled]=\"panel.disabled\"\n [attr.aria-controls]=\"!panel.disabled && panel.open ? getAccordionContentId(panel.templateId) : null\"\n [attr.aria-expanded]=\"panel.open\"\n [class.clr-accordion-header-has-description]=\"(accordionDescription.changes | async)?.length || accordionDescription.length\"\n #headerButton\n >\n <span class=\"clr-accordion-status\">\n <cds-icon shape=\"angle\" direction=\"right\" class=\"clr-accordion-angle\"></cds-icon>\n </span>\n <ng-content select=\"clr-accordion-title, clr-step-title\"></ng-content>\n <ng-content select=\"clr-accordion-description, clr-step-description\"></ng-content>\n </button>\n </div>\n <div\n @skipInitialRender\n role=\"region\"\n class=\"clr-accordion-content-region\"\n [id]=\"getAccordionContentId(panel.templateId)\"\n [attr.aria-hidden]=\"!panel.open\"\n [attr.aria-labelledby]=\"getAccordionHeaderId(panel.templateId)\"\n >\n <div\n *ngIf=\"panel.open\"\n @toggle\n (@toggle.done)=\"collapsePanelOnAnimationDone(panel)\"\n class=\"clr-accordion-content\"\n >\n <div class=\"clr-accordion-inner-content\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: CdsIconCustomTag, selector: "cds-icon" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }], animations: panelAnimation, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionPanel, decorators: [{ type: Component, args: [{ selector: 'clr-accordion-panel', host: { '[class.clr-accordion-panel]': 'true' }, changeDetection: ChangeDetectionStrategy.OnPush, animations: panelAnimation, providers: [IfExpandService], template: "<ng-container *ngIf=\"panel | async; let panel\">\n <div [ngClass]=\"getPanelStateClasses(panel)\">\n <div\n class=\"clr-accordion-header\"\n [attr.role]=\"headingEnabled || explicitHeadingLevel ? 'heading' : null\"\n [attr.aria-level]=\"headingEnabled || explicitHeadingLevel ? headingLevel : null\"\n >\n <button\n type=\"button\"\n class=\"clr-accordion-header-button\"\n (click)=\"togglePanel()\"\n [id]=\"getAccordionHeaderId(panel.templateId)\"\n [disabled]=\"panel.disabled\"\n [attr.aria-controls]=\"!panel.disabled && panel.open ? getAccordionContentId(panel.templateId) : null\"\n [attr.aria-expanded]=\"panel.open\"\n [class.clr-accordion-header-has-description]=\"(accordionDescription.changes | async)?.length || accordionDescription.length\"\n #headerButton\n >\n <span class=\"clr-accordion-status\">\n <cds-icon shape=\"angle\" direction=\"right\" class=\"clr-accordion-angle\"></cds-icon>\n </span>\n <ng-content select=\"clr-accordion-title, clr-step-title\"></ng-content>\n <ng-content select=\"clr-accordion-description, clr-step-description\"></ng-content>\n </button>\n </div>\n <div\n @skipInitialRender\n role=\"region\"\n class=\"clr-accordion-content-region\"\n [id]=\"getAccordionContentId(panel.templateId)\"\n [attr.aria-hidden]=\"!panel.open\"\n [attr.aria-labelledby]=\"getAccordionHeaderId(panel.templateId)\"\n >\n <div\n *ngIf=\"panel.open\"\n @toggle\n (@toggle.done)=\"collapsePanelOnAnimationDone(panel)\"\n class=\"clr-accordion-content\"\n >\n <div class=\"clr-accordion-inner-content\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n" }] }], ctorParameters: function () { return [{ type: ClrAccordionPanel, decorators: [{ type: Optional }, { type: SkipSelf }] }, { type: ClrCommonStringsService }, { type: AccordionService }, { type: IfExpandService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { disabled: [{ type: Input, args: ['clrAccordionPanelDisabled'] }, { type: HostBinding, args: ['class.clr-accordion-panel-disabled'] }], panelOpen: [{ type: Input, args: ['clrAccordionPanelOpen'] }], headingEnabled: [{ type: Input, args: ['clrAccordionPanelHeadingEnabled'] }], explicitHeadingLevel: [{ type: Input, args: ['clrAccordionPanelHeadingLevel'] }], panelOpenChange: [{ type: Output, args: ['clrAccordionPanelOpenChange'] }], accordionDescription: [{ type: ContentChildren, args: [ClrAccordionDescription] }] } }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrAccordion { constructor(accordionService) { this.accordionService = accordionService; this.multiPanel = false; this.subscriptions = []; } ngOnInit() { this.setAccordionStrategy(); } ngOnChanges(changes) { if (changes.multiPanel.currentValue !== changes.multiPanel.previousValue) { this.setAccordionStrategy(); } } ngAfterViewInit() { this.subscriptions.push(this.listenForDOMChanges()); } ngOnDestroy() { this.subscriptions.forEach(s => s.unsubscribe()); } setAccordionStrategy() { const strategy = this.multiPanel ? AccordionStrategy.Multi : AccordionStrategy.Default; this.accordionService.setStrategy(strategy); } listenForDOMChanges() { return this.panels.changes .pipe(startWith(this.panels)) .subscribe((panels) => this.accordionService.updatePanelOrder(panels.toArray().map(p => p.id))); } } ClrAccordion.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordion, deps: [{ token: AccordionService }], target: i0.ɵɵFactoryTarget.Component }); ClrAccordion.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrAccordion, selector: "clr-accordion", inputs: { multiPanel: ["clrAccordionMultiPanel", "multiPanel"] }, host: { properties: { "class.clr-accordion": "true" } }, providers: [AccordionService], queries: [{ propertyName: "panels", predicate: ClrAccordionPanel }], usesOnChanges: true, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordion, decorators: [{ type: Component, args: [{ selector: 'clr-accordion', template: `<ng-content></ng-content>`, host: { '[class.clr-accordion]': 'true' }, providers: [AccordionService], changeDetection: ChangeDetectionStrategy.OnPush, }] }], ctorParameters: function () { return [{ type: AccordionService }]; }, propDecorators: { multiPanel: [{ type: Input, args: ['clrAccordionMultiPanel'] }], panels: [{ type: ContentChildren, args: [ClrAccordionPanel] }] } }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrAccordionContent { } ClrAccordionContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionContent, deps: [], target: i0.ɵɵFactoryTarget.Component }); ClrAccordionContent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrAccordionContent, selector: "clr-accordion-content, clr-step-content", ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionContent, decorators: [{ type: Component, args: [{ selector: 'clr-accordion-content, clr-step-content', template: `<ng-content></ng-content>`, changeDetection: ChangeDetectionStrategy.OnPush, }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class ClrAccordionTitle { } ClrAccordionTitle.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionTitle, deps: [], target: i0.ɵɵFactoryTarget.Component }); ClrAccordionTitle.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrAccordionTitle, selector: "clr-accordion-title, clr-step-title", host: { properties: { "class.clr-accordion-title": "true" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionTitle, decorators: [{ type: Component, args: [{ selector: 'clr-accordion-title, clr-step-title', template: `<ng-content></ng-content>`, host: { '[class.clr-accordion-title]': 'true' }, changeDetection: ChangeDetectionStrategy.OnPush, }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ /* * After a conversation with the Angular core team, it turns out we don't have much of a choice for our * declarative API, we need to fight against change detection and its one-way flow. This is * currently the least dirty solution to do what we want. * * Do not modify or even use this class unless you know exactly what you're doing. * It has the potential to trigger change detection loops or kill app performances. */ class WillyWonka { constructor() { this.disableChocolateCheck = false; this._chocolate = new Subject(); } get chocolate() { return this._chocolate.asObservable(); } ngAfterViewChecked() { if (!this.disableChocolateCheck) { this._chocolate.next(); } } } WillyWonka.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: WillyWonka, deps: [], target: i0.ɵɵFactoryTarget.Directive }); WillyWonka.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: WillyWonka, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: WillyWonka, decorators: [{ type: Directive }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class OompaLoompa { // FIXME: Request Injector once we move to Angular 4.2+, it'll allow easier refactors constructor(cdr, willyWonka) { this.subscription = willyWonka.chocolate.subscribe(() => { if (this.latestFlavor !== this.flavor) { willyWonka.disableChocolateCheck = true; cdr.detectChanges(); willyWonka.disableChocolateCheck = false; } }); } ngAfterContentChecked() { this.latestFlavor = this.flavor; } ngOnDestroy() { this.subscription.unsubscribe(); } } OompaLoompa.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: OompaLoompa, deps: [{ token: i0.ChangeDetectorRef }, { token: WillyWonka }], target: i0.ɵɵFactoryTarget.Directive }); OompaLoompa.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: OompaLoompa, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: OompaLoompa, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: WillyWonka }]; } }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class AccordionWillyWonka extends WillyWonka { } AccordionWillyWonka.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionWillyWonka, deps: null, target: i0.ɵɵFactoryTarget.Directive }); AccordionWillyWonka.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: AccordionWillyWonka, selector: "clr-accordion", usesInheritance: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionWillyWonka, decorators: [{ type: Directive, args: [{ selector: 'clr-accordion', }] }] }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class AccordionOompaLoompa extends OompaLoompa { constructor(cdr, willyWonka, ifExpandService) { if (!willyWonka) { throw new Error('clr-accordion-panel should only be used inside of clr-accordion'); } super(cdr, willyWonka); this.expand = ifExpandService; } get flavor() { return this.expand.expanded; } } AccordionOompaLoompa.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionOompaLoompa, deps: [{ token: i0.ChangeDetectorRef }, { token: AccordionWillyWonka, optional: true }, { token: IfExpandService }], target: i0.ɵɵFactoryTarget.Directive }); AccordionOompaLoompa.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: AccordionOompaLoompa, selector: "clr-accordion-panel", usesInheritance: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: AccordionOompaLoompa, decorators: [{ type: Directive, args: [{ selector: 'clr-accordion-panel', }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: AccordionWillyWonka, decorators: [{ type: Optional }] }, { type: IfExpandService }]; } }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ const declarations$1 = [ ClrAccordion, ClrAccordionPanel, ClrAccordionTitle, ClrAccordionDescription, ClrAccordionContent, AccordionOompaLoompa, AccordionWillyWonka, ]; class ClrAccordionModule { constructor() { ClarityIcons.addIcons(angleIcon, exclamationCircleIcon, checkCircleIcon); } } ClrAccordionModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); ClrAccordionModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionModule, declarations: [ClrAccordion, ClrAccordionPanel, ClrAccordionTitle, ClrAccordionDescription, ClrAccordionContent, AccordionOompaLoompa, AccordionWillyWonka], imports: [CommonModule, ClrIconModule], exports: [ClrAccordion, ClrAccordionPanel, ClrAccordionTitle, ClrAccordionDescription, ClrAccordionContent, AccordionOompaLoompa, AccordionWillyWonka] }); ClrAccordionModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionModule, imports: [CommonModule, ClrIconModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAccordionModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, ClrIconModule], declarations: [...declarations$1], exports: [...declarations$1], }] }], ctorParameters: function () { return []; } }); /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ function triggerAllFormControlValidation(formGroup) { Object.keys(formGroup.controls).forEach(field => { const control = formGroup.get(field); if (control instanceof FormControl) { control.markAsTouched(); control.markAsDirty(); control.updateValueAndValidity(); } else if (control instanceof FormGroup) { triggerAllFormControlValidation(control); } }); } /* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ class StepperModel extends AccordionModel { constructor()