@truenas/ui-components 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { Overlay, OverlayPositionBuilder, OverlayModule } from '@angular/cdk/overlay';
2
2
  import { TemplatePortal, ComponentPortal, PortalModule } from '@angular/cdk/portal';
3
3
  import * as i0 from '@angular/core';
4
- import { InjectionToken, inject, computed, isDevMode, effect, input, ViewEncapsulation, ChangeDetectionStrategy, Component, Injector, Renderer2, ElementRef, Directive, signal, isSignal, ViewContainerRef, output, viewChild, untracked, forwardRef, DestroyRef, NgZone, afterNextRender, model, Injectable, contentChildren, Pipe, HostListener, linkedSignal, contentChild, TemplateRef, viewChildren, ChangeDetectorRef, afterEveryRender, IterableDiffers, booleanAttribute, LOCALE_ID, ApplicationRef, EnvironmentInjector, createComponent, PLATFORM_ID } from '@angular/core';
4
+ import { InjectionToken, inject, computed, isSignal, isDevMode, effect, signal, input, ViewEncapsulation, ChangeDetectionStrategy, Component, Injector, Renderer2, ElementRef, Directive, ViewContainerRef, output, viewChild, untracked, forwardRef, DestroyRef, NgZone, afterNextRender, model, Injectable, contentChildren, Pipe, HostListener, linkedSignal, contentChild, TemplateRef, viewChildren, ChangeDetectorRef, afterEveryRender, IterableDiffers, booleanAttribute, LOCALE_ID, ApplicationRef, EnvironmentInjector, createComponent, PLATFORM_ID } from '@angular/core';
5
5
  import * as i1$3 from '@angular/forms';
6
6
  import { NgControl, NG_VALUE_ACCESSOR, FormsModule, Validators } from '@angular/forms';
7
7
  import { ComponentHarness, HarnessPredicate, parallel, TestKey } from '@angular/cdk/testing';
