@gsa-tts/graymatter-ui 0.4.17 → 0.4.19
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/dist/graymatter-ui.js +1811 -1774
- package/dist/graymatter-ui.umd.cjs +6 -6
- package/package.json +1 -1
- package/src/components/ApiDocSubNavMenu.svelte +21 -4
- package/src/components/DesktopSideNav.svelte +28 -18
- package/src/components/DesktopSideNav.webcomponent.svelte +2 -0
- package/src/components/MobileBottomNav.svelte +9 -3
- package/src/components/MobileBottomNav.webcomponent.svelte +2 -0
package/package.json
CHANGED
|
@@ -187,6 +187,17 @@
|
|
|
187
187
|
let currentSelectedId = $state<string | null>(null);
|
|
188
188
|
let hydrated = $state(false);
|
|
189
189
|
let pageLoadComplete = $state(false);
|
|
190
|
+
let scrollTimeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
191
|
+
|
|
192
|
+
function queueScrollToAnchor(hash: string, delay: number) {
|
|
193
|
+
if (scrollTimeoutId) {
|
|
194
|
+
clearTimeout(scrollTimeoutId);
|
|
195
|
+
}
|
|
196
|
+
scrollTimeoutId = setTimeout(() => {
|
|
197
|
+
scrollTimeoutId = null;
|
|
198
|
+
scrollToAnchorWithOffset(hash);
|
|
199
|
+
}, delay);
|
|
200
|
+
}
|
|
190
201
|
|
|
191
202
|
const effectiveSelectedId = $derived(() => {
|
|
192
203
|
if (!hydrated || !data) return null;
|
|
@@ -296,13 +307,20 @@
|
|
|
296
307
|
if (targetItem && targetItem.href && targetItem.href.includes('#')) {
|
|
297
308
|
const hash = targetItem.href.split('#')[1];
|
|
298
309
|
if (hash) {
|
|
299
|
-
|
|
310
|
+
queueScrollToAnchor(hash, 100);
|
|
300
311
|
}
|
|
301
312
|
}
|
|
302
313
|
|
|
303
314
|
// Mark page load as complete
|
|
304
315
|
pageLoadComplete = true;
|
|
305
316
|
subNavReady.set(true);
|
|
317
|
+
|
|
318
|
+
return () => {
|
|
319
|
+
if (scrollTimeoutId) {
|
|
320
|
+
clearTimeout(scrollTimeoutId);
|
|
321
|
+
scrollTimeoutId = null;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
306
324
|
});
|
|
307
325
|
|
|
308
326
|
function handleItemClick(event: Event, item: SubNavItem) {
|
|
@@ -332,9 +350,7 @@
|
|
|
332
350
|
window.location.hash = hash;
|
|
333
351
|
if (window.innerWidth > 640) {
|
|
334
352
|
// Desktop: use delay for consistent timing
|
|
335
|
-
|
|
336
|
-
scrollToAnchorWithOffset(hash);
|
|
337
|
-
}, 350);
|
|
353
|
+
queueScrollToAnchor(hash, 350);
|
|
338
354
|
} else {
|
|
339
355
|
// Mobile: immediate scroll without delay
|
|
340
356
|
window.dispatchEvent(
|
|
@@ -382,6 +398,7 @@
|
|
|
382
398
|
|
|
383
399
|
// Utility: Scroll to anchor with header offset
|
|
384
400
|
function scrollToAnchorWithOffset(anchorId: string) {
|
|
401
|
+
if (typeof document === 'undefined') return;
|
|
385
402
|
const mainContent = document.getElementById('main-content');
|
|
386
403
|
if (mainContent) {
|
|
387
404
|
const anchor = mainContent.querySelector(
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* -
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
3
|
+
* Initial selection for SSR/first paint.
|
|
4
|
+
* - Discover page: set ssrSelectedItem="discover".
|
|
5
|
+
* - Other pages: set ssrSelectedItem to the nav key (e.g., "api", "chat", "console").
|
|
6
|
+
* - Omit to default to expanded/open on SSR.
|
|
7
|
+
*
|
|
8
|
+
* controlledSelectedItem overrides the nav store after hydration.
|
|
9
|
+
* - Use for web component integrations where bundle/app stores can diverge.
|
|
10
|
+
* - In Svelte/SvelteKit apps, prefer NavigationInitializer and omit
|
|
11
|
+
* controlledSelectedItem to keep store-driven behavior.
|
|
7
12
|
*/
|
|
8
13
|
import { onMount } from 'svelte';
|
|
9
14
|
import {
|
|
@@ -23,6 +28,7 @@
|
|
|
23
28
|
|
|
24
29
|
const {
|
|
25
30
|
ssrSelectedItem = undefined,
|
|
31
|
+
controlledSelectedItem = undefined,
|
|
26
32
|
onNavToggle = undefined,
|
|
27
33
|
onNavItemClick = undefined,
|
|
28
34
|
showAppIcons = true,
|
|
@@ -79,8 +85,16 @@
|
|
|
79
85
|
return hydrated ? hydratedValue : ssrValue;
|
|
80
86
|
}
|
|
81
87
|
|
|
88
|
+
const selectedForUi = $derived(() => controlledSelectedItem ?? $selectedItem);
|
|
89
|
+
const ssrSelectedForUi = $derived(
|
|
90
|
+
() => controlledSelectedItem ?? ssrSelectedItem
|
|
91
|
+
);
|
|
92
|
+
const ssrSelected = $derived(() => ssrSelectedForUi());
|
|
93
|
+
const ssrIsDiscover = $derived(() => ssrSelected() === 'discover');
|
|
94
|
+
const isMenuDisabledForUi = $derived(() => selectedForUi() === 'discover');
|
|
95
|
+
|
|
82
96
|
function isNavSelected(key: NavigationItem) {
|
|
83
|
-
return ssrOrHydrated(
|
|
97
|
+
return ssrOrHydrated(selectedForUi() === key, ssrSelectedForUi() === key);
|
|
84
98
|
}
|
|
85
99
|
|
|
86
100
|
function isNavHovered(key: string) {
|
|
@@ -88,22 +102,16 @@
|
|
|
88
102
|
}
|
|
89
103
|
|
|
90
104
|
const sideNavExpanded = $derived(() =>
|
|
91
|
-
ssrOrHydrated(
|
|
92
|
-
$isExpanded,
|
|
93
|
-
ssrSelectedItem ? ssrSelectedItem !== 'discover' : true
|
|
94
|
-
)
|
|
105
|
+
ssrOrHydrated($isExpanded, ssrSelected() ? !ssrIsDiscover() : true)
|
|
95
106
|
);
|
|
96
107
|
const menuBtnDisabled = $derived(() =>
|
|
97
108
|
ssrOrHydrated(
|
|
98
|
-
|
|
99
|
-
|
|
109
|
+
isMenuDisabledForUi(),
|
|
110
|
+
ssrSelected() ? ssrIsDiscover() : false
|
|
100
111
|
)
|
|
101
112
|
);
|
|
102
113
|
const menuBtnOpen = $derived(() =>
|
|
103
|
-
ssrOrHydrated(
|
|
104
|
-
$isExpanded,
|
|
105
|
-
ssrSelectedItem ? ssrSelectedItem !== 'discover' : true
|
|
106
|
-
)
|
|
114
|
+
ssrOrHydrated($isExpanded, ssrSelected() ? !ssrIsDiscover() : true)
|
|
107
115
|
);
|
|
108
116
|
const menuBtnHovered = $derived(
|
|
109
117
|
() => canHover && menuButtonHovered && !menuBtnDisabled()
|
|
@@ -138,7 +146,7 @@
|
|
|
138
146
|
navigationStore.setExpanded(false);
|
|
139
147
|
} else {
|
|
140
148
|
// Switching to desktop: open navigation if on non-discover page
|
|
141
|
-
const currentItem =
|
|
149
|
+
const currentItem = selectedForUi();
|
|
142
150
|
|
|
143
151
|
if (currentItem && currentItem !== 'discover') {
|
|
144
152
|
navigationStore.setExpanded(true);
|
|
@@ -220,7 +228,7 @@
|
|
|
220
228
|
}
|
|
221
229
|
|
|
222
230
|
function toggleNav() {
|
|
223
|
-
if (
|
|
231
|
+
if (menuBtnDisabled()) return;
|
|
224
232
|
navigationStore.toggleExpanded();
|
|
225
233
|
onNavToggle?.({ expanded: $isExpanded });
|
|
226
234
|
}
|
|
@@ -231,7 +239,9 @@
|
|
|
231
239
|
sessionStorage.setItem('navigatingToMainNav', 'true');
|
|
232
240
|
}
|
|
233
241
|
|
|
234
|
-
|
|
242
|
+
if (controlledSelectedItem === undefined) {
|
|
243
|
+
navigationStore.setSelectedItem(item);
|
|
244
|
+
}
|
|
235
245
|
|
|
236
246
|
// Clear header state for main navigation items (including discover)
|
|
237
247
|
if (item !== 'discover') {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// Props for the web component
|
|
11
11
|
let {
|
|
12
12
|
ssrSelectedItem,
|
|
13
|
+
controlledSelectedItem,
|
|
13
14
|
onNavToggle,
|
|
14
15
|
onNavItemClick,
|
|
15
16
|
showAppIcons = true,
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
|
|
26
27
|
<DesktopSideNav
|
|
27
28
|
{ssrSelectedItem}
|
|
29
|
+
{controlledSelectedItem}
|
|
28
30
|
{onNavToggle}
|
|
29
31
|
{onNavItemClick}
|
|
30
32
|
{showAppIcons}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
chatUrl,
|
|
15
15
|
consoleUrl,
|
|
16
16
|
discoverUrl,
|
|
17
|
+
controlledSelectedItem = undefined,
|
|
17
18
|
}: {
|
|
18
19
|
onNavItemClick?: (data: {
|
|
19
20
|
item: NavigationItem;
|
|
@@ -25,8 +26,11 @@
|
|
|
25
26
|
chatUrl?: string;
|
|
26
27
|
consoleUrl?: string;
|
|
27
28
|
discoverUrl?: string;
|
|
29
|
+
controlledSelectedItem?: NavigationItem;
|
|
28
30
|
} = $props();
|
|
29
31
|
|
|
32
|
+
const selectedForUi = $derived(() => controlledSelectedItem ?? $selectedItem);
|
|
33
|
+
|
|
30
34
|
const allNavItems = [
|
|
31
35
|
{
|
|
32
36
|
id: 'discover',
|
|
@@ -55,7 +59,9 @@
|
|
|
55
59
|
sessionStorage.setItem('navigatingToMainNav', 'true');
|
|
56
60
|
}
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
if (controlledSelectedItem === undefined) {
|
|
63
|
+
navigationStore.setSelectedItem(item);
|
|
64
|
+
}
|
|
59
65
|
|
|
60
66
|
// Clear header state for main navigation items (including discover)
|
|
61
67
|
if (item !== 'discover') {
|
|
@@ -130,12 +136,12 @@
|
|
|
130
136
|
<a
|
|
131
137
|
href={navItem.href}
|
|
132
138
|
class={`nav-item ${navItem.id}-item`}
|
|
133
|
-
class:active={
|
|
139
|
+
class:active={selectedForUi() === navItem.id}
|
|
134
140
|
onclick={() => handleNavItemClick(navItem.id)}
|
|
135
141
|
part={`${navItem.id}-item`}
|
|
136
142
|
>
|
|
137
143
|
<div class="icon">
|
|
138
|
-
<navItem.icon isSelected={
|
|
144
|
+
<navItem.icon isSelected={selectedForUi() === navItem.id} />
|
|
139
145
|
</div>
|
|
140
146
|
<span class="label">{navItem.label}</span>
|
|
141
147
|
</a>
|