Skip to main content
cngx-src documentation
Miscellaneous > Functions

Functions

Function499

Index

adaptFormControlappendAtPathapplyFeaturesapplyFeaturesapplyMaskarrayEqualbucketbuildAsyncStateViewbuildCrumbsbuildCurvePathbuildDotsbuildSiblingscanDeactivateWhenCleancharMatcherclampclampclampHeadingLevelclampHeadingLevelclampVolumecoerceArraycoerceBooleanPropertycoerceColumnscoerceNumberPropertycollectDescendantValuescompileMatchercomputeFixedRangecomputeVariableRangeconnectPaginateEmitconnectPaginateResetOnconnectRecyclerToActiveDescendantconnectRecyclerToRovingcreateAccordionKeyboardNavcreateActionHostBridgecreateADActivationDispatchercreateArrayCommitHandlercreateAsyncStatecreateAutoplayGatecreateBandScalecreateBreadcrumbCollapsecreateChipRemovalHandlercreateChipStripRovingcreateCngxMatTabOverflowDomAdaptercreateCngxTabOverflowDefaultDomAdaptercreateCommitControllercreateCommitControllercreateCommitErrorAnnouncercreateControlledSourcecreateCreateCommitHandlercreateDebouncercreateDefaultFlatNavStrategycreateDirectiveByIdMapcreateDismissHandlercreateDisplayBindingcreateDomAnchorRetrycreateElementWidthSignalcreateEmptyFilterRootcreateFieldSynccreateFieldSynccreateFilterBuilderAnnouncercreateFilterBuilderStatecreateFilterBuilderTemplateRegistrycreateFilterExpressioncreateFilterGroupcreateIdentityPanelRenderercreateLinearScalecreateLocalItemsBuffercreateManualStatecreateMaterialBidirectionalSynccreateMatExpansionSetSynccreateMatStepHandlecreateMatTabHandlecreateMenuAnnouncercreateMenuDismissHandlercreateMenuTriggerDismissBindingcreateMobileViewportSignalcreateMockFieldcreateOrdinalScalecreateOrganismScrollSynccreateOverflowPopoverHighlightSynccreatePaginatorAnnouncercreatePaginatorNavCorecreatePanelLifecycleEmittercreatePasswordStrengthcreatePathBuildercreatePrefixPhoneMetadatacreateProjectedOptionModelcreateRecyclerPanelRendererFactorycreateReorderCommitHandlercreateScalarCommitHandlercreateSearchEffectscreateSelectionControllercreateSliderCorecreateSliderInteractioncreateSliderTickscreateSortHeaderStatecreateStepperCommitHandlercreateStepperDisplayModecreateStepperGroupNavigationcreateStepperGroupSummarycreateStepperHostProxycreateStepperStateViewcreateStepperTemplateBindingscreateStripDensitycreateTabDismissalscreateTabGroupAnnouncementscreateTabGroupTemplateBindingscreateTabKeyboardNavcreateTabOverflowTemplateBindingscreateTabRouterCommitcreateTabsCommitHandlercreateTemplateRegistrycreateThumbValuecreateTimeScalecreateTransitionTrackercreateTreeAdItemscreateTreeControllercreateTriggerFocusStatecreateTypeaheadControllercreateW3CMenuStrategycreateW3CTreeStrategycrumbsEqualdecimalPlacesdedupdefaultHalfWiredSlotWarndefaultRetryCeilingWarndefaultSearchFndefaultSortFndeltaDirectiondeltaSentimentdimensionsEqualdirectionGlyphdotsEqualensureFilterTreeIdsensureObservableevaluateExpressionfeaturefeaturefeaturefeaturefileKeyfilterSelectOptionsfilterTreefilterTreefilterTreeEqualfirstEmptySlotflattenSelectOptionsflattenTreeflattenTreefocusFirstErrorformatDeltafromHttpResourcefromQueryfromResourcegetNodeAtPathhasTransitionheadersEqualinjectAccordionConfiginjectAsyncRegistryinjectAsyncStateinjectAudioConfiginjectBreadcrumbConfiginjectChartContextinjectCngxAudioinjectDataGridAccordionConfiginjectDataSourceinjectDensityinjectFilterBuilderAnnouncerFactoryinjectFilterBuilderConfiginjectFilterBuilderTemplateRegistryinjectFilterEditorsinjectIncrementalListConfiginjectMatTabsConfiginjectMediaQueryinjectMenuAnnouncerinjectMenuConfiginjectNavConfiginjectPaginatorConfiginjectQueryParamSyncinjectRecyclerinjectSelectAnnouncerinjectSelectConfiginjectSidenavConfiginjectSmartDataSourceinjectStepperConfiginjectStepperI18ninjectTabsConfiginjectTabsI18ninjectTagConfiginjectTreeConfiginjectWindowisAsyncStateisCngxSelectOptionGroupDefisNativeEditorisNodeVisibleisOptionDisabledloadTablelocaleToRegionmakeVersionmatchesKeyCombomemoizemergeFeaturesmergeLocalItemsmockValidationErrornextSlotIndexnextUidnodeMatchesSearchonTransitionDoneoptimisticpageWindowpageWindowEqualparseEventBindingsparseKeyComboparseMaskparseStatusBindingspartitionFeaturespatternMatchpointerFractionprevSlotIndexprovideAccordionConfigprovideAccordionConfigAtprovideActionSelectConfigprovideActionSelectConfigAtprovideAsyncHttpObservabilityprovideAsyncRegistryprovideBreadcrumbConfigprovideBreadcrumbConfigAtprovideChartI18nprovideCngxAudioprovideCngxAudioAtprovideCngxMenuprovideCngxPaginatorConfigprovideCngxPaginatorConfigAtprovideCngxSelectprovideCngxSelectAtprovideCngxStepperprovideCngxStepperAtprovideCngxTabsprovideCngxTabsAtprovideDataGridAccordionConfigprovideDataGridAccordionConfigAtprovideDensityprovideDialogprovideDialogStackprovideEagerMaskPresetsprovideEnvironmentprovideErrorMessagesprovideFeedbackprovideFilterBuilderConfigprovideFilterBuilderConfigAtprovideFloatingFallbackprovideFormFieldprovideIncrementalListConfigprovideIncrementalListConfigAtprovideInputConfigprovideMatTabsConfigprovideMatTabsConfigAtprovideMenuConfigprovideMenuConfigAtprovideNavConfigprovideOverlayprovidePhoneMetadataprovidePopoverPanelprovideRecyclerI18nprovideReorderableSelectConfigprovideReorderableSelectConfigAtprovideSelectConfigprovideSelectConfigAtprovideSidenavConfigprovideSidenavConfigAtprovideStepperConfigprovideStepperConfigAtprovideStepperI18nprovideTabsConfigprovideTabsConfigAtprovideTabsI18nprovideTagConfigprovideTagConfigAtprovideToastsprovideTreeConfigprovideTreeConfigAtprovideTreetableprovideWindowrangereflectAsyncDisplayStatusremoveAtPathrequiredTrueresolveAsyncViewresolveBreadcrumbTierresolveCellTplresolveElementresolveFeaturesresolveHeaderTplresolveI18nFeaturesresolvePageJumpTargetresolveParentresolveStepperErrorSummaryresolveStepperStatusLabelresolveZiprunTabsActionscaleGainscaleStepsselectPatternsetEqualsetEqualssiblingsEqualsliderTickValuesslotCountsnapToStepsortTreesortTreesubtreeStatstabOverflowOptionIdtapAsyncProgresstapAsyncStatetapHttpAsyncStatetoFilterPredicatetrackForupdateAtPathuseStatSlotwalkTreewithAccordionLabelswithAccordionSkinwithAccordionTemplateswithActionAriaLabelwithActionPopoverPlacementwithActionPositionwithAlertIconswithAlertswithAnchorRetryAttemptswithAnnouncerwithAriaLabelswithAriaLabelswithArrowwithArrowTemplatewithAsyncLabelwithAsyncSkipwithAutocompleteMappingswithAutoDismisswithBannerswithBreadcrumbAriaLabelswithBreadcrumbDataKeywithBreadcrumbIconKeywithBreadcrumbSkinwithCapitaliseHeaderswithCaretwithChipOverflowwithCloseButtonwithCloseIconwithCloseOnCreatewithCloseOnSelectwithCloseOnSuccesswithCngxAsyncStatewithCommitErrorAnnouncePolicywithCommitErrorDisplaywithConstraintHintswithCopyResetDelaywithCurrencywithCustomTokenswithDataGridSkinwithDateFormatswithDebounceMswithDefaultDragHandlewithDefaultHeadingLevelwithDefaultInitiallyExpandedwithDefaultKeyFnwithDefaultLabelFnwithDefaultNodeIdFnwithDefaultOperatorswithDefaultVariantwithDismissOnwithDismissOnBlurwithDismissOnOutsideClickwithDismissOnScrollwithDotStepperDotTemplatewithEarconswithEnterKeyHintwithErrorMessageswithErrorStrategywithFallbackLabelswithFileMaxFileswithFileMaxSizewithFilterBuilderI18nwithFocusTrapBehaviorwithHalfWiredSlotSinkwithHighlightOnHoverwithIbanPatternswithIncrementalListAriaLabelswithIncrementalListTemplateswithInputAriaLabelswithInputModewithLiveInputFallbackwithLoadingDefaultswithLoadingVariantwithLogicOptionswithMaskGuidewithMaskPlaceholderwithMaxNestingDepthwithMaxVisibleChipswithMutedwithNavAnimationwithNavIndentwithNegationwithNoSpellcheckwithNumericDefaultswithOpenOnwithPaginatorAnnouncementswithPaginatorAriaLabelswithPaginatorPageSizeOptionswithPaginatorPageStatusFormatwithPaginatorRangeFormatwithPaginatorTemplateswithPanelClasswithPanelWidthwithPhoneDefaultRegionwithPhonePatternswithPopoverPlacementwithRefreshingVariantwithReorderAriaLabelwithReorderKeyboardModifierwithReorderStripFreezewithRequiredMarkerwithRespectReducedMotionwithRestoreFocuswithRetrywithSelectionIndicatorwithSelectionIndicatorPositionwithSelectionIndicatorVariantwithSidenavDimensionswithSidenavHoverDwellwithSidenavResponsivewithSidenavRouterSyncwithSidenavShortcutwithSingleAccordionwithSkeletonCountwithSkeletonRowCountwithSpinnerTemplatewithStepBadgeTemplatewithStepBusySpinnerTemplatewithStepErrorTemplatewithStepGroupHeaderTemplatewithStepIndicatorTemplatewithStepperAriaLabelswithStepperCommitModewithStepperConnectorswithStepperDefaultOrientationwithStepperDensitywithStepperEmptyTemplatewithStepperFallbackLabelswithStepperGroupCollapsewithStepperGroupCollapseSummarywithStepperHeaderNavigationwithStepperI18nLabelswithStepperLinearwithStepperMobileBreakpointwithStepperMobileCollapsewithStepperMobileIndicatorPositionwithStepperMobileSwipewithStepperRouterSyncwithStepperSkinwithStepRejectionTemplatewithSubmenuCloseDelaywithSubmenuOpenDelaywithTabAddIconTemplatewithTabBusySpinnerTemplatewithTabCloseIconTemplatewithTabErrorBadgeTemplatewithTabIconTemplatewithTabOverflowItemTemplatewithTabOverflowMaxDeferMswithTabOverflowStabilizeMswithTabOverflowTriggerTemplatewithTabRejectionIconTemplatewithTabsAddablewithTabsAlignwithTabsAriaLabelswithTabsClosablewithTabsCommitModewithTabsDefaultOrientationwithTabsFallbackLabelswithTabsFittedwithTabsFragmentSyncwithTabsI18nLabelswithTabsIconLayoutwithTabsPanelModewithTabsRovingLoopwithTabsSkinwithTagColorswithTagDefaultswithTagGroupDefaultswithTagSlotswithTemplateswithToastswithTreeCacheLimitwithTypeaheadDebouncewithTypeaheadDebouncewithTypeaheadWhileClosedwithVirtualizationwithVolumewithZipPatterns
No matching entities

forms/field/form-control-adapter.ts

adaptFormControl#CngxFieldAccessor
adaptFormControl(control: AbstractControl, name: string, destroyRef: DestroyRef)

Adapts an Angular Reactive Forms AbstractControl (FormControl, FormGroup, FormArray) to the CngxFieldAccessor interface expected by cngx-form-field.

This enables using cngx-form-field without Signal Forms - for teams that haven't migrated yet or for forms that use Reactive Forms by design.

@paramcontrolAbstractControl

The Reactive Forms control to adapt.

@paramnamestring

A unique field name for deterministic ID generation.

@paramdestroyRefDestroyRef

A DestroyRef for automatic subscription cleanup. Required - without it the three RxJS subscriptions on the control would leak for the lifetime of the parent injector. Pass inject(DestroyRef) from a component field initialiser, or wrap the call in runInInjectionContext.

A CngxFieldAccessor compatible with [field] input on cngx-form-field.

readonly emailControl = new FormControl('', [Validators.required, Validators.email]);
readonly emailField = adaptFormControl(this.emailControl, 'email', inject(DestroyRef));

forms/filter-builder/filter-builder.utils.ts

appendAtPath#FilterGroup
appendAtPath(root: FilterGroup, path, child: FilterNode)

Append child to the group at path. Throws when path does not resolve to a group.

@paramrootFilterGroup
@parampath
@paramchildFilterNode
filterTreeEqual#boolean
filterTreeEqual(a: FilterGroup, b: FilterGroup)

Structural equality between two filter trees. Intended as the equal option on computed / linkedSignal exposing a FilterGroup, per the cngx signal-architecture equality rule (object/array computeds MUST pass an explicit equal fn). Identity short-circuits.

getNodeAtPath#FilterNode | null
getNodeAtPath(root: FilterGroup, path)

Pure tree utilities for the filter-builder data model. Every mutator returns a new tree; the originals are never modified. Identity is preserved when no descendant changed - feeds the filterTreeEqual short-circuit on computed / linkedSignal consumers (Pillar 1).

Paths are arrays of child indices. The empty path [] addresses the root group; [2, 0] addresses the first child of the root's third child.

@paramrootFilterGroup
@parampath
removeAtPath#FilterGroup
removeAtPath(root: FilterGroup, path)

Remove the node at path. Throws on empty path - the root cannot be removed.

@paramrootFilterGroup
@parampath
updateAtPath#FilterGroup
updateAtPath(root: FilterGroup, path, updater)

Replace the node at path via updater. Returns the original root when no descendant changed (identity-preserving).

@paramrootFilterGroup
@parampath
@paramupdater

ui/collection/incremental-list-config.ts

injectIncrementalListConfig Injectv0.1.0
provideIncrementalListConfig Providerv0.1.0
provideIncrementalListConfigAt Providerv0.1.0
withIncrementalListAriaLabels Featurev0.1.0
withIncrementalListTemplates Featurev0.1.0
applyFeatures(base: CngxIncrementalListConfig, features)

Reduce a feature list onto a base config, merging each sub-tree in isolation.

@paramfeatures
injectIncrementalListConfig#CngxIncrementalListConfig

Convenience accessor for the incremental-list configuration. Runs in injection context; resolves through the cascade. Equivalent to inject(CNGX_INCREMENTAL_LIST_CONFIG).

provideIncrementalListConfig#EnvironmentProviders
provideIncrementalListConfig(...features: undefined)

Application-root configuration cascade for the incremental list. Pass any combination of with* features in bootstrapApplication's providers. Supplied features merge with the library defaults, so consumers only declare the keys they override.

@paramfeatures
provideIncrementalListConfigAt#Provider[]
provideIncrementalListConfigAt(...features: undefined)

Component-scoped incremental-list configuration override. Pass into a component's or directive's viewProviders; features merge on top of the parent config (an enclosing scope or the application root), so a region can re-phrase its labels without disturbing the rest of the app.

@paramfeatures
withIncrementalListAriaLabels#CngxIncrementalListConfigFeature
withIncrementalListAriaLabels(payload: Partial)

Override any subset of the incremental-list labels. The override applies to both the visible built-in views and the live-region announcements.

provideIncrementalListConfig(
  withIncrementalListAriaLabels({
    empty: 'Noch nichts hier',
    endReached: (total) => `Alle ${total} geladen`,
  }),
);
@parampayloadPartial
withIncrementalListTemplates#CngxIncrementalListConfigFeature
withIncrementalListTemplates(payload: Partial)

Supply application-wide template-slot defaults. A per-instance projected slot still wins over this tier; it only applies where no instance slot is present.

provideIncrementalListConfig(
  withIncrementalListTemplates({ empty: myBrandedEmptyTemplate }),
);
@parampayloadPartial

ui/paginator/paginator-config.ts

injectPaginatorConfig Injectv0.1.0
provideCngxPaginatorConfig Providerv0.1.0
provideCngxPaginatorConfigAt Providerv0.1.0
withPaginatorAnnouncements Featurev0.1.0
withPaginatorAriaLabels Featurev0.1.0
withPaginatorPageSizeOptions Featurev0.1.0
withPaginatorPageStatusFormat Featurev0.1.0
withPaginatorRangeFormat Featurev0.1.0
withPaginatorTemplates Featurev0.1.0
applyFeatures(base: CngxPaginatorConfig, features)

Reduce a feature list onto a base config, merging each sub-tree in isolation.

@paramfeatures
injectPaginatorConfig#CngxPaginatorConfig

Convenience accessor for the paginator configuration. Runs in injection context; resolves through the cascade. Equivalent to inject(CNGX_PAGINATOR_CONFIG).

provideCngxPaginatorConfig#EnvironmentProviders
provideCngxPaginatorConfig(...features: undefined)

Application-root configuration cascade for the paginator. Pass any combination of with* features in bootstrapApplication's providers. Supplied features deep-merge with the library defaults, so consumers only declare the keys they want to override.

@paramfeatures
provideCngxPaginatorConfigAt#Provider[]
provideCngxPaginatorConfigAt(...features: undefined)

Component-scoped paginator configuration override. Pass into a component's or directive's viewProviders; features merge on top of the parent config (an enclosing scope or the application root), so a region can re-phrase its announcements or labels without disturbing the rest of the app.

@paramfeatures
withPaginatorAnnouncements#CngxPaginatorConfigFeature
withPaginatorAnnouncements(payload: Partial)

Override any subset of the paginator live-region announcement phrasing.

provideCngxPaginatorConfig(
  withPaginatorAnnouncements({
    pageChange: (page, total) => `Seite ${page} von ${total}`,
    loading: 'Wird geladen',
    updated: 'Aktualisiert',
  }),
);
@parampayloadPartial
withPaginatorAriaLabels#CngxPaginatorConfigFeature
withPaginatorAriaLabels(payload: Partial)

Override any subset of the paginator accessible-name strings. Per-instance aria-label bindings still win over the cascade for the landmark name.

provideCngxPaginatorConfig(
  withPaginatorAriaLabels({ next: 'Nächste Seite', previous: 'Vorige Seite' }),
);
@parampayloadPartial
withPaginatorPageSizeOptions#CngxPaginatorConfigFeature
withPaginatorPageSizeOptions(payload)

Supply the default items-per-page choices for the cngx-pgn-page-size dropdown app-wide. The segment renders these when no per-instance [options] is bound; a non-empty [options] input still wins. The list replaces the library default wholesale - it is one atomic value, not a merged sub-tree.

provideCngxPaginatorConfig(
  withPaginatorPageSizeOptions([12, 24, 48]),
);
@parampayload
withPaginatorPageStatusFormat#CngxPaginatorConfigFeature
withPaginatorPageStatusFormat(pageStatus)

Override the page-status format. The cngx-pgn-status segment renders the returned string verbatim, so this localises the "Page n of m" readout that the responsive collapse reveals.

provideCngxPaginatorConfig(
  withPaginatorPageStatusFormat((page, totalPages) => `Seite ${page} von ${totalPages}`),
);
@parampageStatus
withPaginatorRangeFormat#CngxPaginatorConfigFeature
withPaginatorRangeFormat(range)

Override the range-readout format. The cngx-pgn-range segment renders the returned string verbatim, so this also localises the of connector.

provideCngxPaginatorConfig(
  withPaginatorRangeFormat((start, end, total) => `${start}-${end} von ${total}`),
);
@paramrange
withPaginatorTemplates#CngxPaginatorConfigFeature
withPaginatorTemplates(payload: Partial)

Supply application-wide template-slot defaults for the paginator. The per-instance *cngxPaginatorLoading slot still wins over this tier; it only applies where no instance slot is projected.

provideCngxPaginatorConfig(
  withPaginatorTemplates({ loading: myBrandedSpinnerTemplate }),
);
@parampayloadPartial

forms/input/input-mask.directive.ts

applyMask#literal type
applyMask(raw: string, tokens, placeholder: string, guide: boolean)
@paramrawstring
@paramtokens
@paramplaceholderstring
@paramguideboolean
firstEmptySlot#number
firstEmptySlot(tokens, masked: string, placeholder: string)
@paramtokens
@parammaskedstring
@paramplaceholderstring
localeToRegion#string
localeToRegion(locale: string)
@paramlocalestring
nextSlotIndex#number
nextSlotIndex(tokens, from: number)
@paramtokens
@paramfromnumber
parseMask#MaskToken[]
parseMask(pattern: string, customTokens?: MaskTokenMap)
@parampatternstring
@paramcustomTokens?MaskTokenMap
prevSlotIndex#number
prevSlotIndex(tokens, from: number)
@paramtokens
@paramfromnumber
resolveZip#literal type
resolveZip(region: string, zips: Record)
@paramregionstring
@paramzipsRecord
selectPattern#string
selectPattern(patterns, rawLength: number, customTokens?: MaskTokenMap)
@parampatterns
@paramrawLengthnumber
@paramcustomTokens?MaskTokenMap
slotCount#number
slotCount(pattern: string, customTokens?: MaskTokenMap)
@parampatternstring
@paramcustomTokens?MaskTokenMap

projects/utils/equality.ts

arrayEqual#boolean
arrayEqual(a, b)

Shallow positional equality for two readonly arrays. Returns true when both arrays reference the same object, or when they have the same length and every index holds a Object.is-equal value.

Intended as an equal arg for computed() / linkedSignal returning readonly T[], so consumers downstream do not re-render when the computed re-runs but produces a positionally-identical array. Two arrays with the same values in a different order compare unequal.

@parama
@paramb
setEqual#boolean
setEqual(a: ReadonlySet, b: ReadonlySet)

Shallow structural equality for two readonly Sets. Returns true when both sets reference the same object, or when they have the same size and every element of a is present in b. Element comparison uses Set.has (SameValueZero semantics).

Intended as an equal arg for computed() / linkedSignal returning ReadonlySet<T>, so consumers downstream do not re-render when the computed re-runs but produces the same element set.

@paramaReadonlySet
@parambReadonlySet

select/shared/provide-cngx-select.ts

provideCngxSelect Provider
provideCngxSelectAt Provider
bucket#BucketedFeatures
bucket(features)
@paramfeatures
provideCngxSelect#EnvironmentProviders[]
provideCngxSelect(...features: undefined)

App-wide entry point for the Select-family configuration surfaces. Routes mixed features from provideSelectConfig, provideActionSelectConfig, and provideReorderableSelectConfig to the correct underlying provider. The three individual providers stay exported.

bootstrapApplication(App, {
  providers: [
    provideCngxSelect(
      // CngxSelectConfig features
      withPanelWidth('trigger'),
      withVirtualization({ estimateSize: 36 }),
      withAriaLabels({ clearButton: 'Clear', chipRemove: 'Remove' }),

      // CngxActionSelectConfig features
      withFocusTrapBehavior('strict'),
      withCloseOnCreate(true),

      // CngxReorderableSelectConfig features
      withReorderKeyboardModifier('alt'),
      withReorderStripFreeze(true),
    ),
  ],
});
@paramfeatures
provideCngxSelectAt#Provider[]
provideCngxSelectAt(...features: undefined)

Component-scoped twin of provideCngxSelect. Returns Provider[] because viewProviders rejects EnvironmentProviders.

@paramfeatures

core/utils/build-async-state-view.ts

buildAsyncStateView#CngxAsyncState
buildAsyncStateView(sources: AsyncStateViewSources)

Build a read-only CngxAsyncState<T> view from source signals.

All derived fields (isLoading, isPending, isEmpty, etc.) are computed() from the provided sources — the result is a consistent, single-source-of-truth state object that cannot become inconsistent.

This is the shared kernel used by all async state factories and state producers. No injection context required — uses only computed().

ui/breadcrumb/breadcrumb-router-sync.directive.ts

buildCrumbs(router: Router, dataKey: string, iconKey: string)

Walks the activated route tree from the root down the firstChild chain, accumulating the URL and emitting one crumb per route whose data[dataKey] is a non-empty string. A non-empty data[iconKey] string rides onto the crumb's opaque icon (the leading icon slot renders it; deepest wins on the componentless-collapse branch, like the label).

@paramrouterRouter
@paramdataKeystring
@paramiconKeystring
crumbsEqual#boolean
crumbsEqual(a, b)

Positional shape equality for two crumb trails. The router source maps a fresh crumb literal per navigation, so reference equality (Object.is) would treat every NavigationEnd as a change; comparing label/href/icon lets a same-shape navigation keep the previous signal reference and stops it cascading the bar (reference_signal_architecture Equality Rule).

The router source populates label, href, and (from data[iconKey]) icon, so those three fully describe a crumb's identity here - icon must be compared or an icon-only route-data change never propagates. When SPA-link emission lands, its equality is defined alongside it.

@parama
@paramb

chart/path/curve.ts

buildCurvePath#string
buildCurvePath(points, curve: CngxCurve)

Build the SVG d attribute for a sequence of points.

@parampoints

Pixel-coordinate points to connect.

@paramcurveCngxCurve

Interpolation strategy. 'linear' joins points with straight L commands; 'monotone' uses cubic Béziers with the monotone-X tangent rule (Fritsch-Carlson) so the curve never overshoots between data points.

The full path data starting with M. Returns '' when the input is empty; M x y when the input has one point.

paginator/segments/paginator-dots.component.ts

buildDots#DotModel
buildDots(current: number, total: number)

Build the full dot sequence plus the viewport anchor. Every page gets a dot; for large counts the dots that fall outside the centred VISIBLE window are shrunk to small (they sit off-screen behind the viewport clip and shrink as they glide out), and the two dots at each truncated visible edge step down medium -> small (iOS page-control edge-shrink). The consumer translates the track by firstVisible so navigation slides the strip instead of reshuffling the DOM - the active dot stays centred and the row glides under it.

@paramcurrentnumber
@paramtotalnumber
dotsEqual#boolean
dotsEqual(a: DotModel, b: DotModel)
@paramaDotModel
@parambDotModel

ui/breadcrumb/breadcrumb-siblings-router-sync.directive.ts

buildSiblings(router: Router, depth: number, dataKey: string)

Enumerates the sibling routes at depth in the activated route chain: the children of that level's parent (or the root config at depth 0) whose data[dataKey] is a non-empty string, marking the active child current. Sibling configs come from the static route configuration, not the activated snapshot (which only holds the one active child), so the whole set of alternatives is visible. Duplicate hrefs are collapsed like buildCrumbs.

@paramrouterRouter
@paramdepthnumber
@paramdataKeystring
siblingsEqual#boolean
siblingsEqual(a, b)

Positional shape equality for two sibling sets. The router source maps a fresh sibling literal per navigation, so reference equality (Object.is) would treat every NavigationEnd as a change; comparing label/href/current lets a same-shape navigation keep the previous signal reference and stops it cascading the dropdown (reference_signal_architecture Equality Rule). Mirrors crumbsEqual.

current is compared because the same set of siblings with a different active member is a genuine change - the aria-current marker moves.

@parama
@paramb

interactive/guard/can-deactivate.ts

canDeactivateWhenClean#boolean
canDeactivateWhenClean(isDirty, message: string)

Creates a functional route guard that blocks navigation when the form is dirty.

Works with Angular's CanDeactivateFn. The isDirty callback is evaluated on each navigation attempt. When dirty, shows a confirm dialog.

Uses DOCUMENT injection for SSR safety — returns true (allow) when no window is available.

Pair with CngxBeforeUnload for full coverage (browser close + route change):