@@ -73,18 +73,20 @@ function tnAccessibleName(config) {
73
73
  // raises the warning rather than being treated as an answer.
74
74
  const hasLabelledby = computed(() => (config.ariaLabelledby() ?? '').trim() !== '', ...(ngDevMode ? [{ debugName: "hasLabelledby" }] : []));
75
75
  const named = computed(() => (config.ariaLabel() ?? '').trim() !== '' || hasLabelledby(), ...(ngDevMode ? [{ debugName: "named" }] : []));
76
+ const fallback = config.fallback;
77
+ const fallbackName = computed(() => (isSignal(fallback) ? fallback() : fallback), ...(ngDevMode ? [{ debugName: "fallbackName" }] : []));
76
78
  const resolved = computed(() => {
77
79
  const label = config.ariaLabel();
78
80
  if ((label ?? '').trim() !== '') {
79
81
  return label;
80
82
  }
81
- return hasLabelledby() ? null : config.fallback;
83
+ return hasLabelledby() ? null : fallbackName();
82
84
  }, ...(ngDevMode ? [{ debugName: "resolved" }] : []));
83
- if (isDevMode()) {
85
+ if (isDevMode() && !config.fallbackIsConfigured) {
84
86
  effect(() => {
85
87
  if (!named()) {
86
88
  console.warn(`[${config.selector}] No ariaLabel or ariaLabelledby was set, so it falls back to `
87
- + `"${config.fallback}". Assistive technology cannot say WHAT is ${config.activity} `
89
+ + `"${fallbackName()}". Assistive technology cannot say WHAT is ${config.activity} `
88
90
  + `— pass ariaLabel, or ariaLabelledby pointing at visible text.`
89
91
  + (config.hint ? ` ${config.hint}` : ''));
90
92
  }
@@ -96,17 +98,175 @@ function tnAccessibleName(config) {
96
98
  /**
97
99
  * The accessible name a spinner falls back to when the caller names neither
98
100
  * `ariaLabel` nor `ariaLabelledby` (#202). Same reasoning as
99
- * `TN_PROGRESS_BAR_DEFAULT_LABEL`, and the case is sharper here: the spinner
100
- * defaults to indeterminate mode, so its unnamed default rendering reached
101
- * assistive technology as a progressbar with neither a name nor a value.
101
+ * {@link TN_PROGRESS_BAR_DEFAULT_LABEL}, and the case is sharper here: the
102
+ * spinner defaults to indeterminate mode, so its unnamed default rendering
103
+ * reached assistive technology as a progressbar with neither a name nor a
104
+ * value.
102
105
  *
103
- * `branded-spinner.component.ts` in this folder already fell back this way —
106
+ * `branded-spinner.component.ts` already fell back this way —
104
107
  * `ariaLabel() || "Loading..."` inline — so a fallback is the shape this
105
108
  * library had already settled on; what it lacked was the warning. It has both
106
- * since #206, through the same `tnAccessibleName` this component uses, which is
109
+ * since #206, through the same `tnAccessibleName` that component uses, which is
107
110
  * why the two constants sit side by side and differ.
108
111
  */
109
112
  const TN_SPINNER_DEFAULT_LABEL = 'Loading';
113
+ /**
114
+ * The name `tn-branded-spinner` falls back to when the caller names neither
115
+ * `ariaLabel` nor `ariaLabelledby`. Same reasoning as
116
+ * {@link TN_SPINNER_DEFAULT_LABEL} and {@link TN_PROGRESS_BAR_DEFAULT_LABEL}.
117
+ *
118
+ * It differs from `TN_SPINNER_DEFAULT_LABEL` — `"Loading..."` against
119
+ * `"Loading"` — only because this is the string the component already rendered,
120
+ * inline in its host binding, before #206 gave it the shared resolver. Aligning
121
+ * the two would change what a screen reader announces for every unnamed branded
122
+ * spinner already in the wild, which is a louder change than the consistency
123
+ * fix it would be part of. Exported so specs assert against it by name rather
124
+ * than by a copied string literal.
125
+ */
126
+ const TN_BRANDED_SPINNER_DEFAULT_LABEL = 'Loading...';
127
+ /**
128
+ * The accessible name a bar falls back to when the caller names neither
129
+ * `ariaLabel` nor `ariaLabelledby` (#202).
130
+ *
131
+ * Deliberately generic, and deliberately not silent: the host carries
132
+ * `role="progressbar"` unconditionally, so without a fallback the default
133
+ * rendering is a progressbar assistive technology announces with no name at all
134
+ * — "progress bar, 40%", with nothing to say what is progressing. The
135
+ * alternative fix, withholding the role until there is a name for it, trades
136
+ * that for no announcement whatever, which is worse: a screen reader would not
137
+ * learn that anything is in progress, and on a determinate bar it would lose
138
+ * the value too.
139
+ *
140
+ * A generic name is still a poor one, so it is paired with the dev-mode warning
141
+ * `tnAccessibleName` raises. Exported so specs assert against it by name rather
142
+ * than by a copied string literal.
143
+ */
144
+ const TN_PROGRESS_BAR_DEFAULT_LABEL = 'Progress';
145
+ /**
146
+ * The accessible name `tn-particle-progress-bar` falls back to when the caller
147
+ * names neither `ariaLabel` nor `ariaLabelledby` (#209).
148
+ *
149
+ * The same string and the same reasoning as
150
+ * {@link TN_PROGRESS_BAR_DEFAULT_LABEL} next door, and deliberately a separate
151
+ * constant rather than an alias of it: `tnAccessibleName` takes a fallback PER
152
+ * COMPONENT because the least-bad generic name differs by what the component is
153
+ * ("Progress" for a bar, "Loading" for a spinner), and sharing the binding would
154
+ * make a future divergence in one a silent change to the other. Exported so
155
+ * specs assert against it by name rather than by a copied string literal.
156
+ */
157
+ const TN_PARTICLE_PROGRESS_BAR_DEFAULT_LABEL = 'Progress';
158
+ /**
159
+ * The accessible name a dialog falls back to when it renders no `title` and the
160
+ * caller named it through neither this component nor the `DialogConfig` (#219).
161
+ *
162
+ * `title` defaults to `''`, so the DEFAULT rendering of this component put an
163
+ * empty `<h2>` in the header and left the CDK container with no naming
164
+ * attribute at all — measured as `empty-heading` on the heading and
165
+ * `aria-dialog-name` on the dialog. A dialog with no name is announced as
166
+ * "dialog" and nothing else, which is the whole of what a screen-reader user is
167
+ * told about a surface that just took over the page and trapped their focus.
168
+ *
169
+ * "Dialog" is a poor name, and says almost exactly what the role already says.
170
+ * It is still better than the two alternatives: leaving the surface unnamed, or
171
+ * withholding `role="dialog"` until there is a name — the latter would move a
172
+ * listener into a focus trap with no announcement that anything had opened. So
173
+ * it is paired with the dev-mode warning `tnAccessibleName` raises, which is
174
+ * what keeps the fallback from becoming a quiet way to ship a nameless dialog.
175
+ *
176
+ * Exported so specs assert against it by name rather than by a copied literal.
177
+ */
178
+ const TN_DIALOG_SHELL_DEFAULT_LABEL = 'Dialog';
179
+ /**
180
+ * The accessible name an open panel falls back to when it has no `title` and the
181
+ * caller named neither `ariaLabel` nor `ariaLabelledby` (#214).
182
+ *
183
+ * `title` defaults to `''`, so the DEFAULT rendering of this component was a
184
+ * `role="dialog"` with `aria-labelledby` pointing at an empty `<h2>` — measured
185
+ * as an `aria-dialog-name` violation, alongside `empty-heading`. A dialog with no
186
+ * name is announced as "dialog" and nothing else, which is the whole of what a
187
+ * screen-reader user gets told about a surface that just covered the page.
188
+ *
189
+ * Withholding `role="dialog"` until there is a name would be the other way to
190
+ * clear the rule, and it is worse: the panel traps focus either way, so a
191
+ * listener would be moved into a region with no announcement that anything had
192
+ * opened. A generic name is still a poor one, so it is paired with the dev-mode
193
+ * warning `tnAccessibleName` raises.
194
+ *
195
+ * Exported so specs assert against it by name rather than by a copied literal.
196
+ */
197
+ const TN_SIDE_PANEL_DEFAULT_LABEL = 'Side panel';
198
+ /**
199
+ * The accessible name a drawer falls back to when the caller names neither
200
+ * `ariaLabel` nor `ariaLabelledby` (#214).
201
+ *
202
+ * `ariaLabel` defaults to `undefined`, so the DEFAULT rendering in `over` mode
203
+ * was a `role="dialog"` with `aria-modal="true"` and no name — measured as an
204
+ * `aria-dialog-name` violation. In `side` mode the same omission leaves a
205
+ * `role="navigation"` landmark unnamed, which axe does not report while there is
206
+ * only one of them on the page, and which stops telling them apart the moment
207
+ * there are two.
208
+ *
209
+ * One fallback for both modes rather than one per mode: the drawer is the same
210
+ * surface either way, the name answers the same question ("what is this?"), and
211
+ * a rule that changes with the mode is one more thing for a caller to be wrong
212
+ * about. A generic name is still a poor one, so it is paired with the dev-mode
213
+ * warning `tnAccessibleName` raises.
214
+ *
215
+ * Exported so specs assert against it by name rather than by a copied literal.
216
+ */
217
+ const TN_DRAWER_DEFAULT_LABEL = 'Drawer';
218
+ /** English defaults used when no {@link TN_FALLBACK_LABELS} provider is registered. */
219
+ const TN_DEFAULT_FALLBACK_LABELS = {
220
+ spinner: TN_SPINNER_DEFAULT_LABEL,
221
+ brandedSpinner: TN_BRANDED_SPINNER_DEFAULT_LABEL,
222
+ progressBar: TN_PROGRESS_BAR_DEFAULT_LABEL,
223
+ particleProgressBar: TN_PARTICLE_PROGRESS_BAR_DEFAULT_LABEL,
224
+ dialog: TN_DIALOG_SHELL_DEFAULT_LABEL,
225
+ sidePanel: TN_SIDE_PANEL_DEFAULT_LABEL,
226
+ drawer: TN_DRAWER_DEFAULT_LABEL,
227
+ };
228
+ /**
229
+ * What the token resolves to when nobody provided it — a COPY of
230
+ * {@link TN_DEFAULT_FALLBACK_LABELS} rather than that object itself, and the
231
+ * difference is the whole of how `configured` below is decided.
232
+ *
233
+ * Comparing against the exported constant would make a consumer who provides it
234
+ * deliberately — `{ provide: TN_FALLBACK_LABELS, useValue: TN_DEFAULT_FALLBACK_LABELS }`,
235
+ * which is what a test environment mirroring an app's providers writes — read as
236
+ * nobody having provided anything. Held privately, this object is reachable only
237
+ * by not providing one, so identity answers exactly the question being asked.
238
+ */
239
+ const builtInLabels = { ...TN_DEFAULT_FALLBACK_LABELS };
240
+ /**
241
+ * DI token for the app-wide fallback names above. Provide either a static
242
+ * object or a `Signal<TnFallbackLabels>` — the latter lets every component
243
+ * react to language changes when the consumer wires it up to an i18n service.
244
+ *
245
+ * An `ariaLabel` on a particular instance still wins over these, and is still
246
+ * what to reach for when a name can say what is loading or what is open.
247
+ */
248
+ const TN_FALLBACK_LABELS = new InjectionToken('TN_FALLBACK_LABELS', { providedIn: 'root', factory: () => builtInLabels });
249
+ /**
250
+ * Reads one component's fallback name out of {@link TN_FALLBACK_LABELS}.
251
+ *
252
+ * Not `injectTnLabels`, which normalizes the token to a Signal and drops the
253
+ * value it started from: telling a configured bundle from the built-in one is an
254
+ * identity check against `builtInLabels`, so this needs the raw injected value.
255
+ * A consumer who provides a bundle equal to the defaults — the exported constant
256
+ * included — still counts as configured, which is the right way round: they said
257
+ * so on purpose.
258
+ *
259
+ * **Must be called from an injection context.**
260
+ */
261
+ function injectTnFallbackName(key) {
262
+ const provided = inject(TN_FALLBACK_LABELS);
263
+ const labels = isSignal(provided) ? provided : signal(provided).asReadonly();
264
+ return {
265
+ label: computed(() => labels()[key]),
266
+ configured: provided !== builtInLabels,
267
+ };
268
+ }
269
+
110
270
  class TnSpinnerComponent {
111
271
  mode = input('indeterminate', ...(ngDevMode ? [{ debugName: "mode" }] : []));
112
272
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
@@ -114,6 +274,7 @@ class TnSpinnerComponent {
114
274
  strokeWidth = input(4, ...(ngDevMode ? [{ debugName: "strokeWidth" }] : []));
115
275
  ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
116
276
  ariaLabelledby = input(null, ...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : []));
277
+ fallbackName = injectTnFallbackName('spinner');
117
278
  /**
118
279
  * The name to render, or `null` to render no `aria-label` attribute — and the
119
280
  * dev-mode warning when the caller named neither input.
@@ -127,7 +288,8 @@ class TnSpinnerComponent {
127
288
  */
128
289
  resolvedAriaLabel = tnAccessibleName({
129
290
  selector: 'tn-spinner',
130
- fallback: TN_SPINNER_DEFAULT_LABEL,
291
+ fallback: this.fallbackName.label,
292
+ fallbackIsConfigured: this.fallbackName.configured,
131
293
  activity: 'loading',
132
294
  ariaLabel: this.ariaLabel,
133
295
  ariaLabelledby: this.ariaLabelledby
@@ -2126,26 +2288,6 @@ function tnScrollableRegion(region) {
2126
2288
  return reachable.asReadonly();
2127
2289
  }
2128
2290
 
2129
- /**
2130
- * The accessible name a drawer falls back to when the caller names neither
2131
- * `ariaLabel` nor `ariaLabelledby` (#214).
2132
- *
2133
- * `ariaLabel` defaults to `undefined`, so the DEFAULT rendering in `over` mode
2134
- * was a `role="dialog"` with `aria-modal="true"` and no name — measured as an
2135
- * `aria-dialog-name` violation. In `side` mode the same omission leaves a
2136
- * `role="navigation"` landmark unnamed, which axe does not report while there is
2137
- * only one of them on the page, and which stops telling them apart the moment
2138
- * there are two.
2139
- *
2140
- * One fallback for both modes rather than one per mode: the drawer is the same
2141
- * surface either way, the name answers the same question ("what is this?"), and
2142
- * a rule that changes with the mode is one more thing for a caller to be wrong
2143
- * about. A generic name is still a poor one, so it is paired with the dev-mode
2144
- * warning `tnAccessibleName` raises.
2145
- *
2146
- * Exported so specs assert against it by name rather than by a copied literal.
2147
- */
2148
- const TN_DRAWER_DEFAULT_LABEL = 'Drawer';
2149
2291
  /**
2150
2292
  * A drawer, which is two different things by `mode`: in `side` it is
2151
2293
  * persistent navigation beside the page's content, and in `over` it is a modal
@@ -2255,6 +2397,7 @@ class TnDrawerComponent {
2255
2397
  trapFocus = computed(() => this.mode() === 'over' && this.opened(), ...(ngDevMode ? [{ debugName: "trapFocus" }] : []));
2256
2398
  /** Role depends on mode: navigation for side, dialog for over */
2257
2399
  panelRole = computed(() => this.mode() === 'over' ? 'dialog' : 'navigation', ...(ngDevMode ? [{ debugName: "panelRole" }] : []));
2400
+ fallbackName = injectTnFallbackName('drawer');
2258
2401
  /**
2259
2402
  * The name to render as `aria-label`, or `null` to render none — and the
2260
2403
  * dev-mode warning when the caller named neither input.
@@ -2269,7 +2412,8 @@ class TnDrawerComponent {
2269
2412
  */
2270
2413
  resolvedAriaLabel = tnAccessibleName({
2271
2414
  selector: 'tn-drawer',
2272
- fallback: TN_DRAWER_DEFAULT_LABEL,
2415
+ fallback: this.fallbackName.label,
2416
+ fallbackIsConfigured: this.fallbackName.configured,
2273
2417
  activity: 'open',
2274
2418
  ariaLabel: computed(() => this.ariaLabel() ?? null),
2275
2419
  ariaLabelledby: this.ariaLabelledby,
@@ -20141,23 +20285,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
20141
20285
  }]
20142
20286
  }] });
20143
20287
 
20144
- /**
20145
- * The name this spinner falls back to when the caller names neither `ariaLabel`
20146
- * nor `ariaLabelledby`. Same reasoning as `TN_SPINNER_DEFAULT_LABEL` and
20147
- * `TN_PROGRESS_BAR_DEFAULT_LABEL`.
20148
- *
20149
- * It differs from `TN_SPINNER_DEFAULT_LABEL` — `"Loading..."` against
20150
- * `"Loading"` — only because this is the string the component already rendered,
20151
- * inline in its host binding, before #206 gave it the shared resolver. Aligning
20152
- * the two would change what a screen reader announces for every unnamed branded
20153
- * spinner already in the wild, which is a louder change than the consistency
20154
- * fix it would be part of. Exported so specs assert against it by name rather
20155
- * than by a copied string literal.
20156
- */
20157
- const TN_BRANDED_SPINNER_DEFAULT_LABEL = 'Loading...';
20158
20288
  class TnBrandedSpinnerComponent {
20159
20289
  ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
20160
20290
  ariaLabelledby = input(null, ...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : []));
20291
+ fallbackName = injectTnFallbackName('brandedSpinner');
20161
20292
  /**
20162
20293
  * The name to render, or `null` to render no `aria-label` attribute — and the
20163
20294
  * dev-mode warning when the caller named neither input.
@@ -20171,7 +20302,8 @@ class TnBrandedSpinnerComponent {
20171
20302
  */
20172
20303
  resolvedAriaLabel = tnAccessibleName({
20173
20304
  selector: 'tn-branded-spinner',
20174
- fallback: TN_BRANDED_SPINNER_DEFAULT_LABEL,
20305
+ fallback: this.fallbackName.label,
20306
+ fallbackIsConfigured: this.fallbackName.configured,
20175
20307
  activity: 'loading',
20176
20308
  ariaLabel: this.ariaLabel,
20177
20309
  ariaLabelledby: this.ariaLabelledby
@@ -20284,30 +20416,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
20284
20416
  }, template: "<div class=\"tn-branded-spinner-container\">\n <svg \n viewBox=\"0 -7 62 62\" \n preserveAspectRatio=\"xMidYMid meet\" \n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"tn-branded-spinner-logo\">\n \n <!-- EXPLODED LOGO PATHS -->\n <path class=\"exploded center\" fill=\"#AFADAE\" d=\"m41.79 24.13-11.26 6.51-11.28-6.51 11.28-6.51 11.26 6.51Z\" />\n <path class=\"exploded top-left\" fill=\"#35BEEB\" d=\"M27.86 0v13.01l-13.93 8.04-11.28-6.5L27.86 0Z\" />\n <path class=\"exploded bottom-right\" fill=\"#35BEEB\" d=\"M61.03 19.16v13.01L33.19 48.25V35.24l27.84-16.08Z\" />\n <path class=\"exploded bottom-left\" fill=\"#0A95D3\" d=\"M27.86 35.24v13L0 32.17v-13l12.59 7.26s.03.02.05.03l15.23 8.79-.01-.01Z\" />\n <path class=\"exploded top-right\" fill=\"#0A95D3\" d=\"m58.38 14.55-11.27 6.51-13.92-8.05V0l25.19 14.55Z\" />\n </svg>\n</div>", styles: [".tn-branded-spinner{display:inline-block;vertical-align:middle}.tn-branded-spinner-container{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100px;min-height:100px}.tn-branded-spinner-logo{width:100px;height:100px}.tn-branded-spinner-logo path.exploded{fill-opacity:0;stroke-width:1px;stroke:var(--tn-primary, #007bff)}.tn-branded-spinner-logo path#morph-target{fill-opacity:0;fill:var(--tn-primary, #007bff)}\n"] }]
20285
20417
  }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }] } });
