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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-gnix",
3
- "version": "5.0.9",
3
+ "version": "5.0.10",
4
4
  "author": "Efterklang <gaojiaxing0220@gmail.com>",
5
5
  "license": "MIT",
6
6
  "description": "Second generation of Hexo theme Icarus, now with Catppuccin flavor and night mode support.",
@@ -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
- const modal = document.getElementById("theme-selector-modal");
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
- // Set initial focus
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
- // Clear all focus states
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(themeOptions);
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(themeOptions);
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", (event) => {
154
- applyTheme(event.target.value, true);
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(themeOptions);
175
- // Small delay before closing to show selection
170
+ updateFocus();
176
171
  setTimeout(() => closeModal(true), 150);
177
172
  };
178
173