@truenas/ui-components 0.1.22 → 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';
|
|
@@ -9643,6 +9643,10 @@ var TnTheme;
|
|
|
9643
9643
|
* Default theme used when no theme is set
|
|
9644
9644
|
*/
|
|
9645
9645
|
const DEFAULT_THEME = TnTheme.Dark;
|
|
9646
|
+
/**
|
|
9647
|
+
* Light theme used when OS preference is light
|
|
9648
|
+
*/
|
|
9649
|
+
const LIGHT_THEME = TnTheme.Blue;
|
|
9646
9650
|
/**
|
|
9647
9651
|
* localStorage key for storing the current theme name
|
|
9648
9652
|
*/
|
|
@@ -9711,7 +9715,8 @@ const THEME_MAP = new Map(TN_THEME_DEFINITIONS.map((theme) => [theme.name, theme
|
|
|
9711
9715
|
*
|
|
9712
9716
|
* Features:
|
|
9713
9717
|
* - Signal-based reactive theme state
|
|
9714
|
-
* -
|
|
9718
|
+
* - OS color scheme detection (prefers-color-scheme)
|
|
9719
|
+
* - LocalStorage persistence for explicit user choices (key: 'tn-theme')
|
|
9715
9720
|
* - Automatic CSS class application to document root
|
|
9716
9721
|
* - SSR-safe (checks for browser platform)
|
|
9717
9722
|
*
|
|
@@ -9731,9 +9736,12 @@ const THEME_MAP = new Map(TN_THEME_DEFINITIONS.map((theme) => [theme.name, theme
|
|
|
9731
9736
|
* // Get current theme (signal)
|
|
9732
9737
|
* const currentTheme = this.themeService.currentTheme();
|
|
9733
9738
|
*
|
|
9734
|
-
* // Set theme using enum (recommended)
|
|
9739
|
+
* // Set theme using enum (recommended) — persists to localStorage
|
|
9735
9740
|
* this.themeService.setTheme(TnTheme.Blue);
|
|
9736
9741
|
*
|
|
9742
|
+
* // Clear user preference and follow OS theme
|
|
9743
|
+
* this.themeService.clearPreference();
|
|
9744
|
+
*
|
|
9737
9745
|
* // React to theme changes
|
|
9738
9746
|
* effect(() => {
|
|
9739
9747
|
* console.log('Theme changed to:', this.themeService.currentTheme()?.label);
|
|
@@ -9745,10 +9753,28 @@ const THEME_MAP = new Map(TN_THEME_DEFINITIONS.map((theme) => [theme.name, theme
|
|
|
9745
9753
|
class TnThemeService {
|
|
9746
9754
|
platformId = inject(PLATFORM_ID);
|
|
9747
9755
|
isBrowser = isPlatformBrowser(this.platformId);
|
|
9756
|
+
destroyRef = inject(DestroyRef);
|
|
9748
9757
|
/**
|
|
9749
9758
|
* Internal signal holding the current theme enum value
|
|
9750
9759
|
*/
|
|
9751
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
|
+
};
|
|
9752
9778
|
/**
|
|
9753
9779
|
* Computed signal that returns the full theme definition for the current theme
|
|
9754
9780
|
*/
|
|
@@ -9762,12 +9788,16 @@ class TnThemeService {
|
|
|
9762
9788
|
currentThemeClass = computed(() => {
|
|
9763
9789
|
return this.currentTheme()?.className ?? TnTheme.Dark;
|
|
9764
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" }] : []));
|
|
9765
9795
|
/**
|
|
9766
9796
|
* All available theme definitions in the library (readonly array)
|
|
9767
9797
|
*/
|
|
9768
9798
|
availableThemes = TN_THEME_DEFINITIONS;
|
|
9769
9799
|
constructor() {
|
|
9770
|
-
// Initialize theme from localStorage or
|
|
9800
|
+
// Initialize theme from localStorage or OS preference
|
|
9771
9801
|
this.initializeTheme();
|
|
9772
9802
|
// Effect to apply theme CSS class to document root whenever theme changes
|
|
9773
9803
|
effect(() => {
|
|
@@ -9775,9 +9805,9 @@ class TnThemeService {
|
|
|
9775
9805
|
this.applyThemeToDOM(this.currentThemeClass());
|
|
9776
9806
|
}
|
|
9777
9807
|
});
|
|
9778
|
-
// Effect to persist theme to localStorage
|
|
9808
|
+
// Effect to persist theme to localStorage only for explicit user choices
|
|
9779
9809
|
effect(() => {
|
|
9780
|
-
if (this.isBrowser) {
|
|
9810
|
+
if (this.isBrowser && this.userSelected()) {
|
|
9781
9811
|
const theme = this.currentTheme();
|
|
9782
9812
|
if (theme) {
|
|
9783
9813
|
this.persistThemeToStorage(theme);
|
|
@@ -9787,7 +9817,8 @@ class TnThemeService {
|
|
|
9787
9817
|
}
|
|
9788
9818
|
/**
|
|
9789
9819
|
* Set the current theme.
|
|
9790
|
-
*
|
|
9820
|
+
* Marks this as an explicit user choice, persists to localStorage,
|
|
9821
|
+
* and stops following OS color scheme changes.
|
|
9791
9822
|
*
|
|
9792
9823
|
* @param theme - The theme to set (use TnTheme enum)
|
|
9793
9824
|
* @returns true if theme was found and set, false otherwise
|
|
@@ -9800,6 +9831,7 @@ class TnThemeService {
|
|
|
9800
9831
|
setTheme(theme) {
|
|
9801
9832
|
const themeDefinition = THEME_MAP.get(theme);
|
|
9802
9833
|
if (themeDefinition) {
|
|
9834
|
+
this.userSelected.set(true);
|
|
9803
9835
|
this.currentThemeSignal.set(theme);
|
|
9804
9836
|
return true;
|
|
9805
9837
|
}
|
|
@@ -9813,10 +9845,27 @@ class TnThemeService {
|
|
|
9813
9845
|
return this.currentThemeSignal();
|
|
9814
9846
|
}
|
|
9815
9847
|
/**
|
|
9816
|
-
* Reset theme to default
|
|
9848
|
+
* Reset theme to default by clearing user preference and reverting to OS detection.
|
|
9817
9849
|
*/
|
|
9818
9850
|
resetToDefault() {
|
|
9819
|
-
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();
|
|
9820
9869
|
}
|
|
9821
9870
|
/**
|
|
9822
9871
|
* Check if a theme exists
|
|
@@ -9825,7 +9874,7 @@ class TnThemeService {
|
|
|
9825
9874
|
return THEME_MAP.has(theme);
|
|
9826
9875
|
}
|
|
9827
9876
|
/**
|
|
9828
|
-
* Initialize theme from localStorage or
|
|
9877
|
+
* Initialize theme from localStorage or OS color scheme preference
|
|
9829
9878
|
*/
|
|
9830
9879
|
initializeTheme() {
|
|
9831
9880
|
if (!this.isBrowser) {
|
|
@@ -9834,18 +9883,54 @@ class TnThemeService {
|
|
|
9834
9883
|
try {
|
|
9835
9884
|
const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
|
|
9836
9885
|
if (storedTheme && this.hasTheme(storedTheme)) {
|
|
9886
|
+
this.userSelected.set(true);
|
|
9837
9887
|
this.currentThemeSignal.set(storedTheme);
|
|
9838
9888
|
}
|
|
9839
9889
|
else {
|
|
9840
|
-
//
|
|
9841
|
-
this.
|
|
9890
|
+
// No valid stored theme — detect from OS preference
|
|
9891
|
+
this.applySystemTheme();
|
|
9892
|
+
this.listenForColorSchemeChanges();
|
|
9842
9893
|
}
|
|
9843
9894
|
}
|
|
9844
9895
|
catch (error) {
|
|
9845
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 {
|
|
9846
9913
|
this.currentThemeSignal.set(DEFAULT_THEME);
|
|
9847
9914
|
}
|
|
9848
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
|
+
}
|
|
9849
9934
|
/**
|
|
9850
9935
|
* Apply theme CSS class to document root.
|
|
9851
9936
|
* Removes all other theme classes first to avoid conflicts.
|
|
@@ -9904,5 +9989,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
9904
9989
|
* Generated bundle index. Do not edit.
|
|
9905
9990
|
*/
|
|
9906
9991
|
|
|
9907
|
-
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 };
|
|
9908
9993
|
//# sourceMappingURL=truenas-ui-components.mjs.map
|