20286
20418
 
20287
- /**
20288
- * The accessible name a bar falls back to when the caller names neither
20289
- * `ariaLabel` nor `ariaLabelledby` (#202).
20290
- *
20291
- * Deliberately generic, and deliberately not silent: the host carries
20292
- * `role="progressbar"` unconditionally, so without a fallback the default
20293
- * rendering is a progressbar assistive technology announces with no name at all
20294
- * — "progress bar, 40%", with nothing to say what is progressing. The
20295
- * alternative fix, withholding the role until there is a name for it, trades
20296
- * that for no announcement whatever, which is worse: a screen reader would not
20297
- * learn that anything is in progress, and on a determinate bar it would lose
20298
- * the value too.
20299
- *
20300
- * A generic name is still a poor one, so it is paired with the dev-mode warning
20301
- * `tnAccessibleName` raises. Exported so specs assert against it by name rather
20302
- * than by a copied string literal.
20303
- */
20304
- const TN_PROGRESS_BAR_DEFAULT_LABEL = 'Progress';
20305
20419
  class TnProgressBarComponent {
20306
20420
  mode = input('determinate', ...(ngDevMode ? [{ debugName: "mode" }] : []));
20307
20421
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
20308
20422
  bufferValue = input(0, ...(ngDevMode ? [{ debugName: "bufferValue" }] : []));
20309
20423
  ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
20310
20424
  ariaLabelledby = input(null, ...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : []));
