@truenas/ui-components 0.1.21 → 0.1.23
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,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, ChangeDetectionStrategy, Component, inject, Injectable, viewChild, signal, effect, computed, ViewEncapsulation, Directive, contentChildren, output, forwardRef, ElementRef, ViewContainerRef, contentChild, ChangeDetectorRef, HostListener, TemplateRef, IterableDiffers, Pipe, model, afterNextRender, PLATFORM_ID } from '@angular/core';
|
|
2
|
+
import { input, ChangeDetectionStrategy, Component, inject, Injectable, viewChild, signal, effect, computed, ViewEncapsulation, Directive, contentChildren, output, forwardRef, ElementRef, ViewContainerRef, contentChild, ChangeDetectorRef, HostListener, TemplateRef, IterableDiffers, Pipe, model, afterNextRender, PLATFORM_ID, DestroyRef } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
5
5
|
import { mdiCheckCircle, mdiAlertCircle, mdiAlert, mdiInformation, mdiDotsVertical, mdiClose, mdiFolderOpen, mdiLock, mdiLoading, mdiFolderPlus, mdiFolderNetwork, mdiHarddisk, mdiDatabase, mdiFile, mdiFolder } from '@mdi/js';
|
|
@@ -477,6 +477,9 @@ class TnIconComponent {
|
|
|
477
477
|
// Convert to registry format for Lucide icons
|
|
478
478
|
effectiveIconName = `lucide:${name}`;
|
|
479
479
|
}
|
|
480
|
+
else if (library === 'custom' && !name.startsWith('app-')) {
|
|
481
|
+
effectiveIconName = `app-${name}`;
|
|
482
|
+
}
|
|
480
483
|
// 1. Try icon registry (libraries and custom icons)
|
|
481
484
|
const iconOptions = {
|
|
482
485
|
size: this.size(),
|
|
@@ -9640,6 +9643,10 @@ var TnTheme;
|
|
|
9640
9643
|
* Default theme used when no theme is set
|
|
9641
9644
|
*/
|
|
9642
9645
|
const DEFAULT_THEME = TnTheme.Dark;
|
|
9646
|
+
/**
|
|
9647
|
+
* Light theme used when OS preference is light
|
|
9648
|
+
*/
|
|
9649
|
+
const LIGHT_THEME = TnTheme.Blue;
|
|
9643
9650
|
/**
|
|
9644
9651
|
* localStorage key for storing the current theme name
|
|
9645
9652
|
*/
|
|
@@ -9708,7 +9715,8 @@ const THEME_MAP = new Map(TN_THEME_DEFINITIONS.map((theme) => [theme.name, theme
|
|
|
9708
9715
|
*
|
|
9709
9716
|
* Features:
|
|
9710
9717
|
* - Signal-based reactive theme state
|
|
9711
|
-
* -
|
|
9718
|
+
* - OS color scheme detection (prefers-color-scheme)
|
|
9719
|
+
* - LocalStorage persistence for explicit user choices (key: 'tn-theme')
|
|
9712
9720
|
* - Automatic CSS class application to document root
|
|
9713
9721
|
* - SSR-safe (checks for browser platform)
|
|
9714
9722
|
*
|
|
@@ -9728,9 +9736,12 @@ const THEME_MAP = new Map(TN_THEME_DEFINITIONS.map((theme) => [theme.name, theme
|
|
|
9728
9736
|
* // Get current theme (signal)
|
|
9729
9737
|
* const currentTheme = this.themeService.currentTheme();
|
|
9730
9738
|
*
|
|
9731
|
-
* // Set theme using enum (recommended)
|
|
9739
|
+
* // Set theme using enum (recommended) — persists to localStorage
|
|
9732
9740
|
* this.themeService.setTheme(TnTheme.Blue);
|
|
9733
9741
|
*
|
|
9742
|
+
* // Clear user preference and follow OS theme
|
|
9743
|
+
* this.themeService.clearPreference();
|
|
9744
|
+
*
|
|
9734
9745
|
* // React to theme changes
|
|
9735
9746
|
* effect(() => {
|
|
9736
9747
|
* console.log('Theme changed to:', this.themeService.currentTheme()?.label);
|
|
@@ -9742,10 +9753,28 @@ const THEME_MAP = new Map(TN_THEME_DEFINITIONS.map((theme) => [theme.name, theme
|
|
|
9742
9753
|
class TnThemeService {
|
|
9743
9754
|
platformId = inject(PLATFORM_ID);
|
|
9744
9755
|
isBrowser = isPlatformBrowser(this.platformId);
|
|
9756
|
+
destroyRef = inject(DestroyRef);
|
|
9745
9757
|
/**
|
|
9746
9758
|
* Internal signal holding the current theme enum value
|
|
9747
9759
|
*/
|
|
9748
9760
|
currentThemeSignal = signal(DEFAULT_THEME, ...(ngDevMode ? [{ debugName: "currentThemeSignal" }] : []));
|
|
9761
|
+
/**
|
|
9762
|
+
* Whether the user has explicitly selected a theme (vs OS-detected default).
|
|
9763
|
+
* When true, theme is persisted to localStorage and OS changes are ignored.
|
|
9764
|
+
*/
|
|
9765
|
+
userSelected = signal(false, ...(ngDevMode ? [{ debugName: "userSelected" }] : []));
|
|
9766
|
+
/**
|
|
9767
|
+
* Reference to the prefers-color-scheme media query for cleanup
|
|
9768
|
+
*/
|
|
9769
|
+
colorSchemeQuery = null;
|
|
9770
|
+
/**
|
|
9771
|
+
* Bound listener reference for cleanup
|
|
9772
|
+
*/
|
|
9773
|
+
colorSchemeListener = (event) => {
|
|
9774
|
+
if (!this.userSelected()) {
|
|
9775
|
+
this.currentThemeSignal.set(event.matches ? DEFAULT_THEME : LIGHT_THEME);
|
|
9776
|
+
}
|
|
9777
|
+
};
|
|
9749
9778
|
/**
|
|
9750
9779
|
* Computed signal that returns the full theme definition for the current theme
|
|
9751
9780
|
*/
|
|
@@ -9759,12 +9788,16 @@ class TnThemeService {
|
|
|
9759
9788
|
currentThemeClass = computed(() => {
|
|
9760
9789
|
return this.currentTheme()?.className ?? TnTheme.Dark;
|
|
9761
9790
|
}, ...(ngDevMode ? [{ debugName: "currentThemeClass" }] : []));
|
|
9791
|
+
/**
|
|
9792
|
+
* Whether the current theme is based on OS preference (no explicit user choice)
|
|
9793
|
+
*/
|
|
9794
|
+
isUsingSystemTheme = computed(() => !this.userSelected(), ...(ngDevMode ? [{ debugName: "isUsingSystemTheme" }] : []));
|
|
9762
9795
|
/**
|
|
9763
9796
|
* All available theme definitions in the library (readonly array)
|
|
9764
9797
|
*/
|
|
9765
9798
|
availableThemes = TN_THEME_DEFINITIONS;
|
|
9766
9799
|
constructor() {
|
|
9767
|
-
// Initialize theme from localStorage or
|
|
9800
|
+
// Initialize theme from localStorage or OS preference
|
|
9768
9801
|
this.initializeTheme();
|
|
9769
9802
|
// Effect to apply theme CSS class to document root whenever theme changes
|
|
9770
9803
|
effect(() => {
|
|
@@ -9772,9 +9805,9 @@ class TnThemeService {
|
|
|
9772
9805
|
this.applyThemeToDOM(this.currentThemeClass());
|
|
9773
9806
|
}
|
|
9774
9807
|
});
|
|
9775
|
-
// Effect to persist theme to localStorage
|
|
9808
|
+
// Effect to persist theme to localStorage only for explicit user choices
|
|
9776
9809
|
effect(() => {
|
|
9777
|
-
if (this.isBrowser) {
|
|
9810
|
+
if (this.isBrowser && this.userSelected()) {
|
|
9778
9811
|
const theme = this.currentTheme();
|
|
9779
9812
|
if (theme) {
|
|
9780
9813
|
this.persistThemeToStorage(theme);
|
|
@@ -9784,7 +9817,8 @@ class TnThemeService {
|
|
|
9784
9817
|
}
|
|
9785
9818
|
/**
|
|
9786
9819
|
* Set the current theme.
|
|
9787
|
-
*
|
|
9820
|
+
* Marks this as an explicit user choice, persists to localStorage,
|
|
9821
|
+
* and stops following OS color scheme changes.
|
|
9788
9822
|
*
|
|
9789
9823
|
* @param theme - The theme to set (use TnTheme enum)
|
|
9790
9824
|
* @returns true if theme was found and set, false otherwise
|
|
@@ -9797,6 +9831,7 @@ class TnThemeService {
|
|
|
9797
9831
|
setTheme(theme) {
|
|
9798
9832
|
const themeDefinition = THEME_MAP.get(theme);
|
|
9799
9833
|
if (themeDefinition) {
|
|
9834
|
+
this.userSelected.set(true);
|
|
9800
9835
|
this.currentThemeSignal.set(theme);
|
|
9801
9836
|
return true;
|
|
9802
9837
|
}
|
|
@@ -9810,10 +9845,27 @@ class TnThemeService {
|
|
|
9810
9845
|
return this.currentThemeSignal();
|
|
9811
9846
|
}
|
|
9812
9847
|
/**
|
|
9813
|
-
* Reset theme to default
|
|
9848
|
+
* Reset theme to default by clearing user preference and reverting to OS detection.
|
|
9814
9849
|
*/
|
|
9815
9850
|
resetToDefault() {
|
|
9816
|
-
this.
|
|
9851
|
+
this.clearPreference();
|
|
9852
|
+
}
|
|
9853
|
+
/**
|
|
9854
|
+
* Clear user preference and revert to OS-based theme detection.
|
|
9855
|
+
* Removes the stored theme from localStorage and follows the OS color scheme.
|
|
9856
|
+
*/
|
|
9857
|
+
clearPreference() {
|
|
9858
|
+
if (this.isBrowser) {
|
|
9859
|
+
try {
|
|
9860
|
+
localStorage.removeItem(THEME_STORAGE_KEY);
|
|
9861
|
+
}
|
|
9862
|
+
catch (error) {
|
|
9863
|
+
console.error('[TnThemeService] Error removing from localStorage:', error);
|
|
9864
|
+
}
|
|
9865
|
+
}
|
|
9866
|
+
this.userSelected.set(false);
|
|
9867
|
+
this.applySystemTheme();
|
|
9868
|
+
this.listenForColorSchemeChanges();
|
|
9817
9869
|
}
|
|
9818
9870
|
/**
|
|
9819
9871
|
* Check if a theme exists
|
|
@@ -9822,7 +9874,7 @@ class TnThemeService {
|
|
|
9822
9874
|
return THEME_MAP.has(theme);
|
|
9823
9875
|
}
|
|
9824
9876
|
/**
|
|
9825
|
-
* Initialize theme from localStorage or
|
|
9877
|
+
* Initialize theme from localStorage or OS color scheme preference
|
|
9826
9878
|
*/
|
|
9827
9879
|
initializeTheme() {
|
|
9828
9880
|
if (!this.isBrowser) {
|
|
@@ -9831,18 +9883,54 @@ class TnThemeService {
|
|
|
9831
9883
|
try {
|
|
9832
9884
|
const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
|
|
9833
9885
|
if (storedTheme && this.hasTheme(storedTheme)) {
|
|
9886
|
+
this.userSelected.set(true);
|
|
9834
9887
|
this.currentThemeSignal.set(storedTheme);
|
|
9835
9888
|
}
|
|
9836
9889
|
else {
|
|
9837
|
-
//
|
|
9838
|
-
this.
|
|
9890
|
+
// No valid stored theme — detect from OS preference
|
|
9891
|
+
this.applySystemTheme();
|
|
9892
|
+
this.listenForColorSchemeChanges();
|
|
9839
9893
|
}
|
|
9840
9894
|
}
|
|
9841
9895
|
catch (error) {
|
|
9842
9896
|
console.error('[TnThemeService] Error reading from localStorage:', error);
|
|
9897
|
+
this.applySystemTheme();
|
|
9898
|
+
this.listenForColorSchemeChanges();
|
|
9899
|
+
}
|
|
9900
|
+
}
|
|
9901
|
+
/**
|
|
9902
|
+
* Detect OS color scheme preference and apply corresponding theme
|
|
9903
|
+
*/
|
|
9904
|
+
applySystemTheme() {
|
|
9905
|
+
if (!this.isBrowser) {
|
|
9906
|
+
return;
|
|
9907
|
+
}
|
|
9908
|
+
try {
|
|
9909
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
9910
|
+
this.currentThemeSignal.set(prefersDark ? DEFAULT_THEME : LIGHT_THEME);
|
|
9911
|
+
}
|
|
9912
|
+
catch {
|
|
9843
9913
|
this.currentThemeSignal.set(DEFAULT_THEME);
|
|
9844
9914
|
}
|
|
9845
9915
|
}
|
|
9916
|
+
/**
|
|
9917
|
+
* Listen for OS color scheme changes and apply them when no user preference is set
|
|
9918
|
+
*/
|
|
9919
|
+
listenForColorSchemeChanges() {
|
|
9920
|
+
if (!this.isBrowser || this.colorSchemeQuery) {
|
|
9921
|
+
return;
|
|
9922
|
+
}
|
|
9923
|
+
try {
|
|
9924
|
+
this.colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
9925
|
+
this.colorSchemeQuery.addEventListener('change', this.colorSchemeListener);
|
|
9926
|
+
this.destroyRef.onDestroy(() => {
|
|
9927
|
+
this.colorSchemeQuery?.removeEventListener('change', this.colorSchemeListener);
|
|
9928
|
+
});
|
|
9929
|
+
}
|
|
9930
|
+
catch {
|
|
9931
|
+
// matchMedia not supported — fall through silently
|
|
9932
|
+
}
|
|
9933
|
+
}
|
|
9846
9934
|
/**
|
|
9847
9935
|
* Apply theme CSS class to document root.
|
|
9848
9936
|
* Removes all other theme classes first to avoid conflicts.
|
|
@@ -9901,5 +9989,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
9901
9989
|
* Generated bundle index. Do not edit.
|
|
9902
9990
|
*/
|
|
9903
9991
|
|
|
9904
|
-
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, 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, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTabsHarness, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
|
|
9992
|
+
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, 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, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTabsHarness, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
|
|
9905
9993
|
//# sourceMappingURL=truenas-ui-components.mjs.map
|