1
1
export const IS_BROWSER = typeof window !== 'undefined'
2
2
3
3
export default class Darkmode {
4
+ /**
5
+ * Create new Darkmode instance
6
+ * @constructor
7
+ * @param {?object } options - object containing options
8
+ */
4
9
constructor ( options ) {
5
10
const defaultOptions = {
6
11
top : 'unset' ,
@@ -18,26 +23,45 @@ export default class Darkmode {
18
23
defaultTheme : 'light'
19
24
}
20
25
26
+ // Parse options based on parameters and defaults
21
27
options = Object . assign ( { } , defaultOptions , options )
22
28
29
+ // Initialize values
23
30
this . options = options
24
31
this . dark = false
25
32
33
+ // Listen for prefers-color-scheme change
26
34
if ( options . autoMatchOsTheme ) {
27
35
window . matchMedia ( '(prefers-color-scheme: dark)' ) . addListener ( ( e ) => e . matches && this . _switchThemePrefers ( ) )
28
36
window . matchMedia ( '(prefers-color-scheme: light)' ) . addListener ( ( e ) => e . matches && this . _switchThemePrefers ( ) )
29
37
}
30
38
31
- const storageValue = this . _getStorageValue ( )
32
- if ( storageValue !== null ) {
33
- storageValue === 'true' || storageValue === true ? this . toDark ( ) : this . toLight ( )
34
- } else if ( options . autoMatchOsTheme ) {
35
- this . _preferedTheme ( ) ? this . toDark ( ) : this . toLight ( )
36
- } else {
37
- options . defaultTheme === 'light' ? this . toLight ( ) : this . toDark ( )
39
+ // Determine to which theme should be set, start with default, precendence based on descending order
40
+ let changeToDark = options . defaultTheme !== 'light'
41
+
42
+ // First check the system theme
43
+ if ( options . autoMatchOsTheme ) {
44
+ changeToDark = this . _preferedThemeIsDark ( )
45
+ }
46
+
47
+ // Then check if a cookie is set
48
+ if ( this . options . cookie ) {
49
+ const match = document . cookie . match ( RegExp ( '(?:^|;\\s*)darkmode=([^;]*)' ) )
50
+ changeToDark = match ? match [ 1 ] === 'true' : null
51
+ }
52
+
53
+ // Lastly check local storage
54
+ if ( this . options . localStorage && window . localStorage !== null ) {
55
+ changeToDark = window . localStorage . getItem ( 'darkmode' ) === 'true'
38
56
}
57
+
58
+ // Change the theme to dark if true or light if false
59
+ this . _changeThemeToDark ( changeToDark )
39
60
}
40
61
62
+ /**
63
+ * Attach the theme toggle to the page
64
+ */
41
65
attach ( ) {
42
66
const css = `
43
67
.drkmd-toggle-button{
@@ -71,13 +95,15 @@ export default class Darkmode {
71
95
72
96
const div = document . createElement ( 'div' )
73
97
const span = document . createElement ( 'span' )
98
+
74
99
span . innerHTML = this . options . label
75
100
div . className = 'drkmd-toggle-button'
76
101
77
102
div . setAttribute ( 'title' , 'Toggle dark mode' )
78
103
div . setAttribute ( 'aria-label' , 'Toggle dark mode' )
79
104
div . setAttribute ( 'aria-checked' , 'false' )
80
105
div . setAttribute ( 'role' , 'checkbox' )
106
+
81
107
div . appendChild ( span )
82
108
83
109
div . addEventListener ( 'click' , ( ) => {
@@ -88,6 +114,9 @@ export default class Darkmode {
88
114
this . _addStyle ( css )
89
115
}
90
116
117
+ /**
118
+ * Change the theme to light
119
+ */
91
120
toLight ( ) {
92
121
if ( this . options . events ) window . dispatchEvent ( new CustomEvent ( 'theme-change' , { detail : { to : 'light' } } ) )
93
122
@@ -99,6 +128,9 @@ export default class Darkmode {
99
128
this . dark = false
100
129
}
101
130
131
+ /**
132
+ * Change the theme to dark
133
+ */
102
134
toDark ( ) {
103
135
if ( this . options . events ) window . dispatchEvent ( new CustomEvent ( 'theme-change' , { detail : { to : 'dark' } } ) )
104
136
@@ -110,39 +142,71 @@ export default class Darkmode {
110
142
this . dark = true
111
143
}
112
144
145
+ /**
146
+ * Toggle between the dark and light theme based on the current one
147
+ * @returns {boolean } isDark - true if theme is now dark and false if it is light
148
+ */
113
149
toggle ( ) {
114
- this . dark ? this . toLight ( ) : this . toDark ( )
115
- return this . dark
150
+ const val = ! this . dark
151
+ this . _changeThemeToDark ( val )
152
+ return val
116
153
}
117
154
155
+ /**
156
+ * Check if the darkmode is activated
157
+ * @deprecated Use isDark and isLight
158
+ * @returns {boolean } isDark - true if theme is dark and false if it is light
159
+ */
118
160
isActivated ( ) {
119
161
return this . dark
120
162
}
121
163
122
- _preferedTheme ( ) {
164
+ /**
165
+ * Determine if the current theme is dark
166
+ * @returns {boolean } isDark - true if theme is dark and false if it is light
167
+ */
168
+ isDark ( ) {
169
+ return this . dark === true
170
+ }
171
+
172
+ /**
173
+ * Determine if the current theme is light
174
+ * @returns {boolean } isLight - true if theme is light and false if it is dark
175
+ */
176
+ isLight ( ) {
177
+ return this . dark === false
178
+ }
179
+
180
+ /**
181
+ * Return the current theme as a string
182
+ * @returns {string } theme - either dark or light
183
+ */
184
+ currentTheme ( ) {
185
+ return this . dark ? 'dark' : 'light'
186
+ }
187
+
188
+ _preferedThemeIsDark ( ) {
123
189
return window . matchMedia && window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches
124
190
}
125
191
126
192
_switchThemePrefers ( ) {
127
- this . _preferedTheme ( ) === true ? this . toDark ( ) : this . toLight ( )
193
+ const val = this . _preferedThemeIsDark ( )
194
+ this . _changeThemeToDark ( val )
128
195
}
129
196
130
- _getStorageValue ( ) {
131
- if ( this . options . localStorage && window . localStorage !== null ) {
132
- return window . localStorage . getItem ( 'darkmode' )
133
- } else if ( this . options . cookie ) {
134
- const match = document . cookie . match ( RegExp ( '(?:^|;\\s*)darkmode=([^;]*)' ) )
135
- return match ? match [ 1 ] : null
136
- }
137
-
138
- return null
197
+ _changeThemeToDark ( toDark ) {
198
+ toDark ? this . toDark ( ) : this . toLight ( )
139
199
}
140
200
141
201
_setStorageValue ( value ) {
142
202
if ( this . options . localStorage && window . localStorage !== null ) {
143
203
window . localStorage . setItem ( 'darkmode' , value )
144
- } else if ( this . options . cookie ) {
204
+ return
205
+ }
206
+
207
+ if ( this . options . cookie ) {
145
208
document . cookie = `darkmode=${ value } `
209
+ return
146
210
}
147
211
}
148
212
0 commit comments