@dashadmin/dash-utils 1.3.73 → 1.3.74-srcfree.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.
Files changed (66) hide show
  1. package/dist/components/LazyAppLoader.d.ts +17 -0
  2. package/dist/components/MinimalLayout.d.ts +6 -0
  3. package/dist/components/RouterComponent.d.ts +22 -0
  4. package/dist/components/index.d.ts +2 -0
  5. package/dist/contexts/IPCMessageBrokerContext.d.ts +42 -0
  6. package/dist/hooks/useCapacitorAppStateRefresh.d.ts +2 -0
  7. package/dist/hooks/useCapacitorKeyboard.d.ts +19 -0
  8. package/dist/hooks/useDeviceStorageSync.d.ts +4 -0
  9. package/dist/hooks/useDraggable.d.ts +24 -0
  10. package/dist/hooks/useMenuStateInit.d.ts +10 -0
  11. package/dist/hooks/useMobileDetection.d.ts +20 -0
  12. package/dist/hooks/useNotifications.d.ts +51 -0
  13. package/dist/hooks/useQuickSearch.d.ts +6 -0
  14. package/dist/hooks/useWindowSize.d.ts +6 -0
  15. package/dist/index.d.ts +30 -0
  16. package/dist/utils/authProviderUtils.d.ts +37 -0
  17. package/dist/utils/dashBootstrapApp.d.ts +9 -0
  18. package/dist/utils/dashDtorage.d.ts +8 -0
  19. package/dist/utils/dashIPCService.d.ts +93 -0
  20. package/dist/utils/dataProviderUtils.d.ts +44 -0
  21. package/dist/utils/electronStoreSync.d.ts +3 -0
  22. package/dist/utils/envUtils.d.ts +1 -0
  23. package/dist/utils/environmentBodyClasses.d.ts +11 -0
  24. package/dist/utils/isDev.d.ts +5 -0
  25. package/dist/utils/notificationPermission.d.ts +5 -0
  26. package/dist/utils/platformDetection.d.ts +13 -0
  27. package/dist/utils/priceFormatter.d.ts +2 -0
  28. package/dist/utils/resourceLoader.d.ts +8 -0
  29. package/dist/utils/speechService.d.ts +7 -0
  30. package/dist/utils/storedTheme.d.ts +11 -0
  31. package/dist/utils/updateDomCssVariables.d.ts +6 -0
  32. package/dist/utils/validation.d.ts +12 -0
  33. package/package.json +13 -10
  34. package/src/components/LazyAppLoader.tsx +0 -143
  35. package/src/components/MinimalLayout.tsx +0 -22
  36. package/src/components/RouterComponent.tsx +0 -169
  37. package/src/components/index.ts +0 -16
  38. package/src/contexts/IPCMessageBrokerContext.tsx +0 -303
  39. package/src/hooks/useCapacitorAppStateRefresh.ts +0 -34
  40. package/src/hooks/useCapacitorKeyboard.ts +0 -213
  41. package/src/hooks/useDeviceStorageSync.ts +0 -70
  42. package/src/hooks/useDraggable.ts +0 -133
  43. package/src/hooks/useMenuStateInit.ts +0 -85
  44. package/src/hooks/useMobileDetection.ts +0 -165
  45. package/src/hooks/useNotifications.ts +0 -220
  46. package/src/hooks/useQuickSearch.ts +0 -42
  47. package/src/hooks/useWindowSize.tsx +0 -36
  48. package/src/index.ts +0 -202
  49. package/src/utils/authProviderUtils.ts +0 -170
  50. package/src/utils/dashBootstrapApp.ts +0 -104
  51. package/src/utils/dashDtorage.tsx +0 -51
  52. package/src/utils/dashDtorage.tsx.old +0 -78
  53. package/src/utils/dashIPCService.ts +0 -204
  54. package/src/utils/dataProviderUtils.ts +0 -221
  55. package/src/utils/electronStoreSync.ts +0 -34
  56. package/src/utils/envUtils.tsx +0 -27
  57. package/src/utils/environmentBodyClasses.ts +0 -72
  58. package/src/utils/isDev.ts +0 -65
  59. package/src/utils/notificationPermission.ts +0 -57
  60. package/src/utils/platformDetection.ts +0 -98
  61. package/src/utils/priceFormatter.ts +0 -36
  62. package/src/utils/resourceLoader.ts +0 -107
  63. package/src/utils/speechService.ts +0 -112
  64. package/src/utils/storedTheme.ts +0 -60
  65. package/src/utils/updateDomCssVariables.tsx +0 -181
  66. package/src/utils/validation.ts +0 -147