// Route config
{
  path: 'edit',
  component: EditComponent,
  canDeactivate: [canDeactivateWhenClean(() => inject(EditComponent).isDirty())]
}
@paramisDirty
  • Callback that returns true when there are unsaved changes.
@parammessagestring= 'You have unsaved changes. Leave anyway?'
  • Confirmation message. Default: 'You have unsaved changes. Leave anyway?'

A functional guard compatible with Angular's canDeactivate.

forms/input/input-filter.directive.ts

charMatcher#boolean
charMatcher(pattern: InputFilterPattern)
@parampatternInputFilterPattern

projects/utils/clamp.ts

clamp#number
clamp(value: number, min, max)

Clamp a number into the inclusive range [min, max]. null or undefined bounds read as -Infinity / +Infinity respectively, so either side can be left open. NaN value propagates and is returned unchanged. When the bounds invert (min > max after coercion), min wins and the returned value is min.

@paramvaluenumber
@parammin
@parammax

interactive/slider/slider-core.ts

createSliderCore Factoryv0.1.0
clamp#number
clamp(value: number, lo: number, hi: number)
@paramvaluenumber
@paramlonumber
@paramhinumber
createSliderCore#CngxSliderCore
createSliderCore(options: CngxSliderCoreOptions)

Pure factory for a slider's value derivation - the brain shared by CngxSlider and each CngxSliderThumb of a range slider. It owns no DI and no DOM: hand it the source signals, get back the clamped value, the track fraction, the aria-valuetext string, and the four mutation helpers the keyboard / pointer handlers call. Snapping and bound-clamping live in CngxSliderCore.setValue, so every write path stays valid without an effect syncing state (Pillar 1).

snapToStep#number
snapToStep(raw: number, origin: number, step: number)
@paramrawnumber
@paramoriginnumber
@paramstepnumber

ui/accordion/accordion-group.component.ts

clampHeadingLevel#number
clampHeadingLevel(value, fallback: number)

Coerce a bound value to a number (via coerceNumberProperty, falling back to fallback) and clamp it into the ARIA heading-level range 2-6.

@paramvalue
@paramfallbacknumber= 3

ui/data-grid-accordion/data-grid-accordion.component.ts

clampHeadingLevel#number
clampHeadingLevel(value, fallback: number)

Coerce a bound value to a number (via coerceNumberProperty, falling back to fallback) and clamp it into the ARIA heading-level range 2-6.

@paramvalue
@paramfallbacknumber= 3
trackFor#string
trackFor(track, isPrimary: boolean)

Map a cell's col track intent to one CSS grid-template-columns track. Unset (undefined) falls back to the derived default: the primary column grows (minmax(0, 1fr)), every other column fits its content (auto). The named sizes resolve against the registered --cngx-dga-col-sm|-md|-lg tokens, each with a rem fallback so the track stays valid even before the token surface loads (an invalid var() would collapse the whole grid-template-columns to one column).

@paramtrack
@paramisPrimaryboolean

audio/engine/audio-engine.ts

clampVolume#number
clampVolume(v: number)
@paramvnumber
scaleGain#number
scaleGain(gain, scale: number)

Apply a per-call [0, 1] scale to a tone's peak gain. Centralised here so every play path (play / tone / sequence) scales identically and an engine override sees per-element volume uniformly, rather than each caller pre-baking its own gain.

@paramgain
@paramscalenumber
scaleSteps#ToneStep[]
scaleSteps(steps, scale)
@paramsteps
@paramscale

projects/utils/array.ts

coerceArray#T[]
coerceArray(value)

Coerce a single value or an array to an array. Returns the input unchanged when already an array; wraps a scalar value in a single-element array otherwise.

@paramvalue

core/utils/coerce.util.ts

coerceBooleanProperty#boolean
coerceBooleanProperty(value)

Coerces a value to a boolean.

Strings are truthy unless they equal 'false'. All other falsy values return false.

@paramvalue
coerceNumberProperty#number
coerceNumberProperty(value, fallback: number)

Coerces a value to a number.

Returns fallback when the value is null, undefined, NaN, or non-numeric.

@paramvalue
@paramfallbacknumber= 0

ui/layout/grid.component.ts

coerceColumns#number | string
coerceColumns(value)
@paramvalue

projects/utils/tree.ts

collectDescendantValues#T[]
collectDescendantValues(node: CngxTreeNode)

Collect all descendant values of a node (exclusive of the node itself), in DFS order. For cascade-select: toggling a parent flips all entries in this list atomically.

@paramnodeCngxTreeNode
filterTree#CngxTreeNode[]
filterTree(nodes, predicate)

Return a new tree containing only nodes whose value matches predicate or have at least one matching descendant. Ancestors of any match are preserved so the path is never broken; branches with zero matches are dropped entirely.

Fresh implementation — not ported from @cngx/data-display/treetable.

@paramnodes
@parampredicate
flattenTree#FlatTreeNode[]
flattenTree(nodes, idFn: IdFn, labelFn: LabelFn)

Flatten a tree in DFS order. Each emitted FlatTreeNode carries aria-level (depth + 1), aria-posinset, and aria-setsize data so the rendering layer can bind them directly.

@paramnodes

Root-level tree nodes.

@paramidFnIdFn= defaultIdFn as IdFn

Derives a stable id from (value, path). Defaults to path.join('.') — adequate for static trees; supply a key-based idFn for data that may be re-ordered without changing identity.

@paramlabelFnLabelFn= defaultLabelFn as LabelFn

Derives visible label. Defaults to String(value).

isNodeVisible#boolean
isNodeVisible(node: FlatTreeNode, expandedIds: ReadonlySet)

A flat node is visible iff every ancestor in its parentIds chain is present in expandedIds. Root nodes (empty chain) are always visible.

@paramnodeFlatTreeNode
@paramexpandedIdsReadonlySet
sortTree#CngxTreeNode[]
sortTree(nodes, by, direction)

Return a new tree where each level's siblings are sorted independently by the by extractor. Child ordering is stable within its own level only — the relative position of nodes across different parents is irrelevant.

Fresh implementation — not ported from @cngx/data-display/treetable.

@paramnodes
@paramby
@paramdirection= 'asc'
walkTree#void
walkTree(nodes, visit)

DFS visitor. visit is called once per node with the current depth.

@paramnodes
@paramvisit

forms/input/phone-metadata.ts

createPrefixPhoneMetadata Factoryv0.2.0
providePhoneMetadata Provider
compileMatcher#number
compileMatcher(matcher: PhonePrefixMatcher)
@parammatcherPhonePrefixMatcher
createPrefixPhoneMetadata#CngxPhoneMetadata
createPrefixPhoneMetadata(prefixes: PhonePrefixMap)

Builds a CngxPhoneMetadata adapter from a region keyed prefix map, so a consumer declares the prefixes that matter instead of hand-writing the region branch and the matching closure.

The adapter resolves the line type by longest matching prefix: the matcher with the most matched leading digits wins, so a specific '0820' fixed-line rule beats a broader '08' mobile rule. Ties resolve to mobile (it is the decisive case auto mask alternation cares about). An unknown region or no matching prefix returns 'unknown', keeping the length-based fallback.

It still ships no numbering data - the caller supplies every prefix - so it is sugar over an inline adapter, not a replacement for a real metadata library like libphonenumber-js.

providePhoneMetadata(
  createPrefixPhoneMetadata({
    DE: { mobile: [/^1[567]/] },
    AT: { mobile: ['650', '660', '664', '676', '699'] },
  }),
);
@paramprefixesPhonePrefixMap
providePhoneMetadata#Provider
providePhoneMetadata(adapter: CngxPhoneMetadata)

Registers a CngxPhoneMetadata adapter for CngxPhoneInput's auto line-type detection.

Returns a plain Provider, so it works app-wide in ApplicationConfig.providers or scoped to a subtree via a component's viewProviders - mirroring provideInputConfig. The nearest provider wins for a subtree by token resolution.

// app.config.ts
providers: [providePhoneMetadata(libphonenumberAdapter)]
@paramadapterCngxPhoneMetadata

data/recycler/range-computer.ts

computeFixedRange#RangeResult
computeFixedRange(scrollTop: number, clientHeight: number, totalCount: number, itemSize: number, overscan: number, columns: number)
@paramscrollTopnumber
@paramclientHeightnumber
@paramtotalCountnumber
@paramitemSizenumber
@paramoverscannumber
@paramcolumnsnumber
computeVariableRange#RangeResult
computeVariableRange(scrollTop: number, clientHeight: number, totalCount: number, estimateSize, overscan: number)
@paramscrollTopnumber
@paramclientHeightnumber
@paramtotalCountnumber
@paramestimateSize
@paramoverscannumber

data/paginate/paginate-emit.ts

connectPaginateEmit v0.1.0
connectPaginateEmit#void
connectPaginateEmit(paginate: CngxPaginate, handlers: CngxPaginateEmitHandlers)

Wires the CngxPaginate brain's page / page-size changes onto a host's two-way outputs with exactly-once emit semantics. Two paths feed each handler, sharing a last-emitted guard:

  • a subscription forwards the brain's nav-only pageChange / pageSizeChange
    • the only signal that captures a controlled-mode setPage, because the brain's pageIndex() stays pinned to the input until the consumer feeds it back;
  • an effect() reads the effective pageIndex() / pageSize() and covers a total-shrink clamp the nav-only output misses.

The shared guard makes a value one path already emitted a no-op on the other, so each change emits exactly once. Seeded with the current effective values, so wiring emits no initial change.

Shared verbatim by the CngxPaginator shell and the CngxIncrementalList organism, so the two-way emit behaviour is byte-identical. Call inside an injection context (constructor or field initialiser) - it reads DestroyRef and creates effects.

@parampaginateCngxPaginate

data/paginate/paginate-reset.directive.ts

connectPaginateResetOn v0.1.0
connectPaginateResetOn#void
connectPaginateResetOn(paginate: CngxPaginate, key)

Wires the reset-on-change behaviour onto a CngxPaginate brain: when key() changes (after the initial run) the paginator jumps to the first page. The first run captures the mounting value without resetting, and an already-first paginator emits nothing.

Shared by [cngxPaginateResetOn], the CngxPaginator shell's resetOn input, and the CngxMatPaginator bridge's resetOn input, so the behaviour is byte-identical across all three. Call inside an injection context (constructor or field initialiser).

@parampaginateCngxPaginate
@paramkey

data/recycler/connect-recycler-active-descendant.ts

connectRecyclerToActiveDescendant#void
connectRecyclerToActiveDescendant(recycler: CngxRecycler, ad: CngxActiveDescendant)

Wires a CngxRecycler to a CngxActiveDescendant in virtual mode.

When the AD directive navigates to an item whose index is not in the recycler's rendered range, it sets pendingHighlight (via the virtualCount path). This helper watches that signal and scrolls the recycler to the target index; AD's own effect observes the resulting DOM update and clears the pending state automatically (see the pendingHighlightState.set(null) branch in CngxActiveDescendant after a re-render brings the target into the rendered range).

Unlike * connectRecyclerToRoving}, we don't re-focus a DOM element after the scroll — AD doesn't move real focus, it only rebinds aria-activedescendant. Once the target index enters the rendered range, the [attr.aria-activedescendant] binding on the combobox trigger resolves to the now-present option element for free.

Must be called in an injection context (typically a component constructor) on the same component that owns both the recycler and the AD directive.

@paramrecyclerCngxRecycler

data/recycler/connect-recycler-roving.ts

connectRecyclerToRoving#void
connectRecyclerToRoving(recycler: CngxRecycler, roving: CngxRovingTabindex)

Wires a CngxRecycler to a CngxRovingTabindex in virtual mode.

When the roving tabindex navigates to an item that is not in the DOM (out of rendered range), this function scrolls the recycler to that item and focuses it after rendering.

Must be called in an injection context (constructor or field initializer) on the component that hosts both the recycler's scroll container and the CngxRovingTabindex directive. The injected ElementRef is used to query [data-cngx-recycle-index] — calling from a child component would query the wrong subtree.

@paramrecyclerCngxRecycler
@paramrovingCngxRovingTabindex

interactive/accordion/accordion-keyboard-nav.ts

createAccordionKeyboardNav Factoryv0.1.0
createAccordionKeyboardNav#CngxAccordionKeyboardNav
createAccordionKeyboardNav(opts: CngxAccordionKeyboardNavOptions)

Level-2 factory implementing the WAI-ARIA APG accordion keyboard model over a registration model rather than contentChildren roving. Registration is immune to component-view boundaries, so any accordion skin - the @cngx/ui/accordion organism, or a future one that renders each header in its own view - gets working Arrow/Home/End nav.

Pillar 1 (Ableitung statt Verwaltung): the tab stop is derived from the coordinator's rovingActiveId, not managed as a second index. Focus movement is a DOM concern the factory owns - the coordinator only records which header should be the stop; it never touches the DOM.

select/shared/action-host-bridge.ts

createActionHostBridge Factory
createActionHostBridge#ActionHostBridge
createActionHostBridge(options: ActionHostBridgeOptions)

Action-host bridge for a select-family variant: dirty signal + stable callbacks bundle + focus-trap policy + dismiss-block signal. dirty is the only writable slot; everything else is computed. Installs a capture-phase Escape listener on the host element via DestroyRef. Injection context required.

select/shared/ad-activation-dispatcher.ts

createADActivationDispatcher Factory
createADActivationDispatcher#void
createADActivationDispatcher(options: ADActivationDispatcherOptions)

Wires listbox.ad.activated into the variant's commit / non-commit callbacks. Single effect(onCleanup) - subscribes on ref resolve, unsubscribes on teardown. Payload runs inside untracked; activations for unknown values are dropped. Value-shape agnostic - rollback ownership stays in the consumer.

select/shared/array-commit-handler.ts

createArrayCommitHandler Factory
createArrayCommitHandler#ArrayCommitHandler
createArrayCommitHandler(opts: ArrayCommitHandlerOptions)

Array-shape commit flow shared by CngxMultiSelect and CngxCombobox. Owns commit-controller lifecycle, reconciliation via sameArrayContents, togglingOption.set(null) on success, optimistic rollback on error, live-region "removed" announce. Consumer owns change-event payloads via the finalize callbacks.

No scalar twin: this handler is array-only by design.

data/async-state/create-async-state.ts

createAsyncState Factory
createAsyncState#MutableAsyncState

Create a mutation async state — for explicit user-triggered actions.

Must be called in an injection context (field initializer or constructor) because it uses inject(DestroyRef) for cleanup.

readonly saveResident = createAsyncState<Resident>();

async handleSave(): Promise<void> {
  await this.saveResident.execute(
    () => this.api.save(this.form().value())
  );
}

audio/autoplay-gate/autoplay-gate.ts

createAutoplayGate Factoryv0.1.0
createAutoplayGate#CngxAutoplayGate
createAutoplayGate(deps)

Create the autoplay gate: a one-shot latch that flips armed to true on the first pointerdown / keydown / touchstart and then removes its own listeners. The engine consults armed() before resuming the shared AudioContext, honouring the browser autoplay policy without a permission prompt.

Pure factory — takes its target and destroyRef as arguments rather than calling inject(), so it composes inside the engine's injection context yet stays testable with a fake target. No DI token: the gate has no independent swap consumer (severity ladder concern: over-abstraction), so it ships token-less and the engine owns it.

@paramdeps

chart/scales/band.ts

createBandScale Factory
createBandScale#BandScale
createBandScale(domain, range, padding: number)

Construct a BandScale from a categorical domain and a numeric range. See the type-level documentation above for parameter semantics.

@paramdomain
@paramrange
@parampaddingnumber= 0

interactive/breadcrumb/breadcrumb-collapse.ts

createBreadcrumbCollapse Factoryv0.1.0
createBreadcrumbCollapse#CngxBreadcrumbCollapseStrategy

The default collapse rule: keep the first crumb and the last maxVisible - 1, folding the middle into the overflow menu. Returns an empty set when maxVisible is unset/invalid (< 1) or the trail already fits (total <= maxVisible), so a short trail never collapses.

select/shared/chip-removal-handler.ts

createChipRemovalHandler Factory
createChipRemovalHandler#CngxChipRemovalHandler
createChipRemovalHandler(opts: CngxChipRemovalHandlerOptions)

Builds a CngxChipRemovalHandler. Owns disabled-guard, snapshot, filter, branch dispatch, WeakMap closure stability. Consumer owns the commit dispatch (beginCommit), rollback snapshotting (onBeforeCommit), and change-event emission (onSyncFinalize).

interactive/reorder/chip-strip-roving.ts

createChipStripRoving Factoryv0.1.0
createChipStripRoving#CngxChipStripRovingController
createChipStripRoving(opts: CngxChipStripRovingOptions)

Plain factory for the chip-strip roving-tabindex controller shared by CngxReorderableMultiSelect today and by any future reorder-aware chip trigger (e.g. a tag-input with user-defined ordering). Extracted from the component so the same focus-state machine doesn't reappear inline in every variant.

Why not CngxRovingTabindex. That directive uses a host (keydown) listener that doesn't check modifier keys. Co-located with CngxReorder on the same chip-strip element it double-fires on Ctrl+Arrow (the reorder emits, then roving also moves focus - racy). This controller deliberately skips modifier-pressed events so the paired reorder directive owns that gesture.

Injection context. Must be called in an injection context (component constructor / field init) because it installs an * effect() for the active-index clamp on count shrink.

mat-tabs/overflow/mat-tab-overflow-dom-adapter.ts

createCngxMatTabOverflowDomAdapter Factoryv0.1.0
createCngxMatTabOverflowDomAdapter#CngxTabOverflowDomAdapter

Material variant of CngxTabOverflowDomAdapter.

resolveStripRoot walks from host up to <mat-tab-header> and locates .mat-mdc-tab-label-container via any rendered .mat-mdc-tab descendant — Material's IO-friendly scroll container.

resolveTabButton indexes positionally; Material owns the DOM and cngx handle ids never reach the button elements. Index correlates against presenter.tabs() registration order.

Wire it via the directive's CNGX_TAB_OVERFLOW_DOM_ADAPTER_FACTORY provider:

providers: [
  { provide: CNGX_TAB_OVERFLOW_DOM_ADAPTER_FACTORY,
    useValue: createCngxMatTabOverflowDomAdapter }
]

tabs/overflow/dom-adapter.ts

createCngxTabOverflowDefaultDomAdapter Factory
createCngxTabOverflowDefaultDomAdapter#CngxTabOverflowDomAdapter

Default adapter for the cngx-native <cngx-tab-group> strip:
walks host.closest('.cngx-tabs__strip-wrapper') for the IO root, then [id="${handle.id}-header"] for each button.

data/commit/commit-controller.ts

createCommitController Factory
createCommitController#CngxCommitController

Factory for the commit controller.

Plain function, not a class — matches the rest of the repo (createManualState, createAsyncState, createTransitionTracker). See reference_api_prefix_convention.md.

select/shared/commit-controller.token.ts

createCommitController Factory
createCommitController#CngxCommitController

Direct (non-DI) factory for a select-side commit controller. Wraps a fresh generic controller with the action-shape adapter; bypasses CNGX_COMMIT_CONTROLLER_FACTORY. Use CNGX_SELECT_COMMIT_CONTROLLER_FACTORY for DI-aware resolution.

select/shared/commit-error-announcer.ts

createCommitErrorAnnouncer Factory
createCommitErrorAnnouncer#void
createCommitErrorAnnouncer(opts: CngxCommitErrorAnnouncerOptions)

Default factory for the scalar commit-error announcer. Dispatches via policy.kind: 'verbose' announces the formatted error message at the configured severity; 'soft' calls the soft-announce hook (CngxTypeahead removal pattern).

Override the CNGX_COMMIT_ERROR_ANNOUNCER_FACTORY token to swap in telemetry or locale-aware variants.

core/utils/controlled-source.ts

createControlledSource Factoryv0.1.0
createControlledSource#Signal
createControlledSource(priority, fallback: Signal)

Derives a controlled/uncontrolled source signal: a higher-precedence priority source wins over a lower-precedence fallback source. Precedence is the only contract - either argument may be an injected token signal, a component input(), or a projected contentChild query, and which role a given source plays flips per seam (the bar lets an injected source win over its [items] input; the overflow lets a forwarded input() win over its projected slot query). Collapses the repeated priority?.() ?? fallback() seam - the "controlled source wins via computed" pattern - into one factory beside its create* siblings.

Pure pass-through: it returns whichever underlying signal's own value, never a fresh literal, so an equal fn is unnecessary and no downstream cascade fires. priority absent (no source injected) or yielding undefined (an unbound input, an unmatched query) both fall through to fallback - one expression covers the accessor-absent seam (source?.crumbs) and the value-undefined seam (itemTemplateInput()).

@parampriority

Optional higher-precedence source. undefined when no source is present; a signal yielding undefined when the source is bound but empty.

@paramfallbackSignal

Lower-precedence source, read when priority is absent or yields undefined.

A computed reading priority?.() ?? fallback().

// an injected source wins over the [items] input, else the input shows
protected readonly items = createControlledSource(
this.itemsSource?.crumbs, // injected source signal, may be absent
this.itemsInput,          // [items] input - the fallback
);

select/shared/create-commit-handler.ts

createCreateCommitHandler Factory
createCreateCommitHandler#CreateCommitHandler
createCreateCommitHandler(opts: CreateCommitHandlerOptions)

Plain factory for the quick-create commit flow. Shared by CngxActionSelect and CngxActionMultiSelect. Two separate factories vs createReorderCommitHandler because create and reorder have different value-shape contracts (materialise new T vs reorder existing T[]).

audio/debouncer/debouncer.ts

createDebouncer Factoryv0.1.0
createDebouncer#CngxDebouncer
createDebouncer(options?)

Per-name time-window debouncer: suppresses repeated fires of the same earcon within windowMs. A separate composed factory rather than logic buried in the engine (Pillar 3). Plain factory, no DI token — withDebounceMs covers configuration and there is no independent swap consumer.

windowMs accepts a getter so a caller whose window is a reactive input can hold ONE debouncer instance for its lifetime and still track changes: the window is resolved per shouldFire call, not captured at construction. That keeps the (stateful) debouncer out of the signal graph — minting one inside a computed would return a fresh object per evaluation and break the equality rule. CngxAudioPitch is the getter consumer; the engine passes a number.

The clock is injectable (now) purely so specs are deterministic; production defaults to Date.now.

@paramoptions?

select/shared/flat-nav-strategy.ts

createDefaultFlatNavStrategy Factory
createDefaultFlatNavStrategy#CngxFlatNavStrategy
createDefaultFlatNavStrategy(options)

Canonical W3C listbox flat-nav: PageUp/Down step 10 with disabled back-probe; typeahead delegates to the variant's TypeaheadController.

@paramoptions= {}

tabs/registry/directive-by-id-map.ts

createDirectiveByIdMap Factory
createDirectiveByIdMap#Signal>
createDirectiveByIdMap(opts: CngxDirectiveByIdMapOptions)

Build a Signal<Map<string, T>> from a Signal<readonly T[]> of directives keyed by id(). Structural equal prevents cascade when contentChildren re-emits an unchanged child set. Shared by <cngx-tab-group>, <cngx-stepper>, and <cngx-mat-stepper>.

select/shared/dismiss-handler.ts

createDismissHandler Factory
createDismissHandler#DismissHandler
createDismissHandler(opts: DismissHandlerOptions)

Click-outside handler. Pure closure over opts - no Angular DI. Override via CNGX_DISMISS_HANDLER_FACTORY for telemetry or conditional-dismiss prompts.

select/shared/display-binding.ts

createDisplayBinding Factory
createDisplayBinding#DisplayBinding
createDisplayBinding(opts: DisplayBindingOptions)

Bidirectional binding between a scalar value signal and the visible text of a co-located <input> running CngxListboxSearch. Two effect()s - value→input (gated on focused) and search-term→callback (gated on writingFlag + skipInitial).

tabs/overflow/dom-anchor-retry.ts

createDomAnchorRetry Factory
createDomAnchorRetry#CngxDomAnchorRetryHandle
createDomAnchorRetry(options: CngxDomAnchorRetryOptions)

Bounded retry loop for DOM-anchoring patterns - shared attempt-counter and give-up and cancellation contract.
Used by <cngx-tab-overflow>'s rAF strip-attach loop and [cngxMatTabs]'s afterNextRender header-anchor loop.

Consumer-supplied scheduler lets different timing primitives flow through one counter.

const retry = createDomAnchorRetry({
  attempt: () => {
    const root = host.closest('.strip-wrapper');
    if (!root) return null;
    observer.observe(root);
    return true;
  },
  maxAttempts: 60,
  schedule: (cb) => {
    const h = requestAnimationFrame(cb);
    return () => cancelAnimationFrame(h);
  },
  onGiveUp: () => console.warn('strip wrapper not found'),
});
afterNextRender(() => retry.start());
destroyRef.onDestroy(() => retry.cancel());

common/stepper/strip-density.ts

createElementWidthSignal Factory
createStripDensity Factory
createElementWidthSignal#Signal
createElementWidthSignal(element: HTMLElement, destroyRef: DestroyRef)

Tracks an element's content-box width as a reactive signal via the ResizeObserver API. Mirrors createMobileViewportSignal's matchMedia wrapper: the API is wrapped directly (not via the CngxResizeObserver directive, which can only attach through hostDirectives). In SSR / non-DOM environments the signal stays 0 and no observer is wired.

@paramelementHTMLElement
@paramdestroyRefDestroyRef
createStripDensity#Signal
createStripDensity(options: CngxStripDensityOptions)

Resolves the classic strip's density rung from its own container width against the step count and two per-step px thresholds. Pure create* factory, sibling to createStepperDisplayMode - it owns a ResizeObserver the way the display-mode factory owns a matchMedia listener, and returns a single derived Signal.

'comfortable' density short-circuits to 'full' (no measurement dependency). Before the first measurement (width === 0) and for an empty strip the rung is 'full', so the strip never flashes 'minimal' on mount.

forms/filter-builder/filter-builder.helpers.ts

createEmptyFilterRoot Factory
createFilterExpression Factory
createFilterGroup Factory
createEmptyFilterRoot#FilterGroup

Frozen empty root used as the presenter's model<FilterGroup> default and by CngxFilterBuilderState.clear(). Always returns the same frozen reference so consumers comparing tree identity short-circuit correctly.

createFilterExpression#FilterExpression
createFilterExpression(field: string, operator: string, value?: TValue)

Build a fresh FilterExpression with a generated id.

@paramfieldstring
@paramoperatorstring
@paramvalue?TValue
createFilterGroup#FilterGroup
createFilterGroup(logic: FilterLogic, filters, opts: CreateFilterGroupOptions)

Build a fresh FilterGroup with a generated id. Defaults to and logic, no children, not negated.

@paramlogicFilterLogic= 'and'
@paramfilters= []
ensureFilterTreeIds#FilterGroup
ensureFilterTreeIds(tree: FilterGroup)

Normalises a tree by assigning a stable id to every node missing one. Identity-preserving short-circuit - when every node already carries an id, the same tree reference is returned. Consumers who hand-construct trees (deserialised JSON, presets, persisted snapshots) run this once at the boundary; the presenter already invokes it on initial read and on every external write through value.

@paramtreeFilterGroup
evaluateExpression#boolean
evaluateExpression(expr: FilterExpression, item: TItem, fieldDef)

Evaluate a single FilterExpression against item. Unfilled expressions short-circuit to true (except isEmpty/isNotEmpty).

@paramitemTItem
@paramfieldDef
toFilterPredicate#unknown | null
toFilterPredicate(tree, fields)

Build an item-level predicate from a FilterGroup. Returns null when the tree itself is null - the consumer typically interprets null as "no filtering, accept every item". For an empty root group, the returned predicate evaluates true for every item (vacuous truth on and).

@paramtree
@paramfields

forms/field/field-sync.ts

createFieldSync Factoryv0.1.0
createFieldSync#void
createFieldSync(options: FieldSyncOptions)

Bidirectional Field <-> control value sync via CngxFormFieldPresenter.

Two effect()s, each reading the opposite branch inside untracked() with valueEquals as the cycle break - the canonical bridge every model()-based cngx control reuses instead of re-implementing field write-back. Both the field and the control's model() are writable sources of truth, so this is coordination, not a single computed(). Requires an injection context; no-op without a surrounding cngx-form-field.

Keeps the create* prefix despite calling inject() in its body: it is a blessed exception (see architecture-summary, mirrors adaptFormControl), not an oversight. The name is also the public @cngx/forms/select export; renaming would break that contract.