20425
+ fallbackName = injectTnFallbackName('progressBar');
20311
20426
  /**
20312
20427
  * The name to render, or `null` to render no `aria-label` attribute — and the
20313
20428
  * dev-mode warning when the caller named neither input.
@@ -20323,7 +20438,8 @@ class TnProgressBarComponent {
20323
20438
  */
20324
20439
  resolvedAriaLabel = tnAccessibleName({
20325
20440
  selector: 'tn-progress-bar',
20326
- fallback: TN_PROGRESS_BAR_DEFAULT_LABEL,
20441
+ fallback: this.fallbackName.label,
20442
+ fallbackIsConfigured: this.fallbackName.configured,
20327
20443
  activity: 'progressing',
20328
20444
  ariaLabel: this.ariaLabel,
20329
20445
  ariaLabelledby: this.ariaLabelledby
@@ -20382,19 +20498,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
20382
20498
  }, template: "<!-- Background/buffer layer -->\n<div class=\"tn-progress-bar-buffer\" aria-hidden=\"true\">\n <!-- Buffer bar hidden in new implementation -->\n <!-- Buffer dots for buffer mode -->\n @if (mode() === 'buffer') {\n <div class=\"tn-progress-bar-buffer-dots\"\n [style.width]=\"bufferStyles().width\"\n [style.right]=\"bufferStyles().right\"></div>\n }\n</div>\n\n<!-- Primary bar -->\n<div class=\"tn-progress-bar-bar tn-progress-bar-primary-bar\" aria-hidden=\"true\">\n <span class=\"tn-progress-bar-bar-inner\"\n [style.transform]=\"primaryTransform()\"></span>\n</div>\n\n<!-- Secondary bar (for indeterminate mode) -->\n@if (mode() === 'indeterminate') {\n <div class=\"tn-progress-bar-bar tn-progress-bar-secondary-bar\" aria-hidden=\"true\">\n <span class=\"tn-progress-bar-bar-inner\"></span>\n </div>\n}\n\n", styles: [":host{display:block;height:4px;overflow:hidden;position:relative;transition:opacity .25s linear;width:100%}.tn-progress-bar-buffer{position:absolute;top:0;bottom:0;width:100%;background-color:var(--tn-bg2, #e5e7eb)}.tn-progress-bar-buffer-bar{display:none}.tn-progress-bar-buffer-dots{position:absolute;top:0;bottom:0;width:100%;background-image:radial-gradient(circle at center,var(--tn-alt-bg2) 2px,transparent 2px);background-size:10px 4px;background-repeat:repeat-x;animation:tn-progress-bar-buffer-dots .25s infinite linear}@keyframes tn-progress-bar-buffer-dots{0%{background-position-x:0}to{background-position-x:-10px}}.tn-progress-bar-bar{position:absolute;top:0;bottom:0;left:0;width:100%;transform-origin:left center}.tn-progress-bar-bar-inner{display:block;position:absolute;top:0;bottom:0;left:0;width:100%;background-color:var(--tn-primary, #3b82f6);transform-origin:left center;height:100%}.tn-progress-bar-primary-bar{z-index:1}.tn-progress-bar-secondary-bar{z-index:0;display:none}.tn-progress-bar-secondary-bar .tn-progress-bar-bar-inner{background-color:var(--tn-primary, #3b82f6)}:host(.tn-progress-bar-indeterminate) .tn-progress-bar-primary-bar .tn-progress-bar-bar-inner{animation:tn-progress-bar-indeterminate 2s infinite linear;background-color:var(--tn-primary, #3b82f6);opacity:1!important;z-index:999!important}@keyframes tn-progress-bar-indeterminate{0%{transform:translate(-100%) scaleX(.3)}to{transform:translate(100%) scaleX(.3)}}:host(.tn-progress-bar-buffer) .tn-progress-bar-buffer-bar{opacity:1}:host(.tn-progress-bar-buffer) .tn-progress-bar-buffer-dots{opacity:1}:host(.tn-progress-bar-determinate) .tn-progress-bar-buffer-dots{display:none}:host(.tn-progress-bar-determinate) .tn-progress-bar-secondary-bar{display:none}:host(.tn-progress-bar-buffer) .tn-progress-bar-secondary-bar{display:none}:host(.tn-progress-bar-indeterminate) .tn-progress-bar-buffer-dots{display:none}:host(.tn-progress-bar-indeterminate) .tn-progress-bar-buffer-bar{display:none}\n"] }]
