hexo-theme-gnix 5.0.9 → 5.0.10
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 +1 -1
- package/source/js/theme-selector.js +47 -52
package/package.json
CHANGED
|
@@ -18,20 +18,25 @@
|
|
|
18
18
|
let previewTheme = null;
|
|
19
19
|
let originalTheme = null;
|
|
20
20
|
let isModalOpen = false;
|
|
21
|
+
let modal = null;
|
|
22
|
+
let themeOptions = [];
|
|
21
23
|
|
|
22
24
|
function getThemePreference() {
|
|
23
25
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
24
26
|
return stored && stored in THEME_MAP ? stored : DEFAULT_THEME;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
function resolveTheme(theme) {
|
|
30
|
+
return theme === "system"
|
|
31
|
+
? colorSchemeMediaQuery.matches
|
|
32
|
+
? "mocha"
|
|
33
|
+
: "nord"
|
|
34
|
+
: theme;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
function applyTheme(theme, persist = false) {
|
|
28
38
|
const html = document.documentElement;
|
|
29
|
-
const resolvedTheme =
|
|
30
|
-
theme === "system"
|
|
31
|
-
? colorSchemeMediaQuery.matches
|
|
32
|
-
? "mocha"
|
|
33
|
-
: "nord"
|
|
34
|
-
: theme;
|
|
39
|
+
const resolvedTheme = resolveTheme(theme);
|
|
35
40
|
html.setAttribute("data-theme", resolvedTheme);
|
|
36
41
|
html.classList.remove("night", "light");
|
|
37
42
|
html.classList.add(THEME_MAP[resolvedTheme]);
|
|
@@ -41,82 +46,73 @@
|
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
|
|
49
|
+
function previewThemeOnOption(option, index) {
|
|
50
|
+
if (index === currentIndex) {
|
|
51
|
+
option.classList.add("is-focused");
|
|
52
|
+
option.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
53
|
+
|
|
54
|
+
const theme = option.getAttribute("data-theme-option");
|
|
55
|
+
if (theme !== previewTheme) {
|
|
56
|
+
previewTheme = theme;
|
|
57
|
+
applyTheme(theme);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
option.classList.remove("is-focused");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function updateFocus() {
|
|
65
|
+
themeOptions.forEach(previewThemeOnOption);
|
|
66
|
+
}
|
|
67
|
+
|
|
44
68
|
function openModal() {
|
|
45
|
-
|
|
69
|
+
modal = document.getElementById("theme-selector-modal");
|
|
46
70
|
if (!modal || isModalOpen) return;
|
|
47
71
|
|
|
48
72
|
isModalOpen = true;
|
|
49
73
|
originalTheme = getThemePreference();
|
|
74
|
+
themeOptions = modal.querySelectorAll(".theme-option");
|
|
50
75
|
|
|
51
|
-
// Find current theme index
|
|
52
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
53
76
|
themeOptions.forEach((option, index) => {
|
|
54
77
|
const theme = option.getAttribute("data-theme-option");
|
|
55
78
|
if (theme === originalTheme) {
|
|
56
79
|
currentIndex = index;
|
|
57
|
-
}
|
|
58
|
-
// Update active state
|
|
59
|
-
if (theme === originalTheme) {
|
|
60
80
|
option.classList.add("is-active");
|
|
61
81
|
} else {
|
|
62
82
|
option.classList.remove("is-active");
|
|
63
83
|
}
|
|
64
84
|
});
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
updateFocus(themeOptions);
|
|
86
|
+
updateFocus();
|
|
68
87
|
modal.classList.add("is-active");
|
|
69
88
|
}
|
|
70
89
|
|
|
71
90
|
function closeModal(apply = false) {
|
|
72
|
-
const modal = document.getElementById("theme-selector-modal");
|
|
73
91
|
if (!modal || !isModalOpen) return;
|
|
74
92
|
|
|
75
93
|
isModalOpen = false;
|
|
76
94
|
|
|
77
95
|
if (apply && previewTheme) {
|
|
78
|
-
// Apply the selected theme
|
|
79
96
|
applyTheme(previewTheme, true);
|
|
80
97
|
} else if (previewTheme && previewTheme !== originalTheme) {
|
|
81
|
-
// Restore original theme if cancelled
|
|
82
98
|
applyTheme(originalTheme);
|
|
83
99
|
}
|
|
84
100
|
|
|
85
101
|
modal.classList.remove("is-active");
|
|
102
|
+
themeOptions.forEach((option) => {
|
|
103
|
+
option.classList.remove("is-active");
|
|
104
|
+
option.classList.remove("is-focused");
|
|
105
|
+
});
|
|
106
|
+
|
|
86
107
|
previewTheme = null;
|
|
87
108
|
originalTheme = null;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
91
|
-
for (const t of themeOptions) {
|
|
92
|
-
t.classList.remove("is-active");
|
|
93
|
-
t.classList.remove("is-focused");
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function updateFocus(themeOptions) {
|
|
98
|
-
themeOptions.forEach((option, index) => {
|
|
99
|
-
if (index === currentIndex) {
|
|
100
|
-
option.classList.add("is-focused");
|
|
101
|
-
option.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
102
|
-
|
|
103
|
-
// Preview theme on focus
|
|
104
|
-
const theme = option.getAttribute("data-theme-option");
|
|
105
|
-
if (theme !== previewTheme) {
|
|
106
|
-
previewTheme = theme;
|
|
107
|
-
applyTheme(theme);
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
option.classList.remove("is-focused");
|
|
111
|
-
}
|
|
112
|
-
});
|
|
109
|
+
modal = null;
|
|
110
|
+
themeOptions = [];
|
|
113
111
|
}
|
|
114
112
|
|
|
115
113
|
function handleKeyboard(event) {
|
|
116
114
|
if (!isModalOpen) return;
|
|
117
115
|
|
|
118
|
-
const modal = document.getElementById("theme-selector-modal");
|
|
119
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
120
116
|
const maxIndex = themeOptions.length - 1;
|
|
121
117
|
|
|
122
118
|
switch (event.key) {
|
|
@@ -125,7 +121,7 @@
|
|
|
125
121
|
case "Down":
|
|
126
122
|
event.preventDefault();
|
|
127
123
|
currentIndex = currentIndex < maxIndex ? currentIndex + 1 : 0;
|
|
128
|
-
updateFocus(
|
|
124
|
+
updateFocus();
|
|
129
125
|
break;
|
|
130
126
|
|
|
131
127
|
case "k":
|
|
@@ -133,7 +129,7 @@
|
|
|
133
129
|
case "Up":
|
|
134
130
|
event.preventDefault();
|
|
135
131
|
currentIndex = currentIndex > 0 ? currentIndex - 1 : maxIndex;
|
|
136
|
-
updateFocus(
|
|
132
|
+
updateFocus();
|
|
137
133
|
break;
|
|
138
134
|
|
|
139
135
|
case "Enter":
|
|
@@ -150,8 +146,10 @@
|
|
|
150
146
|
}
|
|
151
147
|
|
|
152
148
|
// 监听系统主题改变
|
|
153
|
-
colorSchemeMediaQuery.addEventListener("change", (
|
|
154
|
-
|
|
149
|
+
colorSchemeMediaQuery.addEventListener("change", () => {
|
|
150
|
+
if (getThemePreference() === "system") {
|
|
151
|
+
applyTheme("system", true);
|
|
152
|
+
}
|
|
155
153
|
});
|
|
156
154
|
|
|
157
155
|
// 处理 modal 点击事件(关闭背景)
|
|
@@ -168,11 +166,8 @@
|
|
|
168
166
|
event.preventDefault();
|
|
169
167
|
event.stopPropagation();
|
|
170
168
|
|
|
171
|
-
const modal = document.getElementById("theme-selector-modal");
|
|
172
|
-
const themeOptions = modal.querySelectorAll(".theme-option");
|
|
173
169
|
currentIndex = index;
|
|
174
|
-
updateFocus(
|
|
175
|
-
// Small delay before closing to show selection
|
|
170
|
+
updateFocus();
|
|
176
171
|
setTimeout(() => closeModal(true), 150);
|
|
177
172
|
};
|
|
178
173
|
|