@gsa-tts/graymatter-ui 1.0.4 → 1.1.1

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": "@gsa-tts/graymatter-ui",
3
- "version": "1.0.4",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -61,9 +61,9 @@
61
61
  "typescript": "5.7.3",
62
62
  "vite": "^7.3.2",
63
63
  "vitest": "^3.2.4",
64
- "@gsa-tts/graymatter-vitest-config": "0.0.2",
64
+ "@gsa-tts/graymatter-eslint": "0.0.2",
65
65
  "@gsa-tts/graymatter-typescript-config": "0.0.3",
66
- "@gsa-tts/graymatter-eslint": "0.0.2"
66
+ "@gsa-tts/graymatter-vitest-config": "0.0.2"
67
67
  },
68
68
  "dependencies": {
69
69
  "@fontsource/archivo": "^5.2.8",
@@ -94,6 +94,22 @@
94
94
  const ssrSelected = $derived(() => ssrSelectedForUi());
95
95
  const ssrIsDiscover = $derived(() => ssrSelected() === 'discover');
96
96
  const isMenuDisabledForUi = $derived(() => selectedForUi() === 'discover');
97
+ const subNavLabel = $derived(() => {
98
+ const selected = ssrOrHydrated(selectedForUi(), ssrSelectedForUi());
99
+
100
+ switch (selected) {
101
+ case 'chat':
102
+ return 'Chats';
103
+ case 'console':
104
+ return 'Console menu';
105
+ case 'api':
106
+ return 'API documentation menu';
107
+ case 'discover':
108
+ return 'Discover menu';
109
+ default:
110
+ return 'Page menu';
111
+ }
112
+ });
97
113
 
98
114
  function isNavSelected(key: NavigationItem) {
99
115
  return ssrOrHydrated(selectedForUi() === key, ssrSelectedForUi() === key);
@@ -404,104 +420,106 @@
404
420
  </div>
405
421
 
406
422
  {#if showAppIcons}
407
- <div class="nav-items" part="nav-items">
408
- {#if !hideDiscover}
423
+ <nav aria-label="USAi application" part="app-navigation">
424
+ <div class="nav-items" part="nav-items">
425
+ {#if !hideDiscover}
426
+ <a
427
+ href={discoverUrl || '#'}
428
+ class="nav-item discover-item"
429
+ class:selected={isNavSelected('discover')}
430
+ class:hovered={isNavHovered('discover')}
431
+ onclick={() => handleNavItemClick('discover')}
432
+ onkeydown={e => {
433
+ handleKeyDown(e, 'discover');
434
+ handleNavKeyDown(e, 0);
435
+ }}
436
+ onmouseenter={() => (hoveredItem = 'discover')}
437
+ onmouseleave={() => (hoveredItem = null)}
438
+ aria-current={isNavSelected('discover') ? 'page' : undefined}
439
+ part="discover-item"
440
+ bind:this={discoverNavRef}
441
+ >
442
+ <div class="icon-container" part="discover-icon-container">
443
+ <div class="icon-wrapper">
444
+ <DiscoverIcon isSelected={isNavSelected('discover')} />
445
+ </div>
446
+ </div>
447
+ <span class="nav-text">Discover</span>
448
+ </a>
449
+ {/if}
409
450
  <a
410
- href={discoverUrl || '#'}
411
- class="nav-item discover-item"
412
- class:selected={isNavSelected('discover')}
413
- class:hovered={isNavHovered('discover')}
414
- onclick={() => handleNavItemClick('discover')}
451
+ href={chatUrl || '#'}
452
+ class="nav-item chat-item"
453
+ class:selected={isNavSelected('chat')}
454
+ class:hovered={isNavHovered('chat')}
455
+ onclick={() => handleNavItemClick('chat')}
415
456
  onkeydown={e => {
416
- handleKeyDown(e, 'discover');
417
- handleNavKeyDown(e, 0);
457
+ handleKeyDown(e, 'chat');
458
+ handleNavKeyDown(e, 1);
418
459
  }}
419
- onmouseenter={() => (hoveredItem = 'discover')}
460
+ onmouseenter={() => (hoveredItem = 'chat')}
420
461
  onmouseleave={() => (hoveredItem = null)}
421
- aria-current={isNavSelected('discover') ? 'page' : undefined}
422
- part="discover-item"
423
- bind:this={discoverNavRef}
462
+ aria-current={isNavSelected('chat') ? 'page' : undefined}
463
+ part="chat-item"
464
+ bind:this={chatNavRef}
424
465
  >
425
- <div class="icon-container" part="discover-icon-container">
466
+ <div class="icon-container" part="chat-icon-container">
426
467
  <div class="icon-wrapper">
427
- <DiscoverIcon isSelected={isNavSelected('discover')} />
468
+ <ChatIcon isSelected={isNavSelected('chat')} />
428
469
  </div>
429
470
  </div>
430
- <span class="nav-text">Discover</span>
471
+ <span class="nav-text">Chat</span>
431
472
  </a>
432
- {/if}
433
- <a
434
- href={chatUrl || '#'}
435
- class="nav-item chat-item"
436
- class:selected={isNavSelected('chat')}
437
- class:hovered={isNavHovered('chat')}
438
- onclick={() => handleNavItemClick('chat')}
439
- onkeydown={e => {
440
- handleKeyDown(e, 'chat');
441
- handleNavKeyDown(e, 1);
442
- }}
443
- onmouseenter={() => (hoveredItem = 'chat')}
444
- onmouseleave={() => (hoveredItem = null)}
445
- aria-current={isNavSelected('chat') ? 'page' : undefined}
446
- part="chat-item"
447
- bind:this={chatNavRef}
448
- >
449
- <div class="icon-container" part="chat-icon-container">
450
- <div class="icon-wrapper">
451
- <ChatIcon isSelected={isNavSelected('chat')} />
452
- </div>
453
- </div>
454
- <span class="nav-text">Chat</span>
455
- </a>
456
-
457
- <a
458
- href={consoleUrl || '#'}
459
- class="nav-item console-item"
460
- class:selected={isNavSelected('console')}
461
- class:hovered={isNavHovered('console')}
462
- onclick={() => handleNavItemClick('console')}
463
- onkeydown={e => {
464
- handleKeyDown(e, 'console');
465
- handleNavKeyDown(e, 2);
466
- }}
467
- onmouseenter={() => (hoveredItem = 'console')}
468
- onmouseleave={() => (hoveredItem = null)}
469
- aria-current={isNavSelected('console') ? 'page' : undefined}
470
- part="console-item"
471
- bind:this={consoleNavRef}
472
- >
473
- <div class="icon-container" part="console-icon-container">
474
- <div class="icon-wrapper">
475
- <ConsoleIcon isSelected={isNavSelected('console')} />
473
+
474
+ <a
475
+ href={consoleUrl || '#'}
476
+ class="nav-item console-item"
477
+ class:selected={isNavSelected('console')}
478
+ class:hovered={isNavHovered('console')}
479
+ onclick={() => handleNavItemClick('console')}
480
+ onkeydown={e => {
481
+ handleKeyDown(e, 'console');
482
+ handleNavKeyDown(e, 2);
483
+ }}
484
+ onmouseenter={() => (hoveredItem = 'console')}
485
+ onmouseleave={() => (hoveredItem = null)}
486
+ aria-current={isNavSelected('console') ? 'page' : undefined}
487
+ part="console-item"
488
+ bind:this={consoleNavRef}
489
+ >
490
+ <div class="icon-container" part="console-icon-container">
491
+ <div class="icon-wrapper">
492
+ <ConsoleIcon isSelected={isNavSelected('console')} />
493
+ </div>
476
494
  </div>
477
- </div>
478
- <span class="nav-text">Console</span>
479
- </a>
480
-
481
- <a
482
- href={apiUrl || '#'}
483
- class="nav-item api-item"
484
- class:selected={isNavSelected('api')}
485
- class:hovered={isNavHovered('api')}
486
- onclick={() => handleNavItemClick('api')}
487
- onkeydown={e => {
488
- handleKeyDown(e, 'api');
489
- handleNavKeyDown(e, 3);
490
- }}
491
- onmouseenter={() => (hoveredItem = 'api')}
492
- onmouseleave={() => (hoveredItem = null)}
493
- aria-current={isNavSelected('api') ? 'page' : undefined}
494
- part="api-item"
495
- bind:this={apiNavRef}
496
- >
497
- <div class="icon-container" part="api-icon-container">
498
- <div class="icon-wrapper">
499
- <ApiIcon isSelected={isNavSelected('api')} />
495
+ <span class="nav-text">Console</span>
496
+ </a>
497
+
498
+ <a
499
+ href={apiUrl || '#'}
500
+ class="nav-item api-item"
501
+ class:selected={isNavSelected('api')}
502
+ class:hovered={isNavHovered('api')}
503
+ onclick={() => handleNavItemClick('api')}
504
+ onkeydown={e => {
505
+ handleKeyDown(e, 'api');
506
+ handleNavKeyDown(e, 3);
507
+ }}
508
+ onmouseenter={() => (hoveredItem = 'api')}
509
+ onmouseleave={() => (hoveredItem = null)}
510
+ aria-current={isNavSelected('api') ? 'page' : undefined}
511
+ part="api-item"
512
+ bind:this={apiNavRef}
513
+ >
514
+ <div class="icon-container" part="api-icon-container">
515
+ <div class="icon-wrapper">
516
+ <ApiIcon isSelected={isNavSelected('api')} />
517
+ </div>
500
518
  </div>
501
- </div>
502
- <span class="nav-text">API</span>
503
- </a>
504
- </div>
519
+ <span class="nav-text">API</span>
520
+ </a>
521
+ </div>
522
+ </nav>
505
523
  {/if}
506
524
  </div>
507
525
 
@@ -546,14 +564,13 @@
546
564
  class="expanded-content drawer-anim"
547
565
  class:open={sideNavExpanded()}
548
566
  part="expanded-content"
567
+ aria-hidden={!sideNavExpanded()}
549
568
  >
550
- {#if sideNavExpanded()}
551
- <div class="drawer-content" part="drawer-content">
552
- <nav aria-label="Sub navigation" part="sub-navigation">
553
- {@render children?.()}
554
- </nav>
555
- </div>
556
- {/if}
569
+ <div class="drawer-content" part="drawer-content">
570
+ <nav aria-label={subNavLabel()} part="sub-navigation">
571
+ {@render children?.()}
572
+ </nav>
573
+ </div>
557
574
  </div>
558
575
  </div>
559
576
 
@@ -58,14 +58,7 @@ To reach chat completions the documented endpoint is `<base url>/api/v1/chat/com
58
58
  * **model**: The model ID (e.g: gemini-2.0-flash, claude_3_haiku)
59
59
  * **messages**: An array of of message items consisting of User message, Image Content, Document Content, Assistant Message
60
60
  * **max_tokens**: Maximum response length (optional)
61
- * **temperature**: Response creativity (0.0-2.0, optional)
62
-
63
- | **Models** | **Range** | **Default value** |
64
- | :------- | :------: | -------: |
65
- | Google models | 0.0 - 2.0 | 1.0 |
66
- | Anthropic models | 0.0 - 1.0 | 0.5 |
67
- | Meta models | 0.0 - 1.0 | 0.5 |
68
-
61
+ * **temperature**: Response creativity (0.0-1.0, optional)
69
62
  * **top_p**: An alternative to sampling with temperature, called nucleus sampling (optional)
70
63
  * **stream**: a boolean indicating whether to send partials responses as available (optional)
71
64
 
@@ -137,7 +130,7 @@ dimensions: The number of dimensions the resulting output embeddings should have
137
130
  curl -X 'POST' \
138
131
  '<base url>/api/v1/embeddings' \
139
132
  -H 'accept: application/json' \
140
- -H 'Authorization: Bearer <Your API Key>\
133
+ -H 'Authorization: Bearer <Your API Key>' \
141
134
  -H 'Content-Type: application/json' \
142
135
  -d '{
143
136
  "encodingFormat": "float",
@@ -14,25 +14,29 @@ Our API has resource-oriented URLs, accepts JSON request bodies, returns JSON re
14
14
 
15
15
  USAi API is organized around [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer) and provides access to the large language models (LLMs):
16
16
 
17
- **Google AI models**
18
- - [Gemini 2.5 Flash](https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash)
19
- - [Gemini 2.5 Pro](https://ai.google.dev/gemini-api/docs/models#gemini-2.5-pro)
20
-
21
- **Anthropic models**
22
- - [Claude Haiku 3.5](https://docs.claude.com/en/docs/overview)
23
- - [Claude Sonnet 4.5](https://docs.claude.com/en/docs/overview)
24
- - [Claude Opus 4.5](https://docs.claude.com/en/docs/overview)
25
-
26
- **Meta models**
27
- - [Llama 3.2 11B](https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_2/)
28
- - [Llama 4 Maverick](https://www.llama.com/docs/model-cards-and-prompt-formats/llama4/)
29
-
30
- **OpenAI models**
31
- - [GPT 5.2](https://developers.openai.com/api/docs/models/gpt-5.2)
32
- - [GPT 5.4](https://developers.openai.com/api/docs/models/gpt-5.4)
33
-
34
- **xAI models**
35
- - [Grok 4](https://docs.x.ai/developers/models/grok-4.20)
17
+ **[Google AI models](https://ai.google.dev/gemini-api/docs/)**
18
+ - Gemini 2.5 Flash
19
+ - Gemini 2.5 Pro
20
+
21
+ **[Anthropic models](https://docs.claude.com/en/docs/overview)**
22
+ - Claude Haiku 3.5
23
+ - Claude Haiku 4.5
24
+ - Claude Sonnet 4.5
25
+ - Claude Sonnet 4.6
26
+ - Claude Opus 4.5
27
+ - Claude Opus 4.7
28
+ - Claude Opus 4.8
29
+
30
+ **[Meta models](https://www.llama.com/docs/model-cards-and-prompt-formats/)**
31
+ - Llama 4 Maverick
32
+
33
+ **[OpenAI models](https://developers.openai.com/api/docs/models/)**
34
+ - GPT 5.2
35
+ - GPT 5.4
36
+ - GPT 5.5
37
+
38
+ **[xAI models](https://docs.x.ai/developers/models/)**
39
+ - Grok 4
36
40
 
37
41
  The interface is modeled after the [OpenAI Chat Completion API](https://platform.openai.com/docs/guides/text?api-mode=responses). We will continue to add more models over time; we may also remove models if they are found to not meet our standards. You will be notified if a model is removed.
38
42
 
@@ -54,7 +58,12 @@ All API requests require an API key. Upon authentication, your agency-specific i
54
58
 
55
59
  #### Rate limitations
56
60
 
57
- We currently have a rate limit of 3 calls / second / API key. If you hit a rate limit, you should expect a 429 error code. If you need additional capacity, please contact us at [support@usai.gov](mailto:support@usai.gov). We can work with our infrastructure providers to secure higher model limits.
61
+ We currently have the following rate limits:
62
+ - Models – 3 calls / second / API key
63
+ - Chat completions – 3 calls / second / API key
64
+ - Embeddings – 100 calls / second / API key
65
+
66
+ If you hit a rate limit, you should expect a 429 error code. If you need additional capacity, please contact us at [partnerships@usai.gov](mailto:partnerships@usai.gov). We can work with our infrastructure providers to secure higher model limits.
58
67
 
59
68
  #### Feature limitations
60
69
 
@@ -4,7 +4,7 @@ description: ''
4
4
  sortOrder: 30
5
5
  ---
6
6
 
7
- You may encounter issues while working with the USAi API, as it is under active development. We may not be able to fix all issues immediately, but will add them to our backlog for future releases. If you have any questions, hit rate limits, or otherwise need assistance, please contact us at [support@usai.gov](mailto:support@usai.gov).
7
+ If you have any questions, hit rate limits, or otherwise need assistance, please contact us at [support@usai.gov](mailto:support@usai.gov).
8
8
 
9
9
 
10
10
 
@@ -101,21 +101,23 @@ const discover = discoverUrl || '#';
101
101
  </nav>
102
102
 
103
103
  <!-- Fixed Logo (Desktop only) -->
104
- <div
105
- class="logo-fixed-container display-none tablet:display-flex"
106
- aria-label={siteName}
107
- role="region"
108
- >
109
- {
110
- logoLinkUrl ? (
111
- <a class="display-flex" href={logoLinkUrl} aria-label={logoLinkLabel}>
104
+ <nav aria-label="Site logo">
105
+ <div class="logo-fixed-container display-none tablet:display-flex">
106
+ {
107
+ logoLinkUrl ? (
108
+ <a
109
+ class="display-flex"
110
+ href={logoLinkUrl}
111
+ aria-label={logoLinkLabel}
112
+ >
113
+ <Logo width={75} height={22} />
114
+ </a>
115
+ ) : (
112
116
  <Logo width={75} height={22} />
113
- </a>
114
- ) : (
115
- <Logo width={75} height={22} />
116
- )
117
- }
118
- </div>
117
+ )
118
+ }
119
+ </div>
120
+ </nav>
119
121
 
120
122
  <!-- Mobile Main Content -->
121
123
  <main id="main-content-mobile" class="main-content-mobile">