20383
20499
  }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], bufferValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "bufferValue", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }] } });
20384
20500
 
20385
- /**
20386
- * The accessible name this bar falls back to when the caller names neither
20387
- * `ariaLabel` nor `ariaLabelledby` (#209).
20388
- *
20389
- * The same string and the same reasoning as `TN_PROGRESS_BAR_DEFAULT_LABEL`
20390
- * next door, and deliberately a separate constant rather than an import of it:
20391
- * `tnAccessibleName` takes a fallback PER COMPONENT because the least-bad
20392
- * generic name differs by what the component is ("Progress" for a bar,
20393
- * "Loading" for a spinner), and sharing the binding would make a future
20394
- * divergence in one a silent change to the other. Exported so specs assert
20395
- * against it by name rather than by a copied string literal.
20396
- */
20397
- const TN_PARTICLE_PROGRESS_BAR_DEFAULT_LABEL = 'Progress';
20398
20501
  /**
20399
20502
  * The gap in px between the edge of the SVG and each end of the track, on both
20400
20503
  * sides — the `x` the two rects are drawn at, and half of what is subtracted
@@ -20466,6 +20569,7 @@ class TnParticleProgressBarComponent {
20466
20569
  canvasRef = viewChild.required('canvas');
20467
20570
  /** Exposed to the template so the rects and the ARIA value share one inset. */
