@gsa-tts/graymatter-ui 0.3.0 → 0.3.2
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/README.md +33 -3
- package/assets/images/ai-icons/check-circle.svg +3 -0
- package/assets/images/ai-icons/console-icon.svg +6 -6
- package/assets/images/ai-icons/pause-button.svg +5 -0
- package/assets/images/ai-icons/play-button.svg +4 -0
- package/assets/images/api-hero-image.webp +0 -0
- package/assets/images/api-icon-w.svg +3 -0
- package/assets/images/chat-hero-image-mobile.webp +0 -0
- package/assets/images/chat-hero-image.webp +0 -0
- package/assets/images/chat-icon-b.svg +4 -0
- package/assets/images/console-hero-image.webp +0 -0
- package/assets/images/console-icon-w.svg +6 -0
- package/assets/images/og-preview.webp +0 -0
- package/assets/images/partners/gemini-government-logo.svg +129 -0
- package/assets/images/partners/microsoft-logo.svg +14 -0
- package/dist/graymatter-ui.js +1943 -1829
- package/dist/graymatter-ui.umd.cjs +37 -15
- package/package.json +6 -6
- package/src/astro-config/index.ts +10 -0
- package/src/component-options/componentOptions.ts +27 -13
- package/src/components/Button.svelte +168 -6
- package/src/components/DesktopSideNav.webcomponent.svelte +2 -0
- package/src/components/GoogleTagManager.astro +1 -1
- package/src/components/Head.astro +58 -24
- package/src/components/MobileSideMenu.svelte +2 -2
- package/src/components/MobileSideMenu.webcomponent.svelte +2 -4
- package/src/components/MobileTopNav.svelte +9 -2
- package/src/components/MobileTopNav.webcomponent.svelte +2 -2
- package/src/components/icons/ExclamationIcon.svelte +24 -0
- package/src/components/icons/index.ts +1 -0
- package/src/helpers/url.ts +13 -4
- package/src/layouts/BaseLayout.astro +2 -4
- package/src/layouts/GlobalAppLayout.astro +9 -128
- package/src/styles/base/theme.css +6 -1
- package/src/styles/base/typography.css +8 -1
- package/src/utils/getAppUrls.ts +27 -4
- package/static/uswds/styles/styles.css +1 -1
- package/static/uswds/styles/styles.css.map +1 -1
- package/assets/images/api-hero-image.png +0 -0
- package/assets/images/chat-hero-image.png +0 -0
- package/assets/images/console-hero-image.png +0 -0
- package/assets/images/lp-bg-hero-1024.webp +0 -0
- package/assets/images/lp-bg-hero-1920.webp +0 -0
- package/assets/images/lp-bg-hero-640.webp +0 -0
- package/assets/images/lp-bg-hero.png +0 -0
- /package/assets/images/{api-icon.svg → api-icon-b.svg} +0 -0
- /package/assets/images/{chat-icon.svg → chat-icon-w.svg} +0 -0
- /package/assets/images/{console-icon.svg → console-icon-b.svg} +0 -0
|
@@ -19,10 +19,12 @@ const {
|
|
|
19
19
|
logoLinkUrl,
|
|
20
20
|
logoLinkLabel,
|
|
21
21
|
title: pageTitle,
|
|
22
|
+
description,
|
|
23
|
+
openGraphImage,
|
|
22
24
|
} = Astro.props;
|
|
23
25
|
---
|
|
24
26
|
|
|
25
|
-
<BaseLayout title={pageTitle}
|
|
27
|
+
<BaseLayout title={pageTitle} {gtmID} {description} {openGraphImage}>
|
|
26
28
|
<div class="app">
|
|
27
29
|
<!-- Desktop Navigation -->
|
|
28
30
|
<div class="layout-container">
|
|
@@ -48,7 +50,12 @@ const {
|
|
|
48
50
|
|
|
49
51
|
<!-- Mobile Navigation -->
|
|
50
52
|
<nav aria-label="Mobile navigation">
|
|
51
|
-
<MobileTopNav
|
|
53
|
+
<MobileTopNav
|
|
54
|
+
client:load
|
|
55
|
+
{profileMenuData}
|
|
56
|
+
{logoLinkUrl}
|
|
57
|
+
{logoLinkLabel}
|
|
58
|
+
/>
|
|
52
59
|
<MobileSideMenu client:load {logoLinkUrl} {logoLinkLabel}>
|
|
53
60
|
<slot name="sub-nav" />
|
|
54
61
|
</MobileSideMenu>
|
|
@@ -102,10 +109,6 @@ const {
|
|
|
102
109
|
const mobileRect = mobileContent.getBoundingClientRect();
|
|
103
110
|
const scrollTop =
|
|
104
111
|
mobileContent.scrollTop + rect.top - mobileRect.top;
|
|
105
|
-
console.log(
|
|
106
|
-
'[GlobalAppLayout] Immediate mobile scroll to:',
|
|
107
|
-
scrollTop
|
|
108
|
-
);
|
|
109
112
|
mobileContent.scrollTo({ top: scrollTop, behavior: 'auto' });
|
|
110
113
|
|
|
111
114
|
setTimeout(() => {
|
|
@@ -138,11 +141,6 @@ const {
|
|
|
138
141
|
if (mainContent) {
|
|
139
142
|
const desktopAnchor = mainContent.querySelector(`[id="${anchor}"]`);
|
|
140
143
|
if (desktopAnchor) {
|
|
141
|
-
console.log(
|
|
142
|
-
'[GlobalAppLayout] Immediate desktop scroll for:',
|
|
143
|
-
anchor
|
|
144
|
-
);
|
|
145
|
-
|
|
146
144
|
try {
|
|
147
145
|
// Add temporary scroll margin to account for header
|
|
148
146
|
const originalScrollMargin =
|
|
@@ -200,27 +198,16 @@ const {
|
|
|
200
198
|
// Check navigation flag first, before any components mount
|
|
201
199
|
const isMainNavNavigation =
|
|
202
200
|
sessionStorage.getItem('navigatingToMainNav') === 'true';
|
|
203
|
-
console.log(
|
|
204
|
-
'[GlobalAppLayout] DOMContentLoaded - navigation flag:',
|
|
205
|
-
isMainNavNavigation
|
|
206
|
-
);
|
|
207
201
|
|
|
208
202
|
if (isMainNavNavigation) {
|
|
209
203
|
// Clear the flag immediately
|
|
210
204
|
sessionStorage.removeItem('navigatingToMainNav');
|
|
211
|
-
console.log(
|
|
212
|
-
'[GlobalAppLayout] Cleared navigation flag for main nav navigation'
|
|
213
|
-
);
|
|
214
205
|
// Don't clear header state here - let navigation components handle it
|
|
215
206
|
}
|
|
216
207
|
|
|
217
208
|
// Handle URL hash scrolling (fallback for cases where immediate scroll didn't work)
|
|
218
209
|
if (window.location.hash) {
|
|
219
210
|
const anchor = window.location.hash.substring(1);
|
|
220
|
-
console.log(
|
|
221
|
-
'[GlobalAppLayout] DOMContentLoaded fallback hash scroll for:',
|
|
222
|
-
anchor
|
|
223
|
-
);
|
|
224
211
|
|
|
225
212
|
// Only proceed if we haven't already scrolled
|
|
226
213
|
if (sessionStorage.getItem('globalLayoutScrolling') !== 'true') {
|
|
@@ -241,10 +228,6 @@ const {
|
|
|
241
228
|
const mobileRect = mobileContent.getBoundingClientRect();
|
|
242
229
|
const scrollTop =
|
|
243
230
|
mobileContent.scrollTop + rect.top - mobileRect.top;
|
|
244
|
-
console.log(
|
|
245
|
-
'[GlobalAppLayout] Fallback mobile scroll to:',
|
|
246
|
-
scrollTop
|
|
247
|
-
);
|
|
248
231
|
mobileContent.scrollTo({ top: scrollTop, behavior: 'auto' });
|
|
249
232
|
|
|
250
233
|
setTimeout(() => {
|
|
@@ -285,11 +268,6 @@ const {
|
|
|
285
268
|
);
|
|
286
269
|
if (desktopAnchor) {
|
|
287
270
|
setTimeout(() => {
|
|
288
|
-
console.log(
|
|
289
|
-
'[GlobalAppLayout] Fallback desktop scroll for:',
|
|
290
|
-
anchor
|
|
291
|
-
);
|
|
292
|
-
|
|
293
271
|
// Try scrollIntoView first with a temporary offset
|
|
294
272
|
try {
|
|
295
273
|
// Add temporary scroll margin to account for header
|
|
@@ -303,43 +281,18 @@ const {
|
|
|
303
281
|
inline: 'nearest',
|
|
304
282
|
});
|
|
305
283
|
|
|
306
|
-
console.log(
|
|
307
|
-
'[GlobalAppLayout] Used fallback scrollIntoView for desktop'
|
|
308
|
-
);
|
|
309
|
-
|
|
310
284
|
// Restore original scroll margin after a delay
|
|
311
285
|
setTimeout(() => {
|
|
312
286
|
desktopAnchor.style.scrollMarginTop =
|
|
313
287
|
originalScrollMargin;
|
|
314
288
|
}, 1000);
|
|
315
289
|
} catch (e) {
|
|
316
|
-
console.log(
|
|
317
|
-
'[GlobalAppLayout] Fallback scrollIntoView failed, using manual calculation:',
|
|
318
|
-
e
|
|
319
|
-
);
|
|
320
|
-
|
|
321
290
|
// Fallback to manual calculation
|
|
322
291
|
const headerHeight = 56;
|
|
323
292
|
const rect = desktopAnchor.getBoundingClientRect();
|
|
324
293
|
const scrollTop = window.scrollY + rect.top - headerHeight;
|
|
325
|
-
console.log(
|
|
326
|
-
'[GlobalAppLayout] Fallback desktop scroll calculation:',
|
|
327
|
-
{
|
|
328
|
-
anchor,
|
|
329
|
-
rectTop: rect.top,
|
|
330
|
-
windowScrollY: window.scrollY,
|
|
331
|
-
headerHeight,
|
|
332
|
-
scrollTop,
|
|
333
|
-
elementText: desktopAnchor.textContent?.trim(),
|
|
334
|
-
}
|
|
335
|
-
);
|
|
336
|
-
|
|
337
294
|
// Ensure scrollTop is not negative
|
|
338
295
|
const finalScrollTop = Math.max(0, scrollTop);
|
|
339
|
-
console.log(
|
|
340
|
-
'[GlobalAppLayout] Fallback final scroll position:',
|
|
341
|
-
finalScrollTop
|
|
342
|
-
);
|
|
343
296
|
|
|
344
297
|
window.scrollTo({ top: finalScrollTop, behavior: 'auto' });
|
|
345
298
|
}
|
|
@@ -372,25 +325,14 @@ const {
|
|
|
372
325
|
}, 100);
|
|
373
326
|
}, 100);
|
|
374
327
|
} else {
|
|
375
|
-
console.log(
|
|
376
|
-
'[GlobalAppLayout] Fallback desktop anchor not found in main-content container:',
|
|
377
|
-
anchor
|
|
378
|
-
);
|
|
379
328
|
// Log all available anchors for debugging
|
|
380
329
|
const allAnchors = mainContent.querySelectorAll('[id]');
|
|
381
|
-
console.log(
|
|
382
|
-
'[GlobalAppLayout] Available anchors in main-content:',
|
|
383
|
-
Array.from(allAnchors).map(el => el.id)
|
|
384
|
-
);
|
|
385
330
|
// Clear the flag if anchor not found
|
|
386
331
|
if (typeof window !== 'undefined') {
|
|
387
332
|
sessionStorage.removeItem('globalLayoutScrolling');
|
|
388
333
|
}
|
|
389
334
|
}
|
|
390
335
|
} else {
|
|
391
|
-
console.log(
|
|
392
|
-
'[GlobalAppLayout] Fallback desktop main-content container not found'
|
|
393
|
-
);
|
|
394
336
|
// Clear the flag if container not found
|
|
395
337
|
if (typeof window !== 'undefined') {
|
|
396
338
|
sessionStorage.removeItem('globalLayoutScrolling');
|
|
@@ -418,29 +360,10 @@ const {
|
|
|
418
360
|
const wasMobile = lastWidth <= 640;
|
|
419
361
|
const isMobile = currentWidth <= 640;
|
|
420
362
|
|
|
421
|
-
console.log('[GlobalAppLayout] Resize detected:', {
|
|
422
|
-
lastWidth,
|
|
423
|
-
currentWidth,
|
|
424
|
-
wasMobile,
|
|
425
|
-
isMobile,
|
|
426
|
-
changed: wasMobile !== isMobile,
|
|
427
|
-
});
|
|
428
|
-
|
|
429
363
|
if (wasMobile !== isMobile) {
|
|
430
|
-
console.log(
|
|
431
|
-
'[GlobalAppLayout] Layout changed from',
|
|
432
|
-
wasMobile ? 'mobile' : 'desktop',
|
|
433
|
-
'to',
|
|
434
|
-
isMobile ? 'mobile' : 'desktop'
|
|
435
|
-
);
|
|
436
|
-
|
|
437
364
|
// Handle anchor scrolling for layout changes
|
|
438
365
|
if (window.location.hash) {
|
|
439
366
|
const anchor = window.location.hash.substring(1);
|
|
440
|
-
console.log(
|
|
441
|
-
'[GlobalAppLayout] Layout change with URL hash:',
|
|
442
|
-
anchor
|
|
443
|
-
);
|
|
444
367
|
|
|
445
368
|
// Wait for navigation state to update, then scroll
|
|
446
369
|
setTimeout(() => {
|
|
@@ -458,10 +381,6 @@ const {
|
|
|
458
381
|
const mobileRect = mobileContent.getBoundingClientRect();
|
|
459
382
|
const scrollTop =
|
|
460
383
|
mobileContent.scrollTop + rect.top - mobileRect.top;
|
|
461
|
-
console.log(
|
|
462
|
-
'[GlobalAppLayout] Scrolling mobile to anchor:',
|
|
463
|
-
scrollTop
|
|
464
|
-
);
|
|
465
384
|
mobileContent.scrollTo({
|
|
466
385
|
top: scrollTop,
|
|
467
386
|
behavior: 'auto',
|
|
@@ -499,15 +418,6 @@ const {
|
|
|
499
418
|
`[id="${anchor}"]`
|
|
500
419
|
);
|
|
501
420
|
if (desktopAnchor) {
|
|
502
|
-
console.log(
|
|
503
|
-
'[GlobalAppLayout] Desktop anchor found for layout change:',
|
|
504
|
-
{
|
|
505
|
-
anchor,
|
|
506
|
-
elementText: desktopAnchor.textContent?.trim(),
|
|
507
|
-
elementId: desktopAnchor.id,
|
|
508
|
-
}
|
|
509
|
-
);
|
|
510
|
-
|
|
511
421
|
// Try scrollIntoView first with a temporary offset
|
|
512
422
|
try {
|
|
513
423
|
// Add temporary scroll margin to account for header
|
|
@@ -521,44 +431,20 @@ const {
|
|
|
521
431
|
inline: 'nearest',
|
|
522
432
|
});
|
|
523
433
|
|
|
524
|
-
console.log(
|
|
525
|
-
'[GlobalAppLayout] Used scrollIntoView for desktop layout change with scroll margin'
|
|
526
|
-
);
|
|
527
|
-
|
|
528
434
|
// Restore original scroll margin after a delay
|
|
529
435
|
setTimeout(() => {
|
|
530
436
|
desktopAnchor.style.scrollMarginTop =
|
|
531
437
|
originalScrollMargin;
|
|
532
438
|
}, 1000);
|
|
533
439
|
} catch (e) {
|
|
534
|
-
console.log(
|
|
535
|
-
'[GlobalAppLayout] scrollIntoView failed for layout change, using manual calculation:',
|
|
536
|
-
e
|
|
537
|
-
);
|
|
538
|
-
|
|
539
440
|
// Fallback to manual calculation
|
|
540
441
|
const headerHeight = 56;
|
|
541
442
|
const rect = desktopAnchor.getBoundingClientRect();
|
|
542
443
|
const scrollTop =
|
|
543
444
|
window.scrollY + rect.top - headerHeight;
|
|
544
|
-
console.log(
|
|
545
|
-
'[GlobalAppLayout] Desktop scroll calculation for layout change:',
|
|
546
|
-
{
|
|
547
|
-
anchor,
|
|
548
|
-
rectTop: rect.top,
|
|
549
|
-
windowScrollY: window.scrollY,
|
|
550
|
-
headerHeight,
|
|
551
|
-
scrollTop,
|
|
552
|
-
elementText: desktopAnchor.textContent?.trim(),
|
|
553
|
-
}
|
|
554
|
-
);
|
|
555
445
|
|
|
556
446
|
// Ensure scrollTop is not negative
|
|
557
447
|
const finalScrollTop = Math.max(0, scrollTop);
|
|
558
|
-
console.log(
|
|
559
|
-
'[GlobalAppLayout] Final scroll position for layout change:',
|
|
560
|
-
finalScrollTop
|
|
561
|
-
);
|
|
562
448
|
|
|
563
449
|
window.scrollTo({
|
|
564
450
|
top: finalScrollTop,
|
|
@@ -601,11 +487,6 @@ const {
|
|
|
601
487
|
detail: { isMobile },
|
|
602
488
|
})
|
|
603
489
|
);
|
|
604
|
-
console.log(
|
|
605
|
-
'[GlobalAppLayout] Dispatched layoutTransition event for',
|
|
606
|
-
isMobile ? 'mobile' : 'desktop',
|
|
607
|
-
'layout'
|
|
608
|
-
);
|
|
609
490
|
}
|
|
610
491
|
|
|
611
492
|
lastWidth = currentWidth;
|
|
@@ -14,7 +14,12 @@ body {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
*:focus {
|
|
17
|
-
outline
|
|
17
|
+
outline: var(--ai-size-2) solid var(--ai-color-blue-600);
|
|
18
|
+
outline-offset: var(--ai-size-4);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
*:focus:not(:focus-visible) {
|
|
22
|
+
outline: none;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
a:focus {
|
|
@@ -50,7 +50,14 @@ h6,
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
pre {
|
|
53
|
-
padding: var(--ai-size-
|
|
53
|
+
padding: var(--ai-size-16);
|
|
54
|
+
border-radius: var(--ai-size-4);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
code {
|
|
58
|
+
font-family: var(--ai-font-family-monospace);
|
|
59
|
+
font-weight: var(--ai-font-weight-normal);
|
|
60
|
+
font-size: var(--ai-size-14);
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
a {
|
package/src/utils/getAppUrls.ts
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
+
import { getUrlFromBase } from '@gsa-tts/graymatter-ui/helpers/url.js';
|
|
2
|
+
|
|
1
3
|
function warnIfMissing(name: string, value: string | undefined) {
|
|
2
4
|
if (!value) {
|
|
3
5
|
console.warn(`[getAppUrls] Environment variable for ${name} is missing!`);
|
|
4
6
|
}
|
|
5
7
|
}
|
|
6
8
|
|
|
9
|
+
function isAbsoluteUrl(url: string): boolean {
|
|
10
|
+
try {
|
|
11
|
+
new URL(url);
|
|
12
|
+
return true;
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function processUrl(url: string | undefined, fallback: string): string {
|
|
19
|
+
if (!url) {
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (isAbsoluteUrl(url)) {
|
|
24
|
+
return url;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return getUrlFromBase(url);
|
|
28
|
+
}
|
|
29
|
+
|
|
7
30
|
export function getAppUrls(envArg?: Record<string, string | undefined>) {
|
|
8
31
|
const env = envArg || import.meta.env;
|
|
9
32
|
const fallback = '#';
|
|
@@ -18,9 +41,9 @@ export function getAppUrls(envArg?: Record<string, string | undefined>) {
|
|
|
18
41
|
warnIfMissing('api', apiUrl);
|
|
19
42
|
|
|
20
43
|
return {
|
|
21
|
-
chat: chatUrl
|
|
22
|
-
console: consoleUrl
|
|
23
|
-
api: apiUrl
|
|
24
|
-
discover: discoverUrl
|
|
44
|
+
chat: processUrl(chatUrl, fallback),
|
|
45
|
+
console: processUrl(consoleUrl, fallback),
|
|
46
|
+
api: processUrl(apiUrl, getUrlFromBase('/api/documentation')),
|
|
47
|
+
discover: processUrl(discoverUrl, '#'),
|
|
25
48
|
};
|
|
26
49
|
}
|