@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
|
@@ -111,17 +111,11 @@ export function SearchModal({ isOpen, onClose, backend, siteId }: SearchModalPro
|
|
|
111
111
|
|
|
112
112
|
hasTrackedRef.current = true;
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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>
|