createFieldSync<number>({
  componentValue: this.value,
  valueEquals: Object.is,
  coerceFromField: (v) => (typeof v === 'number' ? v : 0),
});
@paramoptionsFieldSyncOptions

select/shared/field-sync.ts

createFieldSync Factory
createFieldSync#void
createFieldSync(options: FieldSyncOptions)

Gate-aware wrapper over the canonical createFieldSync from @cngx/forms/field. Returns early when CNGX_SELECT_DISABLE_FIELD_SYNC is provided truthy in the injection context; otherwise delegates to the one bridge implementation. Array-shape callers keep working unchanged: the field createFieldSync<V> is generic in V and the composites already pass their own valueEquals / coerceFromField / toFieldValue.

Kept as the select-local export so the 9 select composites and cngx-filter-builder import the gate and the sync from one module.

@paramoptionsFieldSyncOptions

forms/filter-builder/filter-builder-announcer.ts

createFilterBuilderAnnouncer Factory
injectFilterBuilderAnnouncerFactory Inject
createFilterBuilderAnnouncer#CngxFilterBuilderAnnouncer
createFilterBuilderAnnouncer(sources: CngxFilterBuilderAnnouncerSources)

Default announcer - derives the live-region string from lastMutation through the i18n formatter bundle.

injectFilterBuilderAnnouncerFactory#CngxFilterBuilderAnnouncerFactory

Inject-context helper that resolves CNGX_FILTER_BUILDER_ANNOUNCER_FACTORY.

forms/filter-builder/filter-builder-state.ts

createFilterBuilderState Factory
createFilterBuilderState#CngxFilterBuilderState
createFilterBuilderState(opts: CngxFilterBuilderStateOptions)

Default factory behind CNGX_FILTER_BUILDER_STATE_FACTORY. Wraps one writable FilterGroup signal as the canonical tree and returns the CngxFilterBuilderState the presenter drives:

  • read-only tree / fieldMap / isEmpty signals
  • path-keyed mutators (addExpression, setLogic, removeNode, clear, ...)
  • the lastMutation event the announcer formats into live-region text

Two-way binding: pass the presenter's model<FilterGroup>() as source, so every mutator write emits through the consumer's [(value)]. Uncontrolled callers omit source and the factory creates its own signal from initial ?? EMPTY_ROOT.

Plain TS, no inject() - testable without TestBed. Override the token to wrap this (logging, undo) rather than reimplementing the mutators.

forms/filter-builder/filter-builder-template-registry.ts

createFilterBuilderTemplateRegistry Factory
injectFilterBuilderTemplateRegistry Inject
createFilterBuilderTemplateRegistry#CngxFilterBuilderTemplateRegistry
createFilterBuilderTemplateRegistry(queries: CngxFilterBuilderTemplateRegistryQueries)

