@opendocsdev/cli 0.2.2 → 0.2.3

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": "@opendocsdev/cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -111,17 +111,11 @@ export function SearchModal({ isOpen, onClose, backend, siteId }: SearchModalPro
111
111
 
112
112
  hasTrackedRef.current = true;
113
113
 
114
- fetch(`${backend}/api/analytics/sq`, {
115
- method: "POST",
116
- headers: { "Content-Type": "application/json" },
117
- body: JSON.stringify({
118
- siteId,
119
- query: searchQuery,
120
- resultCount,
121
- }),
122
- }).catch(() => {
123
- // Silently fail - analytics should not break search
124
- });
114
+ const blob = new Blob(
115
+ [JSON.stringify({ siteId, query: searchQuery, resultCount })],
116
+ { type: "application/json" }
117
+ );
118
+ navigator.sendBeacon(`${backend}/api/analytics/sq`, blob);
125
119
  }, [backend, siteId]);
126
120
 
127
121
  // Handle close with analytics tracking
@@ -187,6 +181,19 @@ export function SearchModal({ isOpen, onClose, backend, siteId }: SearchModalPro
187
181
  }
188
182
  }, [isOpen]);
189
183
 
184
+ // Global Escape key handler - works regardless of focus
185
+ useEffect(() => {
186
+ if (!isOpen) return;
187
+ const handleEscape = (e: KeyboardEvent) => {
188
+ if (e.key === "Escape") {
189
+ e.preventDefault();
190
+ handleClose();
191
+ }
192
+ };
193
+ document.addEventListener("keydown", handleEscape);
194
+ return () => document.removeEventListener("keydown", handleEscape);
195
+ }, [isOpen, handleClose]);
196
+
190
197
  // Scroll selected item into view
191
198
  useEffect(() => {
192
199
  if (resultsRef.current && results.length > 0) {
@@ -220,10 +227,6 @@ export function SearchModal({ isOpen, onClose, backend, siteId }: SearchModalPro
220
227
  handleResultSelect(results[selectedIndex].url);
221
228
  }
222
229
  break;
223
- case "Escape":
224
- e.preventDefault();
225
- handleClose();
226
- break;
227
230
  }
228
231
  };
229
232
 
@@ -236,13 +239,6 @@ export function SearchModal({ isOpen, onClose, backend, siteId }: SearchModalPro
236
239
  className="fixed inset-0 z-50"
237
240
  role="dialog"
238
241
  aria-modal="true"
239
- onKeyDown={(e) => {
240
- // Global escape handler for clicking outside input
241
- if (e.key === "Escape") {
242
- e.preventDefault();
243
- handleClose();
244
- }
245
- }}
246
242
  >
247
243
  {/* Backdrop */}
248
244
  <div
@@ -283,10 +283,17 @@ export function Sidebar({
283
283
  siteName,
284
284
  navigation,
285
285
  logo,
286
- currentPath,
286
+ currentPath: initialPath,
287
287
  githubUrl,
288
288
  }: SidebarProps) {
289
- // No more isDark state or MutationObserver - CSS handles theme switching
289
+ // Track current path locally so it updates after View Transition navigations
290
+ const [currentPath, setCurrentPath] = useState(initialPath);
291
+
292
+ useEffect(() => {
293
+ const updatePath = () => setCurrentPath(window.location.pathname);
294
+ document.addEventListener("astro:after-swap", updatePath);
295
+ return () => document.removeEventListener("astro:after-swap", updatePath);
296
+ }, []);
290
297
 
291
298
  return (
292
299
  <div className="flex flex-col h-full">
@@ -10,6 +10,7 @@ import { Sidebar } from "../components/react/Sidebar";
10
10
  import { PageFooter } from "../components/react/PageFooter";
11
11
  import { PageActions } from "../components/react/PageActions";
12
12
  import { SearchProvider } from "../components/react/SearchProvider";
13
+ import { ViewTransitions } from "astro:transitions";
13
14
  import { loadConfig } from "../lib/config.js";
14
15
  import { generateColorVariants, getPageNavigation } from "../lib/utils";
15
16
  import "../styles/global.css";
@@ -117,23 +118,20 @@ const { previous: previousPage, next: nextPage } = getPageNavigation(navigation,
117
118
  })} />
118
119
  )}
119
120
 
121
+ <ViewTransitions />
120
122
  <Analytics path={currentPath} />
121
123
 
122
124
  <!-- Theme init script - prevents flash of wrong theme -->
123
125
  <script is:inline>
124
- (function () {
125
- const storedTheme = localStorage.getItem("theme");
126
- if (storedTheme === "dark") {
127
- document.documentElement.classList.add("dark");
128
- } else if (storedTheme === "light") {
129
- document.documentElement.classList.remove("dark");
130
- } else {
131
- const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
132
- if (prefersDark) {
133
- document.documentElement.classList.add("dark");
134
- }
135
- }
136
- })();
126
+ function getThemePreference() {
127
+ const stored = localStorage.getItem("theme");
128
+ if (stored === "dark" || stored === "light") return stored;
129
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
130
+ }
131
+ document.documentElement.classList.toggle("dark", getThemePreference() === "dark");
132
+ document.addEventListener("astro:before-swap", function (e) {
133
+ e.newDocument.documentElement.classList.toggle("dark", getThemePreference() === "dark");
134
+ });
137
135
  </script>
138
136
 
139
137
  <!-- Theme injection from docs.json config -->
@@ -159,6 +157,7 @@ const { previous: previousPage, next: nextPage } = getPageNavigation(navigation,
159
157
  <aside class="hidden lg:block fixed inset-y-0 left-0 z-40 w-64 border-r border-[var(--color-border)] bg-[var(--color-surface-raised)]">
160
158
  <Sidebar
161
159
  client:load
160
+ transition:persist="desktop-sidebar"
162
161
  siteName={siteName}
163
162
  navigation={navigation}
164
163
  logo={logo}
@@ -182,6 +181,7 @@ const { previous: previousPage, next: nextPage } = getPageNavigation(navigation,
182
181
  <div class="h-full overflow-y-auto">
183
182
  <Sidebar
184
183
  client:load
184
+ transition:persist="mobile-sidebar"
185
185
  siteName={siteName}
186
186
  navigation={navigation}
187
187
  logo={logo}
@@ -276,7 +276,7 @@ const { previous: previousPage, next: nextPage } = getPageNavigation(navigation,
276
276
  </div>
277
277
 
278
278
  <!-- Search modal -->
279
- <SearchProvider client:load backend={backend} siteId={siteId} />
279
+ <SearchProvider client:load transition:persist="search" backend={backend} siteId={siteId} />
280
280
 
281
281
  <!-- Mobile sidebar toggle script -->
282
282
  <script src="../scripts/mobile-sidebar.ts"></script>