@truenas/ui-components 0.6.1 → 0.6.2

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.
@@ -5746,6 +5746,13 @@ class TnIconButtonHarness extends ComponentHarness {
5746
5746
  // Ordered binary/decimal prefixes; the array index doubles as the power applied
5747
5747
  // to the base (B = base^0, K = base^1, M = base^2, ...).
5748
5748
  const UNIT_PREFIXES = ['B', 'K', 'M', 'G', 'T', 'P', 'E'];
5749
+ // Display spellings for each standard, indexed by the same power as
5750
+ // UNIT_PREFIXES. These are the symbols `filesize` emits, so a value this module
5751
+ // renders itself is spelled exactly like one `formatSize` renders.
5752
+ const UNIT_SYMBOLS = {
5753
+ iec: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'],
5754
+ si: ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB'],
5755
+ };
5749
5756
  /**
5750
5757
  * Formats a raw byte count into a human-readable string (e.g. `2 GiB`).
5751
5758
  *
@@ -5784,6 +5791,17 @@ function formatSize(bytes, standard = 'iec', round = 2) {
5784
5791
  * @param standard Unit standard (defaults to IEC base-2).
5785
5792
  */
5786
5793
  function parseSize(raw, defaultUnit = 'MiB', standard = 'iec') {
5794
+ return parseSizeParts(raw, defaultUnit, standard)?.bytes ?? null;
5795
+ }
5796
+ /**
5797
+ * {@link parseSize}, keeping the parts rather than collapsing them to a byte
5798
+ * count. The unit matters when the text has to be re-rendered: the number the
5799
+ * user wrote and the unit they wrote it in always denote their byte count
5800
+ * exactly, which a rounded rendering may not.
5801
+ *
5802
+ * @internal
5803
+ */
5804
+ function parseSizeParts(raw, defaultUnit = 'MiB', standard = 'iec') {
5787
5805
  if (raw === null || raw === undefined) {
5788
5806
  return null;
5789
5807
  }
@@ -5806,9 +5824,101 @@ function parseSize(raw, defaultUnit = 'MiB', standard = 'iec') {
5806
5824
  return null;
5807
5825
  }
5808
5826
  const base = standard === 'si' ? 1000 : 1024;
5809
- // Round to whole bytes: a byte count is an integer, and rounding absorbs the
5810
- // floating-point drift of e.g. 1.1 * 1024.
5811
- return Math.round(num * base ** exponent);
5827
+ return {
5828
+ // Round to whole bytes: a byte count is an integer, and rounding absorbs the
5829
+ // floating-point drift of e.g. 1.1 * 1024.
5830
+ bytes: Math.round(num * base ** exponent),
5831
+ digits: match[1],
5832
+ exponent,
5833
+ };
5834
+ }
5835
+ /**
5836
+ * Renders a byte count in the largest unit that expresses it EXACTLY within
5837
+ * `round` decimals, or `null` when no suitable unit does.
5838
+ *
5839
+ * The point is a field the user types into. `formatSize` always picks the
5840
+ * natural unit and rounds to fit — 1 572 864 000 becomes `1.46 GiB`, which is a
5841
+ * fine way to READ a size but a lie to hand back to someone who typed
5842
+ * `1500 MiB`: it no longer denotes the value the field holds. One unit down
5843
+ * usually does denote it exactly, so this looks there.
5844
+ *
5845
+ * It looks exactly one step down and no further, which is what keeps the result
5846
+ * readable: a value that is exact in neither its own unit nor the next is
5847
+ * always exact in bytes, and `1567663063 B` helps nobody. Such a value has no
5848
+ * exact spelling worth showing, so this returns `null` and the caller falls
5849
+ * back to the rounded rendering.
5850
+ *
5851
+ * @param bytes The byte count to render. Non-integer and unsafe magnitudes
5852
+ * return `null` — a byte count is a whole number, and past
5853
+ * `MAX_SAFE_INTEGER` "exactly" stops meaning anything.
5854
+ * @param standard Unit standard (defaults to IEC base-2).
5855
+ * @param round Decimal places the rendering may use (defaults to 2).
5856
+ * @internal
5857
+ */
5858
+ function formatSizeExact(bytes, standard = 'iec', round = 2) {
5859
+ if (!Number.isSafeInteger(bytes) || bytes < 0) {
5860
+ return null;
5861
+ }
5862
+ const symbols = UNIT_SYMBOLS[standard];
5863
+ if (bytes === 0) {
5864
+ return `0 ${symbols[0]}`;
5865
+ }
5866
+ const base = standard === 'si' ? 1000 : 1024;
5867
+ // The unit `formatSize` would pick, and the one below it.
5868
+ const natural = Math.min(symbols.length - 1, Math.floor(Math.log(bytes) / Math.log(base)));
5869
+ for (let exponent = natural; exponent >= Math.max(0, natural - 1); exponent--) {
5870
+ const scaled = bytes / base ** exponent;
5871
+ // Exact in this unit when the rounded rendering IS the value, and it still
5872
+ // multiplies back to the byte count we started from.
5873
+ if (Number(scaled.toFixed(round)) === scaled && scaled * base ** exponent === bytes) {
5874
+ return `${scaled} ${symbols[exponent]}`;
5875
+ }
5876
+ }
5877
+ return null;
5878
+ }
5879
+ /**
5880
+ * Formats a byte count for a field the user edits: {@link formatSizeExact} when
5881
+ * some unit states the value exactly, and {@link formatSize}'s rounded
5882
+ * rendering when none does.
5883
+ *
5884
+ * @param bytes The byte count to format.
5885
+ * @param standard Unit standard (defaults to IEC base-2).
5886
+ * @param round Decimal places to round to (defaults to 2).
5887
+ * @internal
5888
+ */
5889
+ function formatSizeForEditing(bytes, standard = 'iec', round = 2) {
5890
+ const rounded = formatSize(bytes, standard, round);
5891
+ if (rounded === '') {
5892
+ return '';
5893
+ }
5894
+ return formatSizeExact(Number(bytes), standard, round) ?? rounded;
5895
+ }
5896
+ /**
5897
+ * Tidies a size the user typed into its canonical spelling, without ever
5898
+ * restating it as a value it does not denote.
5899
+ *
5900
+ * `2048 KiB` becomes `2 MiB` and `200tib` becomes `200 TiB`, because both
5901
+ * renderings are exact. `1500` becomes `1500 MiB` rather than `1.46 GiB`, and
5902
+ * `1.755 GiB` is left at `1.755 GiB`: where no unit expresses the value within
5903
+ * `round` decimals, the number and unit the user wrote do, so those are kept
5904
+ * and only the spelling is normalized.
5905
+ *
5906
+ * Returns `null` for text {@link parseSize} cannot read, which the caller leaves
5907
+ * on screen for its validators to flag.
5908
+ *
5909
+ * @param raw The text to canonicalize.
5910
+ * @param defaultUnit Unit assumed when the input carries no unit (defaults to `MiB`).
5911
+ * @param standard Unit standard (defaults to IEC base-2).
5912
+ * @param round Decimal places a rendering may use (defaults to 2).
5913
+ * @internal
5914
+ */
5915
+ function canonicalizeSize(raw, defaultUnit = 'MiB', standard = 'iec', round = 2) {
5916
+ const parts = parseSizeParts(raw, defaultUnit, standard);
5917
+ if (!parts) {
5918
+ return null;
5919
+ }
5920
+ return (formatSizeExact(parts.bytes, standard, round)
5921
+ ?? `${parts.digits} ${UNIT_SYMBOLS[standard][parts.exponent]}`);
5812
5922
  }
5813
5923
  /**
5814
5924
  * Resolves a unit spelling to its prefix power (B → 0, K → 1, M → 2, ...).
@@ -6011,6 +6121,12 @@ class TnInputComponent {
6011
6121
  /**
6012
6122
  * Decimal places used when formatting a `Size` field's value for display
6013
6123
  * (e.g. `1.5 GiB`). Ignored unless `inputType` is `Size`.
6124
+ *
6125
+ * Display only: the form model always holds the exact byte count the typed
6126
+ * text denotes, and is never re-read from the display. The display avoids
6127
+ * rounding where it can — `1500M` shows as `1500 MiB`, not as a `1.46 GiB`
6128
+ * that means 1 567 663 063 — and where a value fits no unit exactly (a size
6129
+ * read back from the server, say) it is rounded for reading only.
6014
6130
  */
6015
6131
  sizeRound = input(2, ...(ngDevMode ? [{ debugName: "sizeRound" }] : []));
6016
6132
  /**
@@ -6136,7 +6252,10 @@ class TnInputComponent {
6136
6252
  if (this.isSize()) {
6137
6253
  // The model is a byte count; show it as a human-readable string. Empty/null
6138
6254
  // stays blank, and a non-numeric model maps to blank (formatSize returns '').
6139
- this.value.set(formatSize(value, this.sizeStandard(), this.sizeRound()));
6255
+ // `formatSizeForEditing` prefers a unit that states the value exactly, so a
6256
+ // field the user can edit shows '1500 MiB' rather than a '1.46 GiB' that
6257
+ // would parse back ~5 MB short of what it holds.
6258
+ this.value.set(formatSizeForEditing(value, this.sizeStandard(), this.sizeRound()));
6140
6259
  return;
6141
6260
  }
6142
6261
  // Display the model verbatim via String(); do NOT sanitize here. Sanitizing a
@@ -6187,23 +6306,24 @@ class TnInputComponent {
6187
6306
  }
6188
6307
  onBlur() {
6189
6308
  if (this.isSize() && this.value() !== '') {
6190
- // Canonicalize the display on blur: "2048 KiB" -> "2 MiB", "200tib" -> "200 TiB".
6191
- // Leave unparseable text in place so the consumer's validators can flag it.
6192
- const bytes = parseSize(this.value(), this.sizeDefaultUnit(), this.sizeStandard());
6193
- if (bytes !== null) {
6194
- const canonical = formatSize(bytes, this.sizeStandard(), this.sizeRound());
6195
- // Only rewrite + re-emit when the canonical form actually differs from what
6196
- // the user left in the field. This both:
6197
- // (a) skips a no-op onChange that would mark an untouched, pre-filled
6198
- // control dirty (falsely tripping "unsaved changes" guards), and
6199
- // (b) still re-syncs the model when rounding is lossy — e.g. an edited
6200
- // "1.755 GiB" canonicalizes to a different string, so it emits the
6201
- // byte count parsed back from the rounded display, keeping
6202
- // parseSize(display) === model.
6203
- if (canonical !== this.value()) {
6204
- this.value.set(canonical);
6205
- this.onChange(parseSize(canonical, this.sizeDefaultUnit(), this.sizeStandard()));
6206
- }
6309
+ // Canonicalize the DISPLAY on blur: "2048 KiB" -> "2 MiB", "200tib" ->
6310
+ // "200 TiB", "1500" -> "1500 MiB". Leave unparseable text in place so the
6311
+ // consumer's validators can flag it.
6312
+ //
6313
+ // `canonicalizeSize` never restates the value as something it is not: where
6314
+ // no unit expresses it within `sizeRound` decimals it keeps the number and
6315
+ // unit the user wrote. So the text left on screen always denotes the byte
6316
+ // count in the model — "1500" tidies to "1500 MiB", not to a "1.46 GiB"
6317
+ // that means 1_567_663_063, ~5 MB short of the 1_572_864_000 stored.
6318
+ //
6319
+ // The model is still deliberately NOT re-emitted from that text. The byte
6320
+ // count `onValueChange` emitted while typing is already exact, and emitting
6321
+ // again would mark a control dirty for a field the user only tabbed through.
6322
+ const canonical = canonicalizeSize(this.value(), this.sizeDefaultUnit(), this.sizeStandard(), this.sizeRound());
6323
+ if (canonical !== null) {
6324
+ // A no-op for a pre-filled control the user merely tabbed through: the
6325
+ // signal already holds that exact string, so nothing repaints.
6326
+ this.value.set(canonical);
6207
6327
  }
6208
6328
  }
6209
6329
  this.onTouched();
@@ -28024,5 +28144,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
28024
28144
  * Generated bundle index. Do not edit.
28025
28145
  */
28026
28146
 
28027
- 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, composeTestId, controlTestId, createFlatTreeControl, createLucideLibrary, createNestedTreeControl, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, defaultTreeItemSize, formatSize, getSelectableTypes, injectTnCalendarIntl, injectTnFormFieldAria, injectTnLabels, isPathWithinRoot, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, normalizeRootPath, optionTestId, parseLabelMarkup, parseSize, registerLucideIcons, resolveErrorMessage, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
28147
+ 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 };
28028
28148
  //# sourceMappingURL=truenas-ui-components.mjs.map