@@ -1,27 +0,0 @@
1
- const getEnvironmentVariable = (environmentVariable: string): string => {
2
- /* @ts-ignore Expected access to process */
3
- const unvalidatedEnvironmentVariable = process.env[environmentVariable];
4
- /*if (!unvalidatedEnvironmentVariable) {
5
- throw new Error(
6
- `Couldn't find environment variable: ${environmentVariable}`,
7
- );
8
- } else {
9
- return unvalidatedEnvironmentVariable;
10
- }*/
11
- return unvalidatedEnvironmentVariable || null;
12
- };
13
-
14
-
15
- export const getEnv = (key: string) => {
16
-
17
- // @ts-ignore Expected access to process
18
- const PREFIX = process.env.ENV_PREFIX || process.env.NEXT_PUBLIC_ENV_PREFIX || process.env.VITE_ENV_PREFIX || process.env.REACT_ENV_PREFIX || 'VITE_';
19
- //console.log('GET ENV', PREFIX, key);
20
-
21
- if (PREFIX === 'NEXT_PUBLIC_') {
22
- return getEnvironmentVariable(PREFIX + key);
23
- }
24
- // @ts-ignore Expected access to process
25
- return process.env[PREFIX + key] || null;
26
-
27
- };
@@ -1,72 +0,0 @@
1
- /**
2
- * Environment Body Classes Utility
3
- *
4
- * Manages body CSS classes based on the runtime environment.
5
- * Useful for platform-specific styling (Electron, Mac, mobile, etc.)
6
- */
7
-
8
- export interface EnvironmentVars {
9
- PLATFORM_TYPE?: string;
10
- IS_ELECTRON?: boolean;
11
- IS_MAC?: boolean;
12
- IS_WINDOWS?: boolean;
13
- IS_LINUX?: boolean;
14
- PLATFORM?: string;
15
- }
16
-
17
- /**
18
- * Add environment-based classes to the document body
19
- * @param envVars - Environment variables object
20
- * @returns Cleanup function to remove the classes
21
- */
22
- export const setupEnvironmentBodyClasses = (envVars: EnvironmentVars): (() => void) => {
23
- if (typeof document === 'undefined') {
24
- return () => {}; // No-op for SSR
25
- }
26
-
27
- const { PLATFORM_TYPE, IS_ELECTRON, IS_MAC, IS_WINDOWS, IS_LINUX } = envVars;
28
- const classesToAdd: string[] = [];
29
-
30
- if (PLATFORM_TYPE) {
31
- document.body.classList.add(PLATFORM_TYPE);
32
- classesToAdd.push(PLATFORM_TYPE);
33
- }
34
-
35
- if (IS_ELECTRON) {
36
- document.body.classList.add('electron');
37
- classesToAdd.push('electron');
38
- }
39
-
40
- if (IS_MAC) {
41
- document.body.classList.add('mac');
42
- classesToAdd.push('mac');
43
- }
44
-
45
- if (IS_WINDOWS) {
46
- document.body.classList.add('windows');
47
- classesToAdd.push('windows');
48
- }
49
-
50
- if (IS_LINUX) {
51
- document.body.classList.add('linux');
52
- classesToAdd.push('linux');
53
- }
54
-
55
- // Return cleanup function
56
- return () => {
57
- classesToAdd.forEach(className => {
58
- document.body.classList.remove(className);
59
- });
60
- };
61
- };
62
-
63
- /**
64
- * React hook for environment body classes
65
- * Use with useEffect to automatically clean up on unmount
66
- */
67
- export const useEnvironmentBodyClasses = (envVars: EnvironmentVars): void => {
68
- // Note: This is a simple helper. For actual use, wrap in useEffect in your component:
69
- // useEffect(() => setupEnvironmentBodyClasses(envVars), [envVars]);
70
- };
71
-
72
- export default setupEnvironmentBodyClasses;
@@ -1,65 +0,0 @@
1
- /**
2
- * Development Environment Detection Utility
3
- *
4
- * Provides functions to check if the application is running
5
- * in a development environment.
6
- */
7
-
8
- // Safe check for Node.js process object
9
- const getNodeEnv = (): string | undefined => {
10
- try {
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
- if (typeof globalThis !== 'undefined' && (globalThis as any).process?.env?.NODE_ENV) {
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- return (globalThis as any).process.env.NODE_ENV;
15
- }
16
- } catch {
17
- // Ignore errors in environments where process is not available
18
- }
19
- return undefined;
20
- };
21
-
22
- /**
23
- * Check if the application is running in development mode
24
- * Detects localhost, 127.0.0.1, or development hostnames
25
- */
26
- export const isDev = (): boolean => {
27
- if (typeof window === 'undefined') {
28
- // Node.js environment - check for NODE_ENV
29
- return getNodeEnv() === 'development';
30
- }
31
-
32
- const { hostname } = window.location;
33
- return (
34
- hostname === 'localhost' ||
35
- hostname === '127.0.0.1' ||
36
- hostname.startsWith('192.168.') ||
37
- hostname.endsWith('.local') ||
38
- hostname.includes('dev.')
39
- );
40
- };
41
-
42
- /**
43
- * Check if running in production mode
44
- */
45
- export const isProd = (): boolean => {
46
- return !isDev();
47
- };
48
-
49
- /**
50
- * Check if running in test environment
51
- */
52
- export const isTest = (): boolean => {
53
- return getNodeEnv() === 'test';
54
- };
55
-
56
- /**
57
- * Get the current environment name
58
- */
59
- export const getEnvironment = (): 'development' | 'production' | 'test' => {
60
- if (isTest()) return 'test';
61
- if (isDev()) return 'development';
62
- return 'production';
63
- };
64
-
65
- export default isDev;
@@ -1,57 +0,0 @@
1
- /**
2
- * Notification Permission Utilities
3
- *
4
- * Utilities for managing browser notification permissions.
5
- */
6
-
7
- /**
8
- * Request browser notification permission
9
- * Only requests if permission is in 'default' state (not yet decided)
10
- *
11
- * @returns Promise that resolves when permission is granted or rejected
12
- *
13
- * @example
14
- * ```tsx
15
- * // Request permission on app startup
16
- * await requestNotificationPermission();
17
- *
18
- * // Check if granted
19
- * if (Notification.permission === 'granted') {
20
- * new Notification('Hello!');
21
- * }
22
- * ```
23
- */
24
- export const requestNotificationPermission = async (): Promise<NotificationPermission | null> => {
25
- if ('Notification' in window && Notification.permission === 'default') {
26
- return await Notification.requestPermission();
27
- }
28
- return Notification.permission ?? null;
29
- };
30
-
31
- /**
32
- * Check if notifications are supported in the current environment
33
- */
34
- export const isNotificationSupported = (): boolean => {
35
- return 'Notification' in window;
36
- };
37
-
38
- /**
39
- * Check if notification permission has been granted
40
- */
41
- export const hasNotificationPermission = (): boolean => {
42
- return 'Notification' in window && Notification.permission === 'granted';
43
- };
44
-
45
- /**
46
- * Check if notification permission has been denied
47
- */
48
- export const isNotificationDenied = (): boolean => {
49
- return 'Notification' in window && Notification.permission === 'denied';
50
- };
51
-
52
- /**
53
- * Get current notification permission status
54
- */
55
- export const getNotificationPermission = (): NotificationPermission | null => {
56
- return 'Notification' in window ? Notification.permission : null;
57
- };
@@ -1,98 +0,0 @@
1
- /**
2
- * Platform Detection Utilities
3
- *
4
- * Functions to detect the current platform/environment.
5
- * These are used to add appropriate body classes for platform-specific styling.
6
- */
7
-
8
- /**
9
- * Check if running in a WebView
10
- */
11
- export const isWebView = (): boolean => {
12
- if (typeof navigator === 'undefined') return false;
13
-
14
- const userAgent = navigator.userAgent.toLowerCase();
15
- console.log('userAgent', userAgent);
16
- return (/(webview|wv)/.test(userAgent) ||
17
- /android.*(wv|.net)/.test(userAgent) || /iphone|ipod|ipad.*applewebkit(?!.*safari)/i.test(userAgent));
18
- };
19
-
20
- /**
21
- * Check if running on Android
22
- */
23
- export const isAndroid = (): boolean => {
24
- if (typeof navigator === 'undefined') return false;
25
- return /android/i.test(navigator.userAgent.toLowerCase());
26
- };
27
-
28
- /**
29
- * Check if running on iOS
30
- */
31
- export const isIOS = (): boolean => {
32
- if (typeof navigator === 'undefined') return false;
33
- return /iphone|ipad|ipod/i.test(navigator.userAgent.toLowerCase());
34
- };
35
-
36
- /**
37
- * Check if running on Windows
38
- */
39
- export const isWindows = (): boolean => {
40
- try {
41
- // Check via globalThis to avoid process not defined errors
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- const globalProcess = (globalThis as any).process;
44
- const platform = globalProcess?.platform;
45
- return platform === 'win32' ||
46
- (typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().includes('windows'));
47
- } catch (error) {
48
- console.error('Error checking Windows platform:', error);
49
- return false;
50
- }
51
- };
52
-
53
- /**
54
- * Apply platform-specific body classes
55
- */
56
- export const applyPlatformBodyClasses = (): void => {
57
- if (typeof document === 'undefined') return;
58
-
59
- if (isWindows()) {
60
- document.body.classList.add('windows');
61
- }
62
-
63
- if (isWebView()) {
64
- console.log('webview');
65
- document.body.classList.add('webview');
66
-
67
- if (isAndroid()) {
68
- document.body.classList.add('android');
69
- }
70
-
71
- if (isIOS()) {
72
- document.body.classList.add('ios');
73
- }
74
- }
75
-
76
- // Add sanitized user agent as body class
77
- if (typeof navigator !== 'undefined' && navigator.userAgent) {
78
- const userAgent = navigator.userAgent.toLowerCase();
79
- // Sanitize user agent for use as CSS class
80
- const sanitizedUA = userAgent
81
- .replace(/[^a-z0-9]/g, '-') // Replace non-alphanumeric with hyphens
82
- .replace(/-+/g, '-') // Replace multiple hyphens with single
83
- .replace(/^-|-$/g, '') // Remove leading/trailing hyphens
84
- .substring(0, 100); // Limit length
85
-
86
- if (sanitizedUA) {
87
- document.body.classList.add(`ua-${sanitizedUA}`);
88
- }
89
- }
90
- };
91
-
92
- export default {
93
- isWebView,
94
- isAndroid,
95
- isIOS,
96
- isWindows,
97
- applyPlatformBodyClasses,
98
- };
@@ -1,36 +0,0 @@
1
- /***
2
- * Centralized price formatter for all currencies.
3
- *
4
- * Amounts are ALWAYS passed as their real value (never in cents).
5
- * - e.g. CLP 4990 → "$4.990"
6
- * - e.g. USD 6.00 → "$6.00"
7
- * - e.g. USD 6 → "$6"
8
- *
9
- * Formatting rules:
10
- * - CLP: always formatted as an integer (no decimals), with thousands separator.
11
- * - Other currencies: if the value is an integer → no decimals;
12
- * if the value has a fractional part → up to 2 decimal places.
13
- */
14
- export const priceFormatter = (price: number, currencyCode: string = 'CLP'): string => {
15
- // Ensure we work with an actual number
16
- const numericPrice = typeof price === 'number' ? price : parseFloat(String(price));
17
- if (isNaN(numericPrice)) return '$0';
18
-
19
- if (currencyCode === 'CLP') {
20
- // CLP never uses decimals – format as whole number with locale thousands separator
21
- return `$${Math.round(numericPrice).toLocaleString('es-CL')}`;
22
- }
23
-
24
- // For all other currencies: detect int vs float
25
- const isInteger = Number.isInteger(numericPrice);
26
-
27
- if (isInteger) {
28
- // Integer amount → no decimals, with thousands separator
29
- return `$${numericPrice.toLocaleString('en-US')}`;
30
- }
31
-
32
- // Float amount → up to 2 decimal places
33
- return `$${numericPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
34
- };
35
-
36
- export default priceFormatter;
@@ -1,107 +0,0 @@
1
- /**
2
- * Resource Loader Utility
3
- *
4
- * Provides a generic mechanism for lazy-loading and caching resources.
5
- * Useful for loading React-Admin resource configurations on demand.
6
- */
7
-
8
- /**
9
- * Creates a resource loader with caching support
10
- *
11
- * @param loadFn - Async function that loads the resources
12
- * @returns Object with getResources() method and cached resources array
13
- *
14
- * @example
15
- * ```typescript
16
- * const { getResources, resources } = createResourceLoader(async () => {
17
- * const [{ default: systemResources }, { default: todoResource }] = await Promise.all([
18
- * import('dash-admin/src/systemResources'),
19
- * import('@app/resources/demo/todoResource'),
20
- * ]);
21
- * return [...systemResources, todoResource];
22
- * });
23
- *
24
- * // Async usage (recommended)
25
- * const allResources = await getResources();
26
- *
27
- * // Sync usage (returns cached or empty array)
28
- * const cachedResources = resources;
29
- * ```
30
- */
31
- export const createResourceLoader = <T>(
32
- loadFn: () => Promise<T[]>
33
- ): {
34
- getResources: () => Promise<T[]>;
35
- resources: T[];
36
- clearCache: () => void;
37
- isLoaded: () => boolean;
38
- } => {
39
- let cachedResources: T[] | null = null;
40
- let loadingPromise: Promise<T[]> | null = null;
41
-
42
- const getResources = async (): Promise<T[]> => {
43
- // Return cached if available
44
- if (cachedResources) {
45
- return cachedResources;
46
- }
47
-
48
- // If already loading, return the existing promise to avoid duplicate loads
49
- if (loadingPromise) {
50
- return loadingPromise;
51
- }
52
-
53
- // Start loading
54
- loadingPromise = loadFn().then((resources) => {
55
- cachedResources = resources;
56
- loadingPromise = null;
57
- return resources;
58
- }).catch((error) => {
59
- loadingPromise = null;
60
- console.error('Failed to load resources:', error);
61
- throw error;
62
- });
63
-
64
- return loadingPromise;
65
- };
66
-
67
- const clearCache = (): void => {
68
- cachedResources = null;
69
- loadingPromise = null;
70
- };
71
-
72
- const isLoaded = (): boolean => {
73
- return cachedResources !== null;
74
- };
75
-
76
- // Return empty array for sync access, will be populated after getResources() is called
77
- const resources: T[] = [];
78
-
79
- return {
80
- getResources,
81
- resources,
82
- clearCache,
83
- isLoaded,
84
- };
85
- };
86
-
87
- /**
88
- * Simple resource loader for cases where you just need the async getter
89
- *
90
- * @param loadFn - Async function that loads the resources
91
- * @returns Async function that returns cached resources
92
- */
93
- export const createSimpleResourceLoader = <T>(
94
- loadFn: () => Promise<T[]>
95
- ): (() => Promise<T[]>) => {
96
- let cache: T[] | null = null;
97
-
98
- return async (): Promise<T[]> => {
99
- if (cache) {
100
- return cache;
101
- }
102
- cache = await loadFn();
103
- return cache;
104
- };
105
- };
106
-
107
- export default createResourceLoader;
@@ -1,112 +0,0 @@
1
- import { getDashIPCService, isElectron } from './dashIPCService';
2
-
3
- /**
4
- * Unified text-to-speech entry point, routed by platform:
5
- * - Android (native/Capacitor): @capacitor-community/text-to-speech
6
- * - Electron: window.DashIPCService -> Python tts_service (unchanged)
7
- * - Web/other: no-op (not yet supported)
8
- *
9
- * Capacitor is deliberately accessed via `window.Capacitor` rather than a
10
- * static `import ... from '@capacitor/core'`: the Android build externalizes
11
- * @capacitor/core from the Rollup bundle (it's injected as a global by the
12
- * native bridge at runtime), so a static import resolves to a bare, unbundled
13
- * specifier that the WebView cannot load.
14
- */
15
-
16
- interface CapacitorGlobal {
17
- isNativePlatform?: () => boolean;
18
- getPlatform?: () => string;
19
- Plugins?: {
20
- TextToSpeech?: {
21
- speak: (options: {
22
- text: string;
23
- lang?: string;
24
- rate?: number;
25
- pitch?: number;
26
- volume?: number;
27
- }) => Promise<unknown>;
28
- };
29
- };
30
- }
31
-
32
- const getCapacitor = (): CapacitorGlobal | undefined =>
33
- (window as unknown as { Capacitor?: CapacitorGlobal })?.Capacitor;
34
-
35
- const getTextToSpeechPlugin = () => getCapacitor()?.Plugins?.TextToSpeech;
36
-
37
- const LANG_LOCALE_MAP: Record<string, string> = {
38
- es: 'es-ES',
39
- en: 'en-US',
40
- pt: 'pt-BR',
41
- fr: 'fr-FR',
42
- de: 'de-DE',
43
- it: 'it-IT',
44
- };
45
-
46
- // The Electron/Python path accepts short codes (gTTS); the Capacitor plugin
47
- // expects BCP-47 locale tags, so only the Android branch needs this mapping.
48
- const toLocale = (lang?: string): string => {
49
- if (!lang) return LANG_LOCALE_MAP.es;
50
- if (lang.includes('-')) return lang;
51
- return LANG_LOCALE_MAP[lang.toLowerCase()] || lang;
52
- };
53
-
54
- const isNativeAndroid = (): boolean => {
55
- const capacitor = getCapacitor();
56
- return !!capacitor?.isNativePlatform?.() && capacitor.getPlatform?.() === 'android';
57
- };
58
-
59
- export const speak = (text: string, lang?: string): void => {
60
- if (!text) return;
61
-
62
- if (isNativeAndroid()) {
63
- const textToSpeech = getTextToSpeechPlugin();
64
- if (!textToSpeech) {
65
- console.warn('Native Android TTS plugin not available on window.Capacitor.Plugins');
66
- return;
67
- }
68
- textToSpeech
69
- .speak({ text, lang: toLocale(lang), rate: 1.0, pitch: 1.0, volume: 1.0 })
70
- .catch((error) => {
71
- console.error('Native Android TTS failed:', error);
72
- });
73
- return;
74
- }
75
-
76
- if (isElectron()) {
77
- getDashIPCService()?.speak({ message: text, lang });
78
- return;
79
- }
80
-
81
- // Web/other: no-op (unchanged behavior)
82
- };
83
-
84
- export const speakAsync = async (text: string, lang?: string): Promise<void> => {
85
- if (!text) return;
86
-
87
- if (isNativeAndroid()) {
88
- const textToSpeech = getTextToSpeechPlugin();
89
- if (!textToSpeech) {
90
- console.warn('Native Android TTS plugin not available on window.Capacitor.Plugins');
91
- return;
92
- }
93
- await textToSpeech.speak({ text, lang: toLocale(lang), rate: 1.0, pitch: 1.0, volume: 1.0 });
94
- return;
95
- }
96
-
97
- if (isElectron()) {
98
- const ipc = getDashIPCService() as (ReturnType<typeof getDashIPCService> & {
99
- speakAsync?: (text: string, lang?: string) => Promise<unknown>;
100
- });
101
- if (ipc?.speakAsync) {
102
- await ipc.speakAsync(text, lang);
103
- } else {
104
- ipc?.speak({ message: text, lang });
105
- }
106
- return;
107
- }
108
-
109
- // Web/other: no-op (unchanged behavior)
110
- };
111
-
112
- export default { speak, speakAsync };
@@ -1,60 +0,0 @@
1
- /**
2
- * Stored Theme Utility
3
- *
4
- * Handles theme persistence and initialization in localStorage
5
- * and the document's data-theme attribute.
6
- */
7
- import { dashStorage } from './dashDtorage';
8
-
9
- /**
10
- * Get the stored theme from localStorage
11
- */
12
- export const getStoredTheme = (): string | null => {
13
- return dashStorage.getItem('theme');
14
- };
15
-
16
- /**
17
- * Set the theme in localStorage and update the document attribute
18
- */
19
- export const setStoredTheme = (theme: string): void => {
20
- dashStorage.setItem('theme', theme);
21
- if (typeof document !== 'undefined') {
22
- document.documentElement.setAttribute('data-theme', theme);
23
- }
24
- };
25
-
26
- /**
27
- * Initialize the theme from storage or use a default
28
- * Sets both localStorage and the data-theme attribute
29
- */
30
- export const initializeStoredTheme = (defaultTheme: string): string => {
31
- const storedTheme = getStoredTheme();
32
- const themeToUse = storedTheme || defaultTheme;
33
-
34
- if (typeof document !== 'undefined') {
35
- document.documentElement.setAttribute('data-theme', themeToUse);
36
- }
37
-
38
- if (!storedTheme) {
39
- dashStorage.setItem('theme', defaultTheme);
40
- }
41
-
42
- return themeToUse;
43
- };
44
-
45
- /**
46
- * Clear the stored theme
47
- */
48
- export const clearStoredTheme = (): void => {
49
- dashStorage.removeItem('theme');
50
- if (typeof document !== 'undefined') {
51
- document.documentElement.removeAttribute('data-theme');
52
- }
53
- };
54
-
55
- export default {
56
- getStoredTheme,
57
- setStoredTheme,
58
- initializeStoredTheme,
59
- clearStoredTheme,
60
- };