@bagelink/vue 1.5.5 → 1.5.9

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.5.5",
4
+ "version": "1.5.9",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -51,8 +51,9 @@ function isSelected(value: string | number) {
51
51
  <div class="flex flex-wrap gap-05 SelectBtn">
52
52
  <Btn
53
53
  v-for="option in options" :key="option.value" :thin="thin" :outline="outline"
54
- :class="isSelected(option.value) ? 'primary' : 'bg-transparent'" type="button"
55
- class="border px-075 radius-2" @click="toggleOption(option.value)"
54
+ :class="isSelected(option.value) ? 'primary color-white' : 'bg-transparent'"
55
+ :style="{ color: 'var(--bgl-border-color)' }" type="button" class="border px-075 radius-2"
56
+ @click="toggleOption(option.value)"
56
57
  >
57
58
  <Icon v-if="option.icon" :name="option.icon" weight="300" />
58
59
  <p>{{ option.label }}</p>
@@ -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
+ }