20468
20571
  trackInset = TRACK_INSET;
20572
+ fallbackName = injectTnFallbackName('particleProgressBar');
20469
20573
  /**
20470
20574
  * The name to render, or `null` to render no `aria-label` at all — and the
20471
20575
  * dev-mode warning when the caller named neither input.
@@ -20483,7 +20587,8 @@ class TnParticleProgressBarComponent {
20483
20587
  */
20484
20588
  resolvedAriaLabel = tnAccessibleName({
20485
20589
  selector: 'tn-particle-progress-bar',
20486
- fallback: TN_PARTICLE_PROGRESS_BAR_DEFAULT_LABEL,
20590
+ fallback: this.fallbackName.label,
20591
+ fallbackIsConfigured: this.fallbackName.configured,
20487
20592
  activity: 'progressing',
20488
20593
  ariaLabel: this.ariaLabel,
20489
20594
  ariaLabelledby: this.ariaLabelledby
@@ -24406,27 +24511,6 @@ const TN_DIALOG_DEFAULT_CHROME_LABELS = {
24406
24511
  */
24407
24512
  const TN_DIALOG_CHROME_LABELS = new InjectionToken('TN_DIALOG_CHROME_LABELS', { providedIn: 'root', factory: () => TN_DIALOG_DEFAULT_CHROME_LABELS });
24408
24513
  let nextUniqueId = 0;
24409
- /**
24410
- * The accessible name a dialog falls back to when it renders no `title` and the
24411
- * caller named it through neither this component nor the `DialogConfig` (#219).
24412
- *
24413
- * `title` defaults to `''`, so the DEFAULT rendering of this component put an
24414
- * empty `<h2>` in the header and left the CDK container with no naming
24415
- * attribute at all — measured as `empty-heading` on the heading and
24416
- * `aria-dialog-name` on the dialog. A dialog with no name is announced as
24417
- * "dialog" and nothing else, which is the whole of what a screen-reader user is
24418
- * told about a surface that just took over the page and trapped their focus.
24419
- *
24420
- * "Dialog" is a poor name, and says almost exactly what the role already says.
24421
- * It is still better than the two alternatives: leaving the surface unnamed, or
24422
- * withholding `role="dialog"` until there is a name — the latter would move a
24423
- * listener into a focus trap with no announcement that anything had opened. So
24424
- * it is paired with the dev-mode warning `tnAccessibleName` raises, which is
24425
- * what keeps the fallback from becoming a quiet way to ship a nameless dialog.
24426
- *
24427
- * Exported so specs assert against it by name rather than by a copied literal.
24428
- */
24429
- const TN_DIALOG_SHELL_DEFAULT_LABEL = 'Dialog';
24430
24514
  /**
24431
24515
  * The first value that is a name, or `null` if none of them is one.
24432
24516
  *
@@ -24544,6 +24628,7 @@ class TnDialogShellComponent {
24544
24628
  resolvedAriaLabelledby = computed(() => (this.hasTitle() ? this.titleId : firstNonBlank(this.ariaLabelledby(), this.ref.config?.ariaLabelledBy)), ...(ngDevMode ? [{ debugName: "resolvedAriaLabelledby" }] : []));
24545
24629
  /** An explicit label, from this component's input or from the `DialogConfig`. */
24546
24630
  explicitAriaLabel = computed(() => firstNonBlank(this.ariaLabel(), this.ref.config?.ariaLabel), ...(ngDevMode ? [{ debugName: "explicitAriaLabel" }] : []));
24631
+ fallbackName = injectTnFallbackName('dialog');
24547
24632
  /**
24548
24633
  * The name to render as `aria-label`, or `null` to render none — and the
24549
24634
  * dev-mode warning when the dialog has no name from any route.
@@ -24555,7 +24640,8 @@ class TnDialogShellComponent {
24555
24640
  */
24556
24641
  resolvedAriaLabel = tnAccessibleName({
24557
24642
  selector: 'tn-dialog-shell',
24558
- fallback: TN_DIALOG_SHELL_DEFAULT_LABEL,
24643
+ fallback: this.fallbackName.label,
24644
+ fallbackIsConfigured: this.fallbackName.configured,
24559
24645
  activity: 'open',
24560
24646
  hint: 'On this component the usual route is title, which is also the visible heading.',
24561
24647
  ariaLabel: this.explicitAriaLabel,
@@ -24977,25 +25063,6 @@ class TnDialogTesting {
24977
25063
  }
24978
25064
  }
24979
25065
 
24980
- /**
24981
- * The accessible name an open panel falls back to when it has no `title` and the
24982
- * caller named neither `ariaLabel` nor `ariaLabelledby` (#214).
24983
- *
24984
- * `title` defaults to `''`, so the DEFAULT rendering of this component was a
24985
- * `role="dialog"` with `aria-labelledby` pointing at an empty `<h2>` — measured
24986
- * as an `aria-dialog-name` violation, alongside `empty-heading`. A dialog with no
24987
- * name is announced as "dialog" and nothing else, which is the whole of what a
24988
- * screen-reader user gets told about a surface that just covered the page.
24989
- *
24990
- * Withholding `role="dialog"` until there is a name would be the other way to
24991
- * clear the rule, and it is worse: the panel traps focus either way, so a
24992
- * listener would be moved into a region with no announcement that anything had
24993
- * opened. A generic name is still a poor one, so it is paired with the dev-mode
24994
- * warning `tnAccessibleName` raises.
24995
- *
24996
- * Exported so specs assert against it by name rather than by a copied literal.
24997
- */
24998
- const TN_SIDE_PANEL_DEFAULT_LABEL = 'Side panel';
24999
25066
  /**
25000
25067
  * The name given to the scrolling content region once it becomes focusable
25001
25068
  * (#248).
@@ -25202,6 +25269,7 @@ class TnSidePanelComponent {
25202
25269
  * when there is one, the caller's IDREF otherwise.
25203
25270
  */
25204
25271
  resolvedAriaLabelledby = computed(() => (this.hasTitle() ? this.titleId : this.ariaLabelledby()), ...(ngDevMode ? [{ debugName: "resolvedAriaLabelledby" }] : []));
25272
+ fallbackName = injectTnFallbackName('sidePanel');
25205
25273
  /**
25206
25274
  * The name to render as `aria-label`, or `null` to render none — and the
25207
25275
  * dev-mode warning when the panel has no name from any route.
@@ -25213,7 +25281,8 @@ class TnSidePanelComponent {
25213
25281
  */
25214
25282
  resolvedAriaLabel = tnAccessibleName({
25215
25283
  selector: 'tn-side-panel',
25216
- fallback: TN_SIDE_PANEL_DEFAULT_LABEL,
25284
+ fallback: this.fallbackName.label,
25285
+ fallbackIsConfigured: this.fallbackName.configured,
25217
25286
  activity: 'open',
25218
25287
  hint: 'On this component the usual route is title, which is also the visible heading.',
25219
25288
  ariaLabel: this.ariaLabel,
@@ -28150,5 +28219,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
28150
28219
  * Generated bundle index. Do not edit.
28151
28220
  */
28152
28221
 
28153
- export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LabelMarkupPipe, LabelTextPipe, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, THEME_MAP, THEME_STORAGE_KEY, TN_AUTOCOMPLETE_DEFAULT_LABELS, TN_AUTOCOMPLETE_LABELS, TN_BRANDED_SPINNER_DEFAULT_LABEL, TN_CALENDAR_INTL, TN_CALENDAR_INTL_DEFAULTS, TN_DIALOG_CHROME_LABELS, TN_DIALOG_DEFAULT_CHROME_LABELS, TN_DIALOG_SHELL_DEFAULT_LABEL, TN_DRAWER_CONTENT_LABEL, TN_DRAWER_DEFAULT_LABEL, TN_FORM_FIELD_CONTEXT, TN_FORM_FIELD_DISMISSIBLE_ERRORS, TN_FORM_FIELD_ERRORS, TN_FORM_LIST_CONTEXT, TN_PARTICLE_PROGRESS_BAR_DEFAULT_LABEL, TN_PROGRESS_BAR_DEFAULT_LABEL, TN_RADIO_GROUP, TN_SELECT_DEFAULT_LABELS, TN_SELECT_LABELS, TN_SIDE_PANEL_CONTENT_LABEL, TN_SIDE_PANEL_DEFAULT_LABEL, TN_SIDE_PANEL_OVERFLOW_TOLERANCE_PX, TN_SPINNER_DEFAULT_LABEL, TN_STEPPER_STATUS_COMPLETED, TN_STEPPER_STATUS_ERROR, TN_TABLE_DEFAULT_LABELS, TN_TABLE_LABELS, TN_TABLE_PAGER_DEFAULT_LABELS, TN_TABLE_PAGER_LABELS, TN_TABLE_SCROLL_REGION_LABEL, TN_TAB_PANEL_CONTENT_LABEL, TN_TEST_ATTR, TN_THEME_DEFINITIONS, TN_TOAST_ANNOUNCE_DELAY_MS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerActionHarness, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnButtonToggleGroupHarness, TnButtonToggleHarness, TnCalendarCellHarness, TnCalendarComponent, TnCalendarHarness, TnCalendarHeaderComponent, TnCardComponent, TnCardFooterActionsDirective, TnCardHeaderActionsDirective, TnCardHeaderDirective, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnChipHarness, TnChipInputComponent, TnChipInputHarness, TnConfirmDialogComponent, TnDateInputComponent, TnDateInputHarness, TnDateRangeInputComponent, TnDateRangeInputHarness, TnDetailRowDefDirective, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnDrawerComponent, TnDrawerContainerComponent, TnDrawerContainerHarness, TnDrawerContentComponent, TnDrawerHarness, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnExpansionPanelHarness, TnFileInputComponent, TnFileInputHarness, TnFilePickerComponent, TnFilePickerHarness, TnFilePickerPopupComponent, TnFormErrorsComponent, TnFormErrorsHarness, TnFormFieldComponent, TnFormFieldHarness, TnFormListComponent, TnFormListHarness, TnFormListItemComponent, TnFormListItemHarness, TnFormSectionComponent, TnFormSectionHarness, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuHarness, TnMenuItemComponent, TnMenuTesting, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeDataSource, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnRadioGroupComponent, TnRadioGroupHarness, TnRadioHarness, TnRowActionsDefDirective, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSlideToggleHarness, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnStepperHarness, TnStepperNextDirective, TnStepperPreviousDirective, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTableHarness, TnTablePagerComponent, TnTablePagerHarness, TnTableTesting, TnTabsComponent, TnTabsHarness, TnTestIdDirective, TnTheme, TnThemeService, TnTimeInputComponent, TnToastComponent, TnToastMock, TnToastPosition, TnToastRef, TnToastService, TnToastTesting, TnToastType, TnTooltipComponent, TnTooltipDirective, TnTooltipHarness, TnTooltipTesting, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeHarness, TnTreeNodeComponent, TnTreeNodeHarness, TnTreeNodeOutletDirective, TnTreeVirtualScrollNodeOutletDirective, TnTreeVirtualScrollViewComponent, TnTreeVirtualScrollViewHarness, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, allowsCurrentDirectorySelection, canonicalizeSize, composeTestId, controlTestId, createFlatTreeControl, createLucideLibrary, createNestedTreeControl, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, defaultTreeItemSize, formatSize, formatSizeExact, formatSizeForEditing, getSelectableTypes, injectTnCalendarIntl, injectTnFormFieldAria, injectTnLabels, isPathWithinRoot, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, normalizeRootPath, optionTestId, parseLabelMarkup, parseSize, parseSizeParts, registerLucideIcons, resolveErrorMessage, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
28222
+ export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LabelMarkupPipe, LabelTextPipe, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, THEME_MAP, THEME_STORAGE_KEY, TN_AUTOCOMPLETE_DEFAULT_LABELS, TN_AUTOCOMPLETE_LABELS, TN_BRANDED_SPINNER_DEFAULT_LABEL, TN_CALENDAR_INTL, TN_CALENDAR_INTL_DEFAULTS, TN_DEFAULT_FALLBACK_LABELS, TN_DIALOG_CHROME_LABELS, TN_DIALOG_DEFAULT_CHROME_LABELS, TN_DIALOG_SHELL_DEFAULT_LABEL, TN_DRAWER_CONTENT_LABEL, TN_DRAWER_DEFAULT_LABEL, TN_FALLBACK_LABELS, TN_FORM_FIELD_CONTEXT, TN_FORM_FIELD_DISMISSIBLE_ERRORS, TN_FORM_FIELD_ERRORS, TN_FORM_LIST_CONTEXT, TN_PARTICLE_PROGRESS_BAR_DEFAULT_LABEL, TN_PROGRESS_BAR_DEFAULT_LABEL, TN_RADIO_GROUP, TN_SELECT_DEFAULT_LABELS, TN_SELECT_LABELS, TN_SIDE_PANEL_CONTENT_LABEL, TN_SIDE_PANEL_DEFAULT_LABEL, TN_SIDE_PANEL_OVERFLOW_TOLERANCE_PX, TN_SPINNER_DEFAULT_LABEL, TN_STEPPER_STATUS_COMPLETED, TN_STEPPER_STATUS_ERROR, TN_TABLE_DEFAULT_LABELS, TN_TABLE_LABELS, TN_TABLE_PAGER_DEFAULT_LABELS, TN_TABLE_PAGER_LABELS, TN_TABLE_SCROLL_REGION_LABEL, TN_TAB_PANEL_CONTENT_LABEL, TN_TEST_ATTR, TN_THEME_DEFINITIONS, TN_TOAST_ANNOUNCE_DELAY_MS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerActionHarness, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnButtonToggleGroupHarness, TnButtonToggleHarness, TnCalendarCellHarness, TnCalendarComponent, TnCalendarHarness, TnCalendarHeaderComponent, TnCardComponent, TnCardFooterActionsDirective, TnCardHeaderActionsDirective, TnCardHeaderDirective, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnChipHarness, TnChipInputComponent, TnChipInputHarness, TnConfirmDialogComponent, TnDateInputComponent, TnDateInputHarness, TnDateRangeInputComponent, TnDateRangeInputHarness, TnDetailRowDefDirective, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnDrawerComponent, TnDrawerContainerComponent, TnDrawerContainerHarness, TnDrawerContentComponent, TnDrawerHarness, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnExpansionPanelHarness, TnFileInputComponent, TnFileInputHarness, TnFilePickerComponent, TnFilePickerHarness, TnFilePickerPopupComponent, TnFormErrorsComponent, TnFormErrorsHarness, TnFormFieldComponent, TnFormFieldHarness, TnFormListComponent, TnFormListHarness, TnFormListItemComponent, TnFormListItemHarness, TnFormSectionComponent, TnFormSectionHarness, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuHarness, TnMenuItemComponent, TnMenuTesting, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeDataSource, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnRadioGroupComponent, TnRadioGroupHarness, TnRadioHarness, TnRowActionsDefDirective, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSlideToggleHarness, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnStepperHarness, TnStepperNextDirective, TnStepperPreviousDirective, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTableHarness, TnTablePagerComponent, TnTablePagerHarness, TnTableTesting, TnTabsComponent, TnTabsHarness, TnTestIdDirective, TnTheme, TnThemeService, TnTimeInputComponent, TnToastComponent, TnToastMock, TnToastPosition, TnToastRef, TnToastService, TnToastTesting, TnToastType, TnTooltipComponent, TnTooltipDirective, TnTooltipHarness, TnTooltipTesting, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeHarness, TnTreeNodeComponent, TnTreeNodeHarness, TnTreeNodeOutletDirective, TnTreeVirtualScrollNodeOutletDirective, TnTreeVirtualScrollViewComponent, TnTreeVirtualScrollViewHarness, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, allowsCurrentDirectorySelection, canonicalizeSize, composeTestId, controlTestId, createFlatTreeControl, createLucideLibrary, createNestedTreeControl, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, defaultTreeItemSize, formatSize, formatSizeExact, formatSizeForEditing, getSelectableTypes, injectTnCalendarIntl, injectTnFallbackName, injectTnFormFieldAria, injectTnLabels, isPathWithinRoot, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, normalizeRootPath, optionTestId, parseLabelMarkup, parseSize, parseSizeParts, registerLucideIcons, resolveErrorMessage, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
28154
28223
  //# sourceMappingURL=truenas-ui-components.mjs.map