@bagelink/vue 1.5.5 → 1.5.7
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.
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/index.d.ts.map +1 -1
- package/dist/composables/useTheme.d.ts +46 -0
- package/dist/composables/useTheme.d.ts.map +1 -0
- package/dist/index.cjs +7 -7
- package/dist/index.mjs +7 -7
- package/package.json +1 -1
- package/src/composables/index.ts +1 -0
- package/src/composables/useTheme.ts +158 -0
package/package.json
CHANGED
package/src/composables/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { getBagelInstance, setBagelInstance, useBagel } from './useBagel'
|
|
|
8
8
|
export { useDevice } from './useDevice'
|
|
9
9
|
export { useExcel } from './useExcel'
|
|
10
10
|
export { usePolling } from './usePolling'
|
|
11
|
+
export { useTheme } from './useTheme'
|
|
11
12
|
interface UseBglSchemaParamsT<T> {
|
|
12
13
|
schema?: MaybeRefOrGetter<BglFormSchemaT<T>>
|
|
13
14
|
columns?: MaybeRefOrGetter<string[]>
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// composables/useTheme.ts
|
|
2
|
+
import { ref, computed, onMounted, watch } from 'vue'
|
|
3
|
+
|
|
4
|
+
export interface ThemeOption {
|
|
5
|
+
value: string
|
|
6
|
+
class: string
|
|
7
|
+
icon: string
|
|
8
|
+
label: string
|
|
9
|
+
isDark?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const themeOptions = ref<ThemeOption[]>([
|
|
13
|
+
{
|
|
14
|
+
value: 'dark',
|
|
15
|
+
class: 'bgl-dark-mode',
|
|
16
|
+
icon: 'cloudy_night',
|
|
17
|
+
label: 'Dark Mode',
|
|
18
|
+
isDark: true,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
value: 'light',
|
|
22
|
+
class: 'bgl-light-mode',
|
|
23
|
+
icon: 'brightness_7',
|
|
24
|
+
label: 'Light Mode',
|
|
25
|
+
isDark: false,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: 'system',
|
|
29
|
+
class: 'system',
|
|
30
|
+
icon: 'settings_input_component',
|
|
31
|
+
label: 'System Default',
|
|
32
|
+
},
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
const STORAGE_KEY = 'color-mode'
|
|
36
|
+
|
|
37
|
+
const colorMode = ref<string>('system')
|
|
38
|
+
const isDark = ref(false)
|
|
39
|
+
|
|
40
|
+
function getSystemPrefersDark() {
|
|
41
|
+
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function findTheme(value: string) {
|
|
45
|
+
return themeOptions.value.find(t => t.value === value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function applyTheme(themeValue: string) {
|
|
49
|
+
const root = document.documentElement
|
|
50
|
+
|
|
51
|
+
// Remove all theme classes
|
|
52
|
+
themeOptions.value.forEach((t) => {
|
|
53
|
+
if (t.class !== 'system') {
|
|
54
|
+
root.classList.remove(t.class)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
// Handle system theme
|
|
59
|
+
if (themeValue === 'system') {
|
|
60
|
+
const systemIsDark = getSystemPrefersDark()
|
|
61
|
+
isDark.value = systemIsDark
|
|
62
|
+
const darkTheme = themeOptions.value.find(t => t.value === 'dark')
|
|
63
|
+
const lightTheme = themeOptions.value.find(t => t.value === 'light')
|
|
64
|
+
const themeToApply = systemIsDark ? darkTheme : lightTheme
|
|
65
|
+
if (themeToApply) {
|
|
66
|
+
root.classList.add(themeToApply.class)
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
// Apply the selected theme
|
|
70
|
+
const theme = findTheme(themeValue)
|
|
71
|
+
if (theme) {
|
|
72
|
+
root.classList.add(theme.class)
|
|
73
|
+
isDark.value = theme.isDark ?? false
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toggleTheme() {
|
|
79
|
+
// Get all non-system themes
|
|
80
|
+
const cyclableThemes = themeOptions.value.filter(t => t.value !== 'system')
|
|
81
|
+
|
|
82
|
+
if (cyclableThemes.length === 0) return
|
|
83
|
+
|
|
84
|
+
const currentIndex = cyclableThemes.findIndex(t => t.value === colorMode.value)
|
|
85
|
+
const nextIndex = (currentIndex + 1) % cyclableThemes.length
|
|
86
|
+
colorMode.value = cyclableThemes[nextIndex].value
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function addTheme(theme: ThemeOption) {
|
|
90
|
+
// Check if theme with this value already exists
|
|
91
|
+
const exists = themeOptions.value.some(t => t.value === theme.value)
|
|
92
|
+
if (!exists) {
|
|
93
|
+
// Add before 'system' option
|
|
94
|
+
const systemIndex = themeOptions.value.findIndex(t => t.value === 'system')
|
|
95
|
+
if (systemIndex > -1) {
|
|
96
|
+
themeOptions.value.splice(systemIndex, 0, theme)
|
|
97
|
+
} else {
|
|
98
|
+
themeOptions.value.push(theme)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Provides a way to manage the theme of the application.
|
|
104
|
+
*
|
|
105
|
+
* The theme is stored in localStorage and can be toggled between 'dark', 'light', and 'system'.
|
|
106
|
+
* The theme is applied to the document root's classList when the theme is active.
|
|
107
|
+
* the classes are 'bgl-dark-mode', 'bgl-light-mode', and 'system'.
|
|
108
|
+
*
|
|
109
|
+
* Example usage:
|
|
110
|
+
* const { theme, isDark, toggleTheme, addTheme, setTheme } = useTheme()
|
|
111
|
+
* theme.value = 'dark'
|
|
112
|
+
* isDark.value = true
|
|
113
|
+
* toggleTheme()
|
|
114
|
+
* addTheme({ value: 'ocean', label: 'Ocean Blue', class: 'ocean-blue', isDark: false })
|
|
115
|
+
* setTheme('ocean')
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
export function useTheme() {
|
|
119
|
+
onMounted(() => {
|
|
120
|
+
const saved = window.localStorage.getItem(STORAGE_KEY)
|
|
121
|
+
const validTheme = themeOptions.value.find(t => t.value === saved)
|
|
122
|
+
|
|
123
|
+
if (validTheme) {
|
|
124
|
+
colorMode.value = saved!
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Apply initial theme
|
|
128
|
+
applyTheme(colorMode.value)
|
|
129
|
+
|
|
130
|
+
// React to system changes when in "system" mode
|
|
131
|
+
const mq = window.matchMedia('(prefers-color-scheme: dark)')
|
|
132
|
+
const handler = (e: MediaQueryListEvent) => {
|
|
133
|
+
if (colorMode.value === 'system') {
|
|
134
|
+
applyTheme('system')
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
mq.addEventListener('change', handler)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
// Watch for mode changes
|
|
141
|
+
watch(colorMode, (newMode) => {
|
|
142
|
+
window.localStorage.setItem(STORAGE_KEY, newMode)
|
|
143
|
+
applyTheme(newMode)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
const theme = computed(() => colorMode.value)
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
isDark,
|
|
150
|
+
theme,
|
|
151
|
+
themeOptions,
|
|
152
|
+
toggleTheme,
|
|
153
|
+
addTheme,
|
|
154
|
+
setTheme: (value: string) => {
|
|
155
|
+
colorMode.value = value
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
}
|