Wires every slot query through the documented three-stage cascade. Must be called inside an Angular injection context (the helper resolves CNGX_FILTER_BUILDER_CONFIG lazily and the contentChild signals were already created in the caller's context).

The default factory is registered behind CNGX_FILTER_BUILDER_TEMPLATE_REGISTRY_FACTORY so consumers can wrap the resolution path (telemetry, dynamic theme swapping, etc.) without forking the component.

injectFilterBuilderTemplateRegistry#CngxFilterBuilderTemplateRegistry
injectFilterBuilderTemplateRegistry(queries: CngxFilterBuilderTemplateRegistryQueries)

Inject-context helper that resolves the registry factory through the DI token and invokes it with the caller's contentChild queries. The <cngx-filter-builder> component is the canonical caller.

select/shared/panel-renderer.ts

createIdentityPanelRenderer Factory
createIdentityPanelRenderer#PanelRenderer
createIdentityPanelRenderer(input: PanelRendererInput)

Pass-through renderer: every option enters the DOM. Comfortable to ~500 options; beyond that, wire a virtualising renderer via CNGX_PANEL_RENDERER_FACTORY.

chart/scales/linear.ts

createLinearScale Factory
createLinearScale#number
createLinearScale(domain, range)

Pure-TS linear scale. Maps a numeric domain [d0, d1] to a numeric range [r0, r1] via standard linear interpolation. Domain may be inverted (d0 > d1) for SVG Y-axes where the top of the chart is the highest data value but the lowest pixel coordinate.

Values outside the domain extrapolate. Charts that need overflow clamping clamp at the data layer, not the scale.

@paramdomain

[start, end] data range. Equal endpoints collapse the scale to a constant function returning range[0].

@paramrange

[start, end] output range (typically pixel coordinates).

(v: number) => number mapping domain values to range values.

select/shared/local-items-buffer.ts

createLocalItemsBuffer Factory
createLocalItemsBuffer#LocalItemsBuffer
createLocalItemsBuffer(compareWith: Signal)

Builds a LocalItemsBuffer. Reads compareWith lazily so mid-flight comparator swaps are honoured.

@paramcompareWithSignal

data/async-state/create-manual-state.ts

createManualState Factory
createManualState#ManualAsyncState

Create a fully manual async state — no HTTP, no automatic loading.

Use for local operations: heavy computations, Web Workers, complex local processes. Does not require an injection context — uses only signal() and computed().

readonly processState = createManualState<ProcessResult>();

async handleProcess(): Promise<void> {
  this.processState.set('loading');
  this.processState.setProgress(0);
  const result = await heavyComputation((p) => this.processState.setProgress(p));
  this.processState.setSuccess(result);
}

data/material-bridge/bidirectional-sync.ts

createMaterialBidirectionalSync Factory
createMaterialBidirectionalSync#CngxMaterialBidirectionalSyncHandle
createMaterialBidirectionalSync(opts: CngxMaterialBidirectionalSyncOptions)

Single shared bidirectional-sync factory for cngx organisms / directives that bridge a cngx presenter against a Material parent (<mat-tab-group>, <mat-stepper>, etc.).

Lives at Level 2 in @cngx/common/data parallel to createCommitController. Material types never enter the signature — the caller maps Material-specific events and property accessors to a host-agnostic shape at the directive boundary.

Installs:

  1. A presenter→Material effect() that tracks presenterIndex and writes through writeSelectedIndex, equality-guarded against readSelectedIndex() to suppress redundant writes. The Material read+write pair runs inside untracked() per reference_signal_architecture rule 2.
  2. A Material→presenter subscription that forwards each selectionChange$ emission to onMaterialSelection (equality-guarded against presenterIndex() so a Material event whose value already matches the presenter is dropped — closes the re-entrancy loop).

Both sides clean up via destroyRef.

Material-eager-advance reconciliation. Material's MDC click handler advances selectedIndex before the Material→presenter subscription forwards the click. When the presenter HOLDS its index (pessimistic mode + bound commitAction), the subscriber does NOT write Material back: on a SUCCESSFUL commit the presenter later advances to the clicked target and Material is already there, so the mirror effect is a no-op (no flash); on a REJECTED commit the presenter never moves, leaving Material eager-advanced on the refused tab. The host detects the rejection through its own commit lifecycle and calls CngxMaterialBidirectionalSyncHandle.reconcile to snap Material back. Writing from inside the subscriber instead is unsafe: Material's selectedIndex read-back lags a programmatic write, so the mirror effect's equality guard reads a stale value and skips the corrective write, sticking the visual on the wrong tab.

Self-echo suppression (loop-safety). Every programmatic selectedIndex write makes Material re-emit selectionChange. The factory records each value it writes and drops the matching echo (indexOf + splice, which also prunes earlier writes whose echo Material coalesced away) before any other processing. This is load-bearing for an ASYNC commit-action: Material emits the echo a microtask later, by which point the commit may have advanced presenterIndex, so an equality-only guard (presenterIndex() === idx) would FAIL to drop the echo — it would re-enter the subscriber and ping-pong against the in-flight navigation (the demo freezes). Matching the echo by the value we wrote drops it regardless of where the presenter has moved.

mat-accordion/material-bridge/set-sync.ts

createMatExpansionSetSync Factory
createMatExpansionSetSync#void
createMatExpansionSetSync(opts: CngxMatExpansionSetSyncOptions)

Set-based bidirectional sync between a <mat-accordion>'s projected <mat-expansion-panel> tree and the headless CngxAccordion open-set. The accordion open-set is a multi-membership Set<string>, so the index-based createMaterialBidirectionalSync (@cngx/common/data) does not fit — this helper syncs per-panel expanded against set membership instead.

Installs two effects and one listener-set:

  1. brain→Material — an effect() tracking panels() and, per panel, accordion.isOpen(id). When the open-set (or the panel list) changes it writes panel.expanded to match, guarded by a re-entrancy flag so the resulting synchronous expandedChange echo does not loop back. The Material writes run inside untracked() per reference_signal_architecture rule 2.
  2. subscription reconcile — an effect() tracking only panels(); inside untracked() it subscribes freshly-added panels' expandedChange and drops removed ones (diff-only churn, a Map<P, subscription>).
  3. Material→brain — each expandedChange listener flips the brain via accordion.toggle(id), but only when the incoming expanded differs from the brain's current (clamped) membership, so a programmatic echo (or a redundant Material emit) is a no-op. Routing through toggle (not a raw set-write) means single-mode arbitration and the exposed openIds model stay identical to the native CngxAccordionPanel DOM path.

The idempotent membership check plus the re-entrancy flag together close the loop: the flag drops the synchronous echo CdkAccordionItem emits from its expanded setter during our own write, and the membership check drops any Material emit that already agrees with the brain.

mat-stepper/material-bridge/handle.ts

createMatStepHandle Factory
createMatStepHandle#CngxMatStepHandleSetup
createMatStepHandle(matStep: MatStep, idSeed)

Translates a Material MatStep into a cngx CngxStepRegistration.

  • id - always a fresh idSeed() value. Mirrors the tabs instrumentation handle: a label-keyed id would collide when two steps share a label.
  • kind - fixed at 'step'. The instrumentation path does not project nested <mat-step> groups (Material's stepper has no group-of-steps concept; group-aware semantics belong to the <cngx-stepper> thin-wrapper organism).
  • label - snapshot signal resolved through a four-tier fallback at registration time so cngx-side phrases (announcements, aria-label composition, telemetry) never read empty when Material consumers project a <ng-template matStepLabel>:
    1. MatStep.label when it is a plain string - the canonical shape and the only one that emits a runtime change Material itself observes.
    2. MatStep.ariaLabel when the consumer set the input - designed exactly as the substitute for template labels.
    3. Static-text read from MatStep.stepLabel.template via a throwaway detached EmbeddedViewRef (readMatStepLabelTemplateText). Captures literal matStepLabel markup; dynamic interpolation bails through to (4).
    4. Step <id> - deterministic, derived from the cngx handle id. Always non-empty. Documented limitation: runtime label changes do not propagate. CDK's CdkStep does not expose a _stateChanges Subject analogous to MatTab._stateChanges, so cngx cannot re-trigger the snapshot when Material flips the input later. Surface the same Material-internal coupling family typed in MaterialPrivateSurfaces.CompletedOverrideSource.
  • disabled - fixed false. Material owns step gating via linear + editable + completed; surfacing a cngx-side disabled would duplicate Material's own click-time enforcement and is ignored by <mat-stepper> itself.
  • state - computed() over MatStep.hasError / MatStep.completed. CdkStep.completed's getter reads _completedOverride() - a WritableSignal<boolean | null> typed in MaterialPrivateSurfaces.CompletedOverrideSource. The cngx computed transitively tracks that signal through the getter and re-fires whenever Material flips completion. hasError is a plain property setter on CdkStep, NOT a Signal - a hasError write that is not paired with a completed change does not re-trigger this computed. In practice Material wizards write the two together (step.hasError = true; step.completed = false in error-handler patterns and inside Material's own error-state matchers) so the limitation is benign for the documented usage pattern.
  • errorAggregator - points at the shared NO_ERROR_AGGREGATOR constant.
@parammatStepMatStep
@paramidSeed

mat-tabs/material-bridge/handle.ts

createMatTabHandle Factory
createMatTabHandle#CngxMatTabHandleSetup
createMatTabHandle(matTab: MatTab, idSeed, injector: Injector)

Translates a Material MatTab into a cngx CngxTabHandle plus a writable errorAggregator slot the [cngxMatTabError] directive binds.

  • id - fresh idSeed() value; a label-keyed id would collide when two tabs share a label.
  • label / disabled - computed signals retriggered by toSignal(matTab._stateChanges). Bridge lifetime is tied to the supplied injector (typically a per-tab child EnvironmentInjector). _stateChanges is a Material-internal surface.
  • errorAggregator - writable seeded at undefined; [cngxMatTabError] writes its bound aggregator in and resets on teardown. The handle exposes .asReadonly() to preserve the CngxTabHandle contract.
  • directError - writable seeded at false; [cngxMatTabErrorFlag] writes its string | boolean value in and resets on teardown. Folds into hasError / errorMessage.
@parammatTabMatTab
@paramidSeed
@paraminjectorInjector

interactive/menu/menu-announcer.ts

createMenuAnnouncer Factory
injectMenuAnnouncer Inject
createMenuAnnouncer#CngxMenuAnnouncerLike

Default factory that hands out the root-scoped CngxMenuAnnouncer singleton. Consumers wire a custom announcer by replacing CNGX_MENU_ANNOUNCER_FACTORY.

Must run inside an injection context.

injectMenuAnnouncer#CngxMenuAnnouncerLike

Resolve the CngxMenuAnnouncerLike from the current injection scope via the factory token. Must run inside an injection context.

interactive/menu/dismiss-handler.ts

createMenuDismissHandler Factoryv0.1.0
createMenuTriggerDismissBinding Factoryv0.1.0
createMenuDismissHandler#CngxMenuDismissHandler
createMenuDismissHandler(opts: CngxMenuDismissHandlerOptions)

Default factory. Pure closure over opts - no Angular DI. Mirrors the shape of @cngx/forms/select's createDismissHandler so future cross-family consolidation has a clean target.

Override via CNGX_MENU_DISMISS_HANDLER_FACTORY for telemetry-wrapped or test-doubled dismissal.

createMenuTriggerDismissBinding#CngxMenuTriggerDismissBinding
createMenuTriggerDismissBinding(opts: CngxMenuTriggerDismissBindingOptions)

Build the dismiss lifecycle for a menu-bearing trigger directive. Lazily instantiates the handler on first attach() so the trigger's popover input is bound before the factory reads it. The returned lastSource signal is owned by this binding - the factory writes it via its onDismiss callback, which runs from DOM event handlers (never inside an Angular effect()).

common/stepper/mobile-viewport.ts

createMobileViewportSignal Factory
createStepperDisplayMode Factory
createMobileViewportSignal#Signal
createMobileViewportSignal(mediaQuery: string, destroyRef: DestroyRef)

Returns a reactive Signal<boolean> that reflects whether the host window matches a CSS media query (e.g. (max-width: 480px)). Used by <cngx-stepper> to drive its mobile auto-collapse template branch.

In SSR / non-DOM environments the signal stays false and the listener is never wired.

@parammediaQuerystring
@paramdestroyRefDestroyRef
createStepperDisplayMode#Signal<"classic" | "text" | "dots">
createStepperDisplayMode(mediaQuery: string, mobileCollapse, destroyRef: DestroyRef)

Resolves the active stepper display mode by combining a viewport media-query with the configured mobileCollapse policy. 'classic' keeps the full strip; 'text' / 'dots' swap to the matching compact variant.

@parammediaQuerystring
@parammobileCollapse
@paramdestroyRefDestroyRef

field/testing/mock-field.ts

createMockField Factory
createMockField#literal type
createMockField(opts: MockFieldOptions)

Creates a mock CngxFieldAccessor that returns a fully writable MockFieldRef. Tests can mutate any signal to simulate field state changes.

const { accessor, ref } = createMockField({ name: 'email', required: true });
// Pass `accessor` to [field] input
// Mutate ref.touched.set(true) to simulate interaction
@paramoptsMockFieldOptions= {}
mockValidationError#ValidationError.WithFieldTree
mockValidationError(kind: string, message?: string, extra?: Record)

Creates a mock ValidationError.WithFieldTree for testing.

@paramkindstring
@parammessage?string
@paramextra?Record

chart/scales/ordinal.ts

createOrdinalScale Factory
createOrdinalScale#string
createOrdinalScale(domain, colors)

Pure-TS ordinal scale. Maps a discrete categorical domain to a cycling palette of values (typically colours). When the domain is longer than the palette, mappings wrap modulo palette length.

@paramdomain

Ordered list of categorical values. Values are matched by reference equality on lookup.

@paramcolors

Palette to cycle through. Must have at least one entry; an empty palette throws synchronously at construction time.

Callable (v: T) => string returning the palette entry for v. Lookup of an unknown value returns the palette's first entry.

tabs/scroll-sync/organism-scroll-sync.ts

createOrganismScrollSync Factoryv0.1.0
createOrganismScrollSync#void
createOrganismScrollSync(opts: CngxOrganismScrollSyncOptions)

Scroll-into-view effect for any strip-based organism (tabs, stepper headers, future scrolling lists).
Tracks activeId and scrolls the matching [id="<itemId>-header"] into view.

The DOM call sits in untracked() (only activeId is tracked).
scrollIntoView is missing in jsdom - guarded with optional chain.

UX / a11y

  • The active tab is never stranded off-screen: when activation moves to a tab clipped by overflow (keyboard arrow, deep link, programmatic select), its header scrolls into view, so the focused and selected tab is always visible (WCAG 2.4.7 Focus Visible).
  • Pairs with the overflow surface: picking a hidden tab from the "More" popover scrolls it back into the strip, and the overflow recompute then self-trims - keyboard navigation and the overflow list stay in sync.
  • Motion is overridable for reduced motion: the default is smooth-center along the inline axis; pass scrollOptions (e.g. behavior: 'auto') to honour prefers-reduced-motion or to scroll vertically.
// Install once from the organism's field-init (needs an injection context).
createOrganismScrollSync({
  activeId: this.presenter.activeId, // Signal<string | null>
  hostElement: this.hostElement,     // holds the [id="<tabId>-header"] buttons
  injector: this.injector,
  // scrollOptions omitted -> smooth-center; override for reduced motion:
  // scrollOptions: { behavior: 'auto' },
});

tabs/overflow/overflow-template-cascade.ts

createOverflowPopoverHighlightSync Factory
createTabOverflowTemplateBindings Factory
createOverflowPopoverHighlightSync#void
createOverflowPopoverHighlightSync(popover: Signal, ad: Signal)

Resets the AD highlight on popover close.
Keyboard-open paths (ArrowDown / End / typeahead on the closed trigger) set activeIndex via AD's own keydown listener before opening - unaffected. Mouse-open leaves activeIndex === -1 so the popover renders unhighlighted.
Without this reset, the next open would inherit a stale index from the prior keyboard session.

Must run in injection context.

UX / a11y

  • Closing the popover resets the highlight, so a keyboard session never leaves a stale aria-activedescendant for the next open.
  • Each row has a stable descendant id (tabOverflowOptionId), so the SR focus reference never dangles across re-renders.
  • Highlight is virtual focus, not DOM focus: keyboard nav moves aria-activedescendant while real focus stays on the trigger (APG menu-button); the rows are never tab stops.
@parampopoverSignal
@paramadSignal
createTabOverflowTemplateBindings#CngxTabOverflowTemplateBindings
createTabOverflowTemplateBindings(opts: CngxTabOverflowTemplateBindingsOptions)

Wires the 3-stage template cascade for the overflow molecule's two visible regions:
per-instance directive > CNGX_TABS_CONFIG.templates.overflow* > built-in markup (template-outlet returns null). \

Pure - no DI, no side effects, no destroy hooks. Safe to call from a component's field-init block. Mirrors the select-family createTemplateRegistry pattern.

tabOverflowOptionId#string
tabOverflowOptionId(tab: CngxTabHandle)

DOM id for a hidden-tab option row in the overflow listbox.
Stable across CD passes so aria-activedescendant resolves to the same <li>. -overflow-option suffix avoids collision with the strip-button (-header) and per-tab descriptor (-desc).

@paramtabCngxTabHandle

ui/paginator/paginator-announcer.ts

createPaginatorAnnouncer Factoryv0.1.0
createPaginatorAnnouncer#CngxPaginatorAnnouncer

Builds the paginator live-region message as a single derived signal - no class logic baked into the shell, so the skin still ejects cleanly. The message is a linkedSignal over [pageIndex, totalPages, isBusy] from CNGX_PAGINATOR_HOST: it speaks "Page N of M" on every effective-page change (navigation OR a total-shrink clamp, so the clamp is never silent), "Loading" while busy, and "Updated" on the first settle after busy. Phrasing comes from injectPaginatorConfig.

The previous source value (held by linkedSignal) is what distinguishes a settle from a steady state, so there is no signal write in an effect and no imperative previous tracking. Identical consecutive messages dedupe through the signal's value equality, so the live region never re-announces a no-op.

Must run in an injection context (call as a field initialiser on the shell).

paginator/segments/paginator-nav.component.ts

createPaginatorNavCore Factory
createPaginatorNavCore#NavCore
createPaginatorNavCore(options: NavCoreOptions)

Shared nav-button glue. Composition, not an abstract base class: each of the four segments calls this factory as a field initialiser and binds the same template, differing only in selector, glyph, and the three options here.

@paramoptionsNavCoreOptions

select/shared/panel-lifecycle-emitter.ts

createPanelLifecycleEmitter Factory
createPanelLifecycleEmitter#void
createPanelLifecycleEmitter(opts: PanelLifecycleEmitterOptions)

One effect() that emits openedChange/opened/closed on panelOpen flips and restores focus to the trigger after close. Output emits + focus call wrapped in untracked. Injection context required.

forms/input/password-strength.factory.ts

createPasswordStrength Factory
createPasswordStrength#CngxPasswordStrengthFactory

Builds the dependency-less default password-strength estimator.

The heuristic scores length tiers (>= 8 / 12 / 16) plus character-class diversity (lower, upper, digit, symbol) and subtracts a point for a run of three or more identical characters, then clamps to 0..4. It ships no dictionary - enterprises swap in zxcvbn or similar via CNGX_PASSWORD_STRENGTH_FACTORY.

chart/path/path-builder.ts

createPathBuilder Factory
createPathBuilder#PathBuilder
createPathBuilder(opts: PathBuilderOptions)

Pure-TS path builder with single-slot LRU memo on (data, xScale, yScale) reference identity. Pure TS, no Angular dep. Compute guard only - does not know about signals or equal functions; the d computed in <cngx-line> carries the cascade guard separately.

The cache returns the previous result when all three inputs are reference-equal to the previous call. Any reference mismatch triggers a rebuild and updates the slot.

Each call to createPathBuilder returns a fresh builder with its own lastData / lastX / lastY slots - there is no cross-call / cross-consumer state. The cascade guard for layer atoms is the equal: (a, b) => a === b on the builder computed; combined with Angular signals' default behaviour of skipping re-emissions when the inputs to the computed are unchanged, two consecutive cascade ticks with the same (y, x, curve) produce the same builder instance.

select/shared/projected-option-model.ts

createProjectedOptionModel Factory
createProjectedOptionModel#ProjectedOptionModel
createProjectedOptionModel(input: ProjectedOptionModelInput)

Hierarchy-preserving option model derived from projected DOM. Leaves stay leaves, groups stay groups; createSelectCore reflattens for AD lookup. Labels are plain-text via {{ }} interpolation.

select/shared/recycler-panel-renderer.ts

createRecyclerPanelRendererFactory Factory
createRecyclerPanelRendererFactory#CngxPanelRendererFactory
createRecyclerPanelRendererFactory(recycler: CngxRecycler)

Builds a CngxPanelRendererFactory backed by a consumer-owned CngxRecycler. Slices flatOptions to the recycler window and forwards spacer heights + setsize. Consumer wires connectRecyclerToActiveDescendant separately; this factory doesn't touch AD state.

@paramrecyclerCngxRecycler

select/shared/reorder-commit-handler.ts

createReorderCommitHandler Factory
createReorderCommitHandler#ReorderCommitHandler
createReorderCommitHandler(opts: ReorderCommitHandlerOptions)

Plain factory for the reorder-commit flow used by CngxReorderableMultiSelect. Operates on ordered arrays with same-membership semantics.

Why a separate factory (not a flag on createArrayCommitHandler): the array handler's reconcileValues uses sameArrayContents to short-circuit writes when the target matches current state - a pure reorder would silently skip. A bypassReconcile flag would complicate every other call-site; a dedicated factory keeps the array handler's hot path small.

CngxTreeSelect.dispatchValueChange follows the same pattern inline; a future refactor could lift it here.

select/shared/scalar-commit-handler.ts

createScalarCommitHandler Factory
createScalarCommitHandler#ScalarCommitHandler
createScalarCommitHandler(opts: ScalarCommitHandlerOptions)

Scalar-shape commit flow shared by scalar select variants. Owns commit-controller lifecycle, reconciliation, togglingOption.set(null) on success, optimistic rollback on error. Consumer owns change-event emission, announcer severity (onCommitError), input-text mirroring (onValueWrite), and popover-close timing - handler never closes the panel.

select/shared/search-effects.ts

createSearchEffects Factory
createSearchEffects#void
createSearchEffects(opts: SearchEffectsOptions)

One or two effect()s for input-trigger variants: skipInitial-gated searchTermChange forward (when emit is set) and auto-open-on-typing. External calls wrapped in untracked. Injection context required.

core/utils/selection-controller.ts

createSelectionController Factory
createSelectionController#SelectionController
createSelectionController(values: WritableSignal, options?: SelectionControllerOptions)

Create a signal-based selection engine that reads and writes an external WritableSignal<T[]>.

const values = signal<User[]>([]);
const selection = createSelectionController(values, { keyFn: (u) => u.id });

selection.select(alice);
selection.isSelected(alice)();      // true
selection.isSelected(alice) === selection.isSelected(alice); // stable

interactive/slider/slider-interaction.ts

createSliderInteraction Factoryv0.1.0
pointerFraction v0.1.0
createSliderInteraction#CngxSliderInteraction
createSliderInteraction(options: CngxSliderInteractionOptions)

Pure factory for a slider's keyboard + pointer-drag behaviour - the shared interaction brain for both CngxSlider (single) and each CngxSliderThumb (range). Arrow / Page / Home / End map onto the core's step helpers; pointer-down captures the pointer and drags via the supplied fractionFromPointer. Keeping this in one factory means the track and the thumb cannot drift apart.

pointerFraction#number
pointerFraction(el: HTMLElement, orientation, clientX: number, clientY: number)

Maps a pointer position to a 0..1 track fraction against el's geometry. Vertical sliders measure bottom-up (fraction 0 at the lower edge) to match the skin's bottom-anchored fill. Shared by the single slider and the range host so the geometry math lives in exactly one place.

@paramelHTMLElement
@paramorientation
@paramclientXnumber
@paramclientYnumber

interactive/slider/slider-ticks.ts

createSliderTicks Factoryv0.1.0
createSliderTicks#CngxSliderTicksView
createSliderTicks(options)

Derives a slider's tick marks + labels from its bounds, shared by CngxSlider and CngxRangeSlider so the math lives once. marks gates the repeating-gradient interval; labels gates the numeric stops; both are independent. The values signal is arrayEqual-guarded.

@paramoptions
sliderTickValues#number[]
sliderTickValues(min: number, max: number, step: number, maxCount: number)
@paramminnumber
@parammaxnumber
@paramstepnumber
@parammaxCountnumber= 21

data/sort/sort-header-state.ts

createSortHeaderState Factoryv0.1.0
createSortHeaderState#SortHeaderState
createSortHeaderState(sort, field)

Derives the shared sort-header state for one column from a CngxSort getter.

Both CngxSortHeader (table context, aria-sort) and CngxDgaSortHeader (disclosure context, role="button" + aria-describedby) compose this factory and keep only their own a11y presentation. The factory is a11y-agnostic - it returns the plain derived signals each header maps to its own DOM/ARIA surface.

@paramsort

Getter for the owning CngxSort engine (() => sortRef, () => grid.sort).

@paramfield

Getter for the column's field key.

The derived { entry, isActive, isAsc, isDesc, priority, toggle } bundle.

common/stepper/commit-handler.ts

createStepperCommitHandler Factory
createStepperCommitHandler#CngxStepperCommitHandler
createStepperCommitHandler(opts: CngxStepperCommitHandlerOptions)

Build a stepper commit handler over an existing CngxCommitController. Resolves Observable<boolean> / Promise<boolean> / boolean returns into a unified accept: boolean outcome.

common/stepper/group-navigation.ts

createStepperGroupNavigation Factory
createStepperGroupNavigation#CngxStepperGroupNavigationView
createStepperGroupNavigation(options: CngxStepperGroupNavigationOptions)

Builds the collapsed-group pointer-navigation view. Level-2 helper so the organism stays a thin renderer.

Indices resolve against flatSteps (DFS order, live flatIndex) rather than group.children - the flattener spreads group nodes but leaves their children as the tree projection where every step still carries the seeded -1. Each candidate is gated by canNavigateTo + busy (mirroring the step-header reachability), so a linear-blocked leading step is skipped to the first reachable one.

common/stepper/group-summary.ts

createStepperGroupSummary Factory
createStepperGroupSummary#CngxStepperGroupSummaryView
createStepperGroupSummary(options: CngxStepperGroupSummaryOptions)

Builds the collapsed-group summary view. Level-2 helper so the organism stays a thin renderer. status mode defers its SR phrasing to the group's existing status-phrase span, so srText returns null there. English defaults (locale via the i18n cascade is a follow-up).

subtreeStats#literal type
subtreeStats(node: CngxStepNode)

Terminal-step totals for a group's subtree; reads each step state().

@paramnodeCngxStepNode

common/stepper/create-stepper-host-proxy.ts

createStepperHostProxy Factoryv0.1.0
createStepperHostProxy#CngxStepperHost
createStepperHostProxy(supplier)

Builds a live delegating CngxStepperHost proxy over a supplier signal. Every signal member is a computed() reading supplier()?.<member>(), every method forwards to supplier()?.<method>(...). This is the spelled-out shape for re-providing an input-derived host through DI - you cannot useExisting an input() value, so the footer provides this proxy once and it tracks whichever host the supplier currently resolves.

Null-supplier neutral set (the disabled-by-default contract). When the supplier resolves null (a standalone footer with neither [host] nor an ambient stepper), every navigation affordance must render inert, never falsely enabled: canGoPrevious / canGoNext collapse to false so Back / Next render disabled, and every method is a no-op.

create* pure factory - no injection context required (computed() only). Single consumer (the footer); the surface is load-bearing, not speculative.

@paramsupplier

common/stepper/stepper-state-view.ts

createStepperStateView Factoryv0.1.0
resolveStepperErrorSummary v0.1.0
createStepperStateView#CngxStepperStateView
createStepperStateView(inputs)

Build the shared CngxStepperStateView over a presenter host and its step-only projection. Pure factory - computed() only, no injection context required, so any skin can allocate it in a field initializer.

@paraminputs
resolveStepperErrorSummary#string
resolveStepperErrorSummary(view: Pick, stepsOnly: Signal, i18n: CngxStepperI18n, messageOf?)

Aggregate error phrase shared by the minimal skins (text / progress-bar) and the classic mobile-collapse text branch. A single errored step names itself ("Payment: Errored"); several collapse to the i18n count phrase ("2 errors"). Returns '' when no step errored - callers gate on view.hasAnyError() so the empty string never reaches the DOM.

The optional messageOf resolver lets callers surface a per-step reason (a direct [error] string or the first aggregator label) in the single-error case instead of the generic errored status word. When omitted - or when it returns undefined/'' - the helper produces byte-identical output to the no-resolver form, so existing callers (the classic mobile-collapse summary) are a guaranteed no-op.

Pure helper - reads signals at call time, intended to be wrapped in the caller's computed().

@paramviewPick
@paramstepsOnlySignal
@parami18nCngxStepperI18n
@parammessageOf?

stepper/slots/stepper-template-cascade.ts

createStepperTemplateBindings Factory
createStepperTemplateBindings#CngxStepperTemplateBindings
createStepperTemplateBindings(opts: CngxStepperTemplateBindingsOptions)

Wires the 3-stage template cascade for the <cngx-stepper> skin slots: per-instance directive > CNGX_STEPPER_CONFIG.templates.<key>

null (built-in default).

Pure - no DI, no side effects. Safe to call from a field-init block. Sibling of createTabOverflowTemplateBindings and the family-wide createTemplateRegistry.

Tabs has no parallel slot surface yet - see stepper-accepted-debt §3 for the planned Phase-4 closure.

tabs/dismissals/tab-dismissals.ts

createTabDismissals Factoryv0.1.0
createTabDismissals#CngxTabDismissals
createTabDismissals(opts: CngxTabDismissalsOptions)

Helper resolving the dismissable/addable affordances for <cngx-tab-group>.
Keeps the close/add cascade + interaction off the organism class (LOC guard).
Each cascade is one computed(). The actual tab removal is the consumer's - handleClose only routes through the presenter's requestClose, which moves the active index, and restores focus once the consumer's removal has rendered.

// The organism builds it once from field-init; the template reads it.
protected readonly dismiss = createTabDismissals({
  host: this.host,            // CNGX_TAB_GROUP_HOST
  config: this.config,        // injectTabsConfig()
  i18n: this.i18n,            // injectTabsI18n()
  closable: this.closable,    // input<boolean | undefined>('closable')
  addable: this.addable,      // input<boolean | undefined>('addable')
  hostElement: this.hostElement,
  injector: this.injector,
});

// Per-tab close affordance, read from the header template:
dismiss.isTabClosable(tab);              // per-tab override > group resolution
dismiss.closeButtonLabel(tab);           // i18n accessible name for the close button
dismiss.handleClose(tab, clickEvent);    // routes through presenter.requestClose, restores focus
dismiss.handleTabKeydown(tab, keyEvent); // Delete on a focused closable tab closes it (APG)

// Group-level add affordance:
dismiss.resolvedAddable();               // input ?? config ?? false
dismiss.handleAdd();                     // routes through presenter.requestAdd

tabs/announcements/tab-group-announcements.ts

createTabGroupAnnouncements Factoryv0.1.0
createTabGroupAnnouncements#CngxTabGroupAnnouncements
createTabGroupAnnouncements(options: CngxTabGroupAnnouncementsOptions)

Pure factory bundling the <cngx-tab-group> AT-announcement + descriptor surfaces. Owns one internal linkedSignal (prior-active-index, drives the success-arm direction prefix) — lazy by linkedSignal semantics, so the organism reads liveAnnouncement once at construction to seed it.

UX / a11y

  • The live region is declarative, never imperative: liveAnnouncement is a signal the polite region renders, empty between transitions so AT stays silent on no-op ticks.
  • Direction is spoken on every change: a move carries a previous/next prefix plus the landing tab; a rollback announces the safe-harbour tab or a retry, so the outcome is never silent.
  • Accessible names carry position ("Tab 2 of 5: Settings") so AT does not infer it from tablist enumeration.
  • Role descriptions stay distinct from the label: the tablist aria-roledescription is separate from the region aria-label, so AT never reads the same word twice.
  • aria-label and aria-labelledby stay mutually exclusive (resolvedAriaLabel returns null when labelledby is bound).
  • The per-tab descriptor is ARIA-by-value: the cngx-sr-only span is always in the DOM; statusPhrase only fills its content, keeping the aria-describedby reference stable.

tabs/slots/tab-group-template-cascade.ts

createTabGroupTemplateBindings Factoryv0.1.0
createTabGroupTemplateBindings#CngxTabGroupTemplateBindings
createTabGroupTemplateBindings(opts: CngxTabGroupTemplateBindingsOptions)

Wires the 3-stage template cascade for the <cngx-tab-group> skin slots (errorBadge / rejectionIcon / busySpinner / icon / closeIcon / addIcon): per-instance directive > CNGX_TABS_CONFIG.templates.<key> > null.

null means the organism renders its built-in default - a default span for the state decorations, the CNGX_TABS_GLYPHS glyph for closeIcon / addIcon, and nothing for icon.

Pure — no DI, no side effects. Safe in field-init. Sibling to createStepperTemplateBindings and createTabOverflowTemplateBindings.

Single-consumer today: [cngxMatTabs] does not consume this — Material owns the rendered tab-button chrome via its own MDC template, leaving no DOM seam. See tabs-accepted-debt §9.

UX / a11y

  • The cascade is presentation-only; the accessibility contract is invariant under it. Overriding a slot never strips its accessible default (fallthrough to a built-in or the organism default).
  • The screen-reader channel (descriptor / aria-busy / live region) lives on the organism, not the slot template, so swapping a decoration template changes only the visual.
  • An unbound icon slot resolves to nothing, which is correct - the icon is decorative and the label carries the accessible name.

tabs/keyboard/tab-keyboard-nav.ts

createTabKeyboardNav Factoryv0.1.0
createTabKeyboardNav#CngxTabKeyboardNav
createTabKeyboardNav(opts: CngxTabKeyboardNavOptions)

Level-2 helper implementing the WAI-ARIA APG tabs keyboard model for <cngx-tab-group> with automatic activation: an arrow press moves focus AND activates the target tab in one step, so focus and selection never diverge. Keeps the keyboard logic off the organism class (LOC guard) and out of a competing roving-tabindex state machine.

Pillar 1 (Ableitung statt Verwaltung): the tab stop is derived from the presenter's activeId, not managed as a second index. Pillar 2 (Kommunikation): activation routes through host.select(), which owns disabled-skip, loop, commit gating, and the live-region announcement - the keyboard layer adds only focus movement (a DOM concern the presenter, living in @cngx/common, must not own).

Navigation always originates from the active tab: under automatic activation the focused tab is always the active one, so the clamped active index is the correct origin.

common/tabs/router-commit.ts

createTabRouterCommit Factoryv0.1.0
createTabRouterCommit#CngxTabsCommitAction
createTabRouterCommit(opts: CngxTabRouterCommitOptions)

Builds a CngxTabsCommitAction that gates a tab switch through @angular/router. The action navigates to the target tab's route and resolves on the router's own outcome:

  • NavigationEndtrue (commit the switch)
  • NavigationCancel (a CanDeactivate guard blocked) → false
  • NavigationError (guard/resolver threw) → false

Routed tabs reuse the presenter's commit lifecycle verbatim - the router navigation is simply the async op.
In pessimistic mode the active tab follows the resolved route, so a cancelled guard keeps the old tab with zero extra gate machinery. The events subscription is opened before navigate(...) so a synchronously-resolving navigation cannot emit before the action is listening; the commit controller's cancel() unsubscribes on supersede.

common/tabs/commit-handler.ts

createTabsCommitHandler Factory
createTabsCommitHandler#CngxTabsCommitHandler
createTabsCommitHandler(opts: CngxTabsCommitHandlerOptions)

Wraps a CngxCommitController with the action-shape adapter that collapses Observable<boolean> / Promise<boolean> / boolean returns into a single accept: boolean outcome.

runTabsAction#CngxCommitHandle
runTabsAction(action: CngxTabsCommitAction, fromIndex: number, toIndex: number, handlers)
@paramfromIndexnumber
@paramtoIndexnumber
@paramhandlers

select/shared/template-registry.ts

createTemplateRegistry Factory
createTemplateRegistry#CngxSelectTemplateRegistry
createTemplateRegistry(queries: CngxSelectTemplateRegistryQueries)

Build a resolved CngxSelectTemplateRegistry from raw contentChild directive queries. Runs each slot through the 3-stage cascade (instance directive → CNGX_SELECT_CONFIG.templates default → null). Must be called in an injection context.

Used by every select-family variant to replace ~13 inline injectResolvedTemplate(...) cascade blocks. See CngxSelectTemplateRegistryQueries for the input shape.

interactive/slider/slider-thumb.directive.ts

createThumbValue Factory
createThumbValue#WritableSignal
createThumbValue(range: CngxSliderRangeHost, position: Signal)

Builds a WritableSignal<number> view over one end of the range tuple: reads range.value()[index] reactively, routes writes through range.commit(position, …). Lets a thumb run an ordinary createSliderCore (which writes a WritableSignal) while the tuple stays the single source of truth - no local state, no effect sync.

@parampositionSignal

chart/scales/time.ts

createTimeScale Factory
createTimeScale#number
createTimeScale(domain, range)

Pure-TS time scale. Reuses createLinearScale after coercing Date endpoints (and inputs) to epoch milliseconds. Supports inverted domains and bare-number timestamps interchangeably.

@paramdomain

[start, end] time range. Date and number are interchangeable on either endpoint.

@paramrange

[start, end] output range (typically pixel coordinates).

(v: Date | number) => number mapping time values to range values.

core/utils/transition-tracker.ts

createTransitionTracker Factory
createTransitionTracker#StatusTransition
createTransitionTracker(source)

Creates a reactive transition tracker for an AsyncStatus source.

Uses linkedSignal internally — when source() changes, previous holds the prior value and current holds the new one. Both are memoized signals.

@paramsource

Reactive function that reads the current AsyncStatus.

const tracker = createTransitionTracker(() => this.state().status());

effect(() => {
const { current, previous } = tracker;
if (current() === previous()) return; // no change — deduplicated by linkedSignal
if (current() === 'success') { ... }
});

interactive/tree-controller/tree-ad-items.ts

createTreeAdItems Factoryv0.1.0
createTreeAdItems#Signal
createTreeAdItems(ctrl: CngxTreeController)

Projects a tree controller's visibleNodes into the ActiveDescendantItem[] shape consumed by CngxActiveDescendant.items. Kept as a helper (not a method on the controller) so CngxTreeController stays free of the @cngx/common/a11y import and can be reused from contexts that do not render through AD.

Returns a structurally-equal memoized computed - consumers can pass the signal straight into [items]="adItems()" without worrying about cascade re-renders on irrelevant tree re-emissions.

interactive/tree-controller/tree-controller.ts

createTreeController Factoryv0.1.0
createTreeController#CngxTreeController
createTreeController(opts: CngxTreeControllerOptions)

Plain factory for a signal-native tree controller. Reads opts.nodes reactively, derives flat / visible projections via computed, and tracks expanded-id state internally. Must be called in an injection context (reads CNGX_TREE_CONFIG for defaults).

See CngxTreeController for the returned surface and CngxTreeControllerOptions for the configuration cascade.

select/shared/trigger-focus.ts

createTriggerFocusState Factory
createTriggerFocusState#CngxTriggerFocusState

Builds the focus-state slot.

private readonly focus = inject(CNGX_TRIGGER_FOCUS_FACTORY)();
readonly focused = this.focus.focused;

protected handleFocus(): void {
  this.focus.markFocused();
  if (this.config.openOn === 'focus') this.open();
}

select/shared/typeahead-controller.ts

createTypeaheadController Factory
createTypeaheadController#TypeaheadController
createTypeaheadController(options: TypeaheadControllerOptions)

<select> keyboard-typeahead: printable-key guard, lower-case match, disabled skip, round-robin walk, debounced buffer reset. State-holding (buffer + timer) but no DI refs; caller owns the lifetime.

resolvePageJumpTarget#number | null
resolvePageJumpTarget(opts, currentIndex: number, direction, isDisabled, step: number)

PageUp/PageDown helper. Disabled-aware, clamped ±step jump with back-probe fallback. Returns target index or null.

@paramopts
@paramcurrentIndexnumber
@paramdirection
@paramisDisabled
@paramstepnumber= 10

interactive/menu/menu-nav-strategy.ts

createW3CMenuStrategy Factory
createW3CMenuStrategy#CngxMenuNavStrategy

Default W3C APG menu keyboard policy:

  • ArrowRight on a submenu parent that is currently closed → open-submenu. On an already-open submenu or a leaf item → noop (item-level navigation inside the open submenu is owned by the submenu's own active-descendant).
  • ArrowLeft when a submenu is open at the current level → close-submenu. Otherwise → move-to-parent (an enclosing menubar interprets that; a standalone menu trigger treats it as noop).

interactive/hierarchical-nav/hierarchical-nav-strategy.ts

createW3CTreeStrategy Factory
createW3CTreeStrategy#CngxHierarchicalNavStrategy

Default W3C APG treeview keyboard policy:

  • ArrowRight on a collapsed parent expands it. On an already-open parent it moves the active-descendant to the first child. On a leaf it is a no-op.
  • ArrowLeft on an open node collapses it. On a closed node (or leaf) with a parent it moves the active-descendant to the parent. On a root leaf it is a no-op.

Move actions internally verify that ad.highlightByValue actually changed activeId (e.g. disabled skip rejection), and downgrade to 'noop' when it didn't - so consumers bound to (movedToChild) / (movedToParent) only see state-change-truthful emissions.

projects/utils/decimal-places.ts

decimalPlaces v0.1.0
decimalPlaces#number
decimalPlaces(n: number)

Count the decimal places in a finite number's shortest decimal string.

Used to round float-drift artefacts back to the precision a step or origin carries (e.g. 0.1 * 3 = 0.30000000000000004 snaps back to 0.3). Reads the places off String(n) rather than a fixed epsilon so 0.125 reports 3, not a guessed constant. Non-finite input returns 0.

@paramnnumber

select/tree-select/tree-select.component.ts

dedup#T[]
dedup(arr, eq)
@paramarr
@parameq

mat-tabs/decorations/decoration-projectors.ts

defaultHalfWiredSlotWarn#void
defaultHalfWiredSlotWarn(missing)
@parammissing
defaultRetryCeilingWarn#void
defaultRetryCeilingWarn(max: number)
@parammaxnumber

data/data-source/smart-data-source.ts

injectSmartDataSource Inject
defaultSearchFn#boolean
defaultSearchFn(item: T, term: string)
@paramitemT
@paramtermstring
defaultSortFn#number
defaultSortFn(a: T, b: T, field: string, dir)
@paramaT
@parambT
@paramfieldstring
@paramdir
injectSmartDataSource#CngxSmartDataSource
injectSmartDataSource(source, options?: CngxSmartDataSourceOptions)

Factory function for CngxSmartDataSource.

Must be called within an injection context (constructor or field initializer). Accepts either a plain Signal<T[]> or a CngxAsyncState<T[]> for full UX state integration (loading, error, refresh, empty).

// Plain signal
readonly dataSource = injectSmartDataSource(this.items);

// With async state - table shows skeleton, error, loading bar
readonly residents = injectAsyncState(() => this.api.getAll());
readonly dataSource = injectSmartDataSource(this.residents);
@paramsource
isAsyncState#CngxAsyncState
isAsyncState(source)
@paramsource

display/shared/delta-format.ts

deltaDirection#DeltaDirection
deltaDirection(value: number)

> 0 → up, < 0 → down, 0 → flat.

@paramvaluenumber
deltaSentiment#DeltaSentiment
deltaSentiment(direction: DeltaDirection, polarity: DeltaPolarity)

Combine movement with the caller's polarity. flat or neutral polarity collapse to neutral; otherwise up is positive under higher-is-better and negative under lower-is-better (and the reverse for down).

@paramdirectionDeltaDirection
@parampolarityDeltaPolarity
directionGlyph#string
directionGlyph(direction: DeltaDirection)

Arrow glyph for the direction: / / .

@paramdirectionDeltaDirection
formatDelta#string
formatDelta(value: number, mode: DeltaMode, locale: string, format?)

Format the magnitude. The sign is carried by the arrow and colour, not the digits: a positive value gains a leading +, everything else prints its absolute value unsigned. Percent mode appends a narrow-no-break-space + % and defaults to one fraction digit; absolute mode uses the locale grouping. A supplied Intl.NumberFormatOptions overrides the default digit handling in both modes.

@paramvaluenumber
@parammodeDeltaMode
@paramlocalestring
@paramformat?

chart/chart/equal-helpers.ts

dimensionsEqual#boolean
dimensionsEqual(a, b)

Field-wise equality on the chart's { width, height } dimension shape. Used by the dimensions computed; every ResizeObserver tick produces a fresh literal even when the numeric pair is unchanged, so an equal fn on this signal is the foundation of the chart-graph cascade short-circuit.

@parama
@paramb

utils/rxjs-interop/rxjs-interop.ts

ensureObservable#Observable
ensureObservable(value)

Ensures the value is an observable.

@paramvalue

ui/mat-tabs/mat-tabs-config.ts

injectMatTabsConfig Inject
provideMatTabsConfig Provider
provideMatTabsConfigAt Provider
withAnchorRetryAttempts Feature
withHalfWiredSlotSink Feature
feature(config: Partial)
@paramconfigPartial
injectMatTabsConfig#Required

Resolve the effective [cngxMatTabs] configuration for the current injector. Always returns a fully populated, non-undefined object so call sites do not need null-coalescing.

Resolution order per key:

  1. CNGX_MAT_TABS_CONFIG value (set via provideMatTabsConfig / provideMatTabsConfigAt).
  2. CNGX_MAT_TABS_CONFIG_DEFAULTS (library default).
mergeFeatures#Partial
mergeFeatures(features)
@paramfeatures
provideMatTabsConfig#EnvironmentProviders
provideMatTabsConfig(...features: undefined)

App-wide [cngxMatTabs] configuration. Returns EnvironmentProviders for use inside bootstrapApplication's providers array.

bootstrapApplication(App, {
  providers: [
    provideMatTabsConfig(
      withAnchorRetryAttempts(10),
      withHalfWiredSlotSink((missing) => Sentry.captureMessage(`half-wired ${missing}`)),
    ),
  ],
});
@paramfeatures
provideMatTabsConfigAt#Provider[]
provideMatTabsConfigAt(...features: undefined)

Component-scope [cngxMatTabs] configuration. Returns a Provider[] so the result can be spread into a component's providers or viewProviders (which cannot accept opaque environment providers).

@paramfeatures
withAnchorRetryAttempts#CngxMatTabsConfigFeature
withAnchorRetryAttempts(n: number)

Cap on the [cngxMatTabs] overflow-anchor retry loop. See CngxMatTabsConfig.anchorMaxAttempts for default + rationale.

@paramnnumber
withHalfWiredSlotSink#CngxMatTabsConfigFeature
withHalfWiredSlotSink(sink: CngxMatTabHalfWiredSlotSink)

Override the half-wired-slot diagnostic sink. See CngxMatTabsConfig.halfWiredSlotSink.

select/shared/action-select-config.ts

provideActionSelectConfig Provider
provideActionSelectConfigAt Provider
withActionAriaLabel Feature
withActionPopoverPlacement Feature
withActionPosition Feature
withCloseOnCreate Feature
withFocusTrapBehavior Feature
withLiveInputFallback Feature
feature(config: Partial)
@paramconfigPartial
provideActionSelectConfig#EnvironmentProviders
provideActionSelectConfig(...features: undefined)

App-wide action-select config. provideActionSelectConfigAt wins.

bootstrapApplication(App, {
  providers: [
    provideActionSelectConfig(
      withFocusTrapBehavior('always'),
      withActionAriaLabel('Quick action'),
      withCloseOnCreate(true),
      withActionPosition('top'),
      withLiveInputFallback(false),
    ),
  ],
});
@paramfeatures
provideActionSelectConfigAt#Provider[]
provideActionSelectConfigAt(...features: undefined)

Component-scoped action-select config. Returns Provider[] because viewProviders rejects EnvironmentProviders.

@paramfeatures
withActionAriaLabel(label: string)

Sets the action-slot ARIA label.

@paramlabelstring
withActionPopoverPlacement#CngxActionSelectConfigFeature
withActionPopoverPlacement(placement: PopoverPlacement)

Sets the popover placement for the action organisms.

@paramplacementPopoverPlacement
withActionPosition(position: CngxActionPosition)

Sets the default *cngxSelectAction slot position.

@parampositionCngxActionPosition
withCloseOnCreate(closeOnCreate)

Forces closeOnCreate across both action organisms. Pass null to restore the variant baselines.

@paramcloseOnCreate
withFocusTrapBehavior#CngxActionSelectConfigFeature
withFocusTrapBehavior(behavior: CngxActionFocusTrapBehavior)
withLiveInputFallback#CngxActionSelectConfigFeature
withLiveInputFallback(enabled: boolean)

Sets the live-input fallback policy. Disable when consumer owns debouncing.

@paramenabledboolean

select/shared/config.ts

provideSelectConfig Provider
provideSelectConfigAt Provider
withAnnouncer Feature
withAriaLabels Feature
withCaret Feature
withChipOverflow Feature
withCommitErrorAnnouncePolicy Feature
withCommitErrorDisplay Feature
withDismissOn Feature
withEnterKeyHint Feature
withFallbackLabels Feature
withInputMode Feature
withLoadingVariant Feature
withMaxVisibleChips Feature
withOpenOn Feature
withPanelClass Feature
withPanelWidth Feature
withPopoverPlacement Feature
withRefreshingVariant Feature
withRestoreFocus Feature
withSelectionIndicator Feature
withSelectionIndicatorPosition Feature
withSelectionIndicatorVariant Feature
withSkeletonRowCount Feature
withTypeaheadDebounce Feature
withTypeaheadWhileClosed Feature
withVirtualization Feature
feature(config: Partial)
@paramconfigPartial
provideSelectConfig#EnvironmentProviders
provideSelectConfig(...features: undefined)

App-wide defaults for the Select family. provideSelectConfigAt and per-instance inputs win.

@paramfeatures
provideSelectConfigAt#Provider[]
provideSelectConfigAt(...features: undefined)

Component-scoped config. Returns Provider[] because viewProviders rejects EnvironmentProviders.

@paramfeatures
withAnnouncer(config: CngxSelectAnnouncerConfig)

Configure the live-region announcer used for selection changes.

withAriaLabels(labels: CngxSelectAriaLabels)

Sets ARIA-label overrides. Partial. Per-instance inputs win.

bootstrapApplication(App, {
  providers: [
    provideSelectConfig(
      withAriaLabels({
        clearButton: 'Clear selection',
        chipRemove: 'Remove',
      }),
    ),
  ],
});
withCaret(enabled: boolean)

Whether the trigger's dropdown caret glyph is rendered. Default true.

@paramenabledboolean
withChipOverflow#CngxSelectConfigFeature
withChipOverflow(mode: NonNullable)

Sets the chip-strip overflow mode. Default 'wrap'.

@parammodeNonNullable
withCommitErrorAnnouncePolicy#CngxSelectConfigFeature
withCommitErrorAnnouncePolicy(policy)

Forces the scalar-commit error-announce policy. null restores each variant's baseline.

@parampolicy
withCommitErrorDisplay#CngxSelectConfigFeature
withCommitErrorDisplay(display: CngxSelectCommitErrorDisplay)

Default [commitAction] error surface. Default 'banner'.

withDismissOn(mode)

Dismiss strategy for the panel. Default 'both'.

@parammode
withEnterKeyHint#CngxSelectConfigFeature
withEnterKeyHint(hint)

Forces enterkeyhint across input-trigger variants. null restores each variant's baseline.

@paramhint
withFallbackLabels#CngxSelectConfigFeature
withFallbackLabels(labels: CngxSelectFallbackLabels)

Sets the panel-shell visible-fallback labels. Partial. Per-instance template projection wins.

bootstrapApplication(App, {
  providers: [
    provideSelectConfig(
      withFallbackLabels({
        loadFailed: 'Échec du chargement',
        loadFailedRetry: 'Réessayer',
        empty: 'Aucune option',
      }),
    ),
  ],
});
withInputMode(mode: NonNullable)

Sets inputmode for input-trigger variants. Default 'search'.

@parammodeNonNullable
withLoadingVariant#CngxSelectConfigFeature
withLoadingVariant(variant: CngxSelectLoadingVariant)

First-load indicator variant. Default 'spinner'.

withMaxVisibleChips#CngxSelectConfigFeature
withMaxVisibleChips(count: number)

Sets maxVisibleChips for truncate mode. Coerces ≤ 0 to 1. Default 3.

@paramcountnumber
withOpenOn(mode)

Open strategy for the trigger. Default 'click'.

@parammode
withPanelClass(panelClass)

Class list applied to every select panel.

@parampanelClass
withPanelWidth(width)

Panel width: 'trigger' (match), fixed px number, or null (natural).

@paramwidth
withPopoverPlacement#CngxSelectConfigFeature
withPopoverPlacement(placement: PopoverPlacement)

Default popover placement for flat variants. Default 'bottom'. Action organisms use withActionPopoverPlacement.

@paramplacementPopoverPlacement
withRefreshingVariant#CngxSelectConfigFeature
withRefreshingVariant(variant: CngxSelectRefreshingVariant)

Sets the refreshing indicator. Default 'bar'. 'none' suppresses.

withRestoreFocus#CngxSelectConfigFeature
withRestoreFocus(enabled: boolean)

Whether the trigger is re-focused after the panel closes. Default true.

@paramenabledboolean
withSelectionIndicator#CngxSelectConfigFeature
withSelectionIndicator(enabled: boolean)

Whether the selected-option checkmark is rendered at all. Default true.

@paramenabledboolean
withSelectionIndicatorPosition#CngxSelectConfigFeature
withSelectionIndicatorPosition(position: CngxSelectSelectionIndicatorPosition)

Sets the selection-indicator position. Default 'before'.

withSelectionIndicatorVariant#CngxSelectConfigFeature
withSelectionIndicatorVariant(variant: CngxSelectSelectionIndicatorVariant)

Sets the selection-indicator glyph. Default 'auto'.

withSkeletonRowCount#CngxSelectConfigFeature
withSkeletonRowCount(count: number)

Sets skeletonRowCount. Default 3.

@paramcountnumber
withTypeaheadDebounce#CngxSelectConfigFeature
withTypeaheadDebounce(ms: number)

Typeahead buffer debounce in ms. Default 300.

@parammsnumber
withTypeaheadWhileClosed#CngxSelectConfigFeature
withTypeaheadWhileClosed(enabled: boolean)

Typeahead-while-closed (native <select> parity). Default true.

@paramenabledboolean
withVirtualization#CngxSelectConfigFeature
withVirtualization(config)

Opts in to recycler virtualisation. {} / true uses defaults; null / false falls back to identity. Custom pipelines provide CNGX_PANEL_RENDERER_FACTORY directly.

provideSelectConfig(
  withVirtualization({ estimateSize: 36, overscan: 8, threshold: 500 }),
)
@paramconfig= true

select/shared/reorderable-select-config.ts

provideReorderableSelectConfig Provider
provideReorderableSelectConfigAt Provider
withDefaultDragHandle Feature
withReorderAriaLabel Feature
withReorderKeyboardModifier Feature
withReorderStripFreeze Feature
feature(config: Partial)
@paramconfigPartial
provideReorderableSelectConfig#EnvironmentProviders
provideReorderableSelectConfig(...features: undefined)

App-wide defaults for reorder-aware select variants. provideReorderableSelectConfigAt and per-instance inputs win.

bootstrapApplication(App, {
  providers: [
    provideReorderableSelectConfig(
      withReorderKeyboardModifier('alt'),
      withReorderAriaLabel('Reorder with Alt + arrow keys'),
      withReorderStripFreeze(false),
    ),
  ],
});
@paramfeatures
provideReorderableSelectConfigAt#Provider[]
provideReorderableSelectConfigAt(...features: undefined)

Component-scoped reorderable-select config. Returns Provider[] because viewProviders rejects EnvironmentProviders.

@paramfeatures
withDefaultDragHandle(template)

Sets the default drag-handle glyph app-wide via TemplateRef<void>.

@paramtemplate
withReorderAriaLabel(label: string)

Sets the chip-strip ARIA label.

@paramlabelstring
withReorderKeyboardModifier#CngxReorderableSelectConfigFeature
withReorderKeyboardModifier(modifier: CngxReorderModifier)

Sets the keyboard modifier gating reorder moves.

@parammodifierCngxReorderModifier
withReorderStripFreeze(freeze: boolean)

Sets strip-freeze-on-commit. false lets reorders supersede in-flight commits via the commit-controller's supersede semantics.

@paramfreezeboolean

forms/input/file-drop.directive.ts

fileKey#string
fileKey(file: File)

Identity key for dedup across drops.

@paramfileFile

select/shared/option.model.ts

filterSelectOptions#CngxSelectOptionsInput
filterSelectOptions(input: CngxSelectOptionsInput, term: string, match)

Filters by term using a listbox match fn. Preserves group shape; empty groups dropped. The matcher payload's id: '' is synthetic; real DOM ids come from CngxOption, and in-tree matchers ignore the field.

@paramtermstring
@parammatch
flattenSelectOptions#CngxSelectOptionDef[]
flattenSelectOptions(input: CngxSelectOptionsInput)

Flattens grouped + flat input. Used by keyboard nav and compare lookups.

isCngxSelectOptionGroupDef#CngxSelectOptionGroupDef
isCngxSelectOptionGroupDef(item)

Group / flat-option type guard.

@paramitem
isOptionDisabled#boolean
isOptionDisabled(option)

Disabled-check across both option shapes:

  • CngxSelectOptionDef.disabled - plain boolean (data-driven)
  • CngxOption.disabled - InputSignal<boolean> (element-driven, callable)

Direct .disabled access would treat every signal as truthy (TS2774).

@paramoption
mergeLocalItems(provided: CngxSelectOptionsInput, localItems, compareWith)

Folds a local-items buffer onto server-provided options, deduped by value via compareWith. Group shape preserved; locals appended flat after groups. Server wins on collision - locals matching a provided value drop silently.

Identity-stable when localItems is empty (returns provided).

@paramlocalItems
@paramcompareWith

data-display/treetable/tree.utils.ts

filterTree#Node[]
filterTree(nodes, predicate)

Filters a tree recursively. A parent node is kept if it matches the predicate OR if at least one of its descendants matches.

@paramnodes
@parampredicate
flattenTree#FlatNode[]
flattenTree(input, nodeId?)

Flattens a tree (or forest) into a depth-first ordered array of FlatNodes.

@paraminput
  • A single root node or an array of root nodes.
@paramnodeId?
  • Optional function to derive a stable ID from the node value and its path in the tree. When omitted, IDs are the path indices joined by "-" (e.g. "0", "0-1", "0-1-2").

A flat array where every node contains its depth, parent ID chain, and a flag indicating whether it has children.

nodeMatchesSearch#boolean
nodeMatchesSearch(value: T, term: string)

Simple full-text search across all primitive fields of a node value. Used as the default search implementation in CngxSmartDataSource.

@paramvalueT
@paramtermstring
sortTree#Node[]
sortTree(nodes, field: string, direction)

Sorts each level of the tree independently by a field key. Children remain grouped under their parent; only sibling order changes.

@paramnodes
@paramfieldstring
@paramdirection

forms/field/focus-first-error.ts

focusFirstError#boolean
focusFirstError(tree: FieldTree)

Focuses the first invalid leaf field's bound control after form submission.

Uses errorSummary() from the root FieldState to find all descendant errors, then iterates to find the first one with a bound UI control and calls focusBoundControl() on it. Skips group-level validators that have no bound control (where focusBoundControl() would be a no-op).

Call after submit() fails or after manually touching all fields.

@paramtreeFieldTree

The root FieldTree of the form.

true if a field was focused, false if no focusable error found.

async handleSubmit() {
const success = await submit(this.loginForm, async () => { ... });
if (!success) {
focusFirstError(this.loginForm);
}
}

data/async-state/from-http-resource.ts

fromHttpResource#CngxAsyncState
fromHttpResource(ref: HttpResourceLike)

Bridge that projects an Angular httpResource() ref onto CngxAsyncState<T>.

Identical to fromResource but additionally maps the HTTP progress signal to CngxAsyncState.progress (0–100 scale).

Must be called in an injection context.

private readonly res = httpResource<Item[]>(() => ({
  url: '/api/items',
  params: { q: this.filter() },
}));

readonly items = fromHttpResource(this.res);
// items.progress() tracks upload/download progress
// <cngx-progress [state]="items"> — auto-wired progress bar

interop/query/from-query.ts

fromQuery(query: CngxQueryLike)

Bridge that projects a TanStack Query result onto CngxAsyncState<T>.

Reads the query's signal-bag and maps TanStack's status / fetchStatus pair onto the cngx AsyncStatus union, then hands the derived signals to buildAsyncStateView - the same single-source-of-truth kernel every other producer uses. No injection context is required (only computed()), and no boolean view is re-derived here.

Status mapping:

  • error -> error
  • success + fetching -> refreshing (background refetch, data visible)
  • success + idle/paused -> success
  • pending + fetching -> loading (first load, no data yet)
  • pending + idle/paused -> idle (disabled or paused query)
private readonly query = injectQuery(() => ({
  queryKey: ['users', this.filter()],
  queryFn: () => fetchUsers(this.filter()),
}));

readonly users = fromQuery(this.query);
// users.status(), users.data(), users.isFirstLoad() - all work
// <cngx-async-container [state]="users"> - direct binding
@paramqueryCngxQueryLike

data/async-state/from-resource.ts

fromResource#CngxAsyncState
fromResource(ref: Resource)

Bridge that projects an Angular Resource<T> onto CngxAsyncState<T>.

Must be called in an injection context (the effect() that tracks hadSuccess requires one).

All signals are derived reactively from the resource — no manual synchronization. The resource stays the single source of truth.

private readonly res = resource({
  request: () => ({ filter: this.filter() }),
  loader: ({ request, abortSignal }) =>
    fetch(`/api/items?q=${request.filter}`, { signal: abortSignal })
      .then(r => r.json()),
});

readonly items = fromResource(this.res);
// items.status(), items.data(), items.isFirstLoad() — all work
// <cngx-async-container [state]="items"> — direct binding
@paramrefResource

core/utils/transition.util.ts

hasTransition#boolean
hasTransition(el: HTMLElement)

Checks whether an element has any CSS transition applied.

@paramelHTMLElement

true if at least one transition-duration value is greater than 0.

onTransitionDone#void
onTransitionDone(el: HTMLElement, onDone)

Listens for the longest CSS transition on an element, then invokes onDone.

Automatically falls back to a timeout if transitionend never fires.

@paramelHTMLElement
@paramonDone

A cleanup function that removes the listener and clears the fallback timer.

interactive/accordion/accordion.directive.ts

headersEqual#boolean
headersEqual(a, b)

Order-independent identity-set equality for the header registry. Two arrays are equal when they hold the same handle references, regardless of registration order. Handles are stable per panel (carrying disabled by signal reference), so this comparator only suppresses re-fires from a re-register of the same set; it does not gate the roving derivation on disabled state - rovingActiveId reads each handle's disabled() directly, so a disabled flip still re-runs it (which is what keeps the tab stop off a newly-disabled header).

@parama
@paramb

accordion/config/inject-accordion-config.ts

injectAccordionConfig Injectv0.1.0
injectAccordionConfig#CngxAccordionConfig

Convenience accessor for the accordion configuration cascade. Runs in injection context; resolves through the priority chain (per-instance Input -> provideAccordionConfigAt -> provideAccordionConfig -> library defaults). Equivalent to inject(CNGX_ACCORDION_CONFIG) - the helper exists so consumers don't import the token directly. Mirrors injectBreadcrumbConfig in @cngx/ui/breadcrumb.

export class CngxAccordionItem {
  private readonly config = injectAccordionConfig();
  readonly disabledReason = input<string>(this.config.disabledReason);
}

data/async-registry/provide-async-registry.ts

injectAsyncRegistry Inject
provideAsyncRegistry Provider
injectAsyncRegistry#CngxAsyncRegistry | null

Returns the ambient CngxAsyncRegistry, or null when the consumer did not opt in via provideAsyncRegistry. Must run in an injection context.

provideAsyncRegistry#EnvironmentProviders

Provides CngxAsyncRegistry in the host environment.

Opt-in - not providedIn: 'root'. Add it to bootstrapApplication providers to enable app-wide async observability; producers that opt in (injectAsyncState({ register: true }), provideAsyncHttpObservability()) then surface in isAnythingLoading() / activeOperations().

bootstrapApplication(AppComponent, {
  providers: [provideAsyncRegistry()],
});

data/async-state/inject-async-state.ts

injectAsyncState Inject
injectAsyncState#ReactiveAsyncState
injectAsyncState(fn, options?: InjectAsyncStateOptions)

Create a reactive async state that auto-loads when signal dependencies change.

Must be called in an injection context (field initializer or constructor). The computation function is tracked by Angular's effect() — any signal read inside fn will cause a re-load when it changes.

readonly residents = injectAsyncState(
  () => this.api.getResidents(this.filter())
);
// Loads automatically when filter() changes.
// Caches last result during refresh (refreshing state).
// Deduplicates parallel requests.
@paramfn

audio/config/audio-config.ts

injectAudioConfig Injectv0.1.0
provideCngxAudio Providerv0.1.0
withDebounceMs Featurev0.1.0
withEarcons Featurev0.1.0
withMuted Featurev0.1.0
withRespectReducedMotion Featurev0.1.0
withVolume Featurev0.1.0
injectAudioConfig#CngxAudioConfig

Resolve the effective audio config: library defaults merged with whatever provideCngxAudio(...) contributed. Runs in an injection context.

provideCngxAudio#EnvironmentProviders
provideCngxAudio(...features: undefined)

Register global audio defaults. Mirrors provideFeedback — a single small config object folded through with* features.

bootstrapApplication(AppComponent, {
  providers: [
    provideCngxAudio(
      withVolume(0.6),
      withEarcons({ send: { sequence: [{ freq: 880, duration: 60 }] } }),
    ),
  ],
});

Register this at application bootstrap. The shared engine is providedIn: 'root' and reads its configuration once, when it is first built, so config registered in a lazy route's providers never reaches it. To configure a subtree, use provideCngxAudioAt(...) in viewProviders — it layers over this one and re-provides the engine so the scope actually applies.

@paramfeatures
withDebounceMs#CngxAudioFeature
withDebounceMs(ms: number)

Set the same-name suppression window in milliseconds.

@parammsnumber
withEarcons(earcons: Record)

Register or override earcons globally. Merged over the six built-ins and over any earlier withEarcons in the same provideCngxAudio call.

@paramearconsRecord
withMuted(muted: unknown)

Start muted (or explicitly unmuted with withMuted(false)).

@parammutedunknown= true
withRespectReducedMotion#CngxAudioFeature
withRespectReducedMotion(respect: boolean)

Toggle the prefers-reduced-motion mute gate. true by default in the library; pass false to keep audio playing under reduced-motion.

@paramrespectboolean
withVolume(volume: number)

Set the master volume in [0, 1].

@paramvolumenumber

breadcrumb/config/inject-breadcrumb-config.ts

injectBreadcrumbConfig Injectv0.1.0
injectBreadcrumbConfig#CngxBreadcrumbConfig

Convenience accessor for the breadcrumb configuration cascade. Runs in injection context; resolves through the priority chain (per-instance Input -> provideBreadcrumbConfigAt -> provideBreadcrumbConfig -> library defaults). Equivalent to inject(CNGX_BREADCRUMB_CONFIG) - the helper exists so consumers don't import the token directly. Mirrors injectTagConfig in @cngx/common/display.

export class CngxBreadcrumbBar {
  private readonly cfg = injectBreadcrumbConfig();
  readonly label = input<string>(this.cfg.ariaLabels?.bar ?? 'Breadcrumb');
}

chart/chart/chart-context.ts

injectChartContext Inject
injectChartContext#CngxChartContext
injectChartContext(consumerName: string)

Inject the parent chart's reactive context. Throws a clear dev-mode error when the consumer is not mounted as a content child of <cngx-chart>. The consumerName argument is interpolated into the error message so the consumer-class name surfaces at the call site rather than a generic guard string.

Replaces six verbatim copies of the same six-line helper that previously lived inline in every layer atom.

@paramconsumerNamestring

common/audio/inject-audio.ts

injectCngxAudio Injectv0.1.0
provideCngxAudioAt Providerv0.1.0
injectCngxAudio#CngxAudioHandle

Resolve the shared audio handle. Must run in an injection context (field initialiser or constructor).

export class MyToggle {
  private readonly audio = injectCngxAudio();
  protected readonly muted = this.audio.muted;
  protected toggle(): void {
    this.audio.setMuted(!this.muted());
  }
}
provideCngxAudioAt#Provider[]
provideCngxAudioAt(...features: undefined)

Component-scope audio config — place in a component's viewProviders so a subtree runs its own muted / volume / earcon set, independent of the app-wide provideCngxAudio(...).

@paramfeatures

data-grid-accordion/config/inject-data-grid-accordion-config.ts

injectDataGridAccordionConfig Injectv0.1.0
injectDataGridAccordionConfig#CngxDataGridAccordionConfig

Convenience accessor for the data-grid-accordion configuration cascade. Runs in injection context; resolves through the priority chain (per-instance Input -> provideDataGridAccordionConfigAt -> provideDataGridAccordionConfig -> library defaults). Equivalent to inject(CNGX_DATA_GRID_ACCORDION_CONFIG) - the helper exists so consumers don't import the token directly. Mirrors injectAccordionConfig in @cngx/ui/accordion.

export class CngxDataGridAccordion {
  private readonly config = injectDataGridAccordionConfig();
  readonly skin = input<CngxDataGridSkin | undefined>(undefined);
}

data/data-source/data-source.ts

injectDataSource Inject
injectDataSource#CngxDataSource
injectDataSource(data: Signal)

Factory function for CngxDataSource.

Must be called within an injection context (constructor or field initializer).

readonly dataSource = injectDataSource(this.items);
@paramdataSignal

core/theming/density.ts

injectDensity Injectv0.1.0
provideDensity Providerv0.1.0
injectDensity#WritableSignal

Read the app-wide density signal in an injection context. The returned signal is writable, so injectDensity().set('spacious') re-densifies the whole document reactively.

provideDensity#EnvironmentProviders
provideDensity(initial: CngxDensityValue)

Install the density preference at app root and reflect it onto <html data-density>, mirroring how the colour ramp is applied by attribute. The reflector is an effect (not afterNextRender) so it re-runs on every runtime injectDensity().set(...); the DOM write is wrapped in untracked() per the signal-architecture rules.

bootstrapApplication(AppComponent, {
  providers: [provideDensity('compact')],
});
@paraminitialCngxDensityValue= 'comfortable'

forms/filter-builder/filter-builder.config.ts

injectFilterBuilderConfig Inject
provideFilterBuilderConfig Provider
provideFilterBuilderConfigAt Provider
withDefaultOperators Feature
withFilterBuilderI18n Feature
withLogicOptions Feature
withMaxNestingDepth Feature
withNegation Feature
withSkeletonCount Feature
withTemplates Feature
injectFilterBuilderConfig#CngxFilterBuilderConfig

Inject-context helper that resolves CNGX_FILTER_BUILDER_CONFIG.

isNativeEditor(value: CngxFilterEditor)

Narrowing helper for CngxFilterEditor.

@paramvalueCngxFilterEditor
provideFilterBuilderConfig#EnvironmentProviders
provideFilterBuilderConfig(...features: undefined)

Root / environment-level config. Compose with withFilterBuilderI18n(...), withNegation(true), etc.

@paramfeatures
provideFilterBuilderConfigAt#Provider[]
provideFilterBuilderConfigAt(...features: undefined)

Component/route-level config - same shape as provideFilterBuilderConfig but for non-environment injectors.

@paramfeatures
withDefaultOperators(operators: Readonly)

Extend or override the default operator lists keyed by editor type.

@paramoperatorsReadonly
withFilterBuilderI18n#CngxFilterBuilderConfigFeature
withFilterBuilderI18n(partial: Partial)

Override any subset of the i18n bundle. operators is shallow-merged.

@parampartialPartial
withLogicOptions(logics)

Restrict which logic operators (and / or / xor) appear in the group toggle.

@paramlogics
withMaxNestingDepth(depth: number)

Cap the nesting depth of the builder tree. Default 8.

@paramdepthnumber
withNegation(enabled: boolean)

Reveal the per-group negation toggle. Off by default.

@paramenabledboolean
withSkeletonCount(count: number)

Number of skeleton rows the builder renders while async fields are loading.

@paramcountnumber
withTemplates(templates: CngxFilterBuilderTemplates)

Register global template overrides - keyed fallback below per-instance content-child slots.

forms/filter-builder/filter-builder.tokens.ts

injectFilterEditors Inject
injectFilterEditors#ReadonlyMap

Inject the resolved editor registry. Sugar over inject(CNGX_FILTER_EDITORS). Exists so consumers can read editors without importing the token directly when they already inject other filter-builder helpers (e.g. inside a slot directive context).

Snapshot semantics. The returned ReadonlyMap is captured at injection time. Runtime swaps of CNGX_FILTER_EDITORS in nested DI scopes are NOT observed by an already-injected consumer. If a consumer needs reactive editor swap behaviour, re-inject() the token at the swap-boundary's injector instead of cached references.

layout/observers/inject-media-query.ts

injectMediaQuery Injectv0.1.0
injectMediaQuery#Signal
injectMediaQuery(query: string)

Inject-form of CngxMediaQuery: returns a reactive Signal<boolean> that reflects whether the host window currently matches a CSS media query, without needing a host element.

Use it where the directive form has nowhere to attach - inside a route guard, a store, a computed(), or any injection context that reacts to a viewport or preference query. For host-bound templates, prefer the [cngxMediaQuery] directive; for pure styling, prefer CSS @media / @container.

Wraps window.matchMedia(): seeds the signal from MediaQueryList.matches, updates on the change event, and removes the listener via DestroyRef when the injection scope is destroyed. In SSR / non-DOM environments (no defaultView or no matchMedia) it returns a static false signal and wires no listener, so it never throws off the browser.

Returns a Signal<boolean> - never an Observable; the reactive boundary stays inside cngx.

@paramquerystring

A CSS media query string, e.g. (max-width: 640px).

A reactive Signal<boolean> tracking the query's match state.

interactive/menu/menu-config.ts

injectMenuConfig Inject
provideMenuConfig Provider
provideMenuConfigAt Provider
injectMenuConfig#CngxMenuConfig

Resolves the CngxMenuConfig from the current injection scope. Must run inside an injection context.

provideMenuConfig#EnvironmentProviders
provideMenuConfig(...features: undefined)

Provide a menu configuration at app root. Each feature is a partial override produced by with* helpers (see menu-config-features.ts).

bootstrapApplication(AppComponent, {
  providers: [
    provideMenuConfig(
      withAriaLabels({ submenuOpened: 'Untermenü geöffnet' }),
      withTypeaheadDebounce(500),
    ),
  ],
});
@paramfeatures
provideMenuConfigAt#Provider[]
provideMenuConfigAt(...features: undefined)

Component-scoped menu configuration override. Pass into a directive or component's viewProviders; features merge on top of the parent config (root or an enclosing scope).

@paramfeatures

interactive/nav/nav-config.ts

injectNavConfig Inject
provideNavConfig Provider
withNavAnimation Feature
withNavIndent Feature
withSingleAccordion Feature
injectNavConfig#Readonly>

Injects the resolved nav config, merging provided values with defaults. Must be called in an injection context.

provideNavConfig#Provider[]
provideNavConfig(...features: undefined)

Provides nav system configuration. Accepts withXxx() feature functions for composable setup.

Automatically includes CngxNavGroupRegistry when singleAccordion is enabled (either directly or via withSingleAccordion()).

providers: [provideNavConfig(withSingleAccordion(), withNavIndent(16))]
@paramfeatures
withNavAnimation#NavConfigFeature
withNavAnimation(ms: number)

Sets the animation duration for nav group expand/collapse in ms.

@parammsnumber
withNavIndent#NavConfigFeature
withNavIndent(px: number)

Sets the indentation per depth level in px.

@parampxnumber
withSingleAccordion#NavConfigFeature

Enables single-accordion mode - only one nav group can be open at a time.

layout/router/inject-query-param-sync.ts

injectQueryParamSync Injectv0.1.0
injectQueryParamSync#void
injectQueryParamSync(state: WritableSignal, opts: QueryParamSyncOptions)

Bidirectional sync between a caller-owned WritableSignal<T> and a named query param. URL wins on initial load (deep-link intent); after hydrate the signal is the source and reflects outward. Re-hydrates on browser back/forward. Dev-warns once and no-ops when @angular/router is absent.

Loop-safety (the core of this helper): the reflect effect writes the URL in untracked() and skips navigate when the serialized state() equals the last value it wrote - a local closure seeded from the initial URL read, not the live URL param (the live param races the navigate-settle window). The hydrate path updates that same closure whenever it accepts a URL value, so back/forward re-hydration never triggers a reflex navigate. A param rename is migrated in one navigate ({ [old]: null, [new]: serialize(state()) }) by a dedicated effect whose only tracked source is the normalized param signal; its first run seeds bookkeeping and never navigates.

The state.set inside the hydrate effect is a deliberate signal-write-in- effect: the URL is an external system and state is a caller-owned signal the consumer must stay able to toggle, so hydrate cannot be a computed. It is edge-guarded by serialized equality and wrapped in untracked().

data/recycler/recycler.ts

injectRecycler Inject
provideRecyclerI18n Provider
injectRecycler#CngxRecycler
injectRecycler(config: RecyclerConfig)

Creates a Signal-based virtualizer for DOM recycling.

Must be called in an injection context (field initializer or constructor). Internally injects DestroyRef and DOCUMENT for cleanup and selector resolution.

Basic list

readonly recycler = injectRecycler({
  scrollElement: '.scroll-container',
  totalCount: () => this.items().length,
  estimateSize: 48,
});
readonly visibleItems = this.recycler.sliced(this.items);

With async state

readonly state = injectAsyncState(() => this.api.getAll());
readonly recycler = injectRecycler({
  scrollElement: '.scroll-container',
  totalCount: () => (this.state.data() ?? []).length,
  estimateSize: 64,
  state: this.state,
});
@paramconfigRecyclerConfig
provideRecyclerI18n#
provideRecyclerI18n(i18n: RecyclerI18n)

Provider function for custom recycler i18n texts.

providers: [provideRecyclerI18n({
  loaded: (n, t) => `${n} weitere Einträge. ${t} gesamt.`,
  filtered: (c) => `${c} Ergebnisse.`,
  empty: () => 'Keine Ergebnisse.',
  error: () => 'Fehler beim Laden.',
})]
@parami18nRecyclerI18n

select/shared/inject-helpers.ts

injectSelectAnnouncer Inject
injectSelectConfig Inject
injectSelectAnnouncer#CngxSelectAnnouncer

Root-scoped CngxSelectAnnouncer for custom composites that want to share the family live-region.

const announcer = injectSelectAnnouncer();
announcer.announce('Filter applied: Red', 'polite');
injectSelectConfig#ReturnType

Effective select config for the current injector, merged with library defaults. Always fully populated - never null. Injection context required.

import { injectSelectConfig } from '@cngx/forms/select';

export class MyComposite {
  private readonly config = injectSelectConfig();
  protected readonly panelWidth = this.config.panelWidth;
}

sidenav/config/inject-sidenav-config.ts

injectSidenavConfig Injectv0.1.0
injectSidenavConfig#CngxSidenavConfig

Convenience accessor for the sidenav configuration cascade. Runs in injection context; resolves through the priority chain (per-instance Input -> provideSidenavConfigAt -> provideSidenavConfig -> library defaults). Equivalent to inject(CNGX_SIDENAV_CONFIG) - the helper exists so consumers don't import the token directly. Mirrors injectBreadcrumbConfig in @cngx/ui/breadcrumb.

export class CngxSidenav {
  private readonly cfg = injectSidenavConfig();
  readonly width = model<string>(this.cfg.dimensions?.width ?? '280px');
}

common/stepper/stepper-config.ts

injectStepperConfig Inject
provideStepperConfig Provider
provideStepperConfigAt Provider
withDotStepperDotTemplate Feature
withStepBadgeTemplate Feature
withStepBusySpinnerTemplate Feature
withStepErrorTemplate Feature
withStepGroupHeaderTemplate Feature
withStepIndicatorTemplate Feature
withStepperAriaLabels Feature
withStepperCommitMode Feature
withStepperConnectors Feature
withStepperDefaultOrientation Feature
withStepperDensity Feature
withStepperEmptyTemplate Feature
withStepperFallbackLabels Feature
withStepperGroupCollapse Feature
withStepperGroupCollapseSummary Feature
withStepperHeaderNavigation Feature
withStepperLinear Feature
withStepperMobileBreakpoint Feature
withStepperMobileCollapse Feature
withStepperMobileIndicatorPosition Feature
withStepperMobileSwipe Feature
withStepperRouterSync Feature
withStepperSkin Feature
withStepRejectionTemplate Feature
injectStepperConfig#CngxStepperConfig

Inject the resolved stepper config in an injection context.

provideStepperConfig#EnvironmentProviders
provideStepperConfig(...features: undefined)

Root-level provider for the stepper config. Apply once in the application providers array. Sibling of provideTabsConfig / provideSelectConfig.

@paramfeatures
provideStepperConfigAt#Provider[]
provideStepperConfigAt(...features: undefined)

Component-scoped config override. Spread the returned Provider[] into providers or viewProviders - viewProviders cannot accept opaque EnvironmentProviders, so the twin returns a list. Sibling of provideTabsConfigAt.

Resolution priority: per-instance Input > viewProviders (At) > root provider > library default.

@paramfeatures
withDotStepperDotTemplate#CngxStepperConfigFeature
withDotStepperDotTemplate(template: TemplateRef)

Override the default *cngxDotStepperDot template app-wide. The <cngx-dot-stepper> variant resolves the cascade per dot: per-instance directive > this feature > built-in empty body (the dot fill is painted by .cngx-dot-stepper__dot regardless).

@paramtemplateTemplateRef
withStepBadgeTemplate#CngxStepperConfigFeature
withStepBadgeTemplate(template: TemplateRef)

Override the default *cngxStepBadge template app-wide.

@paramtemplateTemplateRef
withStepBusySpinnerTemplate#CngxStepperConfigFeature
withStepBusySpinnerTemplate(template: TemplateRef)

Override the default *cngxStepBusySpinner template app-wide.

@paramtemplateTemplateRef
withStepErrorTemplate#CngxStepperConfigFeature
withStepErrorTemplate(template: TemplateRef)

Override the default *cngxStepError template app-wide. The slot renders the per-step validation reason on the skins with a label area (classic / stripe-status-rich). Per-instance directive still wins; this moves the cascade middle tier.

@paramtemplateTemplateRef
withStepGroupHeaderTemplate#CngxStepperConfigFeature
withStepGroupHeaderTemplate(template: TemplateRef)

Override the default *cngxStepGroupHeader template app-wide.

@paramtemplateTemplateRef
withStepIndicatorTemplate#CngxStepperConfigFeature
withStepIndicatorTemplate(template: TemplateRef)

Override the default *cngxStepIndicator template app-wide. Per-instance directive still wins; this only moves the cascade middle tier.

@paramtemplateTemplateRef
withStepperAriaLabels#CngxStepperConfigFeature
withStepperAriaLabels(labels: CngxStepperAriaLabels)

Merge ARIA labels into the cascade. Keys not provided keep their library defaults; per-instance overrides on the stepper still win.

withStepperCommitMode#CngxStepperConfigFeature
withStepperCommitMode(mode)

Override the default commit mode for async step transitions. 'optimistic' advances on action dispatch and rolls back on error; 'pessimistic' waits for success. Per-instance [commitMode] Input still wins.

@parammode
withStepperConnectors#CngxStepperConfigFeature
withStepperConnectors(on: boolean)

Opt the classic <cngx-stepper> skin into the connector-rail presentation: a solid completed/upcoming rail between adjacent step indicators, horizontal and vertical, with per-segment coloring driven by the preceding step's [data-state]. The rule is double-scoped on [data-skin='classic']; the four other skins each ship their own inter-step decoration and ignore this flag. Per-instance [connectors] Input still wins.

@paramonboolean
withStepperDefaultOrientation#CngxStepperConfigFeature
withStepperDefaultOrientation(orientation)

Override the default orientation. Per-instance [orientation] Input still wins; this only moves the cascade default.

@paramorientation
withStepperDensity#CngxStepperConfigFeature
withStepperDensity(mode: CngxStepperDensity, breakpoints?: CngxStepperDensityBreakpoints)

Set the app-wide space-driven density policy for the classic <cngx-stepper> strip. 'auto' degrades labels on the strip's own container width (full -> compact -> minimal); 'comfortable' (library default) keeps full labels at every width. The optional second argument overrides the per-step px thresholds (default STEPPER_DEFAULT_DENSITY_BREAKPOINTS). Orthogonal to the mobileCollapse axis; the Material twin ignores this setting.

withStepperEmptyTemplate#CngxStepperConfigFeature
withStepperEmptyTemplate(template: TemplateRef)

Override the default *cngxStepperEmpty template app-wide.

@paramtemplateTemplateRef
withStepperFallbackLabels#CngxStepperConfigFeature
withStepperFallbackLabels(labels: CngxStepperFallbackLabels)

Merge text fallback labels (button captions, error strings) into the cascade. Used when a slot directive is not present.

withStepperGroupCollapse#CngxStepperConfigFeature
withStepperGroupCollapse(mode: CngxStepperGroupCollapse)

Set the app-wide focus-driven group-collapse policy for grouped <cngx-stepper> flows. 'expand-active' collapses every non-active cngxStepGroup branch to its header node and expands only the group holding the active step; 'off' (library default) keeps the full strip. Orthogonal to the mobileCollapse axis. The Material twin ignores this setting.

withStepperGroupCollapseSummary#CngxStepperConfigFeature
withStepperGroupCollapseSummary(mode: CngxStepperGroupSummary)

Choose what a collapsed cngxStepGroup header shows beside its label under groupCollapse: 'expand-active'. 'progress' (library default) shows completed/total steps; 'count' the step count; 'status' a status dot coloured by the group's rolled-up state; 'off' the bare label. No effect unless groupCollapse is 'expand-active'.

withStepperHeaderNavigation#CngxStepperConfigFeature
withStepperHeaderNavigation(mode: CngxStepperHeaderNavigation)

Set the app-wide default header-navigation policy for <cngx-stepper>. 'none' renders inert label headers (footer-only navigation); 'visited' (library default) keeps the headers as focusable buttons whose reachability folds into the linear axis. Per-instance [headerNavigation] Input still wins.

withStepperLinear#CngxStepperConfigFeature
withStepperLinear(linear: boolean)

Override the default linear-progression setting. Per-instance [linear] Input still wins.

@paramlinearboolean
withStepperMobileBreakpoint#CngxStepperConfigFeature
withStepperMobileBreakpoint(query: string)

Override the media query the mobile auto-collapse policy reacts to. Default '(max-width: 480px)'. Useful for tablet-tier consumers who want the collapse to engage at 768px or for design systems aligned with --mat-sys-breakpoint-* tokens.

@paramquerystring
withStepperMobileCollapse#CngxStepperConfigFeature
withStepperMobileCollapse(mode: CngxStepperMobileCollapse)

Configure the mobile auto-collapse target for <cngx-stepper>. Under a narrow viewport (max-width: 480px), the classic strip swaps to the chosen variant - 'text' (default) renders <cngx-text-stepper>, 'dots' renders <cngx-dot-stepper>, 'off' keeps the classic strip. The Material twin <cngx-mat-stepper> ignores this setting.

withStepperMobileIndicatorPosition#CngxStepperConfigFeature
withStepperMobileIndicatorPosition(position: CngxStepperMobileIndicatorPosition)

Set the app-wide default position of the mobile auto-collapse indicator relative to panel content. 'top' keeps the indicator above (library default); 'bottom' flips it below so panel content reads first and the navigation cue sits at thumb height. Per- instance [mobileIndicatorPosition] on <cngx-stepper> still wins.

withStepperMobileSwipe#CngxStepperConfigFeature
withStepperMobileSwipe(enabled: boolean)

Toggle the built-in horizontal-swipe navigation on <cngx-stepper> in mobile-collapse mode. Default true - the 'dots' and 'text' variants read as carousels, so users expect to swipe. Per-instance [mobileSwipe] Input still wins; the classic strip is unaffected.

@paramenabledboolean
withStepperRouterSync#CngxStepperConfigFeature
withStepperRouterSync(mode, param: string)

Configure router synchronisation for the active step. mode chooses the URL surface (URL fragment or query parameter); param names the key (default 'step').

@parammode
@paramparamstring= 'step'
withStepperSkin(skin: CngxStepperSkin)

Select the visual skin for the cngx-standard <cngx-stepper>. The default is 'classic'. Per-instance [skin] Input still wins; this moves the cascade default. Structure, slots, ARIA, and keyboard behaviour are identical across skins - only the [data-skin] host attribute changes the CSS layer that paints the strip.

@paramskinCngxStepperSkin
withStepRejectionTemplate#CngxStepperConfigFeature
withStepRejectionTemplate(template: TemplateRef)

Override the default *cngxStepRejection template app-wide. Symmetric with the upcoming tabs cngxTabRejectionIcon (Phase 4).

@paramtemplateTemplateRef

stepper/i18n/stepper-i18n.ts

injectStepperI18n Inject
provideStepperI18n Provider
withStepperI18nLabels Feature
injectStepperI18n#CngxStepperI18n

Inject the resolved stepper i18n bundle in an injection context.

provideStepperI18n#Provider
provideStepperI18n(...features: undefined)

Provider for the stepper i18n bundle. Compose withStepperI18nLabels(...) (plus any future i18n with*) - unset keys fall back to English.

bootstrapApplication(AppComponent, {
  providers: [
    provideStepperI18n(
      withStepperI18nLabels({ stepperLabel: 'Schrittfolge', previousStep: 'Vorheriger' }),
    ),
  ],
});
@paramfeatures
withStepperI18nLabels#CngxStepperI18nFeature
withStepperI18nLabels(overrides: CngxStepperI18nOverrides)

Override stepper i18n labels. Partial override - unset keys keep the English default. CngxStepperStatusLabels is merged key-by-key so consumers can override one pill label without restating the rest. Sibling of withStepperAriaLabels / withStepperFallbackLabels.

common/tabs/tabs-config.ts

injectTabsConfig Inject
provideTabsConfig Provider
provideTabsConfigAt Provider
withTabAddIconTemplate Feature
withTabBusySpinnerTemplate Feature
withTabCloseIconTemplate Feature
withTabErrorBadgeTemplate Feature
withTabIconTemplate Feature
withTabOverflowItemTemplate Feature
withTabOverflowMaxDeferMs Feature
withTabOverflowStabilizeMs Feature
withTabOverflowTriggerTemplate Feature
withTabRejectionIconTemplate Feature
withTabsAddable Feature
withTabsAlign Feature
withTabsAriaLabels Feature
withTabsClosable Feature
withTabsCommitMode Feature
withTabsDefaultOrientation Feature
withTabsFallbackLabels Feature
withTabsFitted Feature
withTabsFragmentSync Feature
withTabsIconLayout Feature
withTabsPanelMode Feature
withTabsRovingLoop Feature
withTabsSkin Feature
injectTabsConfig#CngxTabsConfig

Inject the resolved tabs config in an injection context.

provideTabsConfig#EnvironmentProviders
provideTabsConfig(...features: undefined)

Root-level provider. Apply once in bootstrapApplication / appConfig.providers. Returns EnvironmentProviders per the canonical cngx config-cascade signature.

@paramfeatures
provideTabsConfigAt#Provider[]
provideTabsConfigAt(...features: undefined)

Component-scoped override. Returns Provider[] (not EnvironmentProviders) because viewProviders rejects opaque environment providers. Resolution priority: per-instance Input > viewProviders (At) > root > default.

@paramfeatures
resolveFeatures#CngxTabsConfig
resolveFeatures(features)
@paramfeatures
withTabAddIconTemplate#CngxTabsConfigFeature
withTabAddIconTemplate(template: TemplateRef)

App-wide override for the add-tab button glyph. Middle tier; per-instance *cngxTabAddIcon still wins.

@paramtemplateTemplateRef
withTabBusySpinnerTemplate#CngxTabsConfigFeature
withTabBusySpinnerTemplate(template: TemplateRef)

App-wide override for the commit-pending busy-spinner overlay. Middle tier; per-instance *cngxTabBusySpinner still wins. Sibling of withStepBusySpinnerTemplate.

@paramtemplateTemplateRef
withTabCloseIconTemplate#CngxTabsConfigFeature
withTabCloseIconTemplate(template: TemplateRef)

App-wide override for a tab's close-button glyph. Middle tier; per-instance *cngxTabCloseIcon still wins.

@paramtemplateTemplateRef
withTabErrorBadgeTemplate#CngxTabsConfigFeature
withTabErrorBadgeTemplate(template: TemplateRef)

App-wide override for the error-badge decoration. Middle tier; per-instance *cngxTabErrorBadge still wins. Sibling of the stepper family's withStepBadgeTemplate.

@paramtemplateTemplateRef
withTabIconTemplate#CngxTabsConfigFeature
withTabIconTemplate(template: TemplateRef)

App-wide override for the tab-icon slot. Middle tier of the 3-stage cascade; per-instance *cngxTabIcon still wins. Sibling of withStepIndicatorTemplate.

@paramtemplateTemplateRef
withTabOverflowItemTemplate#CngxTabsConfigFeature
withTabOverflowItemTemplate(template: TemplateRef)

App-wide override for each row inside the overflow popover.
Middle tier; per-instance *cngxTabOverflowItem still wins.

@paramtemplateTemplateRef
withTabOverflowMaxDeferMs#CngxTabsConfigFeature
withTabOverflowMaxDeferMs(ms: number)

Override the worst-case staleness ceiling on the visibility-map commit. See CngxTabsConfig.overflowMaxDeferMs.

@parammsnumber
withTabOverflowStabilizeMs#CngxTabsConfigFeature
withTabOverflowStabilizeMs(ms: number)

Override the IO-debounce window (ms). See CngxTabsConfig.overflowStabilizeMs.

@parammsnumber
withTabOverflowTriggerTemplate#CngxTabsConfigFeature
withTabOverflowTriggerTemplate(template: TemplateRef)

App-wide override for the More-button label. Middle tier;
per-instance *cngxTabOverflowTrigger still wins.

readonly moreTrigger = viewChild.required<TemplateRef<CngxTabOverflowTriggerContext>>(
  'moreTrigger',
  { read: TemplateRef },
);

providers: [provideTabsConfig(withTabOverflowTriggerTemplate(this.moreTrigger()))]
@paramtemplateTemplateRef
withTabRejectionIconTemplate#CngxTabsConfigFeature
withTabRejectionIconTemplate(template: TemplateRef)

App-wide override for the rejection-icon decoration. Middle tier;
per-instance *cngxTabRejectionIcon still wins. Sibling of withStepRejectionTemplate.

@paramtemplateTemplateRef
withTabsAddable#CngxTabsConfigFeature
withTabsAddable(addable: boolean)

Set the app-wide default for whether the group renders an add-tab button.
Default false. Per-instance [addable] Input wins.

@paramaddableboolean
withTabsAlign(align: CngxTabAlign)

Set the app-wide default tab-cluster alignment (horizontal only).
Default 'start'. Per-instance [tabAlign] Input still wins. Ignored under orientation="vertical" and when the group is fitted.

@paramalignCngxTabAlign
withTabsAriaLabels#CngxTabsConfigFeature
withTabsAriaLabels(labels: CngxTabsAriaLabels)

Merge ARIA labels into the cascade. Keys not provided keep their library defaults; per-instance overrides on the tab group still win.

@paramlabelsCngxTabsAriaLabels
withTabsClosable#CngxTabsConfigFeature
withTabsClosable(closable: boolean)

Set the app-wide default for whether tabs render a close affordance.
Default false. Per-instance [closable] Input wins; a per-CngxTab [closable] override wins over both.

@paramclosableboolean
withTabsCommitMode#CngxTabsConfigFeature
withTabsCommitMode(mode)

Override the default commit mode for async tab transitions. 'optimistic' activates the tab on action dispatch and rolls back on error; 'pessimistic' waits for success. Per-instance [commitMode] Input still wins.

@parammode
withTabsDefaultOrientation#CngxTabsConfigFeature
withTabsDefaultOrientation(orientation)

Override the default orientation. Per-instance [orientation] still wins; this changes the cascade default only.

@paramorientation
withTabsFallbackLabels#CngxTabsConfigFeature
withTabsFallbackLabels(labels: CngxTabsFallbackLabels)

Merge text fallback labels (overflow trigger, busy / rejection text) into the cascade. Used when a slot directive is not present.

withTabsFitted(fitted: boolean)

Set the app-wide default for stretching tabs to the full strip width (horizontal only).
Default false. Per-instance [fitted] Input still wins. No effect under orientation="vertical".

@paramfittedboolean
withTabsFragmentSync#CngxTabsConfigFeature
withTabsFragmentSync(mode, param: string)

Configure URL fragment / query-param deep-linking for the active tab (the CngxTabsFragmentSync directive).
mode chooses the URL surface (URL fragment or query parameter); param names the key (default 'tab').

Not to be confused with [cngxTabsRouteSync], the router-outlet integration - this feature configures fragment deep-linking only.

@parammode
@paramparamstring= 'tab'
withTabsIconLayout#CngxTabsConfigFeature
withTabsIconLayout(layout: CngxTabIconLayout)

Set the app-wide default icon layout for <cngx-tab-group>.
Default'start'. Per-instance [iconLayout] Input still wins. Orthogonal to skin and orientation - only the [data-icon-layout] host attribute changes.

@paramlayoutCngxTabIconLayout
withTabsPanelMode#CngxTabsConfigFeature
withTabsPanelMode(mode: CngxTabsPanelMode)

Set the app-wide default panel render strategy for <cngx-tab-group>.
Default 'eager' (every panel's content rendered up front, toggled via [hidden]). 'lazy' keep-alives content after first activation; 'lazy-destroy' renders only the active panel's content. Per-instance [panelMode] Input still wins. The panel <div> always stays in the DOM regardless of mode (the aria-controls target).

withTabsRovingLoop#CngxTabsConfigFeature
withTabsRovingLoop(loop: boolean)

Override whether roving-tabindex navigation loops from last back to first (and vice versa). Per-instance [loop] Input still wins.

@paramloopboolean
withTabsSkin(skin: CngxTabsSkin)

Select the app-wide default visual skin for <cngx-tab-group>.
Default 'line'. Per-instance [skin] Input still wins; this moves the cascade default. Structure, slots, ARIA, and keyboard behaviour are identical across skins - only the [data-skin] host attribute changes the CSS layer. The Material twin ([cngxMatTabs]) ignores it.

@paramskinCngxTabsSkin

tabs/i18n/tabs-i18n.ts

injectTabsI18n Inject
provideTabsI18n Provider
withTabsI18nLabels Feature
injectTabsI18n#CngxTabsI18n

Inject the resolved tabs i18n bundle.

provideTabsI18n#Provider
provideTabsI18n(...features: undefined)

Provider for the tabs i18n bundle. Compose withTabsI18nLabels(...) (and future i18n with* features); unset keys fall back to the English default.

bootstrapApplication(AppComponent, {
  providers: [
    provideTabsI18n(
      withTabsI18nLabels({ tabsLabel: 'Reiter', previousTab: 'Vorheriger' }),
    ),
  ],
});
@paramfeatures
resolveI18nFeatures#CngxTabsI18n
resolveI18nFeatures(features)
@paramfeatures
withTabsI18nLabels#CngxTabsI18nFeature
withTabsI18nLabels(overrides: Partial)

Override i18n labels via a partial bundle - unset keys keep the English default. Same shape as withTabsAriaLabels / withTabsFallbackLabels so provideCngxTabs composes both surfaces uniformly.

@paramoverridesPartial

tag/config/inject-tag-config.ts

injectTagConfig Inject
injectTagConfig#CngxTagConfig

Convenience accessor for the tag-family configuration cascade. Runs in injection context; resolves through the priority chain (per-instance Input → provideTagConfigAtprovideTagConfig → library defaults).

Equivalent to inject(CNGX_TAG_CONFIG) — the helper exists so consumers don't need to import the token directly. Mirrors injectSelectConfig in @cngx/forms/select.

export class MyDirective {
  private readonly cfg = injectTagConfig();
  readonly variant = input<CngxTagVariant>(
    this.cfg.defaults?.variant ?? 'filled',
  );
}

interactive/tree-controller/tree-config.ts

injectTreeConfig Injectv0.1.0
provideTreeConfig Providerv0.1.0
provideTreeConfigAt Providerv0.1.0
withDefaultInitiallyExpanded Featurev0.1.0
withDefaultKeyFn Featurev0.1.0
withDefaultLabelFn Featurev0.1.0
withDefaultNodeIdFn Featurev0.1.0
withTreeCacheLimit Featurev0.1.0
injectTreeConfig#CngxTreeConfig

Inject the currently-resolved config. Safe to call in any injection context; returns {} if no provideTreeConfig is registered.

provideTreeConfig#Provider[]
provideTreeConfig(...features: undefined)

Register an app-wide CngxTreeConfig composed from with* features.

bootstrapApplication(AppComponent, {
  providers: [
    provideTreeConfig(
      withDefaultNodeIdFn<MyDomain>((v) => v.uuid),
      withDefaultKeyFn<MyDomain>((v) => v.uuid),
      withTreeCacheLimit(5000),
    ),
  ],
});
@paramfeatures
provideTreeConfigAt#Provider[]
provideTreeConfigAt(...features: undefined)

Sub-tree / component-scoped variant - use in viewProviders so the tree config only applies to descendants of this component.

@paramfeatures
withDefaultInitiallyExpanded#CngxTreeConfigFeature
withDefaultInitiallyExpanded(mode)

App-wide default initiallyExpanded seed.

@parammode
withDefaultKeyFn#CngxTreeConfigFeature
withDefaultKeyFn(fn)

App-wide default keyFn. Library default is identity.

@paramfn
withDefaultLabelFn#CngxTreeConfigFeature
withDefaultLabelFn(fn)

App-wide default labelFn. Library default is String(value).

@paramfn
withDefaultNodeIdFn#CngxTreeConfigFeature
withDefaultNodeIdFn(fn)

App-wide default nodeIdFn. Per-controller options still override. Use this to enforce a domain id convention across the whole app (e.g. (v) => (v as { uuid: string }).uuid) without repeating it at every call site.

@paramfn
withTreeCacheLimit#CngxTreeConfigFeature
withTreeCacheLimit(limit: number)

Bound the isExpanded(id) signal cache. See CngxTreeConfig.cacheLimit for the trade-off.

@paramlimitnumber

core/tokens/window.token.ts

injectWindow Inject
provideWindow Provider
injectWindow#Window | null

Injects the WINDOW token. Returns null in SSR contexts.

provideWindow#Provider
provideWindow(win)

Provides a custom Window reference (useful for testing or SSR).

@paramwin

input/mask-presets/registry.ts

provideEagerMaskPresets Providerv0.1.0
loadTable#Promise>
loadTable(key: MaskPresetKey)
@paramkeyMaskPresetKey
provideEagerMaskPresets#EnvironmentProviders
provideEagerMaskPresets(...keys: undefined)

Eagerly loads the lazily code-split mask preset tables at application start, instead of on first use. Reach for it when the on-demand import() is a problem - chiefly offline / PWA apps that must have every mask pattern cached before connectivity drops, or to avoid the one-frame generic-fallback mask on first focus.

Pass specific keys to warm only the tables you ship; omit them to load all four. For strict offline-first apps, also list the emitted mask-presets-* chunks in your service-worker precache so the eager fetch is cached.

bootstrapApplication(App, {
  providers: [provideEagerMaskPresets()],            // all tables
});
// or: provideEagerMaskPresets('phone', 'date')      // only these
@paramkeys

projects/utils/version.ts

makeVersion#Version
makeVersion(full: string)

Creates a parsed Version from a semver string.

@paramfullstring

core/utils/keyboard.util.ts

matchesKeyCombo#boolean
matchesKeyCombo(event: KeyboardEvent, combo: KeyCombo, isMac: boolean)

Tests whether a KeyboardEvent matches a parsed KeyCombo.

@parameventKeyboardEvent

The keyboard event to test.

@paramcomboKeyCombo

The parsed combo to match against.

@paramisMacboolean

Whether the current platform is macOS (affects mod resolution).

parseKeyCombo#KeyCombo
parseKeyCombo(combo: string)

Parses a keyboard shortcut string like 'ctrl+shift+k' or 'mod+b' into a structured KeyCombo.

The mod modifier resolves to meta on macOS and ctrl elsewhere. Modifier names are case-insensitive.

const combo = parseKeyCombo('mod+b');
// { key: 'b', ctrl: false, meta: false, mod: true, shift: false, alt: false }
@paramcombostring

core/utils/memo.util.ts

memoize#V
memoize(fn)

Creates a memoized version of a single-argument pure function. Each call to memoize() produces an independent cache.

const expensive = memoize((id: string) => computeHeavy(id)); expensive('a'); // computes expensive('a'); // cached

@paramfn

core/utils/uid.util.ts

nextUid#string
nextUid(prefix: string)

Generates a unique ID string with the given prefix.

Each call returns a monotonically increasing ID: prefix-0, prefix-1, etc. Used internally for ARIA id attributes on dialogs, popovers, and tooltips.

@paramprefixstring

interactive/optimistic/optimistic.ts

optimistic#unknown
optimistic(current: WritableSignal, action)

Creates an optimistic update function for a signal.

Sets the new value immediately (optimistic), then confirms via the async action. On success, applies the server-confirmed value. On failure, rolls back to the previous value.

This is a utility function, not a directive — it composes with any signal.

readonly name = signal('Alice');
readonly [updateName, nameState] = optimistic(
  this.name,
  (value) => this.http.put('/api/name', { name: value })
);

// In template:
<input [value]="name()" (change)="updateName($event.target.value)" />
<ng-container [cngxToastOn]="nameState.state" toastError="Update failed" />
@paramcurrentWritableSignal
  • The writable signal to update optimistically.
@paramaction
  • Async action that confirms the value. Should return the confirmed value.

Tuple of [applyFn, state].

paginator/segments/page-model.ts

pageWindow#PageWindow
pageWindow(current: number, total: number, siblingCount: number, boundaryCount: number)

Compute the windowed page sequence around current for total pages.
A run of more than one hidden page collapses into a gap carrying the hidden 0-based indices (the ellipsis menu's options); a single hidden page renders as a plain page button instead of a gap.

Derived from the MUI usePagination range algorithm, 0-based. siblingCount is how many pages flank current on each side; boundaryCount is how many pages are pinned at each end. Both default to 1, reproducing the v1 window byte-for-byte; the cngx-pgn-pages inputs and CNGX_PAGINATOR_PAGE_WINDOW_FACTORY feed non-default values.

@paramcurrentnumber
@paramtotalnumber
@paramsiblingCountnumber= 1
@paramboundaryCountnumber= 1
pageWindowEqual#boolean
pageWindowEqual(a: PageWindow, b: PageWindow)

Structural equality for two page windows. The equal fn for the segment's computed() - keeps the reference stable across recomputes that yield an identical window, so downstream @for does not churn.

@paramaPageWindow
@parambPageWindow
range#number[]
range(start: number, end: number)
@paramstartnumber
@paramendnumber

audio/event-mode/parse-bindings.ts

parseEventBindings#ParsedEventBindings
parseEventBindings(spec: string)

Parse the event:earcon grammar ('click:tap, focus:notification') into a DOM-event map. Pure — no DOM, no inject(). Keys are categorised so the directive can dev-warn on unknown earcon keys and, separately, on lifecycle keys that should have used [cngxAudioStatus].

@paramspecstring

audio/status-mode/parse-status-bindings.ts

parseStatusBindings#ParsedStatusBindings
parseStatusBindings(spec: string)

Parse the status:earcon grammar ('pending:tap, succeeded:success') into a status map. Pure — no DOM, no inject(). Keys are categorised so the directive can dev-error on DOM-event keys that should have used [cngxAudio] and dev-warn on unknown keys. succeeded/failed normalise to success/error so a lookup by the tracker's raw AsyncStatus hits.

@paramspecstring

common/tabs/provide-cngx-tabs.ts

provideCngxTabs Providerv0.1.0
provideCngxTabsAt Providerv0.1.0
partitionFeatures#PartitionedFeatures
partitionFeatures(features)
@paramfeatures
provideCngxTabs#EnvironmentProviders
provideCngxTabs(...features: undefined)

Unified aggregator for tabs configuration.
Routes features by _target to provideTabsConfig and provideTabsI18n.
Sibling to

  • provideCngxMenu and
  • provideCngxSelect; apply once in the app providers array.
    Returns EnvironmentProviders; for
  • viewProviders use provideCngxTabsAt — opaque
  • EnvironmentProviders cannot live there.
bootstrapApplication(AppComponent, {
  providers: [
    provideCngxTabs(
      withTabsDefaultOrientation('vertical'),
      withTabsAriaLabels({ tabsRegion: 'Bereiche' }),
      withTabsI18nLabels({ tabsLabel: 'Bereiche', moreTabsLabel: (n) => `${n} mehr` }),
      withTabOverflowStabilizeMs(150),
    ),
  ],
});
@paramfeatures
provideCngxTabsAt#Provider[]
provideCngxTabsAt(...features: undefined)

Component-scoped twin of provideCngxTabs.
Returns Provider[] for viewProviders/providers; same dispatch semantics, different scope.

@paramfeatures

forms/validators/pattern-match.validator.ts

patternMatch#ValidatorFn
patternMatch(pattern: RegExp)

Validates that the string control value matches the given regular expression. Returns null when valid, { patternMatch: { pattern, actual } } otherwise.

Returns null (valid) when the control value is empty or falsy — pair with Validators.required when an empty value is not acceptable.

@parampatternRegExp

accordion/config/provide-accordion-config.ts

provideAccordionConfig Providerv0.1.0
provideAccordionConfigAt Providerv0.1.0
provideAccordionConfig#EnvironmentProviders
provideAccordionConfig(...features: undefined)

Application-root configuration cascade for the accordion. Pass any combination of withAccordionLabels / withDefaultHeadingLevel features in bootstrapApplication's providers array.

Resolution priority (high -> low):

  1. Per-instance Input binding.
  2. provideAccordionConfigAt(...) in a parent component's viewProviders.
  3. provideAccordionConfig(...) at the application root.
  4. Library defaults (CNGX_ACCORDION_DEFAULTS).

The provider merges supplied features with the library defaults so consumers only declare keys they want to override.

bootstrapApplication(AppComponent, {
  providers: [
    provideAccordionConfig(
      withAccordionLabels({ disabledReason: 'Dieser Abschnitt ist gesperrt.' }),
      withDefaultHeadingLevel(2),
      withAccordionSkin('categorized'),
    ),
  ],
});
@paramfeatures
provideAccordionConfigAt#Provider[]
provideAccordionConfigAt(...features: undefined)

Component-scoped configuration cascade for the accordion. Pass any combination of feature factories in a parent component's viewProviders array.

Unlike provideAccordionConfig (root-only), provideAccordionConfigAt injects the parent injector's CNGX_ACCORDION_CONFIG value (resolves through the priority chain - root provider, library defaults, or another provideAccordionConfigAt further up) and merges the supplied features on top. Descendant accordion instances see the merged config; sibling sub-trees keep the inherited value untouched.

@paramfeatures

data/async-registry/http-interceptor.ts

provideAsyncHttpObservability Provider
provideAsyncHttpObservability#EnvironmentProviders

Sets up HttpClient with cngxAsyncInterceptor so every request surfaces in CngxAsyncRegistry. Opt-in - add it to bootstrapApplication providers alongside provideAsyncRegistry().

bootstrapApplication(AppComponent, {
  providers: [
    provideAsyncRegistry(),
    provideAsyncHttpObservability(),
  ],
});

Use this only when cngx owns the HttpClient setup. It calls provideHttpClient(withInterceptors([cngxAsyncInterceptor])) internally, so an app that already calls provideHttpClient (especially with withFetch() or other features) would get a second, feature-less HttpClient configuration - last-provider-wins on HttpBackend can silently revert withFetch() to the XHR backend. In that case do not call this; add the exported cngxAsyncInterceptor to your own withInterceptors instead:

provideHttpClient(withFetch(), withInterceptors([authInterceptor, cngxAsyncInterceptor]))

breadcrumb/config/provide-breadcrumb-config.ts

provideBreadcrumbConfig Providerv0.1.0
provideBreadcrumbConfigAt Providerv0.1.0
provideBreadcrumbConfig#EnvironmentProviders
provideBreadcrumbConfig(...features: undefined)

Application-root configuration cascade for the breadcrumb family. Pass any combination of withBreadcrumbAriaLabels, withBreadcrumbDataKey, withBreadcrumbIconKey, and withBreadcrumbSkin features in bootstrapApplication's providers array.

Resolution priority (high -> low):

  1. Per-instance Input binding.
  2. provideBreadcrumbConfigAt(...) in a parent component's viewProviders.
  3. provideBreadcrumbConfig(...) at the application root.
  4. Library defaults (CNGX_BREADCRUMB_DEFAULTS).

The provider deep-merges supplied features with the library defaults so consumers only declare keys they want to override.

bootstrapApplication(AppComponent, {
  providers: [
    provideBreadcrumbConfig(
      withBreadcrumbAriaLabels({ bar: 'Navigation trail' }),
      withBreadcrumbDataKey('crumb'),
    ),
  ],
});
@paramfeatures
provideBreadcrumbConfigAt#Provider[]
provideBreadcrumbConfigAt(...features: undefined)

Component-scoped configuration cascade for the breadcrumb family. Pass any combination of feature factories in a parent component's viewProviders array.

Unlike provideBreadcrumbConfig (root-only), provideBreadcrumbConfigAt injects the parent injector's CNGX_BREADCRUMB_CONFIG value (resolves through the priority chain - root provider, library defaults, or another provideBreadcrumbConfigAt further up) and deep-merges the supplied features on top. Descendant breadcrumb instances see the merged config; sibling sub-trees keep the inherited value untouched.

@paramfeatures

chart/i18n/chart-i18n.ts

provideChartI18n Provider
provideChartI18n#literal type
provideChartI18n(i18n: CngxChartI18n)

Provider helper for custom chart i18n strings.

providers: [provideChartI18n({
  summary: ({ trend, min, max, current, thresholds }) =>
    `${trend === 'up' ? 'Aufwärtstrend' : 'Abwärtstrend'}. Min ${min}, Max ${max}, aktuell ${current}.`,
  dataTable: () => 'Datentabelle',
  // ...remaining keys
})]
@parami18nCngxChartI18n

interactive/menu/provide-cngx-menu.ts

provideCngxMenu Provider
provideCngxMenu#EnvironmentProviders
provideCngxMenu(...features: undefined)

Unified aggregator for the menu family's configuration. Filters features by _target and forwards to the matching provide*Config function.

Today there is exactly one config surface (CNGX_MENU_CONFIG), so all features dispatch to provideMenuConfig. The discriminator scaffolding is in place so adding a future surface does not break the public API of existing with* features.

Mirrors provideCngxSelect from the select-family A+ closure.

bootstrapApplication(AppComponent, {
  providers: [
    provideCngxMenu(
      withAriaLabels({ submenuOpened: 'Untermenü geöffnet' }),
      withTypeaheadDebounce(500),
    ),
  ],
});
@paramfeatures

common/stepper/provide-cngx-stepper.ts

provideCngxStepper Provider
provideCngxStepperAt Provider
provideCngxStepper#EnvironmentProviders
provideCngxStepper(...features: undefined)

Unified aggregator for the stepper family. Filters by _target and forwards: config features to provideStepperConfig, i18n features to provideStepperI18n. Mirrors provideCngxTabs / provideCngxSelect.

Returns EnvironmentProviders for app-root use; the component-scoped twin provideCngxStepperAt returns Provider[] because viewProviders cannot accept opaque EnvironmentProviders.

bootstrapApplication(AppComponent, {
  providers: [
    provideCngxStepper(
      withStepperDefaultOrientation('vertical'),
      withStepperLinear(true),
      withStepperAriaLabels({ stepperRegion: 'Schrittfolge' }),
      withStepperI18nLabels({ stepperLabel: 'Schrittfolge', previousStep: 'Vorheriger' }),
    ),
  ],
});
@paramfeatures
provideCngxStepperAt#Provider[]
provideCngxStepperAt(...features: undefined)

Component-scoped twin of provideCngxStepper. Spread into viewProviders or providers. Same dispatch semantics - only the provider scope differs.

@paramfeatures

data-grid-accordion/config/provide-data-grid-accordion-config.ts

provideDataGridAccordionConfig Providerv0.1.0
provideDataGridAccordionConfigAt Providerv0.1.0
provideDataGridAccordionConfig#EnvironmentProviders
provideDataGridAccordionConfig(...features: undefined)

Application-root configuration cascade for the data-grid-accordion. Pass a withDataGridSkin feature in bootstrapApplication's providers array to move the app-wide default skin.

Resolution priority (high -> low):

  1. Per-instance [skin] Input binding.
  2. provideDataGridAccordionConfigAt(...) in a parent component's viewProviders.
  3. provideDataGridAccordionConfig(...) at the application root.
  4. Library defaults (CNGX_DATA_GRID_ACCORDION_DEFAULTS).
bootstrapApplication(AppComponent, {
  providers: [provideDataGridAccordionConfig(withDataGridSkin('ledger'))],
});
@paramfeatures
provideDataGridAccordionConfigAt#Provider[]
provideDataGridAccordionConfigAt(...features: undefined)

Component-scoped configuration cascade for the data-grid-accordion. Pass a withDataGridSkin feature in a parent component's viewProviders array.

Unlike provideDataGridAccordionConfig (root-only), provideDataGridAccordionConfigAt injects the parent injector's CNGX_DATA_GRID_ACCORDION_CONFIG value (resolves through the priority chain) and merges the supplied features on top. Descendant grid instances see the merged config; sibling sub-trees keep the inherited value untouched.

@paramfeatures

dialog/dialog/dialog.service.ts

provideDialog Provider
provideDialog#Provider[]

Provide CngxDialogOpener for programmatic dialog opening.

Must be called in the application's providers array or a route's providers for CngxDialogOpener to be injectable.

bootstrapApplication(AppComponent, {
  providers: [provideDialog()],
});

dialog/dialog/dialog-stack.ts

provideDialogStack Provider
provideDialogStack#Provider

Provide a scoped CngxDialogStack instance for nested dialog backdrop management.

By default, CngxDialogStack is providedIn: 'root', so all dialogs share one stack. Call provideDialogStack() in a component's providers array to create an isolated stack scope (e.g., for a sub-application or dialog group).

core/tokens/environment.token.ts

provideEnvironment Provider
provideEnvironment#Provider
provideEnvironment(env: Environment)

Provides an Environment value for the ENVIRONMENT token.

@paramenvEnvironment

forms/field/form-field.token.ts

provideErrorMessages Provider
provideFormField Provider
withAutocompleteMappings Feature
withConstraintHints Feature
withErrorMessages Feature
withErrorStrategy Feature
withNoSpellcheck Feature
withRequiredMarker Feature
provideErrorMessages#EnvironmentProviders
provideErrorMessages(messages: ErrorMessageMap)

Binds only the validation message map, for apps that need no other form-field config. Equivalent to provideFormField(withErrorMessages(messages)), but provides CNGX_ERROR_MESSAGES directly without the config wrapper.

Returns EnvironmentProviders - same placement as provideFormField: an environment injector (app bootstrap or a route's providers), never a component.

providers: [provideErrorMessages({ required: () => 'Required.' })]
@parammessagesErrorMessageMap
provideFormField#EnvironmentProviders
provideFormField(...features: undefined)

Registers application-wide defaults for every CngxFormField in scope. Each with* feature contributes one slice of FormFieldConfig; features apply left to right, so a later feature overrides an earlier one on the same key.

Returns EnvironmentProviders, so it sits at an environment injector - bootstrapApplication's providers, or a lazy route's providers. It cannot be placed on a component. Resolution is nearest-wins and replace, not merge: a route-level provideFormField shadows the root one for that subtree rather than deep-merging into it.

bootstrapApplication(AppComponent, {
  providers: [
    provideFormField(
      withErrorMessages({ required: () => 'Required.' }),
      withConstraintHints(),
    ),
  ],
});
@paramfeatures
withAutocompleteMappings#FormFieldFeature
withAutocompleteMappings(mappings: Record)

Override or extend the autocomplete mappings for CngxInput.

@parammappingsRecord

Additional or replacement field-name-to-autocomplete entries. Merged with built-in defaults. Pass a key with value '' to remove a mapping.

provideFormField(withAutocompleteMappings({
iban: 'cc-number',
taxid: 'off',
}))
withConstraintHints#FormFieldFeature
withConstraintHints(formatters?: Partial)

Enable auto-generated constraint hints for all form fields. Pass true for English defaults, or a ConstraintHintFormatters object for i18n.

English defaults

provideFormField(withConstraintHints())

German

provideFormField(withConstraintHints({
  lengthRange: (min, max) => `${min}–${max} Zeichen`,
  minLength: (min) => `Mind. ${min} Zeichen`,
  maxLength: (max) => `Max. ${max} Zeichen`,
  valueRange: (min, max) => `${min}–${max}`,
  minValue: (min) => `Mind. ${min}`,
  maxValue: (max) => `Max. ${max}`,
}))
@paramformatters?Partial
withErrorMessages#FormFieldFeature
withErrorMessages(messages: ErrorMessageMap)

Register the application-wide validation error message map. Each entry maps an error kind to a function that renders its display string; CngxFieldErrors and CngxFormErrors resolve messages against it.

Merges into any messages already on the config, so later features add to or override earlier ones by kind.

provideFormField(withErrorMessages({
  required: () => 'Required.',
  minLength: (e) => `Min ${(e as { minLength: number }).minLength} chars.`,
}))
@parammessagesErrorMessageMap
withErrorStrategy#FormFieldFeature
withErrorStrategy(strategy)

Configures the error visibility strategy used by CngxFormFieldPresenter.showError.

Pass a built-in name ('onTouched', 'onDirty', 'onSubmit', 'onTouchedOrSubmit', 'always') or a custom ErrorStrategyFn. The strategy fully overrides the default gate (touched OR errorScope.showErrors).

built-in

provideFormField(withErrorStrategy('onSubmit'))

custom

provideFormField(withErrorStrategy(
  (c) => c.invalid && (c.dirty || c.submitted),
))
@paramstrategy
withNoSpellcheck#FormFieldFeature
withNoSpellcheck(fields)

Override or extend the set of field names where spellcheck="false" is auto-applied.

@paramfields

Additional field names to disable spellcheck for.

provideFormField(withNoSpellcheck(['iban', 'accountnumber', 'serialnumber']))
withRequiredMarker#FormFieldFeature
withRequiredMarker(marker: string)

Auto-render a required marker (e.g. *) inside every CngxLabel for required fields. Individual labels can opt out via [showRequired]="false".

@parammarkerstring= '*'

The marker text. Defaults to '*'.

provideFormField(withRequiredMarker())       // shows '*'
provideFormField(withRequiredMarker('(required)'))

feedback/config/feedback-config.ts

provideFeedback Provider
withAlertIcons Feature
withAlerts Feature
withBanners Feature
withCloseIcon Feature
withLoadingDefaults Feature
withSpinnerTemplate Feature
withToasts Feature
provideFeedback#EnvironmentProviders
provideFeedback(...features: undefined)

Register global defaults for all feedback components.

bootstrapApplication(AppComponent, {
  providers: [
    provideFeedback(
      withSpinnerTemplate(MyLucideSpinner),
      withAlertIcons({ error: MyErrorIcon, warning: MyWarningIcon }),
      withLoadingDefaults({ delay: 300, minDuration: 600 }),
    ),
  ],
});
@paramfeatures
withAlertIcons#FeedbackFeature
withAlertIcons(icons: Partial)

Replace the built-in SVG icons in CngxAlert per severity.

Each component receives no inputs - it should render a single icon. Only specified severities are replaced; others keep the built-in SVG.

provideFeedback(withAlertIcons({
  error: MyErrorIcon,
  warning: MyWarningIcon,
  success: MyCheckIcon,
  info: MyInfoIcon,
}))
@paramiconsPartial
withAlerts(opts?)

Enable the scoped alert system within provideFeedback().

Provides CngxAlerter at the environment level for root-level injection. Without this feature, CngxAlerter is only available via CngxAlertStack's viewProviders (scoped injection).

The token is opaque - always use provideFeedback() with feature functions, never construct the config object manually.

@paramopts?

Optional alert defaults.

provideFeedback(
withToasts(),
withAlerts(),
)
withBanners#FeedbackFeature

Enable the global banner system within provideFeedback().

Provides CngxBanner at the environment level. Without this feature, CngxBannerOutlet will throw a NullInjectorError.

Banners are always persistent - no duration. Dismiss programmatically via banner.dismiss(id) when the condition resolves.

provideFeedback(
  withToasts(),
  withAlerts(),
  withBanners(),
)
withCloseIcon#FeedbackFeature
withCloseIcon(component: Type)

Replace the built-in X SVG in all close/dismiss buttons globally.

The component receives no inputs - it should render a single icon. Per-instance override via content projection on CngxCloseButton takes precedence.

provideFeedback(withCloseIcon(MyLucideXIcon))
@paramcomponentType
withLoadingDefaults#FeedbackFeature
withLoadingDefaults(opts)

Set default timing for all loading indicators and overlays.

Individual components can still override via their [delay] and [minDuration] inputs.

provideFeedback(withLoadingDefaults({ delay: 300, minDuration: 600 }))
@paramopts
withSpinnerTemplate#FeedbackFeature
withSpinnerTemplate(component: Type)

Replace the built-in SVG spinner in CngxLoadingIndicator and CngxLoadingOverlay.

The component receives no inputs - it should be a self-contained spinner (e.g. a Lucide <loader-2> with CSS animation, or a Material <mat-spinner>).

provideFeedback(withSpinnerTemplate(MatProgressSpinner))
@paramcomponentType
withToasts(opts?)

Enable the toast system within provideFeedback().

Provides CngxToaster at the environment level. Without this feature, CngxToastOn and CngxToastOutlet will throw a NullInjectorError at runtime.

@paramopts?

Optional toast defaults.

provideFeedback(
withToasts(),
withAlertIcons({ error: MyErrorIcon }),
)

common/popover/floating-fallback.ts

provideFloatingFallback Provider
provideFloatingFallback#Provider
provideFloatingFallback(computePosition: ComputePositionFn, middleware?)

Provides the Floating UI positioning fallback for browsers without CSS Anchor Positioning support.

The consumer must install @floating-ui/dom themselves - this library never imports it directly, keeping the bundle at zero cost for modern browsers.

import { computePosition, flip, offset, shift } from '@floating-ui/dom';

// In app.config.ts or component providers:
providers: [
  provideFloatingFallback(computePosition, [offset(8), flip(), shift()]),
]
@paramcomputePositionComputePositionFn
@parammiddleware?

forms/input/input-config.ts

provideInputConfig Provider
withCopyResetDelay Feature
withCustomTokens Feature
withDateFormats Feature
withFileMaxFiles Feature
withFileMaxSize Feature
withIbanPatterns Feature
withInputAriaLabels Feature
withMaskGuide Feature
withMaskPlaceholder Feature
withNumericDefaults Feature
withPhoneDefaultRegion Feature
withPhonePatterns Feature
withZipPatterns Feature
provideInputConfig#Provider
provideInputConfig(...features: undefined)

Provides global configuration for @cngx/forms/input directives.

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideInputConfig(
      withPhonePatterns({ LI: '+000 000 00 00' }),
      withMaskPlaceholder('·'),
      withNumericDefaults({ decimals: 2, locale: 'de-CH' }),
      withCopyResetDelay(3000),
    ),
  ],
};

Returns a plain Provider, so it works app-wide in ApplicationConfig.providers or scoped to a subtree via a component's viewProviders. The nearest provideInputConfig wins for a subtree by token resolution - it replaces an ancestor config, it does not deep-merge.

Compose with the feature functions:

@paramfeatures
withCopyResetDelay#InputConfigFeature
withCopyResetDelay(ms: number)

Sets the global delay in milliseconds before CngxCopyValue reverts its copied state - the window where the button reads as copied before snapping back to idle. Library default is 2000.

  • A per-input binding overrides it.
  • Maps to the copyResetDelay config key.
provideInputConfig(withCopyResetDelay(3000));
@parammsnumber
withCustomTokens#InputConfigFeature
withCustomTokens(tokens: MaskTokenMap)

Registers mask tokens globally, beyond the built-in 0 9 A a *.

  • Each token maps one mask character to a pattern regex, an optional flag, and an optional per-char transform.
  • Use it when a pattern needs a character class the built-ins lack (hex digit, restricted letter set) across the app rather than per input.
  • Merged as { ...config.customTokens, ...input.customTokens }, so a per-input [customTokens] entry overrides the global one of the same key.
provideInputConfig(withCustomTokens({
  H: { pattern: /[0-9a-fA-F]/, transform: (c) => c.toUpperCase() },
}));
// <input cngxInputMask="#HHHHHH" />
@paramtokensMaskTokenMap
withDateFormats#InputConfigFeature
withDateFormats(formats: Record)

Adds or overrides date mask patterns keyed by BCP-47 locale (e.g. de-CH).

  • Built-ins ship per-locale separators (de-* dots, fr-CH dots, sv-SE/lt-LT/ en-CA ISO, en-US/en-GB slashes, ...) for the date and datetime presets.
  • Resolution for date/datetime: exact locale (case-insensitive), then a bare language key (so a language-keyed override like { sv: '...' } still applies), then any same-language locale, then en-US.
  • Masks capture separators and group count only, NOT field order: en-US (MM/DD) and en-GB (DD/MM) share 00/00/0000.
  • Tokens: 0 = required digit, separators are literals.
  • Does not feed date:short - that uses a separate built-in table.
  • Consumer entries merge per key and win on collision.
provideInputConfig(withDateFormats({ 'en-NZ': '00/00/0000' }));
// LOCALE_ID 'en-NZ' + <input cngxInputMask="date" />
@paramformatsRecord
withFileMaxFiles#InputConfigFeature
withFileMaxFiles(count: number)

Set the default maxFiles for CngxFileDrop.

@paramcountnumber
withFileMaxSize#InputConfigFeature
withFileMaxSize(bytes: number)

Sets the global maximum accepted file size in bytes for CngxFileDrop.

  • No library default; unset means the directive enforces no size cap.
  • Value is raw bytes, not KB/MB.
  • A per-input binding overrides it.
  • Maps to the fileMaxSize config key.
provideInputConfig(withFileMaxSize(5 * 1024 * 1024)); // 5 MiB
@parambytesnumber
withIbanPatterns#InputConfigFeature
withIbanPatterns(patterns: Record)

Adds or overrides IBAN mask patterns keyed by country code.

  • Built-in: ~30 IBAN-using countries (Europe + parts of the Middle East), keyed by ISO 3166-1 alpha-2.
  • Patterns encode length and 4-char grouping with tokens (A = required letter, 0 = required digit).
  • Resolved against the lazily-loaded built-in table merged with config.ibanPatterns; an unknown region falls back to AA00 0000 0000 0000 0000 00.
  • Consumer entries merge per key and win on collision.
  • Region comes from iban:<REGION> or LOCALE_ID.
provideInputConfig(withIbanPatterns({ BE: 'AA00 0000 0000 0000' }));
// <input cngxInputMask="iban:BE" />
@parampatternsRecord
withInputAriaLabels#InputConfigFeature
withInputAriaLabels(labels: Partial)

Overrides the built-in ARIA label strings the input directives announce.

  • Unset keys fall back to DEFAULT_INPUT_ARIA_LABELS per key, so a partial override is safe.
  • Library defaults are English; German (or any locale) is consumer-supplied here. Mirrors the select family's withAriaLabels.
  • clear -> CngxInputClear button label.
  • copySuccess / copyError -> CngxCopyValue live-region announcements.
  • otpGroup / otpSlot(index, length) / otpComplete -> CngxOtpInput group, per-slot labels, and completion announcement.
  • capsLockOn -> CngxCapsLock assertive warning.
  • passwordStrength(label) -> CngxPasswordStrength polite announcement.
  • inputRejected -> CngxInputFilter assertive rejection.
  • sensitiveReveal / sensitiveHide -> CngxSensitiveValue reveal/hide announcements.
  • ratingValue(value, max) -> CngxRating polite committed-value announcement.
  • ratingItem(step, max) -> CngxRating per-star radio aria-label.
  • phoneCountry -> CngxPhoneInput country-picker aria-label.
provideInputConfig(
  withInputAriaLabels({ clear: 'Leeren', copySuccess: 'Kopiert' }),
);
@paramlabelsPartial
withMaskGuide#InputConfigFeature
withMaskGuide(guide: boolean)

Sets the global guide mode for CngxInputMask. Library default is true.

  • true: placeholder characters fill unfilled slots and the cursor snaps to the next empty slot on focus.
  • false: a bare mask showing only typed characters and their literals.
  • Resolution order: [guide] input, then config.maskGuide, then true.
provideInputConfig(withMaskGuide(false));
@paramguideboolean
withMaskPlaceholder#InputConfigFeature
withMaskPlaceholder(char: string)

Sets the global placeholder character CngxInputMask shows for unfilled slots in guide mode. Library default is '_'.

  • Resolution order: [placeholder] input, then config.maskPlaceholder, then '_'.
  • Sets the app-wide baseline for every masked input that does not bind its own [placeholder].
  • Also fills the aria-placeholder the mask exposes.
provideInputConfig(withMaskPlaceholder('·')); // middle dot
@paramcharstring
withNumericDefaults#InputConfigFeature
withNumericDefaults(defaults)

Sets app-wide defaults for CngxNumericInput.

  • locale overrides LOCALE_ID for numeric inputs only.
  • decimals and step set formatting (step default 1).
  • Each key applies only when supplied; a partial override leaves the rest at the directive's defaults.
  • Per-input bindings still win over these.
  • Maps to the numericLocale / numericDecimals / numericStep keys.
provideInputConfig(withNumericDefaults({ decimals: 2, locale: 'de-CH' }));
@paramdefaults
withPhoneDefaultRegion#InputConfigFeature
withPhoneDefaultRegion(region: string)

Sets the app-wide default selected region (ISO key, e.g. 'AT') for CngxPhoneInput, instead of the first country in the list.

  • The region must match a CngxPhoneInput country region; an unknown region is ignored (the first country stays selected).
  • A per-instance [country] binding overrides it.
provideInputConfig(withPhoneDefaultRegion('AT'));
@paramregionstring
withPhonePatterns#InputConfigFeature
withPhonePatterns(patterns: Record)

Adds or overrides phone mask patterns keyed by region code.
Reach for it when a cngxInputMask="phone" / "phone:<REGION>" needs a region the library does not ship, or to override one it does.

  • Built-in regions: ~45 ISO 3166-1 alpha-2 keys across Europe, the Americas, East Asia, and Oceania (UK kept as a back-compat alias of GB).
  • Regions whose landline and mobile national-number lengths differ ship |-separated landline+mobile alternates picked by length; uniform-length plans ship a single pattern. Masks are coarse approximations, not validators - reach for libphonenumber-js when you need real validation.
  • Consumer entries merge per key onto the built-ins and win on collision.
  • Resolved as { ...PHONE_PATTERNS, ...config.phonePatterns }[region], falling back to US when the region is absent.
  • Region comes from phone:<REGION> or LOCALE_ID.
  • Pattern tokens: 0 = required digit, literals pass through.
provideInputConfig(withPhonePatterns({ LI: '+000 000 00 00' }));
// <input cngxInputMask="phone:LI" />
@parampatternsRecord
withZipPatterns#InputConfigFeature
withZipPatterns(patterns: Record)

Adds or overrides postal-code mask patterns keyed by country code.

  • Built-in: ~50 countries keyed by ISO 3166-1 alpha-2 (GB, with UK kept as an alias). Countries with no postal-code system (HK, AE, ...) are intentionally absent.
  • A | in a pattern declares alternates picked by input length (the GB entry: A0A 0AA|AA0 0AA|...).
  • Resolved against the lazily-loaded built-in table merged with config.zipPatterns; an unknown region falls back to 00000.
  • Consumer entries merge per key and win on collision.
  • Region comes from zip:<REGION> or LOCALE_ID.
provideInputConfig(withZipPatterns({ NL: '0000 AA' }));
// <input cngxInputMask="zip:NL" />
@parampatternsRecord

ui/overlay/overlay.service.ts

provideOverlay Provider
provideOverlay#EnvironmentProviders

Provides CngxOverlay as an environment-scoped service.

common/popover/popover-panel.config.ts

providePopoverPanel Provider
withArrow Feature
withArrowTemplate Feature
withAutoDismiss Feature
withCloseButton Feature
withCloseOnSuccess Feature
withDefaultVariant Feature
providePopoverPanel#Provider
providePopoverPanel(...features: undefined)

Provides configuration for CngxPopoverPanel instances.

providers: [
  providePopoverPanel(
    withAutoDismiss({ info: 5000, success: 3000 }),
    withCloseOnSuccess(300),
  ),
]
@paramfeatures
withArrow(show: unknown)

Show the arrow on all panels by default.

@paramshowunknown= true
withArrowTemplate#PopoverPanelFeature
withArrowTemplate(tpl: TemplateRef)

Register an app-wide default template for the panel's arrow ornament. The template receives a CngxPopoverArrowContext with edge and offsetPx so the consumer's glyph can match the resolved placement.

Per-instance *cngxPopoverArrow still wins over this default; the library's rotated-diamond fallback only renders when neither tier is set.

providers: [
  providePopoverPanel(withArrowTemplate(brandArrowTpl)),
]
@paramtplTemplateRef
withAutoDismiss#PopoverPanelFeature
withAutoDismiss(timing: Record)

Auto-dismiss the panel after a timeout, per variant.

@paramtimingRecord
  • Map of variant name to dismiss duration in ms.
withAutoDismiss({ info: 5000, success: 3000 })
withCloseButton#PopoverPanelFeature
withCloseButton(show: unknown)

Show the close button on all panels by default.

@paramshowunknown= true
withCloseOnSuccess#PopoverPanelFeature
withCloseOnSuccess(delay: number)

Auto-close the panel after an async action in the footer succeeds.

@paramdelaynumber= 300
  • Delay in ms before closing. Defaults to 300.
withDefaultVariant#PopoverPanelFeature
withDefaultVariant(variant: string)

Set the default variant applied when no variant input is set.

@paramvariantstring

sidenav/config/provide-sidenav-config.ts

provideSidenavConfig Providerv0.1.0
provideSidenavConfigAt Providerv0.1.0
provideSidenavConfig#EnvironmentProviders
provideSidenavConfig(...features: undefined)

Application-root configuration cascade for the sidenav family. Pass any combination of withSidenavDimensions, withSidenavResponsive, withSidenavShortcut, withSidenavHoverDwell, and withSidenavRouterSync features in bootstrapApplication's providers array.

Resolution priority (high -> low):

  1. Per-instance Input binding.
  2. provideSidenavConfigAt(...) in a parent component's viewProviders.
  3. provideSidenavConfig(...) at the application root.
  4. Library defaults (CNGX_SIDENAV_DEFAULTS).

The provider deep-merges supplied features with the library defaults so consumers only declare keys they want to override.

bootstrapApplication(AppComponent, {
  providers: [
    provideSidenavConfig(
      withSidenavDimensions({ width: '320px' }),
      withSidenavShortcut('mod+b'),
    ),
  ],
});
@paramfeatures
provideSidenavConfigAt#Provider[]
provideSidenavConfigAt(...features: undefined)

Component-scoped configuration cascade for the sidenav family. Pass any combination of feature factories in a parent component's viewProviders array.

Unlike provideSidenavConfig (root-only), provideSidenavConfigAt injects the parent injector's CNGX_SIDENAV_CONFIG value (resolves through the priority chain - root provider, library defaults, or another provideSidenavConfigAt further up) and deep-merges the supplied features on top. Descendant sidenav instances see the merged config; sibling sub-trees keep the inherited value untouched.

@paramfeatures

tag/config/provide-tag-config.ts

provideTagConfig Provider
provideTagConfigAt Provider
provideTagConfig#EnvironmentProviders
provideTagConfig(...features: undefined)

Application-root configuration cascade for the tag family. Pass any combination of withTagDefaults / withTagGroupDefaults / withTagColors / withTagSlots features in bootstrapApplication's providers array.

Resolution priority (high → low):

  1. Per-instance Input binding.
  2. provideTagConfigAt(...) in a parent component's viewProviders.
  3. provideTagConfig(...) at the application root.
  4. Library defaults (CNGX_TAG_DEFAULTS).

The provider deep-merges supplied features with the library defaults so consumers only declare keys they want to override.

bootstrapApplication(AppComponent, {
  providers: [
    provideTagConfig(
      withTagDefaults({ variant: 'subtle' }),
      withTagColors({
        'my-brand': {
          bg: '#4f46e5',
          color: '#ffffff',
          border: 'transparent',
        },
      }),
    ),
  ],
});
@paramfeatures
provideTagConfigAt#Provider[]
provideTagConfigAt(...features: undefined)

Component-scoped configuration cascade for the tag family. Pass any combination of feature factories in a parent component's viewProviders array.

Unlike provideTagConfig (root-only), provideTagConfigAt injects the parent injector's CNGX_TAG_CONFIG value (resolves through the priority chain — root provider, library defaults, or another provideTagConfigAt further up) and deep-merges the supplied features on top. This produces cumulative cascade behaviour: descendant tag instances see the merged config, sibling sub-trees keep the inherited value untouched.

@paramfeatures

feedback/toast/toast.service.ts

provideToasts Provider

Standalone provider for the toast system - use when not using provideFeedback().

bootstrapApplication(AppComponent, {
  providers: [provideToasts()],
});

data-display/treetable/treetable.token.ts

provideTreetable Provider
withCapitaliseHeaders Feature
withHighlightOnHover Feature
provideTreetable#EnvironmentProviders
provideTreetable(...features: undefined)

Registers application-wide defaults for every CngxTreetable in the injection scope. Composes any number of TreetableFeature helpers via left-to-right reduction; later features can override earlier ones if you call the same withXxx() twice (rare).

Calling with no arguments is valid and produces an empty TreetableConfig - identical to not calling provideTreetable at all. Per-instance [options] input always wins over whatever lands here.

Application bootstrap:

bootstrapApplication(AppComponent, {
  providers: [
    provideTreetable(
      withHighlightOnHover(),       // turn hover-highlight on app-wide
      withCapitaliseHeaders(false), // keep raw header keys app-wide
    ),
  ],
});

Per-route scope (Angular 16+ provide* works inside Route.providers):

const routes: Routes = [{
  path: 'admin',
  providers: [provideTreetable(withHighlightOnHover())],
  children: adminChildren,
}];
@paramfeatures
withCapitaliseHeaders#TreetableFeature
withCapitaliseHeaders(enabled: unknown)

Feature: auto-capitalisation of column header labels.

The library default for capitaliseHeader is true, so headers already capitalise without this helper. Use withCapitaliseHeaders(false) to opt out and render the raw column-key strings (useful for snake_case domain keys you want to keep verbatim, or for fully custom *cngxHeader slot rendering).

@paramenabledunknown= true
  • Capitalise on/off. Default true.
withHighlightOnHover#TreetableFeature
withHighlightOnHover(enabled: unknown)

Feature: row highlight on mouse-hover.

The library default for highlightRowOnHover is false, so calling withHighlightOnHover() opts in across the app. Pass false explicitly to be loud about the off state (e.g. when overlaying on top of an earlier provideTreetable(withHighlightOnHover()) in a nested scope).

@paramenabledunknown= true
  • Hover-highlight on/off. Default true.

interactive/async-status/async-status.directive.ts

reflectAsyncDisplayStatus#CngxAsyncDisplayStatus
reflectAsyncDisplayStatus(state)

Single source for collapsing a CngxAsyncState into its display bucket. Owned by the CngxAsyncStatus reflector so every consumer (the reflector directive, CngxActionButton's [externalState] branch) maps an externally-owned state the same way - one reflection code path.

@paramstate

forms/validators/required-true.validator.ts

requiredTrue#ValidatorFn

Validates that the control value is strictly true.

Returns { requiredTrue: { actual } } for any value other than true. Intended for checkbox agreement fields.

data/async-state/resolve-view.ts

resolveAsyncView#AsyncView
resolveAsyncView(status: AsyncStatus, firstLoad: boolean, empty: boolean)

Pure function that resolves which view to show based on async state.

Encodes the state machine as a lookup table — no branching:

status firstLoad empty view
idle true * none
loading true * skeleton
refreshing true * skeleton
pending true * skeleton
error true * error
success * true empty
error false * content+error
(all other) * * content
@paramstatusAsyncStatus
@paramfirstLoadboolean
@paramemptyboolean

interactive/breadcrumb/breadcrumb-responsive.ts

resolveBreadcrumbTier v0.1.0
resolveBreadcrumbTier#number
resolveBreadcrumbTier(width: number, tiers)

Pure width->count resolver: returns the maxVisible of the tier with the highest minWidth that is still <= width. Order-independent - the tier list is normalised (sorted by descending minWidth) before matching, so a consumer may pass tiers in any order. When width sits below every tier's minWidth the narrowest tier's maxVisible is the floor; an empty tier list yields Number.POSITIVE_INFINITY (never collapse), leaving the trail intact.

No DOM, no Angular - the width source (a CngxResizeObserver) lives in the bar; this stays jsdom-testable and shared by the bar and the headless recipe.

@paramwidthnumber
@paramtiers

data-display/treetable/column-template.utils.ts

resolveCellTpl#TemplateRef | null
resolveCellTpl(col: string, tpls: Signal)

Resolves a custom cell template for the given column key, or returns null when no matching template is projected.

@paramcolstring
@paramtplsSignal
resolveHeaderTpl#TemplateRef | null
resolveHeaderTpl(col: string, tpls: Signal)

Resolves a custom header template for the given column key, or returns null when no matching template is projected.

@paramcolstring
@paramtplsSignal

data/recycler/scroll-observer.ts

resolveElement#HTMLElement | null
resolveElement(ref, doc: Document)
@paramref
@paramdocDocument

interactive/button-toggle/button-toggle.directive.ts

resolveParent#ParentResolution

common/stepper/status-label.ts

resolveStepperStatusLabel#string
resolveStepperStatusLabel(node: CngxStepNode, i18n: CngxStepperI18n, isActive: boolean)

Resolve the status-pill label for a step node against the resolved i18n bundle. Used by skins that surface a per-step status pill (e.g. stripe-status-rich). Pure factory - no injection context, no signal graph involvement.

Resolution order:

  1. success data-state -> statusLabels.done
  2. error data-state -> statusLabels.errored
  3. aria-current="step" -> statusLabels.inProgress
  4. otherwise -> statusLabels.upNext

Group nodes (non-step) return an empty string.

@paramnodeCngxStepNode
@parami18nCngxStepperI18n
@paramisActiveboolean

data/paginate/bucket-paginate.directive.ts

setEquals#boolean
setEquals(a: ReadonlySet, b: ReadonlySet)

Two ReadonlySets are equal when they hold the same members.

@paramaReadonlySet
@parambReadonlySet

data/async-state/operators.ts

tapAsyncProgress#MonoTypeOperatorFunction
tapAsyncProgress(state: Pick)

RxJS operator that extracts upload/download progress from an HttpEvent stream and reports it to a ManualAsyncState.

Filters progress events, calculates percentage, calls setProgress(). Non-progress events pass through unchanged.

Use with { observe: 'events', reportProgress: true } on HttpClient.

readonly upload = createManualState<UploadResult>();

handleUpload(file: File): void {
  this.http.post('/api/upload', file, {
    reportProgress: true,
    observe: 'events',
  }).pipe(
    tapAsyncProgress(this.upload),
    takeUntilDestroyed(this.destroyRef),
  ).subscribe();
}
@paramstatePick
tapAsyncState#MonoTypeOperatorFunction
tapAsyncState(state: AsyncStateSink, options?)

RxJS operator that wires an Observable's lifecycle to a ManualAsyncState.

On subscribe: sets loading (or refreshing if data was already loaded). On next: calls setSuccess(value). On error: calls setError(err) and re-throws (does not swallow).

The Observable passes through unchanged — tapAsyncState is a side-effect operator.

readonly residents = createManualState<Resident[]>();

load(): void {
  this.http.get<Resident[]>('/api/residents').pipe(
    tapAsyncState(this.residents),
    takeUntilDestroyed(this.destroyRef),
  ).subscribe();
}
@paramstateAsyncStateSink
@paramoptions?
tapHttpAsyncState#OperatorFunction
tapHttpAsyncState(state: AsyncStateSink, options?)

RxJS operator that combines tapAsyncState + tapAsyncProgress for HTTP event streams.

Pipe this onto an HttpClient call with { observe: 'events', reportProgress: true }. It will:

  1. Set loading on subscribe
  2. Report upload/download progress via setProgress()
  3. Extract the response body on HttpEventType.Response
  4. Call setSuccess(body) with the extracted body
  5. Call setError(err) on error

The output Observable emits the response body (not HttpEvents). Throws if the response body is null.

readonly upload = createManualState<UploadResult>();

handleUpload(file: File): void {
  this.http.post('/api/upload', file, {
    reportProgress: true,
    observe: 'events',
  }).pipe(
    tapHttpAsyncState(this.upload),
    takeUntilDestroyed(this.destroyRef),
  ).subscribe();
  // upload.status(), upload.progress(), upload.data() — all wired
}
@paramstateAsyncStateSink
@paramoptions?

display/stat/stat-slots.ts

useStatSlot#string
useStatSlot(kind: CngxStatSlotKind)

Generate a stable id, register it with the enclosing CngxStat (if any), and withdraw it on destroy. Shared by the four slot directives via plain composition - no base class, no inheritance (Pillar 3).

accordion/config/features.ts

withAccordionLabels Featurev0.1.0
withAccordionSkin Featurev0.1.0
withAccordionTemplates Featurev0.1.0
withDefaultHeadingLevel Featurev0.1.0
withAccordionLabels#CngxAccordionConfigFeature
withAccordionLabels(payload)

Override the accordion's locale-sensitive announced strings - disabledReason (spoken when an item is disabled) and errorMessage (spoken via role="alert" when an item's [state] is error and no error slot is given). Pass either or both. Per-instance [disabledReason] / [errorMessage] still win over the cascade; this only sets the fallback.

provideAccordionConfig(
  withAccordionLabels({
    disabledReason: 'This section is locked.',
    errorMessage: 'This section failed to load.',
  }),
);
@parampayload
withAccordionSkin(skin: CngxAccordionSkin)

Set the app-wide default visual skin for <cngx-accordion-group>. Unset by default (the base flat look). Per-instance [skin] Input still wins; this moves the cascade default. Structure, slots, ARIA, and keyboard behaviour are identical across skins - only the [data-skin] host attribute changes the CSS. Typed class-sugar, not a mode flag.

provideAccordionConfig(withAccordionSkin('categorized'));
withAccordionTemplates#CngxAccordionConfigFeature
withAccordionTemplates(payload: NonNullable)

Set app-wide slot templates - the config tier of the slot cascade (*cngxAccordionItemXxx per-instance -> this -> CSS default). Three slots carry a config tier: icon (chevron; $implicit is the item's expanded state), busySpinner (loading/refreshing visual), and error (error affordance). Hand a TemplateRef per key here and every item renders it unless a per-instance slot overrides it. Partial payloads compose - repeated calls merge per key.

provideAccordionConfig(
  withAccordionTemplates({ icon: myChevronTpl, busySpinner: mySpinnerTpl }),
);
@parampayloadNonNullable
withDefaultHeadingLevel#CngxAccordionConfigFeature
withDefaultHeadingLevel(headingLevel: number)

Override the default heading level (aria-level) a CngxAccordionGroup applies when [headingLevel] is not bound. Per-instance [headingLevel] still wins; the group clamps the resolved value into the ARIA 2-6 range.

provideAccordionConfig(withDefaultHeadingLevel(2));
@paramheadingLevelnumber

interactive/menu/menu-config-features.ts

withAriaLabels Feature
withCloseOnSelect Feature
withDismissOnBlur Feature
withDismissOnOutsideClick Feature
withDismissOnScroll Feature
withSubmenuCloseDelay Feature
withSubmenuOpenDelay Feature
withTypeaheadDebounce Feature
withAriaLabels(partial: Partial)

Override one or more ARIA strings (English defaults). Unset keys keep their default value, so consumers can supply only the locale strings they care about.

@parampartialPartial
withCloseOnSelect#CngxMenuConfigFeature
withCloseOnSelect(close: boolean)

Whether activating a leaf item closes the menu. Default: true (menu semantics — distinct from listbox/combobox which stay open).

@paramcloseboolean
withDismissOnBlur#CngxMenuConfigFeature
withDismissOnBlur(dismiss: boolean)

Whether the "context lost" bundle dismisses the menu. The bundle covers BOTH window blur (system notification, OS-native menu overlaying, tab switch) AND document pointercancel outside the popover and trigger host (palm rejection on touch, gesture cancelled by the browser). The two sources share one toggle because consumers who want one rarely want the other off; consumers needing one without the other replace the entire handler via CNGX_MENU_DISMISS_HANDLER_FACTORY. Set to false to keep both listeners off; lastDismissSource will then never report 'blur' or 'pointer-cancel'.

Default: true.

@paramdismissboolean
withDismissOnOutsideClick#CngxMenuConfigFeature
withDismissOnOutsideClick(dismiss: boolean)

Whether pointerdown outside the menu's popover and the trigger host dismisses the menu. Default: true. Pass false for ESC-only semantics (e.g. a tutorial overlay that wants to keep the menu open while the user clicks through other UI).

@paramdismissboolean
withDismissOnScroll#CngxMenuConfigFeature
withDismissOnScroll(dismiss: boolean)

Whether window scroll while the menu is open dismisses it. Default: false. Opt in when the menu should follow native context-menu behaviour and close as soon as the page scrolls. Scroll-dismiss listens to window only - the nearest scrollable ancestor is not traversed.

@paramdismissboolean
withSubmenuCloseDelay#CngxMenuConfigFeature
withSubmenuCloseDelay(ms: number)

Override the delay between leaving a submenu parent and closing the submenu (milliseconds). Default: 0. Reserved for hover-driven menubar implementations.

@parammsnumber
withSubmenuOpenDelay#CngxMenuConfigFeature
withSubmenuOpenDelay(ms: number)

Override the delay between hovering a submenu parent and opening the submenu (milliseconds). Default: 0 (open immediately on activation). Reserved for hover-driven menubar implementations.

@parammsnumber
withTypeaheadDebounce#CngxMenuConfigFeature
withTypeaheadDebounce(ms: number)

Override the typeahead debounce window (milliseconds) for menu navigation. Default: 300.

@parammsnumber

data/async-registry/http-context.ts

withAsyncLabel Feature
withAsyncSkip Feature
withAsyncLabel#HttpContext
withAsyncLabel(label: string, context: HttpContext)

Returns an HttpContext that labels the request for async observability. Pass an existing context to chain with other tokens.

this.http.get('/api/users', { context: withAsyncLabel('users') });
@paramlabelstring
@paramcontextHttpContext= new HttpContext()
withAsyncSkip#HttpContext
withAsyncSkip(context: HttpContext)

Returns an HttpContext that opts the request out of async observability. Pass an existing context to chain with other tokens.

this.http.get('/api/ping', { context: withAsyncSkip() });
@paramcontextHttpContext= new HttpContext()

breadcrumb/config/features.ts

withBreadcrumbAriaLabels Featurev0.1.0
withBreadcrumbDataKey Featurev0.1.0
withBreadcrumbIconKey Featurev0.1.0
withBreadcrumbSkin Featurev0.1.0
withBreadcrumbAriaLabels#CngxBreadcrumbConfigFeature
withBreadcrumbAriaLabels(payload: NonNullable)

Override the breadcrumb family's ARIA-string fallbacks - the bar landmark name and the overflow/siblings trigger + list labels. Per-instance [label] / [triggerLabel] / [menuLabel] bindings still win over the cascade; this only sets the fallback.

provideBreadcrumbConfig(
  withBreadcrumbAriaLabels({ bar: 'Navigation trail' }),
);
@parampayloadNonNullable
withBreadcrumbDataKey#CngxBreadcrumbConfigFeature
withBreadcrumbDataKey(dataKey: string)

Override the route-data key the breadcrumb router-sync directives (CngxBreadcrumbRouterSync, CngxBreadcrumbSiblingsRouterSync) read crumbs and siblings from. Per-instance [dataKey] still wins.

provideBreadcrumbConfig(withBreadcrumbDataKey('crumb'));
@paramdataKeystring
withBreadcrumbIconKey#CngxBreadcrumbConfigFeature
withBreadcrumbIconKey(iconKey: string)

Override the route-data key CngxBreadcrumbRouterSync reads the per-crumb opaque icon token from (default 'icon'). Per-instance [iconKey] still wins. Mirrors withBreadcrumbDataKey for cascade parity.

provideBreadcrumbConfig(withBreadcrumbIconKey('glyph'));
@paramiconKeystring
withBreadcrumbSkin(skin: CngxBreadcrumbSkin)

Select the app-wide default visual skin for CngxBreadcrumbBar. Per-instance [skin] still wins; this only moves the cascade default. Structure, slots, and ARIA are identical across skins - only the [data-skin] host attribute changes which @scope paint applies.

provideBreadcrumbConfig(withBreadcrumbSkin('pill'));

interop/signals/with-cngx-async-state.ts

withCngxAsyncState Feature
withCngxAsyncState#

@ngrx/signals store feature that grants a store a CngxAsyncState-shaped slice with zero hand-written status flags.

The element type is supplied up front and the key is inferred from the argument, so the two contributed members carry the literal key: withCngxAsyncState<User[]>()('users') adds usersState (the read-only CngxAsyncState<User[]> view) and usersSink (the writable ManualAsyncState<User[]>). Drive the status with the existing tapAsyncState operator - no new state machine, no manual isLoading boolean. Both members are the same underlying createManualState instance, exposed under a read type and a write type.

The <T>() / (key) split is deliberate: TypeScript cannot infer the literal key while T is given explicitly in one call, so a single-call form collapses the key to a string index signature. Currying keeps the key literal - and therefore the store members concretely named.

export const UsersStore = signalStore(
  withCngxAsyncState<User[]>()('users'),
  withMethods((store) => {
    const http = inject(HttpClient);
    return {
      load: () =>
        http.get<User[]>('/api/users').pipe(
          tapAsyncState(store.usersSink),
          takeUntilDestroyed(),
        ).subscribe(),
    };
  }),
);
// store.usersState.status(), store.usersState.data() - derived, no flags

forms/input/currency.feature.ts

withCurrency Feature
withCurrency(options: CurrencyOptions)

Configures CngxNumericInput to format its value with a currency's grouping and standard fraction digits (USD -> 2, JPY -> 0) - the currency code drives the number; the symbol is never baked into the editable value. Render the symbol with a CngxPrefix / CngxSuffix affix instead, so a screen reader hears the field label rather than "dollar sign" and the editable text stays a plain number (Pillar 3: configuration over a new organism).

provideInputConfig(withCurrency({ code: 'CHF', locale: 'de-CH' }));
<span class="row">
  <span cngxPrefix>CHF</span>
  <input cngxInput cngxNumericInput [field]="f.price" />
</span>
@paramoptionsCurrencyOptions

data-grid-accordion/config/features.ts

withDataGridSkin Featurev0.1.0
withDataGridSkin(skin: CngxDataGridSkin)

Set the app-wide default visual skin for <cngx-data-grid-accordion>. Unset by default (the base flat grid look). Per-instance [skin] Input still wins; this moves the cascade default. Structure, cells, ARIA, and keyboard behaviour are identical across skins - only the [data-skin] host attribute changes the CSS. Typed class-sugar, not a mode flag.

provideDataGridAccordionConfig(withDataGridSkin('ledger'));

interactive/retry/with-retry.ts

withRetry Feature
withRetry#unknown
withRetry(action: AsyncAction, config?: RetryConfig)

Wraps an AsyncAction with automatic retry logic.

Returns a tuple: [action, retryState] where action is a new AsyncAction that retries on failure, and retryState exposes attempt/retry signals and a state: CngxAsyncState for feedback system integration.

Composes naturally with CngxAsyncClick and CngxActionButton:

const [saveWithRetry, retryState] = withRetry(
  () => this.http.post('/api/save', data),
  { maxAttempts: 3, delay: 1000, backoff: 'exponential' }
);

// Use with CngxAsyncClick + toast
<button [cngxAsyncClick]="saveWithRetry">Save</button>
<ng-container [cngxToastOn]="retryState.state"
  toastSuccess="Saved" toastError="All retries failed" />
@paramactionAsyncAction
@paramconfig?RetryConfig

sidenav/config/features.ts

withSidenavDimensions Featurev0.1.0
withSidenavHoverDwell Featurev0.1.0
withSidenavResponsive Featurev0.1.0
withSidenavRouterSync Featurev0.1.0
withSidenavShortcut Featurev0.1.0
withSidenavDimensions#CngxSidenavConfigFeature
withSidenavDimensions(payload: NonNullable)

Override the sidenav family's panel dimensions - width, miniWidth, minWidth, and maxWidth. Per-instance [width] / [miniWidth] / [minWidth] / [maxWidth] bindings still win over the cascade; this only moves the defaults. Partial payloads deep-merge, so pass only the keys you want to change.

provideSidenavConfig(withSidenavDimensions({ width: '320px', miniWidth: '64px' }));
@parampayloadNonNullable
withSidenavHoverDwell#CngxSidenavConfigFeature
withSidenavHoverDwell(payload: NonNullable)

Set the app-wide default mini expand-on-hover dwell - enterDelay (ms before the rail expands) and leaveDelay (ms before it collapses). Flows into the composed CngxHoverIntent via CNGX_HOVER_INTENT_DEFAULTS. Per-instance [enterDelay] / [leaveDelay] still win; the shipped literals (120 / 0) apply when neither is set. Partial payloads deep-merge, so pass only the key you want to change.

provideSidenavConfig(withSidenavHoverDwell({ enterDelay: 200, leaveDelay: 150 }));
@parampayloadNonNullable
withSidenavResponsive#CngxSidenavConfigFeature
withSidenavResponsive(query: string)

Set the app-wide default CSS media-query string for responsive mode switching. When the query matches, the sidenav resolves to 'side'; otherwise it falls back to its mode. Per-instance [responsive] still wins.

provideSidenavConfig(withSidenavResponsive('(min-width: 1024px)'));
@paramquerystring
withSidenavRouterSync#CngxSidenavConfigFeature
withSidenavRouterSync(payload: NonNullable)

Set the app-wide default query-param key for [cngxSidenavRouterSync] - the param the sidenav's opened state deep-links to. Per-instance [param] still wins; the 'nav' literal applies when neither is set.

provideSidenavConfig(withSidenavRouterSync({ param: 'menu' }));
@parampayloadNonNullable
withSidenavShortcut#CngxSidenavConfigFeature
withSidenavShortcut(combo: string)

Set the app-wide default keyboard shortcut to toggle the sidenav (e.g. 'mod+b', which resolves to ctrl on Windows/Linux and meta on macOS). Per-instance [shortcut] still wins.

provideSidenavConfig(withSidenavShortcut('mod+b'));
@paramcombostring

tag/config/features.ts

withTagColors Feature
withTagDefaults Feature
withTagGroupDefaults Feature
withTagSlots Feature
withTagColors(payload: NonNullable)

Register consumer-defined colour entries. Each key adds a [data-color="<key>"] cascade entry resolved through --cngx-tag-bg/-color/-border custom properties at the consumer's own CSS layer.

The five predefined keys (neutral/success/warning/error/ info) ship in tag.css and are NOT part of this map; passing them here is a no-op against the predefined cascade. Consumer keys composed via data-color="my-brand" resolve through the registered entry.

provideTagConfig(
  withTagColors({
    'my-brand': {
      bg: '#4f46e5',
      color: '#ffffff',
      border: 'transparent',
    },
  }),
);
@parampayloadNonNullable
withTagDefaults#CngxTagConfigFeature
withTagDefaults(payload: NonNullable)

Override the default CngxTag input values (variant, color, size, truncate, maxWidth). Per-instance bindings still win over the cascade — this only sets the fallback per directive.

provideTagConfig(
  withTagDefaults({ variant: 'subtle', size: 'sm' }),
);
@parampayloadNonNullable
withTagGroupDefaults#CngxTagConfigFeature
withTagGroupDefaults(payload: NonNullable)

Override the default CngxTagGroup input values (gap, align, semanticList). Per-instance bindings still win.

provideTagConfig(
  withTagGroupDefaults({ gap: 'md', semanticList: true }),
);
@parampayloadNonNullable
withTagSlots(payload: NonNullable)

Register app-wide template overrides for the five Tag-family slots. Resolved in tier 2 of the slot cascade — instance directives still win, the host's <ng-template> default body is the floor.

Staging note. This factory ships ahead of a documented second consumer — the headless CngxTag + CngxTagGroup are the only current consumers. The staging is intentional and tracked in display-accepted-debt.md §2 (Material organism deferral): a future cngx-mat-tag / cngx-mat-tag-group wrapper inherits the cascade for free without forking. If §2 is rejected outright, withTagSlots re-evaluates as a sunsetting candidate at the same time. Per the cngx-review architecture lens, the surface is tracked rather than left silent.

@parampayloadNonNullable